bun.sh.md•1.42 MB
=== bun.sh/1.0.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun 1.0
* * *
[Jarred Sumner](https://twitter.com/jarredsumner), [Ashcon Partovi](https://twitter.com/ashconpartovi), [Colin McDonnell](https://twitter.com/colinhacks) · September 8, 2023
[](rss.xml)
Bun 1.0 is finally here.
Bun is a fast, all-in-one toolkit for running, building, testing, and debugging JavaScript and TypeScript, from a single file to a full-stack application. Today, Bun is stable and production-ready.
**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
```
**Upgrade Bun**
```
bun upgrade
```
## []()[Bun is an all-in-one toolkit](1.0.html#bun-is-an-all-in-one-toolkit)
We love JavaScript. It's mature, it moves fast, and its developer community is vibrant and passionate. It's awesome.
However, since Node.js debuted 14 years ago, layers and layers of tooling have accumulated on top of each other. And like any system that grows and evolves without centralized planning, JavaScript tooling has become slow and complex.
### []()[Why Bun exists](1.0.html#why-bun-exists)
Bun's goal is simple: eliminate slowness and complexity *without* throwing away everything that's great about JavaScript. Your favorite libraries and frameworks should still work, and you shouldn't need to unlearn the conventions you're familiar with.
You *will* however need to unlearn the many tools that Bun makes unnecessary:
**Node.js** — Bun is a drop-in replacement for Node.js, so you don't need:
- `node`
- `npx` — `bunx` is 5x faster
- `dotenv`, `cross-env` — Bun reads `.env` files by default
- `nodemon`, `pm2` — built-in watch mode
- `ws` — built-in WebSocket server
- `node-fetch`, `isomorphic-fetch` — built-in `fetch`
**Transpilers** — Bun can run `.js`, `.ts`, `.cjs`, `.mjs`, `.jsx`, and `.tsx` files, which can replace:
- `tsc` — (but you can keep it for typechecking!)
- `babel`, `.babelrc`, `@babel/preset-*`
- `ts-node`, `ts-node-esm`
- `tsx`
**Bundlers** — Bun is a JavaScript bundler with best-in-class performance and an esbuild-compatible plugin API, so you don't need:
- `esbuild`
- `webpack`
- `parcel`, `.parcelrc`
- `rollup`, `rollup.config.js`
**Package managers** — Bun is an npm-compatible package manager with familiar commands. It reads your `package.json` and writes to `node_modules`, just like other package managers, so you can replace:
- `npm`, `.npmrc`, `package-lock.json`
- `yarn`, `yarn.lock`
- `pnpm`, `pnpm.lock`, `pnpm-workspace.yaml`
- `lerna`
**Testing libraries** — Bun is a Jest-compatible test runner with support for snapshot testing, mocking, and code coverage, so you no longer need:
- `jest`, `jest.config.js`
- `ts-jest`, `@swc/jest`, `babel-jest`
- `jest-extended`
- `vitest`, `vitest.config.ts`
While these tools are each good in their own right (mostly), using them all together inevitably creates fragility and a slow developer experience. They perform a lot of redundant work; when you run `jest`, your code will be parsed 3+ times by various tools! And the duct tape, plugins, and adapters required to stitch everything together always frays eventually.
Bun is a single integrated toolkit that avoids these integration problems. Each tool in this toolkit provides a best-in-class developer experience, from performance to API design.
## []()[Bun is a JavaScript runtime](1.0.html#bun-is-a-javascript-runtime)
Bun is a fast JavaScript runtime. Its goal is to make the experience of building software faster, less frustrating, and more fun.
### []()[Node.js compatibility](1.0.html#node-js-compatibility)
Bun is a drop-in replacement for Node.js. That means existing Node.js applications and npm packages *just work* in Bun. Bun has built-in support for Node APIs, including:
- built-in modules like `fs`, `path`, and `net`,
- globals like `__dirname` and `process`,
- and the Node.js module resolution algorithm. (e.g. `node_modules`)
While *perfect* compatibility with Node.js isn't possible — looking at you `node:v8` — Bun can run virtually any Node.js application in the wild.
Bun is tested against test suites of the most popular Node.js packages on npm. Server frameworks like Express, Koa, and Hono just work. As do applications built using the most popular full-stack frameworks. Collectively, these libraries and frameworks touch every part of Node.js's API surface that matters.
[](https://github.com/oven-sh/bun/assets/3084745/e4c4ee5d-a859-4a7b-97f7-9fb477939fe6)
Full-stack applications built with Next.js, Remix, Nuxt, Astro, SvelteKit, Nest, SolidStart, and Vite work in Bun.
**Note** — For a detailed breakdown of Node.js compatibility, check out: [bun.sh/nodejs](nodejs.html).
### []()[Speed](1.0.html#speed)
Bun is fast, starting up to 4x [faster](https://twitter.com/jarredsumner/status/1499225725492076544) than Node.js. This difference is only magnified when running a TypeScript file, which requires transpilation before it can be run by Node.js.
[](https://github.com/oven-sh/bun/assets/3084745/e65fa63c-99c7-4bcf-950b-e2fe9408a942)
Bun runs a "hello world" TypeScript file 5x faster than esbuild with Node.js.
Unlike Node.js and other runtimes that are built using Google's V8 engine, Bun is built using Apple's [WebKit](https://webkit.org/) engine. WebKit is the engine that powers Safari and is used by billions of devices every day. It's fast, efficient, and has been battle-tested for decades.
### []()[TypeScript and JSX support](1.0.html#typescript-and-jsx-support)
Bun has a JavaScript transpiler that's baked into the runtime. That means you can run JavaScript, TypeScript, and even JSX/TSX files, no dependencies needed.
```
bun index.ts
```
```
bun index.jsx
```
```
bun index.tsx
```
### []()[ESM & CommonJS compatibility](1.0.html#esm-commonjs-compatibility)
The transition from CommonJS to ES modules has been slow and full of terrors. After ESM was introduced, Node.js took 5 years before supporting it without an `--experimental-modules` flag. Regardless, the ecosystem is still full of CommonJS.
Bun supports both module systems, all the time. No need to worry about file extensions, `.js` vs `.cjs` vs `.mjs`, or including `"type": "module"` in your `package.json`.
You can even use `import` and `require()`, *in the same file.* It just works.
```
import lodash from "lodash";
const _ = require("underscore");
```
### []()[Web APIs](1.0.html#web-apis)
Bun has built-in support for the Web standard APIs that are available in browsers, such as `fetch`, `Request`, `Response`, `WebSocket`, and `ReadableStream`.
```
const response = await fetch("https://example.com/");
const text = await response.text();
```
You no longer need to install packages like `node-fetch` and `ws`. Bun's built-in Web APIs are implemented in native code, and are faster and more reliable than the third-party alternatives.
### []()[Hot reloading](1.0.html#hot-reloading)
Bun makes it easier for you to be productive as a developer. You can run Bun with `--hot` to enable hot reloading, which reloads your application when files change.
```
bun --hot server.ts
```
Unlike tools that hard-restart the entire process, like `nodemon`, Bun reloads your code without terminating the old process. That means HTTP and WebSocket connections don't disconnect and state isn't lost.
[](hot.gif)
### []()[Plugins](1.0.html#plugins)
Bun is designed to be highly-customizable.
You can define plugins to intercept imports and perform custom loading logic. A plugin can add support for additional file types, like `.yaml` or `.png`. The [Plugin API](docs/runtime/plugins.html) is inspired by esbuild, which means that most esbuild plugins will just work in Bun.
```
import { plugin } from "bun";
plugin({
name: "YAML",
async setup(build) {
const { load } = await import("js-yaml");
const { readFileSync } = await import("fs");
build.onLoad({ filter: /\.(yaml|yml)$/ }, (args) => {
const text = readFileSync(args.path, "utf8");
const exports = load(text) as Record<string, any>;
return { exports, loader: "object" };
});
},
});
```
## []()[Bun APIs](1.0.html#bun-apis)
Bun ships with highly-optimized, standard-library APIs for the things you need most as a developer.
In contrast to Node.js APIs, which exist for backwards compatibility, these *Bun-native* APIs are designed to be fast and easy-to-use.
### []()[`Bun.file()`](1.0.html#bun-file)
Use `Bun.file()` to lazily load a `File` at a particular path.
```
const file = Bun.file("package.json");
const contents = await file.text();
```
It returns a `BunFile`, which extends the Web standard [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File). The file contents can be lazily loaded in various formats.
```
const file = Bun.file("package.json");
await file.text(); // string
await file.arrayBuffer(); // ArrayBuffer
await file.blob(); // Blob
await file.json(); // {...}
```
Bun reads files up to 10x times [faster](https://twitter.com/jarredsumner/status/1513878964531519494) than Node.js.
### []()[`Bun.write()`](1.0.html#bun-write)
Use `Bun.write()` is a single, flexible API for writing almost anything to disk — string, binary data, `Blobs`, even a `Response` object.
```
await Bun.write("index.html", "<html/>");
await Bun.write("index.html", Buffer.from("<html/>"));
await Bun.write("index.html", Bun.file("home.html"));
await Bun.write("index.html", await fetch("https://example.com/"));
```
Bun writes files up to 3x [faster](https://twitter.com/jarredsumner/status/1551003252920946688) than Node.js.
### []()[`Bun.serve()`](1.0.html#bun-serve)
Use `Bun.serve()` to spin up an HTTP server, WebSocket server, or both. It's based on familiar Web-standard APIs like `Request` and `Response`.
```
Bun.serve({
port: 3000,
fetch(request) {
return new Response("Hello from Bun!");
},
});
```
Bun can serve 4x [more](https://github.com/oven-sh/bun/tree/main/bench/react-hello-world) requests per second than Node.js.
You can also configure TLS using the `tls` option.
```
Bun.serve({
port: 3000,
fetch(request) {
return new Response("Hello from Bun!");
},
tls: {
key: Bun.file("/path/to/key.pem"),
cert: Bun.file("/path/to/cert.pem"),
}
});
```
To support WebSockets alongside HTTP, simply define an event handler inside `websocket`. Compare this with Node.js, which doesn't provide a built-in WebSocket API and requires a third-party dependency like `ws`.
```
Bun.serve({
fetch() { ... },
websocket: {
open(ws) { ... },
message(ws, data) { ... },
close(ws, code, reason) { ... },
},
});
```
Bun can serve 5x [more](https://github.com/oven-sh/bun/tree/main/bench/websocket-server) messages per second than `ws` on Node.js.
### []()[`bun:sqlite`](1.0.html#bun-sqlite)
Bun has built-in support for SQLite. It has an API that's inspired by `better-sqlite3`, but is written in native code to be faster.
```
import { Database } from "bun:sqlite";
const db = new Database(":memory:");
const query = db.query("select 'Bun' as runtime;");
query.get(); // => { runtime: "Bun" }
```
Bun can query SQLite up to 4x [faster](https://github.com/oven-sh/bun/tree/main/bench/sqlite) than `better-sqlite3` on Node.js.
### []()[`Bun.password`](1.0.html#bun-password)
Bun also supports APIs for common, but complex things you wouldn't want to implement yourself.
You can use `Bun.password` to hash and verify passwords using bcrypt or argon2, no external dependencies required.
```
const password = "super-secure-pa$$word";
const hash = await Bun.password.hash(password);
// => $argon2id$v=19$m=65536,t=2,p=1$tFq+9AVr1bfPxQdh...
const isMatch = await Bun.password.verify(password, hash);
// => true
```
## []()[Bun is a package manager](1.0.html#bun-is-a-package-manager)
Even if you don't use Bun as a runtime, Bun's built-in package manager can speed up your development workflow. Gone are the days of staring at that `npm` spinner as your dependencies install.
Bun may *look* like the package managers you're used to —
```
bun install
```
```
bun add <package> [--dev|--production|--peer]
```
```
bun remove <package>
```
```
bun update <package>
```
— but it doesn't *feel* like them.
> Wow, bun install is ridiculously fast
>
> So fast I didn't believe it worked. I had to stare at the console for a while to fully believe that the package install actually happened
>
> Feels really nice to use, huge kudos to [@jarredsumner](https://twitter.com/jarredsumner?ref_src=twsrc%5Etfw)
>
> — Steve (Builder.io) (@Steve8708) [August 21, 2022](https://twitter.com/Steve8708/status/1561412958722306049?ref_src=twsrc%5Etfw)
### []()[Install speeds](1.0.html#install-speeds)
Bun is orders of magnitude faster than `npm`, `yarn`, and `pnpm`. It uses a global module cache to avoid redundant downloads from the npm registry and uses the fastest system calls available on each operating system.
[](https://github.com/oven-sh/bun/assets/3084745/23cbde35-b859-41b5-9480-98b88bf40c44)
Installing dependencies for a starter Remix project from cache.
### []()[Running scripts](1.0.html#running-scripts)
Chances are, you haven't ran a script directly with `node` in a while. Instead, we often use our package managers to interface with the frameworks and CLIs to build our apps.
```
npm run dev
```
You can replace `npm run` with `bun run` to save 150ms milliseconds *every time* you run a command.
These numbers may all seem small, but when running CLIs, the perceptual difference is huge. Running `npm run` is noticably laggy—
[](https://github-production-user-asset-6210df.s3.amazonaws.com/3084745/265893417-fbfb4172-5a91-4158-904f-55f2dbb0acde.gif)
—whereas `bun run` feels instantaneous.
[](https://github-production-user-asset-6210df.s3.amazonaws.com/3084745/265893406-6d7e0e3f-cd70-409c-8c1e-9b5493d18e51.gif)
And we're not just picking on npm. In fact, `bun run <command>` is [faster](https://gist.github.com/colinhacks/436b6836cd13291a79dd50dcde2d45bf) than the equivalent in `yarn` and `pnpm`.
Script runnerAvg. time`npm run``176ms``yarn run``131ms``pnpm run``259ms``bun run``7ms` 🚀
## []()[Bun is a test runner](1.0.html#bun-is-a-test-runner)
If you’ve written tests in JavaScript before, you’re probably familiar with Jest, which pioneered the "expect"-style APIs.
Bun has a built-in testing module `bun:test` that is fully Jest-compatible.
```
import { test, expect } from "bun:test";
test("2 + 2", () => {
expect(2 + 2).toBe(4);
});
```
You can run your tests with the `bun test` command.
```
bun test
```
You also get all the benefits of the Bun runtime, including TypeScript and JSX support.
Migration from Jest or Vitest is easy. Any imports from `@jest/globals` or `vitest` will be internally re-mapped to `bun:test`, so everything works, even without code changes.
index.test.ts
```
import { test } from "@jest/globals";
describe("test suite", () => {
// ...
});
```
In a benchmark against the test suite for [`zod`](https://github.com/colinhacks/zod), Bun was 13x faster than Jest and 8x faster than than Vitest.
[](https://github.com/oven-sh/bun/assets/3084745/05148dc1-eb42-419b-8c92-8c1b574447e4)
Running the test suite for Zod
Bun's matchers are implemented in fast native code — `expect().toEqual()` in Bun is 100x [faster](https://twitter.com/jarredsumner/status/1595681235606585346) than Jest and 10x faster than Vitest.
To get started, you can speed up your CI using `bun test`. In Github Actions, use the official [`oven-sh/setup-bun`](https://github.com/oven-sh/setup-bun) action.
.github/workflows/ci.yml
```
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: oven-sh/setup-bun@v1
- run: bun test
```
And to make things that even nicer, Bun automatically adds annotations to your test failures, so your CI logs are easy to read.
[](https://github.com/oven-sh/bun/assets/3238291/cb8c6070-4f9c-423c-88bc-6f392adaf66d)
## []()[Bun is a bundler](1.0.html#bun-is-a-bundler)
Bun is a JavaScript and TypeScript bundler and minifier that can be used to bundle code for the browser, Node.js, and other platforms.
CLI
```
bun build ./index.tsx --outdir ./build
```
It's heavily inspired by [esbuild](https://esbuild.github.io/api/) and provides a compatible plugin API.
```
import mdx from "@mdx-js/esbuild";
Bun.build({
entrypoints: ["index.tsx"],
outdir: "build",
plugins: [mdx()],
});
```
Bun's plugin API is universal, meaning it works for both the bundler *and* the runtime. So that `.yaml` plugin from earlier can be used here to support `.yaml` imports during bundling.
Using esbuild's own benchmarks, Bun is 1.75x faster than esbuild, 150x faster than Parcel 2, 180x times faster than Rollup + Terser, and 220x times faster than Webpack.
[](https://github.com/oven-sh/bun/assets/3084745/49fe1da7-b3d7-4b7c-9c9b-26d532c6a57b)
Bundling 10 copies of three.js from scratch, with sourcemaps and minification.
Since Bun's runtime and bundler are integrated, it means that Bun can do things that no other bundler can do.
Bun introduces JavaScript macros, a mechanism for running JavaScript functions at *bundle*-time. The value returned from these functions are directly inlined into your bundle.
index.ts
release.ts
index.ts
```
import { getRelease } from "./release.ts" with { type: "macro" };
// The value of `release` is evaluated at bundle-time,
// and inlined into the bundle, not run-time.
const release = await getRelease();
```
release.ts
```
export async function getRelease(): Promise<string> {
const response = await fetch(
"https://api.github.com/repos/oven-sh/bun/releases/latest"
);
const { tag_name } = await response.json();
return tag_name;
}
```
CLI
```
bun build index.ts
```
```
// index.ts
var release = await "bun-v1.0.0";
```
This is a new paradigm for bundling JavaScript, and we're excited to see what you build with it.
## []()[Bun more thing...](1.0.html#bun-more-thing)
Bun provides native builds for macOS and Linux, but there's been one notable absence: Windows. Previously, to run Bun on Windows, you would need to install Windows Subsystem for Linux... but not anymore.
For the first time, we're excited to release an experimental, native build of Bun for Windows.
[](https://github.com/oven-sh/bun/assets/3084745/42e0657e-4421-42de-88bc-61a9ec9fa8a7)
While the macOS and Linux builds of Bun are production-ready, **the Windows build is highly experimental**. At the moment, only the JavaScript runtime is supported; the package manager, test runner, and bundler have been disabled until they are more stable. The performance has also not been optimized — yet.
We'll be rapidly improving support for Windows over the coming weeks. If you're excited about Bun for Windows, we'd encourage you to join the `#windows` channel on our [Discord](discord.html) for updates.
## []()[Thank you](1.0.html#thank-you)
Bun's journey to 1.0 would have not been possible without Bun's amazing team of engineers and the growing community of contributors.
We'd like to thank those who helped us get here.
- Node.js & its contributors: Software is built on the shoulder of giants.
- WebKit & its contributors, especially [Constellation](https://twitter.com/Constellation): Thank you for making WebKit faster, you're amazing.
- The [nearly 300 contributors](https://github.com/oven-sh/bun/graphs/contributors) who have helped build Bun over the past two years!
## []()[What's next?](1.0.html#what-s-next)
Bun 1.0 is just the beginning.
We’re developing a new way to deploy JavaScript and TypeScript to production. And we’re [hiring](careers.html) low-level systems engineers if you want to help us build the future of JavaScript.
You can also:
- [Join](discord.html) our Discord server to hear the latest about Bun.
- [Follow](https://twitter.com/bunjavascript) us on X/Twitter for JavaScript memes and daily updates from Jarred and the team.
- [Star](https://github.com/oven-sh/bun) us on Github — it pays the bills! (/s)
* * *
**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
```
**Upgrade Bun**
```
bun upgrade
```
* * *
### []()[Changelog since v0.8](1.0.html#changelog-since-v0-8)
If you were using Bun *before* 1.0, there are a few changes since Bun 0.8.
- Next.js, Astro, and Nest.js are now supported!
- The deprecated `bun dev` command has been removed. Running `bun dev` will now run the `"dev"` script in your package.json.
Bun now supports the following Node.js APIs:
- [`child_process.fork()`](https://nodejs.org/api/child_process.html#child_processforkmodulepath-args-options) and IPC.
- [`fs.cp()`](https://nodejs.org/api/fs.html#fscpsrc-dest-options-callback) and [`fs.cpSync()`](https://nodejs.org/api/fs.html#fscpsyncsrc-dest-options).
- [`fs.watchFile()`](https://nodejs.org/api/fs.html#fswatchfilefilename-options-listener) and [`fs.unwatchFile()`](https://nodejs.org/api/fs.html#fsunwatchfilefilename-listener).
- Unix sockets in `node:http`.
Hot reloading now supports `Bun.serve()`. Previously, this was only possible if the server was defined as a `default export`.
server.ts
```
Bun.serve({
fetch(request) {
return new Response("Reload!");
},
})
```
CLI
```
bun --hot server.ts
```
* * *
#### [Bun v1.0.1](blog/bun-v1.0.1.html)
On this page
- [Bun is an all-in-one toolkit](1.0.html#bun-is-an-all-in-one-toolkit)
- [Why Bun exists](1.0.html#why-bun-exists)
- [Bun is a JavaScript runtime](1.0.html#bun-is-a-javascript-runtime)
- [Node.js compatibility](1.0.html#node-js-compatibility)
- [Speed](1.0.html#speed)
- [TypeScript and JSX support](1.0.html#typescript-and-jsx-support)
- [ESM & CommonJS compatibility](1.0.html#esm-commonjs-compatibility)
- [Web APIs](1.0.html#web-apis)
- [Hot reloading](1.0.html#hot-reloading)
- [Plugins](1.0.html#plugins)
- [Bun APIs](1.0.html#bun-apis)
- [`Bun.file()`](1.0.html#bun-file)
- [`Bun.write()`](1.0.html#bun-write)
- [`Bun.serve()`](1.0.html#bun-serve)
- [`bun:sqlite`](1.0.html#bun-sqlite)
- [`Bun.password`](1.0.html#bun-password)
- [Bun is a package manager](1.0.html#bun-is-a-package-manager)
- [Install speeds](1.0.html#install-speeds)
- [Running scripts](1.0.html#running-scripts)
- [Bun is a test runner](1.0.html#bun-is-a-test-runner)
- [Bun is a bundler](1.0.html#bun-is-a-bundler)
- [Bun more thing...](1.0.html#bun-more-thing)
- [Thank you](1.0.html#thank-you)
- [What's next?](1.0.html#what-s-next)
- [Changelog since v0.8](1.0.html#changelog-since-v0-8)
Resources
[Docs](docs/index.html)
[Guides](guides.html)
[Discord](discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](blog.html)
[](rss.xml)
Toolkit
[Runtime](docs/cli/run.html)
[Package manager](docs/cli/install.html)
[Test runner](docs/cli/test.html)
[Bundler](docs/bundler.html)
[Package runner](docs/cli/bunx.html)
Project
[Bun 1.0](1.0.html)
[Bun 1.1](blog/bun-v1.1.html)
[Bun 1.2](blog/bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](docs/project/contributing.html)
[License](docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](careers.html)
=== bun.sh/blog/bun-bundler.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# The Bun Bundler
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · May 16, 2023
[](../rss.xml)
Bun's fast native bundler is now in beta. It can be used via the `bun build` CLI command or the new `Bun.build()` JavaScript API.
[](../images/bundler-speed.png)
Bundling 10 copies of three.js from scratch, with sourcemaps and minification
Use the bundler to build frontend apps with the built-in `Bun.build()` function or the `bun build` CLI command.
JavaScript
CLI
JavaScript
```
Bun.build({
entrypoints: ['./src/index.tsx'],
outdir: './build',
minify: true,
// additional config
});
```
CLI
```
bun build ./src/index.tsx --outdir ./build --minify
```
## []()[Reducing complexity in JavaScript](bun-bundler.html#reducing-complexity-in-javascript)
JavaScript started as autofill for form fields, and today it powers the instruments that launch rockets to space.
Unsurprisingly, the JavaScript ecosystem has exploded in complexity. How do you run TypeScript files? How do you build/bundle your code for production? Does that package work with ESM? How do you load local-only configuration? Do I need to install peer dependencies? How do I get sourcemaps working?
Complexity costs time, usually spent glueing together tools or waiting for things to finish. Installing npm packages takes too long. Running tests should take seconds (or less). Why does it take minutes to deploy software in 2023 when it took milliseconds to upload files to an FTP server in 2003?
For years, I’ve been frustrated by how slow everything around JavaScript is. When the iteration cycle time from saving a file to testing changes gets long enough to instinctively check Hacker News, something is wrong.
There are good reasons for the complexity. Bundlers & minifiers make websites load faster. TypeScript’s in-editor interactive documentation makes developers more productive. Type safety helps catch bugs before they ship to users. Dependencies as versioned packages are usually easier to maintain than copying files.
The Unix philosophy of “do one thing well” breaks down when that “one thing” is split between so many isolated tools.
This is why we're building Bun, and why today we're excited to introduce the Bun bundler.
## []()[Yes, a new bundler](bun-bundler.html#yes-a-new-bundler)
With the new bundler, bundling is now a first-class element of the Bun ecosystem, complete with a `bun build` CLI command, a new top-level `Bun.build` function, and a stable plugin system.
There are a few reasons we decided Bun needed its own bundler.
### []()[Cohesiveness](bun-bundler.html#cohesiveness)
Bundlers are the meta-tool that orchestrates and enables all other tools, like JSX, TypeScript, CSS modules, and server components—all things that require bundler integration to work.
Today, bundlers are a source of immense complexity in the JavaScript ecosystem. By bringing bundling into the JavaScript runtime, we think we can make shipping frontend & full-stack code simpler and faster.
- **Fast plugins.** Plugins are executed in a lightweight Bun process that starts fast.
- **No redundant transpilation**. With `target: "bun"`, the bundler generates pre-transpiled files that are optimized for Bun's runtime, improving running performance and avoiding unnecessary re-transpilations.
- **Unified plugin API**. Bun provides a unified plugin API that works with both the bundler *and* the runtime. Any plugin that extends Bun's bundling capabilities can also be used to extend Bun's runtime capabilities.
- **Runtime integration**. Builds return an array of `BuildArtifact` objects, which implement the `Blob` interface and can be passed directly into HTTP APIs like `new Response()`. The runtime implements special pretty-printing for `BuildArtifact`.
- **Standalone executables**. The bundler can generate standalone executables from TypeScript & JavaScript scripts via the `--compile` flag. These executables are entirely self-contained and include a copy of the Bun runtime.
Soon, the bundler will be integrated with Bun's HTTP server API (`Bun.serve`), making it possible to represent currently-complicated build pipelines with a simple declarative API. More on that later.
### []()[Performance](bun-bundler.html#performance)
This one won't surprise anybody. As a runtime, Bun's codebase already contains the groundwork (implemented in Zig) for quickly parsing and transforming source code. While possible, it would have been hard to integrate with an existing native bundler, and the overhead involved in interprocess communication would hurt performance.
Ultimately the results speak for themselves. In [our benchmarks](https://github.com/oven-sh/bun/tree/main/bench/bundle) (which is derived from esbuild's three.js benchmark), Bun is 1.75x faster than esbuild, 150x faster than Parcel 2, 180x times faster than Rollup + Terser, and 220x times faster than Webpack.
### []()[Developer experience](bun-bundler.html#developer-experience)
Looking at the APIs of existing bundlers, we saw a lot of room for improvement. No one likes wrestling with bundler configurations. Bun's bundler API is designed to be unambiguous and unsurprising. Speaking of which...
## []()[The API](bun-bundler.html#the-api)
The API is currently minimal by design. Our goal with this initial release is to implement a minimal feature set that fast, stable, and accommodates most modern use cases without sacrificing performance.
Here is the API as it currently exists:
```
interface Bun {
build(options: BuildOptions): Promise<BuildOutput>;
}
interface BuildOptions {
entrypoints: string[]; // required
outdir?: string; // default: no write (in-memory only)
target?: "browser" | "bun" | "node"; // "browser"
format?: "esm"; // later: "cjs" | "iife"
splitting?: boolean; // default false
plugins?: BunPlugin[]; // [] // see https://bun.sh/docs/bundler/plugins
loader?: { [k in string]: string }; // see https://bun.sh/docs/bundler/loaders
external?: string[]; // default []
sourcemap?: "none" | "inline" | "external"; // default "none"
root?: string; // default: computed from entrypoints
publicPath?: string; // e.g. http://mydomain.com/
naming?:
| string // equivalent to naming.entry
| { entry?: string; chunk?: string; asset?: string };
minify?:
| boolean // default false
| { identifiers?: boolean; whitespace?: boolean; syntax?: boolean };
}
```
Other bundlers have made poor architectural decisions in the pursuit of feature-completeness that end up crippling performance; this is a mistake we are carefully trying to avoid.
### []()[Module systems](bun-bundler.html#module-systems)
Only `format: "esm"` is supported for now. We plan to add support for other module systems and targets like `iife`. If enough people ask, we'll add `cjs` otuput support as well (CommonJS input is supported, but not output).
### []()[Targets](bun-bundler.html#targets)
Three "targets" are supported: `"browser"` (the default), `"bun"`, and `"node"`.
#### `browser`
- TypeScript and JSX are automatically transpiled to vanilla JavaScript.
- Modules are resolved using the `"browser"` package.json `"exports"` condition when availabile
- Bun automatically polyfills certain Node.js APIs when imported in the browser such as `node:crypto`, similarly to [Webpack 4's behavior](https://github.com/facebook/create-react-app/issues/11756). Bun's own APIs are currently prohibited from being imported, but we might revisit this in the future.
#### `bun`
- Bun and Node.js APIs are supported and left untouched.
- Modules are resolved using the default resolution algorithm used by Bun's runtime.
- The generated bundles are marked with a special `// @bun` pragma comment to indicate that they were generated by Bun. This indicates to Bun's runtime that the file does not need to be re-transpiled before execution. Synergy!
#### `node`
Currently, this is identical to `target: "bun"`. In the future, we plan to automatically polyfill Bun APIs like the `Bun` global and `bun:*` built-in modules.
### []()[File types](bun-bundler.html#file-types)
The bundler supports the following file types:
- `.js` `.jsx` `.ts` `.tsx` - JavaScript and TypeScript files. Duh.
- `.txt` — Plain text files. These are inlined as strings.
- `.json` `.toml` — These are parsed at compile time and inlined as JSON.
Everything else is treated as an *asset*. Assets are copied into the `outdir` as-is, and the import is replaced with a relative path or URL to the file, e.g. `/images/logo.png`.
Input
Output
Input
```
import logo from "./images/logo.png";
console.log(logo);
```
Output
```
var logo = "./images/logo.png";
console.log(logo);
```
### []()[Plugins](bun-bundler.html#plugins)
As with the runtime itself, the bundler is designed to be extensible via plugins. In fact, there's no difference at all between a runtime plugin and a bundler plugin.
```
import YamlPlugin from "bun-plugin-yaml";
const plugin = YamlPlugin();
// register a runtime plugin
Bun.plugin(plugin);
// register a bundler plugin
Bun.build({
entrypoints: ["./src/index.ts"],
plugins: [plugin],
});
```
### []()[Build outputs](bun-bundler.html#build-outputs)
The `Bun.build` function returns a `Promise<BuildOutput>`, defined as:
```
interface BuildOutput {
outputs: BuildArtifact[];
success: boolean;
logs: Array<object>; // see docs for details
}
interface BuildArtifact extends Blob {
kind: "entry-point" | "chunk" | "asset" | "sourcemap";
path: string;
loader: Loader;
hash: string | null;
sourcemap: BuildArtifact | null;
}
```
The `outputs` array contains all the files that were generated by the build. Each artifact implements the [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) interface.
```
const build = await Bun.build({
/* */
});
for (const output of build.outputs) {
output.size; // file size in bytes
output.type; // MIME type of file
await output.arrayBuffer(); // => ArrayBuffer
await output.text(); // string
}
```
Artifacts also contain the following additional properties:
`kind`What kind of build output this file is. A build generates bundled entrypoints, code-split "chunks", sourcemaps, and copied assets (like images).`path`Absolute path to the file on disk or the output path if the files were not written to disk.`loader`The loader was used to interpret the file. See [Bundler > Loaders](../docs/bundler/loaders.html) to see how Bun maps file extensions to the appropriate built-in loader.`hash`The hash of the file contents. Always defined for assets.`sourcemap`Another `BuildArtifact` of the sourcemap corresponding to this file, if generated. Only defined for entrypoints and chunks.
Similar to `BunFile`, `BuildArtifact` objects can be passed directly into `new Response()`.
```
const build = Bun.build({
/* */
});
const artifact = build.outputs[0];
// Content-Type is set automatically
return new Response(artifact);
```
The Bun runtime implements special pretty-printing when logging `BuildArtifact` objects to make debugging easier.
Build script
Shell output
Build script
```
// build.ts
const build = Bun.build({/* */});
const artifact = build.outputs[0];
console.log(artifact);
```
Shell output
```
bun run build.ts
```
```
BuildArtifact (entry-point) {
path: "./index.js",
loader: "tsx",
kind: "entry-point",
hash: "824a039620219640",
Blob (114 bytes) {
type: "text/javascript;charset=utf-8"
},
sourcemap: null
}
```
### []()[Server components](bun-bundler.html#server-components)
Bun's bundler has experimental support for React Server Components via the `--server-components` flag. We'll be releasing additional documentation and a sample project later in the week.
## []()[Tree shaking](bun-bundler.html#tree-shaking)
Bun's bundler supports tree-shaking of unused code. This is always enabled when bundling.
#### package.json `"sideEffects"` field
Bun supports `"sideEffects": false` in `package.json`. This is a hint to the bundler that the package has no side effects and enables more aggressive dead code elimination.
#### `__PURE__` comments
Bun supports `__PURE__` annotations:
file.js
file.js
```
function foo() {
return 123;
}
/** #__PURE__ */ foo();
```
Since `foo` is side effect free, this results in an empty file:
output.js
```
```
Learn more on [Webpack's documentation](https://webpack.js.org/guides/tree-shaking/#mark-a-function-call-as-side-effect-free).
#### `process.env.NODE_ENV` and `--define`
Bun supports the `NODE_ENV` environment variable and the `--define` CLI flag. These are often used to conditionally include code in production builds.
If `process.env.NODE_ENV` is set to `"production"`, Bun will automatically remove code that is wrapped in `if (process.env.NODE_ENV !== "production") { ... }`.
node-env.js
node-env.js
```
if (process.env.NODE_ENV !== "production") {
module.exports = require("./cjs/react.development.js");
} else {
module.exports = require("./cjs/react.production.min.js");
}
```
### []()[ES Module tree-shaking](bun-bundler.html#es-module-tree-shaking)
ESM tree-shaking is supported for both ESM and CommonJS input files. Bun's bundler will automatically remove unused exports from ESM files when it is safe to do so.
entry.js
foo.js
entry.js
```
import { foo } from "./foo.js";
console.log(foo);
```
foo.js
```
export const bar = 123;
export const foo = 456;
```
The unused `bar` export is eliminated, resulting in:
output.js
output.js
```
// foo.js
var $foo = 456;
console.log($foo);
```
### []()[CommonJS tree-shaking](bun-bundler.html#commonjs-tree-shaking)
In limited cases, Bun's bundler automatically converts CommonJS into ESM with zero runtime overhead. Consider this trivial example:
index.ts
foo.js
index.ts
```
import { foo } from "./foo.js";
console.log(foo);
```
foo.js
```
// foo.js
exports.foo = 123;
exports.bar = "this will be treeshaken";
```
Bun will automatically convert `foo.js` to ESM and tree-shake the unused `exports` object.
Bundled
```
// foo.js
var $foo = 123;
// entry.js
console.log($foo);
```
Note that there are many cases where the dynamic nature of CommonJS makes this very difficult. For instance, consider these three files:
entry.js
foo.js
bar.js
entry.js
```
// entry.js
export default require("./foo");
```
foo.js
```
// foo.js
exports.foo = 123;
Object.assign(module.exports, require("./bar"));
```
bar.js
```
// bar.js
exports.foobar = 123;
```
Bun can't statically determine the exports of `foo.js` without executing it. (Also `Object.assign` can be overridden, making static analysis impossible in the general case.) In this case, Bun will not tree-shake the `exports` object; instead it injects some CommonJS runtime code to make it work as expected.
CommonJS wrapper
```
var __commonJS = (cb, mod) => () => (
mod || cb((mod = { exports: {} }).exports, mod), mod.exports
);
// bar.js
var require_bar = __commonJS((exports) => {
exports.fooba = 123;
});
// foo.js
var require_foo = __commonJS((exports, module) => {
exports.foo = 123;
Object.assign(exports, require_bar());
});
// entry.js
var entry_default = require_foo();
export { entry_default as default };
```
## []()[Source maps](bun-bundler.html#source-maps)
The bundler supports both inline and external source maps.
```
const build = await Bun.build({
entrypoints: ["./src/index.ts"],
// generates a *.js.map file alongside each output
sourcemap: "external",
sourcemap: "inline",
});
console.log(await build.outputs[0].sourcemap.json()); // => { version: 3, ... }
```
## []()[Minifier](bun-bundler.html#minifier)
A JavaScript bundler is not complete without a minifier. This release also introduces an all-new JavaScript minifier built into Bun. Enable minification with `minify: true`, or configure minification behavior more granularly with the following options:
```
{
minify?: boolean | {
identifiers?: boolean; // default: false
whitespace?: boolean; // default: false
syntax?: boolean; // default: false
}
}
```
The minifier is capable of removing dead code, renaming identifiers, removing whitespace, and intelligently condensing & inlining constant values.
Input
Minified
Input
```
// This comment will be removed!
console.log("this" + " " + "text" + " will" + " be " + "merged");
```
Minified
```
console.log("this text will be merged");
```
## []()[Sneak peek: `Bun.App`](bun-bundler.html#sneak-peek-bun-app)
The bundler is just laying the groundwork for a more ambitious effort. In the next couple months, we'll be announcing `Bun.App`: a "super-API" that stitches together Bun's native-speed bundler, HTTP server, and file system router into a cohesive whole.
The goal is to make it easy to express any kind of app with Bun with just a few lines of code:
Static file server
API server
Next.js-style framework
Static file server
```
new Bun.App({
bundlers: [
{
name: "static-server",
outdir: "./out",
},
],
routers: [
{
mode: "static",
dir: "./public",
build: "static-server",
},
],
});
app.serve();
app.build();
```
API server
```
const app = new Bun.App({
configs: [
{
name: "simple-http",
target: "bun",
outdir: "./.build/server",
// bundler config...
},
],
routers: [
{
mode: "handler",
handler: "./handler.tsx", // automatically included as entrypoint
prefix: "/api",
build: "simple-http",
},
],
});
app.serve();
app.build();
```
Next.js-style framework
```
const projectRoot = process.cwd();
const app = new Bun.App({
configs: [
{
name: "react-ssr",
target: "bun",
outdir: "./.build/server",
// bundler config
},
{
name: "react-client",
target: "browser",
outdir: "./.build/client",
transform: {
exports: {
pick: ["default"],
},
},
},
],
routers: [
{
mode: "handler",
handler: "./handler.tsx",
build: "react-ssr",
style: "nextjs",
dir: projectRoot + "/pages",
},
{
mode: "build",
build: "react-client",
dir: "./pages",
// style: "build",
// dir: projectRoot + "/pages",
prefix: "_pages",
},
],
});
app.serve();
app.build();
```
This API is still under [active discussion](https://github.com/oven-sh/bun/pull/2551) and subject to change.
## []()[Credits](bun-bundler.html#credits)
- The architecture of bun's bundler and minifier is based on esbuild's design, so thank you Evan Wallace (evanw).
- Thank you to [@paperclover](https://github.com/paperclover) for porting esbuild's test suite to Bun.
- Thank you to [@dylan-conway](https://github.com/dylan-conway) for implementing source maps support and fixing so many bugs.
On this page
- [Reducing complexity in JavaScript](bun-bundler.html#reducing-complexity-in-javascript)
- [Yes, a new bundler](bun-bundler.html#yes-a-new-bundler)
- [Cohesiveness](bun-bundler.html#cohesiveness)
- [Performance](bun-bundler.html#performance)
- [Developer experience](bun-bundler.html#developer-experience)
- [The API](bun-bundler.html#the-api)
- [Module systems](bun-bundler.html#module-systems)
- [Targets](bun-bundler.html#targets)
- [File types](bun-bundler.html#file-types)
- [Plugins](bun-bundler.html#plugins)
- [Build outputs](bun-bundler.html#build-outputs)
- [Server components](bun-bundler.html#server-components)
- [Tree shaking](bun-bundler.html#tree-shaking)
- [ES Module tree-shaking](bun-bundler.html#es-module-tree-shaking)
- [CommonJS tree-shaking](bun-bundler.html#commonjs-tree-shaking)
- [Source maps](bun-bundler.html#source-maps)
- [Minifier](bun-bundler.html#minifier)
- [Sneak peek: `Bun.App`](bun-bundler.html#sneak-peek-bun-app)
- [Credits](bun-bundler.html#credits)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-lock-text-lockfile.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun's new text-based lockfile
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · December 17, 2024
[](../rss.xml)
`bun install` is a fast npm-compatible package manager you can use with Node.js or Bun.
The most common piece of feedback teams migrating from npm, pnpm, or yarn to `bun install` share is about Bun's `bun.lockb` binary lockfile format. Binary lockfiles are tricky to review in pull requests. Merge conflicts get harder to resolve. Tooling can't easily read a binary lockfile.
To help with that, we previously added support for `bun ./bun.lockb` to generate a `yarn.lock`-compatible lockfile, but this wasn't enough. The source of truth was still the binary lockfile. You had to run `bun` on the binary lockfile in order to get the yarn's lockfile. This doesn't work well with Github, with tools or with merge conflicts.
That's why in Bun v1.1.39, we're introducing a `bun.lock` - a new text-based lockfile format for `bun install`:
```
bun install --save-text-lockfile
```
Instead of saving the binary `bun.lockb` file, this flag makes Bun save a text-based `bun.lock` file. In Bun v1.2, we're planning to make this the default.
bun.lock
```
{
"lockfileVersion": 0,
"workspaces": {
"": {
"dependencies": {
"uWebSocket.js": "uNetworking/uWebSockets.js#v20.51.0",
},
},
},
"packages": {
"uWebSocket.js": ["uWebSockets.js@github:uNetworking/uWebSockets.js#6609a88", {}, "uNetworking-uWebSockets.js-6609a88"],
}
}
```
If a `bun.lockb` file or `package-lock.json` file exists the first time you run `bun install --save-text-lockfile`, bun will use the existing lockfile to generate the `bun.lock` file, preserving resolutions and metadata.
## []()[Cached `bun install` gets 30% faster](bun-lock-text-lockfile.html#cached-bun-install-gets-30-faster)
**Some projects start out being faster than alternatives, and then get slower as they add missing features and fix bugs. Bun is *not* one of those projects**. We don't accept performance regressions.
In Bun v1.1.39, we made cached `bun install` using the text lockfile 30% faster compared to cached `bun install` with the binary lockfile in Bun v1.1.38.
cached-no-op-install
no-node-modules-install
package.json
cached-no-op-install
```
# --warmup=10
Benchmark 1: bun install --cwd=./with-text # Text-based lockfile
Time (mean ± σ): 45.8 ms ± 2.2 ms [User: 17.4 ms, System: 34.7 ms]
Range (min … max): 43.8 ms … 55.1 ms 60 runs
Benchmark 2: bun-1.1.38 install --cwd=./with-binary # Binary lockfile
Time (mean ± σ): 60.4 ms ± 2.1 ms [User: 14.8 ms, System: 52.1 ms]
Range (min … max): 58.3 ms … 69.9 ms 44 runs
Benchmark 3: cd with-pnpm && pnpm install
Time (mean ± σ): 709.5 ms ± 3.7 ms [User: 914.5 ms, System: 318.7 ms]
Range (min … max): 705.3 ms … 716.1 ms 10 runs
Benchmark 4: cd with-yarn && yarn install
Time (mean ± σ): 243.1 ms ± 3.0 ms [User: 415.9 ms, System: 24.2 ms]
Range (min … max): 240.6 ms … 248.4 ms 12 runs
Benchmark 5: cd with-npm && npm install
Time (mean ± σ): 1.525 s ± 0.174 s [User: 1.459 s, System: 0.119 s]
Range (min … max): 1.275 s … 1.709 s 10 runs
Summary
bun install --cwd=./with-text # Text-based lockfile ran
1.32 ± 0.08 times faster than bun-1.1.38 install --cwd=./with-binary # Binary lockfile
5.31 ± 0.27 times faster than cd with-yarn && yarn install
15.49 ± 0.76 times faster than cd with-pnpm && pnpm install
33.28 ± 4.13 times faster than cd with-npm && npm install
```
no-node-modules-install
```
# --warmup=2 --prepare="rm -rf ./with-{text,binary,pnpm,yarn,npm}/node_modules"
Benchmark 1: bun install --cwd=./with-text --ignore-scripts # Text-based lockfile
Time (mean ± σ): 1.590 s ± 0.029 s [User: 0.018 s, System: 0.809 s]
Range (min … max): 1.546 s … 1.651 s 10 runs
Benchmark 2: bun-1.1.38 install --cwd=./with-binary --ignore-scripts # Binary lockfile
Time (mean ± σ): 1.749 s ± 0.024 s [User: 0.015 s, System: 0.882 s]
Range (min … max): 1.719 s … 1.788 s 10 runs
Benchmark 3: cd with-pnpm && pnpm install --ignore-scripts
Time (mean ± σ): 11.303 s ± 0.142 s [User: 4.093 s, System: 107.544 s]
Range (min … max): 10.926 s … 11.442 s 10 runs
Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs.
Benchmark 4: cd with-yarn && yarn install --ignore-scripts
Time (mean ± σ): 6.372 s ± 0.104 s [User: 5.980 s, System: 17.191 s]
Range (min … max): 6.286 s … 6.603 s 10 runs
Benchmark 5: cd with-npm && npm install --ignore-scripts
Time (mean ± σ): 8.309 s ± 0.081 s [User: 8.598 s, System: 9.838 s]
Range (min … max): 8.194 s … 8.418 s 10 runs
Summary
bun install --cwd=./with-text --ignore-scripts # Text-based lockfile ran
1.10 ± 0.02 times faster than bun-1.1.38 install --cwd=./with-binary --ignore-scripts # Binary lockfile
4.01 ± 0.10 times faster than cd with-yarn && yarn install --ignore-scripts
5.23 ± 0.11 times faster than cd with-npm && npm install --ignore-scripts
7.11 ± 0.16 times faster than cd with-pnpm && pnpm install --ignore-scripts
```
package.json
```
{
"name": "desktop",
"type": "module",
"module": "index.ts",
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5.6.2"
},
"dependencies": {
"@anthropic-ai/sdk": "^0.32.1",
"@babel/core": "^7.26.0",
"@octokit/rest": "^21.0.2",
"@sentry/bun": "^8.37.1",
"date-fns": "^4.1.0",
"debug": "^4.3.7",
"express": "^4.21.1",
"gatsby": "^5.14.0",
"ink": "^5.0.1",
"isbot": "^5.1.17",
"next": "^15.1.0",
"postgres": "^3.4.5",
"puppeteer": "^23.10.4",
"ts552": "npm:typescript@5.5.2",
"ts562": "npm:typescript@5.6.2",
"vite": "^5.4.9"
}
}
```
### []()[What makes bun install fast?](bun-lock-text-lockfile.html#what-makes-bun-install-fast)
`bun install` is fast because we try really hard to make it fast. There's no "one thing" like a binary lockfile format that makes it fast.
#### Structure of Arrays
We do a lot of work to avoid O(N^3) memory allocations. When you have many dependent and nested objects/structs to serialize (such as packages, their dependencies, their dependencies' dependencies, and the resolutions), how do you avoid allocating each object/struct separately? You use indices into linearly-serializable arrays instead of pointers/objects.
In TypeScript, the slow but relatively common approach to storing packages in a package manager would look something like this:
slow.ts
```
interface SlowPackage {
name: string;
version: string;
dependencies: Record<string, Dependency>;
/// ... more fields ...
}
interface Workspace {
packages: Record<string, Package>;
root: Package;
}
```
The fast (and overly simplified) version would look something like this:
fast.ts
```
interface Package {
/** Index into strings array */
name: number;
/** Index into strings array */
version: number;
/** Index into dependencies array */
dependenciesStart: number;
/** Length of dependencies array */
dependenciesCount: number;
/** Start offset into resolutions array */
resolutionsStart: number;
/** Length of resolutions array */
resolutionsCount: number;
}
interface Workspace {
packages: Package[];
dependencies: Dependency[];
resolutions: number[];
strings: string[];
}
```
Instead of arrays for each element inside of an array, we use one big array for each type and append to it. This is usually called a [Structure of Arrays](https://en.wikipedia.org/wiki/AoS_and_SoA).
#### Small string optimizations
When you have lots of usually-tiny strings (such as package names or versions), instead of allocating each string separately, you could store tiny strings in the same space used to reference them. In higher-level languages like JavaScript, strings are abstracted away from you, but in Zig, C++, or Rust, ["small string optimizations"](https://devblogs.microsoft.com/oldnewthing/20230803-00/?p=108532) are [well-known](https://fasterthanli.me/articles/small-strings-in-rust).
In Zig, our `semver.String` struct optimizes for small strings:
```
pub const String = extern struct {
pub const max_inline_len: usize = 8;
/// This is three different types of string.
/// 1. Empty string. If it's all zeroes, then it's an empty string.
/// 2. If the final bit is set, then it's a string that is stored inline.
/// 3. If the final bit is not set, then it's a string that is stored in an external buffer.
bytes: [max_inline_len]u8 = [8]u8{ 0, 0, 0, 0, 0, 0, 0, 0 },
};
```
#### Careful I/O
We pay close attention to what system calls are used. We avoid opening directories and reading files unless we need to. We use extremely specific, sometimes uncommon platform-specific system calls like `clonefile`, `sendfile`, `faccessat`, `memfd_create`, etc to avoid unnecessary work.
I could rant for a really long time about all the optimizations we make in `bun install`, but you get the idea. It was never the binary lockfile format. We just try really hard to make it fast, and all that work applies to the text-based lockfile format too.
## []()[Not a breaking change](bun-lock-text-lockfile.html#not-a-breaking-change)
We're planning to make `bun.lock` the default in Bun v1.2.0. In the meantime, we continue to support the binary `bun.lockb` format and will do so for awhile.
Until Bun v1.2, the `bun install --save-text-lockfile` flag will be required to generate the text-based lockfile. When a `bun.lock` file exists, `bun install` will use the text-based lockfile and ignore the binary lockfile. Otherwise, it will generate the binary lockfile.
## []()[Tooling compatibility](bun-lock-text-lockfile.html#tooling-compatibility)
The `bun.lock` file is JSONC (like tsconfig.json)
### []()[Visual Studio Code](bun-lock-text-lockfile.html#visual-studio-code)
VSCode will syntax highlight the `bun.lock` file for you, thanks to [@remcohaszing](https://github.com/remcohaszing).
> In the next version of [@Code](https://twitter.com/code?ref_src=twsrc%5Etfw)
>
> bun.lock gets syntax highlighting, thanks to [@remcohaszing](https://twitter.com/remcohaszing?ref_src=twsrc%5Etfw) [pic.twitter.com/TFXv5KuhZi](https://t.co/TFXv5KuhZi)
>
> — Bun (@bunjavascript) [December 13, 2024](https://twitter.com/bunjavascript/status/1867486870458052726?ref_src=twsrc%5Etfw)
### []()[GitHub & git](bun-lock-text-lockfile.html#github-git)
GitHub renders `bun.lock` in diffs, which is important when reviewing code.
[](https://github.com/user-attachments/assets/bc77ae27-b076-43ed-8958-857bd6034ff9)
GitHub showing the text-based bun.lock file
Previously, GitHub didn't render the binary `bun.lockb` file.
[](https://github.com/user-attachments/assets/2ee313b4-b997-4cd3-9474-e26d15d90a7c)
GitHub showing the binary bun.lockb file
### []()[Dependabot](bun-lock-text-lockfile.html#dependabot)
At the time of writing, Dependabot's [#1 most upvoted feature request](https://github.com/dependabot/dependabot-core/issues/6528) is to support `bun`. A text-based lockfile makes this a lot easier for the Dependabot team to add support for.
[](https://github.com/dependabot/dependabot-core/issues/6528)
Dependabot's most upvoted feature request
On this page
- [Cached `bun install` gets 30% faster](bun-lock-text-lockfile.html#cached-bun-install-gets-30-faster)
- [What makes bun install fast?](bun-lock-text-lockfile.html#what-makes-bun-install-fast)
- [Not a breaking change](bun-lock-text-lockfile.html#not-a-breaking-change)
- [Tooling compatibility](bun-lock-text-lockfile.html#tooling-compatibility)
- [Visual Studio Code](bun-lock-text-lockfile.html#visual-studio-code)
- [GitHub & git](bun-lock-text-lockfile.html#github-git)
- [Dependabot](bun-lock-text-lockfile.html#dependabot)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-macros.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# JavaScript Macros in Bun
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · May 31, 2023
[](../rss.xml)
Two weeks ago, we launched our new JavaScript [bundler](bun-bundler.html) in Bun [v0.6.0](bun-v0.6.0.html). Today we're releasing a new feature that highlights the tight integration between Bun's bundler and runtime: Bun Macros.
Macros are a mechanism for running JavaScript functions *at bundle-time*. The value returned from these functions are directly inlined into your bundle.
As a toy example, consider this simple function that returns a random number.
```
export function random() {
return Math.random();
}
```
Inside our source code, we can import this function as a macro using [*import attribute*](https://github.com/tc39/proposal-import-attributes) syntax. If you haven't seen this syntax before, it's a Stage 3 TC39 proposal that lets you attach additional metadata to `import` statements.
cli.tsx
```
import { random } from './random.ts' with { type: 'macro' };
console.log(`Your random number is ${random()}`);
```
Now we'll bundle this file with `bun build`. The bundled file will be printed to stdout.
```
bun build ./cli.tsx
```
```
console.log(`Your random number is ${0.6805550949689833}`);
```
As you can see, the source code of the `random` function occurs nowhere in the bundle. Instead, it is executed *during bundling* and the function call (`random()`) is replaced with the result of the function. Since the source code will never be included in the bundle, macros can safely perform privileged operations like reading from a database.
## []()[When to use macros](bun-macros.html#when-to-use-macros)
For small things where you would otherwise have a one-off build script, bundle-time code execution can be easier to maintain. It lives with the rest of your code, it runs with the rest of the build, it is automatically paralellized, and if it fails, the build fails too.
If you find yourself running a lot of code at bundle-time though, consider running a server instead.
Let's look at some scenarios where macros might be useful.
### []()[Embed latest git commit hash](bun-macros.html#embed-latest-git-commit-hash)
in-the-browser.ts
getGitCommitHash.ts
in-the-browser.ts
```
import { getGitCommitHash } from './getGitCommitHash.ts' with { type: 'macro' };
console.log(`The current Git commit hash is ${getGitCommitHash()}`);
```
getGitCommitHash.ts
```
export function getGitCommitHash() {
const {stdout} = Bun.spawnSync({
cmd: ["git", "rev-parse", "HEAD"],
stdout: "pipe",
});
return stdout.toString();
}
```
When we build it, the `getGitCommitHash` is replaced with the result of calling the function:
output.js
CLI
output.js
```
console.log(`The current Git commit hash is 3ee3259104f`);
```
CLI
```
bun build --target=browser ./in-the-browser.ts
```
You're probably thinking "Why not just use `process.env.GIT_COMMIT_HASH`?" Well, you can do that too. But can you do this with an environment variable?
### []()[Make `fetch()` requests at bundle-time](bun-macros.html#make-fetch-requests-at-bundle-time)
In this example, we make an outgoing HTTP request using `fetch()`, parse the HTML response using `HTMLRewriter`, and return an object containing the title and meta tags–all at bundle-time.
in-the-browser.tsx
meta.ts
in-the-browser.tsx
```
import { extractMetaTags } from './meta.ts' with { type: 'macro' };
export const Head = () => {
const headTags = extractMetaTags("https://example.com");
if (headTags.title !== "Example Domain") {
throw new Error("Expected title to be 'Example Domain'");
}
return <head>
<title>{headTags.title}</title>
<meta name="viewport" content={headTags.viewport} />
</head>;
};
```
meta.ts
```
export async function extractMetaTags(url: string) {
const response = await fetch(url);
const meta = {
title: "",
};
new HTMLRewriter()
.on("title", {
text(element) {
meta.title += element.text;
},
})
.on("meta", {
element(element) {
const name =
element.getAttribute("name") ||
element.getAttribute("property") ||
element.getAttribute("itemprop");
if (name) meta[name] = element.getAttribute("content");
},
})
.transform(response);
return meta;
}
```
The `extractMetaTags` function is erased at bundle-time and replaced with the result of the function call. This means that the `fetch` request happens at bundle-time, and the result is embedded in the bundle. Also, the branch throwing the error is eliminated since it's unreachable.
output.js
CLI
output.js
```
import { jsx, jsxs } from "react/jsx-runtime";
export const Head = () => {
jsxs("head", {
children: [
jsx("title", {
children: "Example Domain",
}),
jsx("meta", {
name: "viewport",
content: "width=device-width, initial-scale=1",
}),
],
});
};
export { Head };
```
CLI
```
bun build --target=browser --minify-syntax ./in-the-browser.ts
```
## []()[How it works](bun-macros.html#how-it-works)
Bun Macros are import statements annotated the `{type: 'macro'}` [import attribute](https://github.com/tc39/proposal-import-attributes).
```
import { myMacro } from './macro.ts' with { type: 'macro' }
```
Import attributes are a Stage 3 ECMAScript proposal, which means it is overwhelmingly likely they will be added as an official part of the JavaScript language.
Bun also supports *import assertion* syntax. Import assertions were an earlier incarnation of import attributes that has now been abandoned (but is [already supported](https://caniuse.com/mdn-javascript_statements_import_import_assertions) by a number of browsers and runtimes).
```
import { myMacro } from "./macro.ts" assert { type: "macro" };
```
When Bun's transpiler sees one of these special imports, it calls the function inside the transpiler using Bun's JavaScript runtime and converts the return value from JavaScript into an AST node. These JavaScript functions are called at bundle-time, not runtime.
### []()[Execution order](bun-macros.html#execution-order)
Bun Macros are executed synchronously in the transpiler during the visiting phase—before plugins and before the transpiler generates the AST. They are executed in the order they are called. The transpiler will wait for the macro to finish executing before continuing. The transpiler will also `await` any `Promise` returned by a macro.
Bun's bundler is multi-threaded. As such, macros execute in parallel inside of multiple spawned JavaScript "workers".
### []()[Dead code elimination](bun-macros.html#dead-code-elimination)
The bundler performs dead code elimination *after* running and inlining macros. So given the following macro:
returnFalse.ts
```
export function returnFalse() {
return false;
}
```
...then bundling the following file will produce an empty bundle.
```
import {returnFalse} from './returnFalse.ts' with { type: 'macro' };
if (returnFalse()) {
console.log("This code is eliminated");
}
```
## []()[Security considerations](bun-macros.html#security-considerations)
Macros must explicitly be imported with `{ type: "macro" }` in order to be executed at bundle-time. These imports have no effect if they are not called, unlike regular JavaScript imports which may have side effects.
You can disable macros entirely by passing the `--no-macros` flag to Bun. It produces a build error like this:
```
error: Macros are disabled
foo();
^
./hello.js:3:1 53
```
### []()[*Macros are disabled in node\_modules*](bun-macros.html#macros-are-disabled-in-node-modules)
To reduce the potential attack surface for malicious packages, macros cannot be *invoked* from inside `node_modules/**/*`. If a package attempts to invoke a macro, you'll see an error like this:
```
error: For security reasons, macros cannot be run from node_modules.
beEvil();
^
node_modules/evil/index.js:3:1 50
```
Your application code can still import macros from `node_modules` and invoke them.
```
import {macro} from "some-package" with { type: "macro" };
macro();
```
## []()[Limitations](bun-macros.html#limitations)
Some things to know.
### []()[*The result of the macro must be serializable!*](bun-macros.html#the-result-of-the-macro-must-be-serializable)
Bun's transpiler needs to be able to serialize the result of the macro so it can be inlined into the AST. All JSON-compatible data structures are supported:
macro.ts
```
export function getObject() {
return {
foo: "bar",
baz: 123,
array: [ 1, 2, { nested: "value" }],
};
}
```
Macros can be async, or return `Promise` instances. Bun's transpiler will automatically `await` the `Promise` and inline the result.
macro.ts
```
export async function getText() {
return "async value";
}
```
Functions and instances of most classes (except those mentioned above) are not serializable.
```
export function getText(url: string) {
// this doesn't work!
return () => {};
}
```
### []()[*The input arguments must be statically analyzable.*](bun-macros.html#the-input-arguments-must-be-statically-analyzable)
Macros can accept inputs, but only in limited cases. The value must be statically known. For example, the following is not allowed:
```
import {getText} from './getText.ts' with { type: 'macro' };
export function howLong() {
// the value of `foo` cannot be statically known
const foo = Math.random() ? "foo" : "bar";
const text = getText(`https://example.com/${foo}`);
console.log("The page is ", text.length, " characters long");
}
```
However, if the value of `foo` is known at bundle-time (say, if it's a constant or the result of another macro) then it's allowed:
```
import {getText} from './getText.ts' with { type: 'macro' };
import {getFoo} from './getFoo.ts' with { type: 'macro' };
export function howLong() {
// this works because getFoo() is statically known
const foo = getFoo();
const text = getText(`https://example.com/${foo}`);
console.log("The page is", text.length, "characters long");
}
```
This outputs:
```
function howLong() {
console.log("The page is", 1322, "characters long");
}
export { howLong };
```
On this page
- [When to use macros](bun-macros.html#when-to-use-macros)
- [Embed latest git commit hash](bun-macros.html#embed-latest-git-commit-hash)
- [Make `fetch()` requests at bundle-time](bun-macros.html#make-fetch-requests-at-bundle-time)
- [How it works](bun-macros.html#how-it-works)
- [Execution order](bun-macros.html#execution-order)
- [Dead code elimination](bun-macros.html#dead-code-elimination)
- [Security considerations](bun-macros.html#security-considerations)
- [Macros are disabled in node\_modules](bun-macros.html#macros-are-disabled-in-node-modules)
- [Limitations](bun-macros.html#limitations)
- [The result of the macro must be serializable!](bun-macros.html#the-result-of-the-macro-must-be-serializable)
- [The input arguments must be statically analyzable.](bun-macros.html#the-input-arguments-must-be-statically-analyzable)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-report-is-buns-new-crash-reporter.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# bun.report is Bun's new crash reporter
* * *
[Chloe Caruso](https://github.com/paperclover) · April 26, 2024
[](../rss.xml)
At the time of writing, Bun has over [2,600 open GitHub issues](https://github.com/oven-sh/bun). We love having users and feedback, but some issues are really hard for us to reproduce and debug.
Apps and SaaS products get to use wonderful crash reporting services like [Sentry](https://sentry.io/), but for CLI tooling like Bun, uploading core dumps has privacy, performance, and executable size tradeoffs that are harder to justify.
That's why in Bun v1.1.5, I wrote a compact new format for Zig and C++ crash reports. The crash report fits in a ~150 byte URL containing zero personal information.
[](../images/crash-report-1.png)
## []()[Why not just use the OS crash reporter?](bun-report-is-buns-new-crash-reporter.html#why-not-just-use-the-os-crash-reporter)
Some operating systems like macOS have built-in crash reporters, but that usually means shipping debug symbols with the application. For Linux, these debug symbols are around 30 MB and macOS around 9 MB.
```
du -h ./bun
```
```
60M ./bun
```
```
llvm-strip bun
```
```
du -h ./bun
```
```
51M ./bun
```
And on Windows, the `.pdb` file is over 250 MB
```
(gi bun.pdb).Length / 1mb
```
```
252.44921875
```
30 MB - 250 MB is a huge amount of bloat to add to every install of Bun.
But without debug symbols, crashes are pretty limited. And with [Address space layout randomization](https://en.wikipedia.org/wiki/Address_space_layout_randomization) in the mix, all of the function addresses are made useless.
```
uh-oh: reached unreachable code
bun will crash now 😭😭😭
----- bun meta -----
Bun v1.1.0 (5903a614) Windows x64
AutoCommand:
Builtins: "bun:main"
Elapsed: 27ms | User: 0ms | Sys: 0ms
RSS: 91.69MB | Peak: 91.69MB | Commit: 0.14GB | Faults: 22579
----- bun meta -----
Search GitHub issues https://bun.sh/issues or join in #windows channel in https://bun.sh/discord
thread 104348 panic: reached unreachable code
???:?:?: 0x7ff62a629f17 in ??? (bun.exe)
???:?:?: 0x7ff62a907a83 in ??? (bun.exe)
???:?:?: 0x7ff62a61f392 in ??? (bun.exe)
???:?:?: 0x7ff62ade7ff1 in ??? (bun.exe)
???:?:?: 0x7ff62ab2193c in ??? (bun.exe)
???:?:?: 0x7ff62ab21166 in ??? (bun.exe)
???:?:?: 0x7ff62cd3ddeb in ??? (bun.exe)
???:?:?: 0x7ff62b7a4bb6 in ??? (bun.exe)
???:?:?: 0x7ff62b7a33bd in ??? (bun.exe)
???:?:?: 0x1bab9ca115d in ??? (???)
???:?:?: 0x1bab9ca111f in ??? (???)
```
## []()[The new crash reporter](bun-report-is-buns-new-crash-reporter.html#the-new-crash-reporter)
In Bun v1.1.5, when a crash or panic occurs, Bun prints a message like this:
```
Bun v1.1.5 (0989f1a) Windows x64
Args: "C:\Users\chloe\.bun\bin\bun.exe", ".\crash.js"
Builtins: "bun:main"
Elapsed: 40ms | User: 15ms | Sys: 15ms
RSS: 92.80MB | Peak: 92.80MB | Commit: 0.14GB | Faults: 22857
panic(main thread): Internal assertion failure
oh no: Bun has crashed. This indicates a bug in Bun, not your code.
To send a redacted crash report to Bun's team,
please file a GitHub issue using the link below:
https://bun.report/1.1.5/wa10989f1aAAg6xyL+rqoIwzn0F+oqC0v5R+52pGkr6Om7h+Oy3voK+9qoKA0eNrzzCtJLcpLzFFILC5OLSrJzM9TSEvMzCktSgUAiSkKPg
```
This `bun.report` link, when clicked, redirects to open a pre-filled GitHub issue form, with the remapped stack trace encoded in the URL.
[](https://github.com/oven-sh/bun/assets/24465214/18867c15-663b-469a-ba98-1088e6bbd424)
## []()[Making addresses useful](bun-report-is-buns-new-crash-reporter.html#making-addresses-useful)
The function addresses are pointers in memory to where the application code is loaded, which includes a randomized offset for security reasons. This means if we try and demangle these, we get nothing.
```
llvm-symbolizer --exe ./bun.pdb 0x7ff62a629f17 0x7ff62a907a83
```
```
??
??:0:0
```
The trick is to simply subtract the address from the base address of the binary.
```
pub fn getRelativeAddress(address: usize) ?usize {
const module = getModuleFromAddress(address) orelse {
// Could not resolve address! This can be hit for some
// Windows internals, as well as JIT'd JavaScript.
return null;
};
return address - module.base_address;
}
```
And inside various APIs, we would increment these numbers to mark usage of a feature.
For encoding these into a single `u64` integer, we can use `std.meta` to iterate over the list of features and create a list.
```
pub const feature_list = brk: {
const decls = std.meta.declarations(Features);
var names: [decls.len][:0]const u8 = undefined;
var i = 0;
for (decls) |decl| {
if (@TypeOf(@field(Features, decl.name)) == usize) {
names[i] = decl.name;
i += 1;
}
}
const names_const = names[0..i].*;
break :brk names_const;
};
```
Then, a packed struct can be created dynamically derivied to use one bit per feature. This structure functions like an integer, but interacts like a struct.
```
// note: some fields omitted for brevity
pub const PackedFeatures = @Type(.{
.Struct = .{
.layout = .@"packed",
.backing_integer = u64,
.fields = brk: {
var fields: [64]StructField = undefined;
for (feature_list, 0..) |name, i| {
fields[i] = .{ .name = name, .type = bool };
}
fields[feature_list.len] = .{
.name = "__padding",
.type = @Type(.{ .Int = .{ .bits = 64 - feature_list.len } }),
};
break :brk fields[0..feature_list.len + 1];
},
},
});
```
And finally, when Bun crashes, the bitfield can be constructed very trivially using `inline for`, a way to iterate over something at compile time, but perform the inner contents at runtime.
```
pub fn packedFeatures() PackedFeatures {
var bits = PackedFeatures{};
inline for (feature_list) |name| {
if (@field(Features, name) > 0) {
@field(bits, name) = true;
}
}
return bits;
}
```
Now, adding a new feature to the original struct `Features` will properly handle it in the crash reporter, without needing to repeat ourselves.
Doing this sort of thing is possible with C or Rust via macros, but I feel like it's so much simpler and readable with Zig `comptime`.
## []()[How does this compare to a core dump?](bun-report-is-buns-new-crash-reporter.html#how-does-this-compare-to-a-core-dump)
Core dumps have a lot more information, but they are massive, need debug symbols to be useful, and include lots of potentially sensitive or confidential information.
We wanted to avoid the possibility of sending any JavaScript/TypeScript source code, environment variables, or other sensitive information in the reports. This is why we only send the Zig/C++ stack trace and a few other details. Instead of sending everything by default, this approach sends only what we (probably) need to diagnose the issue. If we need more information, we can ask the user to provide it, but this is so much better than nothingness of a bunch of unmapped addresses we had before.
## []()[Demo](bun-report-is-buns-new-crash-reporter.html#demo)
To put it all together, I wrote a small webapp that lets you test out the crash reporter, which is available at the homepage, [bun.report](https://bun.report/1.1.5/wa10989f1aAAg6xyL+rqoIwzn0F+oqC0v5R+52pGkr6Om7h+Oy3voK+9qoKA0eNrzzCtJLcpLzFFILC5OLSrJzM9TSEvMzCktSgUAiSkKPg/view). It is also where you end up if you append `/view` to the end of any crash report URL.
## []()[Bun is hiring in San Francisco](bun-report-is-buns-new-crash-reporter.html#bun-is-hiring-in-san-francisco)
If you're interested in working on projects like this, we're hiring engineers in San Francisco! We're looking for systems engineers to help build the future of JavaScript. [**Apply here**](../careers.html)
On this page
- [Why not just use the OS crash reporter?](bun-report-is-buns-new-crash-reporter.html#why-not-just-use-the-os-crash-reporter)
- [The new crash reporter](bun-report-is-buns-new-crash-reporter.html#the-new-crash-reporter)
- [Making addresses useful](bun-report-is-buns-new-crash-reporter.html#making-addresses-useful)
- [bun.report's URL Structure](bun-report-is-buns-new-crash-reporter.html#bun-report-s-url-structure)
- [VLQs are fun](bun-report-is-buns-new-crash-reporter.html#vlqs-are-fun)
- [What are "Features"](bun-report-is-buns-new-crash-reporter.html#what-are-features)
- [How does this compare to a core dump?](bun-report-is-buns-new-crash-reporter.html#how-does-this-compare-to-a-core-dump)
- [Demo](bun-report-is-buns-new-crash-reporter.html#demo)
- [Bun is hiring in San Francisco](bun-report-is-buns-new-crash-reporter.html#bun-is-hiring-in-san-francisco)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.1.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.1
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · September 12, 2023
[](../rss.xml)
Bun v1.0.1 adds named imports for .json & .toml files, fixes a bug with `bun install` and `error.PathAlreadyExists`, fixes a bug importing node: builtins in `bun build --compile`, fixes a bug in relative() within node:path, fixes a bug where bun would load the wrong .env file, fixes a bug where tsconfig.json would be loaded in `bun run <package.json script>`, fixes a path.parse() bug, and fixes a bug where build errors would be printed twice.
Thank you for reporting issues. We are working hard to fix them as quickly as possible.
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. We've been releasing a lot of changes to Bun recently. Here's a recap of the last few releases. In case you missed it:
- [`v1.0.0`](../1.0.html) - Bun's first stable release!
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
```
## []()[Named imports for .json & .toml files](bun-v1.0.1.html#named-imports-for-json-toml-files)
When you import a .json or .toml file in Bun, you can now import the top-level keys directly.
```
import { name, version } from "./package.json";
console.log({ name, version }); // { name: "bun", version: "1.0.1" }
```
Previously, only the default export was supported.
```
import pkg from "./package.json";
const { name, version } = pkg;
console.log({ name, version }); // { name: "bun", version: "1.0.1" }
```
You can also import `tsconfig.json` files even if they have comments. This internally uses Bun's JSONC parser.
```
import { paths } from "./tsconfig.json";
console.log(paths); // { "paths": { "b": ["./a.js"] } }
```
You can continue to use the default export if you prefer. The named import values are `===` to the default export's value at the same key.
```
import boop, { array } from "./file.json";
console.log(boop.array === array); // true
```
This all works with `require` as well.
## []()[bun install bug with `error.PathAlreadyExists`](bun-v1.0.1.html#bun-install-bug-with-error-pathalreadyexists)
A bug was fixed where bun install would fail with `error.PathAlreadyExists` when installing a package via hardlink.
## []()[Bug importing node: builtins in `bun build --compile` fixed](bun-v1.0.1.html#bug-importing-node-builtins-in-bun-build-compile-fixed)
Bun 1.0 added a regression where importing node: builtins in `bun build --compile` would fail. This has been fixed.
```
// This failed in `bun build --compile`! It should not have.
import "node:fs/promises";
```
## []()[Bug in relative() within node:path](bun-v1.0.1.html#bug-in-relative-within-node-path)
Previously, the following would print `""`:
```
console.log(path.relative("../", "../../"));
```
Now it correctly prints `..`, thanks to [@Hanaasagi](https://github.com/Hanaasagi).
## []()[Bug where bun would load the wrong .env file](bun-v1.0.1.html#bug-where-bun-would-load-the-wrong-env-file)
When you run `bun` in a nested `bun run` package.json script, bun would potentially load the wrong NODE\_ENV variable. This has been fixed.
https://github.com/oven-sh/bun/pull/4630
## []()[tsconfig.json no longer loaded in `bun run <package.json script>`](bun-v1.0.1.html#tsconfig-json-no-longer-loaded-in-bun-run-package-json-script)
Previously, bun would load the tsconfig.json file in the current working directory when running a package.json script. There was no need to do this. It just wasted your time. We shouldn't do that. So we don't load tsconfig.json for package.json `"scripts"`. Note that we still load it for the runtime, just not when running a package.json script.
## []()[Build errors printed twice bug](bun-v1.0.1.html#build-errors-printed-twice-bug)
A bug was fixed where build errors would be printed twice.
## []()[Bun.file() .slice offset on macOS bug](bun-v1.0.1.html#bun-file-slice-offset-on-macos-bug)
A bug was fixed where Bun.file().text(), when using .slice() to offset the buffer, would in certain cases not have seek the data to the expected position
## []()[Buffer.from with a UTF-16 encoded hex](bun-v1.0.1.html#buffer-from-with-a-utf-16-encoded-hex)
A bug was fixed where Buffer.from would not correctly handle hex strings from a UTF-16 encoded source.
Thanks to [@Hanaasagi](https://github.com/Hanaasagi) for fixing this.
#### Disable TLS verification using NODE\_TLS\_REJECT\_UNAUTHORIZED
Bun now supports disabling TLS verification using NODE\_TLS\_REJECT\_UNAUTHORIZED. This is useful for testing, but should not be used in production.
Set `NODE_TLS_REJECT_UNAUTHORIZED=0` to disable TLS verification.
```
NODE_TLS_REJECT_UNAUTHORIZED=0 bun run ./server.js
```
Thanks to [@cirospaciari](https://github.com/cirospaciari).
## []()[path.parse() bug](bun-v1.0.1.html#path-parse-bug)
The `path.parse()` function was not correctly cloning the output strings. This has been fixed, thanks to [@davidmhewitt](https://github.com/davidmhewitt).
* * *
#### [Bun v1.0.2](bun-v1.0.2.html)
On this page
- [Named imports for .json & .toml files](bun-v1.0.1.html#named-imports-for-json-toml-files)
- [bun install bug with `error.PathAlreadyExists`](bun-v1.0.1.html#bun-install-bug-with-error-pathalreadyexists)
- [Bug importing node: builtins in `bun build --compile` fixed](bun-v1.0.1.html#bug-importing-node-builtins-in-bun-build-compile-fixed)
- [Bug in relative() within node:path](bun-v1.0.1.html#bug-in-relative-within-node-path)
- [Bug where bun would load the wrong .env file](bun-v1.0.1.html#bug-where-bun-would-load-the-wrong-env-file)
- [tsconfig.json no longer loaded in `bun run <package.json script>`](bun-v1.0.1.html#tsconfig-json-no-longer-loaded-in-bun-run-package-json-script)
- [Build errors printed twice bug](bun-v1.0.1.html#build-errors-printed-twice-bug)
- [Bun.file() .slice offset on macOS bug](bun-v1.0.1.html#bun-file-slice-offset-on-macos-bug)
- [Buffer.from with a UTF-16 encoded hex](bun-v1.0.1.html#buffer-from-with-a-utf-16-encoded-hex)
- [path.parse() bug](bun-v1.0.1.html#path-parse-bug)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.10.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.10
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · November 7, 2023
[](../rss.xml)
Bun v1.0.10 fixes 14 bugs (addressing 102 👍 reactions), `node:http` gets 14% faster, adds stability improvements to Bun for Linux ARM64, and fixes bugs in `bun install` and `node:http`.
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun:
- [`v1.0.0`](../1.0.html) - First stable release!
- [`v1.0.1`](bun-v1.0.1.html) - Named imports for .json and .toml files, fixes to `bun install`, `node:path`, and `Buffer`
- [`v1.0.2`](bun-v1.0.2.html) - Make `--watch` faster and lots of bug fixes
- [`v1.0.3`](bun-v1.0.3.html) - `emitDecoratorMetadata` and Nest.js support, fixes for private registries and more
- [`v1.0.4`](bun-v1.0.4.html) - `server.requestIP`, virtual modules in runtime plugins, and more
- [`v1.0.5`](bun-v1.0.5.html) - Fixed memory leak with `fetch()`, `KeyObject` support in `node:crypto` module, `expect().toEqualIgnoringWhitespace` in `bun:test`, and more
- [`v1.0.6`](bun-v1.0.6.html) - Fixes 3 bugs (addressing 85 👍 reactions), implements `overrides` & `resolutions` in `package.json`, and fixes regression impacting Docker usage with Bun
- [`v1.0.7`](bun-v1.0.7.html) - Fixes 59 bugs (addressing 78 👍 reactions), implements optional peer dependencies in `bun install`, and makes improvements to Node.js compatibility.
- [`v1.0.8`](bun-v1.0.8.html) - Fixes 138 bugs (addressing 257 👍 reactions), makes `require()` use 30% less memory, adds module mocking to `bun test`, fixes more `bun install` bugs
- [`v1.0.9`](bun-v1.0.9.html) - Fixes a glibc symbol version error, illegal instruction error, a Bun.spawn bug, an edgecase with peer dependency installs, and a JSX transpiler bugfix
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
```
## []()[node:http gets 14% faster](bun-v1.0.10.html#node-http-gets-14-faster)
Bun's `node:http` implementation currently wraps [`Bun.serve()`](../docs/api/http.html#bun-serve). [`Bun.serve()`](../docs/api/http.html#bun-serve) is built on web standards like [`Request`](https://developer.mozilla.org/en-US/docs/Web/API/Request) and [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response), which is incompatible with the Node.js [`IncomingMessage`](https://nodejs.org/api/http.html#class-httpincomingmessage) and [`ServerResponse`](https://nodejs.org/api/http.html#class-httpserverresponse) classes. That means our wrapper has to do a lot of work to convert between the two.
While fixing a couple bugs, we moved some of the wrapper code which was previously implemented in TypeScript over to native code. This slightly reduced the overhead of the wrapper, making `node:http` 14% faster.
[](https://github.com/oven-sh/bun/assets/709451/aaea8599-26ee-47f0-a9dd-3ac4ef5a057c)
Left: Bun v1.0.10. Right: Bun v1.0.9
### []()[I want the DETAILS](bun-v1.0.10.html#i-want-the-details)
We made two changes to improve performance.
When you run [`request.headers`](https://developer.mozilla.org/en-US/docs/Web/API/Request/headers) in Bun, we serialize headers from Bun's web server into a web-standard [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers) object. Normally, that's great. In this case, `node:http` only used it to convert from the web `Headers` object into a Node.js `headers` object and `rawHeaders` array. The [`Headers`](https://developer.mozilla.org/en-US/docs/Web/API/Headers) object does a lot of extra work behind the scenes - joining strings, normalizing whitespace, and more that the Node.js API does not do.
When you run [`request.url`](https://developer.mozilla.org/en-US/docs/Web/API/Request/url) in Bun, it parses & normalizes the pathname joined with the `Host` header (when available), producing an absolute URL as a string you can use in `fetch` and with the `URL` constructor. In Node.js, `req.url` is a string containing the raw path and query string (`/path?query`). It's not a valid url. We were doing a lot of extra work to produce a valid URL string and then parse it back a 2nd time to convert into a pathname + query string.
Instead of doing all that work: creating these temporary objects & parsing, we now just create the Node.js `headers` object, `rawHeaders` array, and `url` string in native code.
### []()[Fixed: multiple Set-Cookie headers in node:http bugfix](bun-v1.0.10.html#fixed-multiple-set-cookie-headers-in-node-http-bugfix)
As a side effect of moving the above code to native, we also fixed a bug where multiple `Set-Cookie` headers were not being exposed to JavaScript correctly in our `node:http` bindings. This lead to errors like this:
```
undefined is not an object (evaluating 'header.toLowerCase')
```
### []()[Fixed: "\*\*" cannot be parsed as URL](bun-v1.0.10.html#fixed-cannot-be-parsed-as-url)
In Node, it's expected that `IncomingMessage` can receive an invalid url string. Previously, Bun was using the `URL` constructor to parse, validate, and normalize the incoming url string, which caused spurious errors like this:
```
TypeError: "*" cannot be parsed as a URL.
at new IncomingMessage (node:http:420:26)
at fetch (node:http:383:26)
OPTIONS - * failed
```
Now, Bun just passes the url string through to `node:http`, which is what it expects.
## []()[Stability improvements to Bun for Linux ARM64/Docker](bun-v1.0.10.html#stability-improvements-to-bun-for-linux-arm64-docker)
Most software on your computer interacts with the operating system through a layer called the ["C standard library"](https://en.wikipedia.org/wiki/C_standard_library). The C standard library is a set of functions that are implemented by your operating system. For example, when you call `fs.read` in Bun or Node.js, it eventually calls the [`read`](https://man7.org/linux/man-pages/man2/read.2.html) function in the C standard library. That `read` function probably just wraps the `read` system call, which is a function implemented by the Linux kernel (or darwin kernel on macOS).
On Linux x64 & arm64, Bun often skips the C standard library and uses Linux system calls directly. This is a little faster, but it also makes error handling sometimes more complicated and means we need to spend more time reading/understanding internals. Our code for reading errors on Linux arm64 was assuming that libc `errno` was always in use, but that isn't true. TLDR: we were sometimes reading `errno` wrong on Linux arm64.
This lead to many strange issues, like:
```
docker-compose up
```
```
my-app-ui-1 | Failed to load PostCSS config: Failed to load PostCSS config (searchPath: /app): [EBADF] Bad file descriptor
my-app-ui-1 | undefined
my-app-ui-1 | code: "EBADF"
my-app-ui-1 | syscall: "fstat"
my-app-ui-1 | errno: -9
my-app-ui-1 |
```
Or like:
```
#8 [4/4] RUN bun install
#8 0.077 bun install v1.0.9 (98f20170)
#8 0.077 error: Unexpected installing typescript
#8 0.077 error: Unexpected installing bun-types
#8 0.077 Failed to install 2 packages
#8 0.078 [2.00ms] done
#8 DONE 0.1s
```
This release fixes those issues.
## []()[Fixed: Loading extensions in bun:sqlite on macOS](bun-v1.0.10.html#fixed-loading-extensions-in-bun-sqlite-on-macos)
A bug caused Bun to not support loading extensions in the `bun:sqlite` module on macOS. This has been fixed, thanks to [@paulbaumgart](https://github.com/paulbaumgart).
## []()[Fixed: Semver parsing bug with pre-releases in bun install](bun-v1.0.10.html#fixed-semver-parsing-bug-with-pre-releases-in-bun-install)
Bun implements a `node-semver` compatible parser for `bun install`.
There was an edgecase when parsing invalid semver strings that contained a pre-release version with a dist-tag that would potentially cause Bun to crash. This issue has been fixed (thanks to [@dylan-conway](https://github.com/dylan-conway)) and we've added more test coverage.
#### Misc
We also updated to the latest version of simdutf.
## []()[Thanks to 4 contributors](bun-v1.0.10.html#thanks-to-4-contributors)
- [@paulbaumgart](https://github.com/paulbaumgart)
- [@dylan-conway](https://github.com/dylan-conway)
- [@jarred-sumner](https://github.com/jarred-sumner)
- [@liz3](https://github.com/liz3)
Full changelog: [bun-v1.0.9...bun-v1.0.10](https://github.com/oven-sh/bun/compare/bun-v1.0.9...bun-v1.0.10)
* * *
#### [Bun v1.0.9](bun-v1.0.9.html)
#### [Bun v1.0.11](bun-v1.0.11.html)
On this page
- [node:http gets 14% faster](bun-v1.0.10.html#node-http-gets-14-faster)
- [I want the DETAILS](bun-v1.0.10.html#i-want-the-details)
- [Fixed: multiple Set-Cookie headers in node:http bugfix](bun-v1.0.10.html#fixed-multiple-set-cookie-headers-in-node-http-bugfix)
- [Fixed: "\*\*" cannot be parsed as URL](bun-v1.0.10.html#fixed-cannot-be-parsed-as-url)
- [Stability improvements to Bun for Linux ARM64/Docker](bun-v1.0.10.html#stability-improvements-to-bun-for-linux-arm64-docker)
- [Fixed: Loading extensions in bun:sqlite on macOS](bun-v1.0.10.html#fixed-loading-extensions-in-bun-sqlite-on-macos)
- [Fixed: Semver parsing bug with pre-releases in bun install](bun-v1.0.10.html#fixed-semver-parsing-bug-with-pre-releases-in-bun-install)
- [Thanks to 4 contributors](bun-v1.0.10.html#thanks-to-4-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.11.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.11
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · November 8, 2023
[](../rss.xml)
Bun v1.0.11 fixes 5 bugs, adds `Bun.semver`, fixes a bug in bun install and fixes bugs impacting `astro` and `@google-cloud/storage`
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun:
- [`v1.0.0`](../1.0.html) - First stable release!
- [`v1.0.1`](bun-v1.0.1.html) - Named imports for .json and .toml files, fixes to `bun install`, `node:path`, and `Buffer`
- [`v1.0.2`](bun-v1.0.2.html) - Make `--watch` faster and lots of bug fixes
- [`v1.0.3`](bun-v1.0.3.html) - `emitDecoratorMetadata` and Nest.js support, fixes for private registries and more
- [`v1.0.4`](bun-v1.0.4.html) - `server.requestIP`, virtual modules in runtime plugins, and more
- [`v1.0.5`](bun-v1.0.5.html) - Fixed memory leak with `fetch()`, `KeyObject` support in `node:crypto` module, `expect().toEqualIgnoringWhitespace` in `bun:test`, and more
- [`v1.0.6`](bun-v1.0.6.html) - Fixes 3 bugs (addressing 85 👍 reactions), implements `overrides` & `resolutions` in `package.json`, and fixes regression impacting Docker usage with Bun
- [`v1.0.7`](bun-v1.0.7.html) - Fixes 59 bugs (addressing 78 👍 reactions), implements optional peer dependencies in `bun install`, and makes improvements to Node.js compatibility.
- [`v1.0.8`](bun-v1.0.8.html) - Fixes 138 bugs (addressing 257 👍 reactions), makes `require()` use 30% less memory, adds module mocking to `bun test`, fixes more `bun install` bugs
- [`v1.0.9`](bun-v1.0.9.html) - Fixes a glibc symbol version error, illegal instruction error, a Bun.spawn bug, an edgecase with peer dependency installs, and a JSX transpiler bugfix
- [`v1.0.10`](bun-v1.0.10.html) - Fixes 14 bugs (addressing 102 👍 reactions), node:http gets 14% faster, stability improvements to Bun for Linux ARM64, bun install bugfix, and node:http bugfixes
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.semver is a fast builtin SemVer parser](bun-v1.0.11.html#bun-semver-is-a-fast-builtin-semver-parser)
`bun install`'s fast node-semver compatible parser is now available as a builtin Bun API: `Bun.semver`.
```
import { semver } from "bun";
semver.satisfies("1.0.0", "^1.0.0"); // true
semver.satisfies("1.0.0", "^2.0.0"); // false
const versions = ["2.1.0", "1.0.0", "1.0.1", "1.1.0", "2.0.0", "2.0.1"];
versions.sort(semver.compare); // ["1.0.0", "1.0.1", "1.1.0", "2.0.0", "2.0.1", "2.1.0"]
```
It's 20x faster than `node-semver`, and passes `node-semver`'s test suite.
> The next version of Bun gets a builtin API for comparing semver ranges
>
> 20x faster than node-semver, and passes their tests [pic.twitter.com/Vcli83ZDB3](https://t.co/Vcli83ZDB3)
>
> — Jarred Sumner (@jarredsumner) [November 8, 2023](https://twitter.com/jarredsumner/status/1722225679570473173?ref_src=twsrc%5Etfw)
### []()[Fixed: Semver sorting bug with build tags](bun-v1.0.11.html#fixed-semver-sorting-bug-with-build-tags)
Previously, Bun was sorting semver versions incorrectly when build tags with multiple segments containing the `.` character were present. This has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
### []()[Fixed: `=` and `v` prefix in package.json versions](bun-v1.0.11.html#fixed-and-v-prefix-in-package-json-versions)
Previously, Bun only supported `=` and `v` prefixes in dependency versions, but not in `package.json` versions. This has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
## []()[Fixed: potential crash when printing exceptions](bun-v1.0.11.html#fixed-potential-crash-when-printing-exceptions)
A crash that has been present since before Bun v0.1.0 has been fixed. When displaying the preview of the source code that caused an exception, sometimes Bun would crash. This has been fixed.
## []()[Fixed: TLS handshaking error-handling issue](bun-v1.0.11.html#fixed-tls-handshaking-error-handling-issue)
A bug in `Bun.serve` that could cause Bun to eventually no longer respond to incoming requests with client-side certificates has been fixed, thanks to [@cirospaciari](https://github.com/cirospaciari).
## []()[A bug impacting `@google-cloud/storage` has been fixed](bun-v1.0.11.html#a-bug-impacting-google-cloud-storage-has-been-fixed)
A Node.js compatibilty bug caused `@google-cloud/storage` to not work as expected.
With `DEBUG="*"`, it would print a message like this:
```
retry-request Current retry attempt: 1 +0ms
retry-request Next retry delay: 2351 +221ms
retry-request Current retry attempt: 2 +2s
retry-request Next retry delay: 4143 +150ms
retry-request Current retry attempt: 3 +4s
retry-request Next retry delay: 8135 +185ms
retry-request Current retry attempt: 4 +8s
TypeError: undefined is not an object
```
This has been fixed. It no longer errors, and it no longer erroneously retries (which would cause it to take a long time to fail).
## []()[A bug impacting Astro has been fixed](bun-v1.0.11.html#a-bug-impacting-astro-has-been-fixed)
A Node.js compatibility bug caused `astro dev` to return "file not found" errors when using Bun in v1.0.10. This has been fixed. We will soon add an integration test that runs Astro to prevent this from happening again.
Full changelog: [bun-v1.0.10...bun-v1.0.11](https://github.com/oven-sh/bun/compare/bun-v1.0.10...bun-v1.0.11)
* * *
#### [Bun v1.0.10](bun-v1.0.10.html)
#### [Bun v1.0.12](bun-v1.0.12.html)
On this page
- [Bun.semver is a fast builtin SemVer parser](bun-v1.0.11.html#bun-semver-is-a-fast-builtin-semver-parser)
- [Fixed: Semver sorting bug with build tags](bun-v1.0.11.html#fixed-semver-sorting-bug-with-build-tags)
- [Fixed: `=` and `v` prefix in package.json versions](bun-v1.0.11.html#fixed-and-v-prefix-in-package-json-versions)
- [Fixed: potential crash when printing exceptions](bun-v1.0.11.html#fixed-potential-crash-when-printing-exceptions)
- [Fixed: TLS handshaking error-handling issue](bun-v1.0.11.html#fixed-tls-handshaking-error-handling-issue)
- [A bug impacting `@google-cloud/storage` has been fixed](bun-v1.0.11.html#a-bug-impacting-google-cloud-storage-has-been-fixed)
- [A bug impacting Astro has been fixed](bun-v1.0.11.html#a-bug-impacting-astro-has-been-fixed)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.12.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.12
* * *
[Ashcon Partovi](https://twitter.com/ashconpartovi) · November 16, 2023
[](../rss.xml)
Bun v1.0.12 fixes 24 bugs, makes bun's CLI help menus easier to read, adds support for `bun -e`, `bun --env-file`, `server.url`, `import.meta.env`, `expect.unreachable()`, improves support for module mocks, allows importing builtin modules at bundle-time, and improves Node.js compatibility.
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun:
- [`v1.0.8`](bun-v1.0.8.html) - Fixes 138 bugs (addressing 257 👍 reactions), makes `require()` use 30% less memory, adds module mocking to `bun test`, fixes more `bun install` bugs
- [`v1.0.9`](bun-v1.0.9.html) - Fixes a glibc symbol version error, illegal instruction error, a Bun.spawn bug, an edgecase with peer dependency installs, and a JSX transpiler bugfix
- [`v1.0.10`](bun-v1.0.10.html) - Fixes 14 bugs (addressing 102 👍 reactions), node:http gets 14% faster, stability improvements to Bun for Linux ARM64, bun install bugfix, and node:http bugfixes
- [`v1.0.11`](bun-v1.0.11.html) - Fixes 5 bugs, adds `Bun.semver`, fixes a bug in bun install and fixes bugs impacting `astro` and `@google-cloud/storage`
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 -e` evaluates a script](bun-v1.0.12.html#bun-e-evaluates-a-script)
Bun now supports the `-e` flag, which is short for `--eval`, and allows you to run a script without creating a file. This is useful for quick scripts where you don't want to create a file and is similar to `node -e`.
```
bun -e "console.log('Hello, JavaScript!')"
```
```
Hello, JavaScript!
```
`bun -e` leverages Bun's builtin support for TypeScript & JSX:
```
$ bun -e "console.log(<div>Hello, TSX</div> as React.ReactNode);"
<div>Hello, TSX</div>
```
Top-level await also works:
```
$ bun -e "console.write(await fetch('https://api.github.com/repos/oven-sh/bun').then(r => r.text()))"
{
"id": 357728969,
"node_id": "MDEwOlJlcG9zaXRvcnkzNTc3Mjg5Njk=",
"name": "bun",
"full_name": "oven-sh/bun",
"private": false,
"owner": {
"login": "oven-sh",
"id": 108928776,
...
```
## []()[`bun --env-file <path>` overrides the .env file to load](bun-v1.0.12.html#bun-env-file-path-overrides-the-env-file-to-load)
Bun's automatic `.env` loader first landed nearly two years ago in v0.0.x, and today we're releasing support for `--env-file` to override which specific `.env` file to load. This is useful for testing different environments.
If you have custom environment variables that you want to load into your process, you can use `--env-file` to specify a file containing environment variables to load into the process. You can define multiple `--env-file` arguments.
```
bun --env-file=.env.1 src/index.ts
```
```
bun --env-file=.env.abc --env-file=.env.def run build
```
You can use `--env-file` when running scripts in bun's runtime, or when running package.json scripts.
Thanks to [@otgerrogla](https://github.com/otgerrogla) for implementing this feature.
## []()[`server.url`](bun-v1.0.12.html#server-url)
We added support for `server.url`, which returns a URL object that defines the location of the HTTP server. This is especially useful in tests when you want to get the formatted URL of the server.
```
const server = Bun.serve({
port: 0, // random port
fetch(request) {
return new Response();
},
});
console.log("Listening...", `${server.url}`);
// Listening... http://localhost:1234/
```
## []()[`import.meta.env` for accessing environment variables](bun-v1.0.12.html#import-meta-env-for-accessing-environment-variables)
You can now access environment variables using `import.meta.env`, a pattern used by frameworks such as Vite.
```
console.log(import.meta.env.NODE_ENV); // "development"
```
`import.meta.env` is an alias of `process.env` and `Bun.env`. It exists for compatibility with other parts of the JavaScript ecosystem.
Thanks to [@otgerrogla](https://github.com/otgerrogla) for implementing this feature.
## []()[`expect.unreachable()`](bun-v1.0.12.html#expect-unreachable)
`bun test` gets support for `expect.unreachable()`, which throws an error if the code path is reached. This is useful for ensuring that a function is never called.
```
import { expect, test } from "bun:test";
import { foo } from "my-lib";
test("enum handles every case", () => {
switch (foo()) {
case "a":
break;
case "b":
break;
default: {
// Now:
expect.unreachable();
// Previously:
// throw new Error("Unreachable");
}
}
});
```
## []()[Improved CLI help output](bun-v1.0.12.html#improved-cli-help-output)
We've redone the help menus for Bun's CLI to make them easier to read and understand.
bun
install
build
test
run
bun
```
$ bun --help
Bun is a fast JavaScript runtime, package manager, bundler, and test runner. (1.0.12 (904134cc))
Usage: bun <command> [...flags] [...args]
Commands:
run ./my-script.ts Execute a file with Bun
lint Run a package.json script
test Run unit tests with Bun
x prettier Execute a package binary (CLI), installing if needed (bunx)
repl Start a REPL session with Bun
install Install dependencies for a package.json (bun i)
add astro Add a dependency to package.json (bun a)
remove left-pad Remove a dependency from package.json (bun rm)
update backbone Update outdated dependencies
link [<package>] Register or link a local npm package
unlink Unregister a local npm package
pm <subcommand> Additional package management utilities
build ./a.ts ./b.jsx Bundle TypeScript & JavaScript into a single file
init Start an empty Bun project from a blank template
create @evan/duckdb Create a new project from a template (bun c)
upgrade Upgrade to latest version of Bun.
<command> --help Print help text for command.
Flags:
--watch Automatically restart the process on file change
--hot Enable auto reload in the Bun runtime, test runner, or bundler
--smol Use less memory, but run garbage collection more often
-r, --preload Import a module before other modules are loaded
--inspect Activate Bun's debugger
--inspect-wait Activate Bun's debugger, wait for a connection before executing
--inspect-brk Activate Bun's debugger, set breakpoint on first line of code and wait
--if-present Exit without an error if the entrypoint does not exist
--no-install Disable auto install in the Bun runtime
--install Configure auto-install behavior. One of "auto" (default, auto-installs when no node_modules), "fallback" (missing packages only), "force" (always).
-i Auto-install dependencies during execution. Equivalent to --install=fallback.
-e, --eval Evaluate argument as a script
--prefer-offline Skip staleness checks for packages in the Bun runtime and resolve from disk
--prefer-latest Use the latest matching versions of packages in the Bun runtime, always checking npm
-p, --port Set the default port for Bun.serve
-b, --bun Force a script or package to use Bun's runtime instead of Node.js (via symlinking node)
--silent Don't print the script command
-v, --version Print version and exit
--revision Print version with revision and exit
--env-file Load environment variables from the specified file(s)
--cwd Absolute path to resolve files & entry points from. This just changes the process' cwd.
-c, --config Specify path to Bun config file. Default $cwd/bunfig.toml
-h, --help Display this menu and exit
(more flags in bun install --help, bun test --help, and bun build --help)
Learn more about Bun: https://bun.sh/docs
Join our Discord community: https://bun.sh/discord
```
install
```
$ bun install --help
Usage: bun install [flags] [...<pkg>]
Alias: bun i
Install the dependencies listed in package.json
Flags:
-c, --config Specify path to config file (bunfig.toml)
-y, --yarn Write a yarn.lock file (yarn v1)
-p, --production Don't install devDependencies
--no-save Don't update package.json or save a lockfile
--save Save to package.json (true by default)
--dry-run Don't install anything
--frozen-lockfile Disallow changes to lockfile
-f, --force Always request the latest versions from the registry & reinstall all dependencies
--cache-dir Store & load cached data from a specific directory path
--no-cache Ignore manifest cache entirely
--silent Don't log anything
--verbose Excessively verbose logging
--no-progress Disable the progress bar
--no-summary Don't print a summary
--no-verify Skip verifying integrity of newly downloaded packages
--ignore-scripts Skip lifecycle scripts in the project's package.json (dependency scripts are never run)
-g, --global Install globally
--cwd Set a specific cwd
--backend Platform-specific optimizations for installing dependencies. Possible values: "clonefile" (default), "hardlink", "symlink", "copyfile"
--link-native-bins Link "bin" from a matching platform-specific "optionalDependencies" instead. Default: esbuild, turbo
--help Print this help menu
-d, --dev Add dependency to "devDependencies"
--optional Add dependency to "optionalDependencies"
-E, --exact Add the exact version instead of the ^range
Examples:
Install the dependencies for the current project
bun install
Skip devDependencies
bun install --production
Full documentation is available at https://bun.sh/docs/cli/install
```
build
```
$ bun build --help
Usage:
Transpile and bundle one or more files.
bun build [...flags] [...entrypoints]
Flags:
--compile Generate a standalone Bun executable containing your bundled code
--watch Automatically restart the process on file change
--target The intended execution environment for the bundle. "browser", "bun" or "node"
--outdir Default to "dist" if multiple files
--outfile Write to a file
--sourcemap Build with sourcemaps - 'inline', 'external', or 'none'
--format Specifies the module format to build to. Only "esm" is supported.
--root Root directory used for multiple entry points
--splitting Enable code splitting
--public-path A prefix to be appended to any import paths in bundled code
-e, --external Exclude module from transpilation (can use * wildcards). ex: -e react
--entry-naming Customize entry point filenames. Defaults to "[dir]/[name].[ext]"
--chunk-naming Customize chunk filenames. Defaults to "[name]-[hash].[ext]"
--asset-naming Customize asset filenames. Defaults to "[name]-[hash].[ext]"
--server-components Enable React Server Components (experimental)
--no-bundle Transpile file only, do not bundle
--minify Enable all minification flags
--minify-syntax Minify syntax and inline data
--minify-whitespace Minify whitespace
--minify-identifiers Minify identifiers
Examples:
Frontend web apps:
bun build ./src/index.ts --outfile=bundle.js
bun build ./index.jsx ./lib/worker.ts --minify --splitting --outdir=out
Bundle code to be run in Bun (reduces server startup time)
bun build ./server.ts --target=bun --outfile=server.js
Creating a standalone executable (see https://bun.sh/docs/bundler/executables)
bun build ./cli.ts --compile --outfile=my-app
A full list of flags is available at https://bun.sh/docs/bundler
```
test
```
$ bun test --help
Usage: bun test [...flags] [<pattern>...]
Run all matching test files and print the results to stdout
Flags:
--timeout Set the per-test timeout in milliseconds, default is 5000.
--update-snapshots Update snapshot files
--rerun-each Re-run each test file <NUMBER> times, helps catch certain bugs
--only Only run tests that are marked with "test.only()"
--todo Include tests that are marked with "test.todo()"
--coverage Generate a coverage profile
--bail Exit the test suite after <NUMBER> failures. If you do not specify a number, it defaults to 1.
-t, --test-name-pattern Run only tests with a name that matches the given regex.
Examples:
Run all test files
bun test
Run all test files with "foo" or "bar" in the file name
bun test foo bar
Run all test files, only including tests whose names includes "baz"
bun test --test-name-pattern baz
Full documentation is available at https://bun.sh/docs/cli/test
```
run
```
$ bun run --help
Usage: bun run [flags] <file or script>
Flags:
--silent Don't print the script command
-b, --bun Force a script or package to use Bun's runtime instead of Node.js (via symlinking node)
--watch Automatically restart the process on file change
--hot Enable auto reload in the Bun runtime, test runner, or bundler
--smol Use less memory, but run garbage collection more often
-r, --preload Import a module before other modules are loaded
--inspect Activate Bun's debugger
--inspect-wait Activate Bun's debugger, wait for a connection before executing
--inspect-brk Activate Bun's debugger, set breakpoint on first line of code and wait
--if-present Exit without an error if the entrypoint does not exist
--no-install Disable auto install in the Bun runtime
--install Configure auto-install behavior. One of "auto" (default, auto-installs when no node_modules), "fallback" (missing packages only), "force" (always).
-i Auto-install dependencies during execution. Equivalent to --install=fallback.
-e, --eval Evaluate argument as a script
--prefer-offline Skip staleness checks for packages in the Bun runtime and resolve from disk
--prefer-latest Use the latest matching versions of packages in the Bun runtime, always checking npm
-p, --port Set the default port for Bun.serve
--main-fields Main fields to lookup in package.json. Defaults to --target dependent
--extension-order Defaults to: .tsx,.ts,.jsx,.js,.json
--tsconfig-override Specify custom tsconfig.json. Default <d>$cwd<r>/tsconfig.json
-d, --define Substitute K:V while parsing, e.g. --define process.env.NODE_ENV:"development". Values are parsed as JSON.
-l, --loader Parse files with .ext:loader, e.g. --loader .js:jsx. Valid loaders: js, jsx, ts, tsx, json, toml, text, file, wasm, napi
--no-macros Disable macros from being executed in the bundler, transpiler and runtime
--jsx-factory Changes the function called when compiling JSX elements using the classic JSX runtime
--jsx-fragment Changes the function called when compiling JSX fragments
--jsx-import-source Declares the module specifier to be used for importing the jsx and jsxs factory functions. Default: "react"
--jsx-runtime "automatic" (default) or "classic"
--env-file Load environment variables from the specified file(s)
--cwd Absolute path to resolve files & entry points from. This just changes the process' cwd.
-c, --config Specify path to Bun config file. Default <d>$cwd<r>/bunfig.toml
-h, --help Display this menu and exit
Examples:
Run a JavaScript or TypeScript file
bun run ./index.js
bun run ./index.tsx
Run a package.json script
bun run dev
bun run lint
Full documentation is available at https://bun.sh/docs/cli/run
```
Thanks to [@colinhacks](https://github.com/colinhacks) and @paperclover.
## []()[Macros now support builtin modules](bun-v1.0.12.html#macros-now-support-builtin-modules)
You can now import builtin modules at bundle-time using macros in Bun.
### []()[Read a file into a string at bundle-time](bun-v1.0.12.html#read-a-file-into-a-string-at-bundle-time)
```
// file.ts
import { readFileSync } from "node:fs" with {type: "macro"};
export const contents = readFileSync("hello.txt", "utf8");
```
Build:
```
bun build --target=browser ./file.ts
```
### []()[Spawn a process at bundle-time](bun-v1.0.12.html#spawn-a-process-at-bundle-time)
```
// spawn.ts
import { spawnSync } from "node:child_process" with {type: "macro"};
const result = spawnSync("echo", ["Hello, world!"], {encoding: "utf-8"}).stdout;
console.log(result); // "Hello, world!"
```
Build:
```
bun build --target=browser ./spawn.ts
```
## []()[`mock.module(...)` now supports default exports](bun-v1.0.12.html#mock-module-now-supports-default-exports)
We fixed a bug preventing `mock.module` from overriding default exports.
```
import { mock } from "bun:test";
mock.module("node:fs", () => ({
default: {
readFileSync() {
return "Hello, world!";
},
},
}));
import fs from "node:fs";
// Previously, this would have tried to read from the file system:
console.log(fs.readFileSync("hello.txt")); // "Hello, world!"
```
## []()[`mock.module(...)` now supports re-exports](bun-v1.0.12.html#mock-module-now-supports-re-exports)
We fixed a bug preventing `mock.module` from overriding re-exports.
```
// # c.test.ts
import { mock } from "bun:test";
mock.module("./a.ts", () => ({
exportedFromB: 123,
}));
import { exportedFromB } from "./a.ts";
// # a.ts
import { exportedFromB } from "./b.ts";
export { exportedFromB };
// # b.ts
export const exportedFromB = 456;
// Previously, this would have returned 456:
console.log(exportedFromB); // 123
```
For ESM, this updates live-bindings. For CommonJS modules, the changes will apply the next time the module is `require`'d.
## []()[Fixed: transpiler preserves custom directives](bun-v1.0.12.html#fixed-transpiler-preserves-custom-directives)
Previously, if you had an unknown directive at the top of the file, Bun's transpiler would consider it dead code and remove it. This has been fixed.
```
"use client"; // <-- this line is preserved now
export const MyComponent = () => <div>Hello, world!</div>;
```
## []()[Fixed: `Dirent.name` setter must be a string](bun-v1.0.12.html#fixed-dirent-name-setter-must-be-a-string)
Previously, if you tried to create an instance of the `node:fs` module's `Dirent` class via `Object.create(Dirent)`, accessing the `name` property would throw an error since it was not created via `new`.
```
import { Dirent } from "node:fs";
const dirent = Object.create(Dirent);
dirent.name = "hello.txt";
console.log(dirent.name); // "hello.txt"
```
Some libraries depend on this behaviour, and it has been fixed.
## []()[Fixed: Assertion failures and crashes](bun-v1.0.12.html#fixed-assertion-failures-and-crashes)
We recently made changes to our version of JavaScriptCore to ensure that assertions are enabled in debug builds. This allowed us to fix a wide range of bugs that were previously causing crashes or assertion failures. This will also help make Bun more stable going forward.
Some of the issues fixed include:
- Potential crash with `process.mainModule`
- Crash when constructing a `Worker`
- Crash when calling `Server.close()`
- Crash with `Bun.serve()` that could theoretically occur when an in-flight request is aborted
- Assertion failure in `Headers.prototype.getAll` that theoretically could cause a crash
- Assertion failure in `module.require` && `module.reoslve` that theoretically could cause a crash
- Assertion failure in `ServerWebSocket.close` caused by incorrectly checking the types of arguments passed to the function
- Assertion failure when rejecting a Promise that could cause a missing stacktrace
- Assertion failure in the `onerror` callback on the global object that could lead to a crash
## []()[Fixed: potential crash in `require()` after exception is thrown](bun-v1.0.12.html#fixed-potential-crash-in-require-after-exception-is-thrown)
A crash that sometimes happened when a CommonJS module that was loaded via `require()` and threw an exception during initialization while nested inside many other modules that were also incompletely initialized has been fixed.
One way this crash manifested was a module requiring `sharp` when native addons were not installed and that module was nested inside many other modules that were also incompletely initialized.
#### What caused this?
The source code was garbage collected before the exception was thrown, and it was assumed that the source code could not be garbage collected at that point. We added the missing null check to fix this issue.
## []()[Fixed: `ENOENT` when using `bun install` + `package-lock.json`](bun-v1.0.12.html#fixed-enoent-when-using-bun-install-package-lock-json)
We fixed an edge-case in `bun install` that would have caused a barrage of `ENOENT` errors. This would have occured when no `bun.lockb` existed, but a `package-lock.json` existed.
## []()[Fixed: `bun install` with a package that contains `~`](bun-v1.0.12.html#fixed-bun-install-with-a-package-that-contains)
We fixed a bug where `bun install` would fail if a package contained a `~` in the version. This has been fixed, thanks to [@Hanaasagi](https://github.com/Hanaasagi).
## []()[Fixed: Bun does not forward arguments to lifecycle scripts](bun-v1.0.12.html#fixed-bun-does-not-forward-arguments-to-lifecycle-scripts)
We fixed a bug where Bun would pass arguments to lifecycle scripts. For example, if you ran `bun run build --production`, Bun would pass `--production` to the `prebuild` script, which could cause unexpected failures.
package.json
```
{
"scripts": {
"prebuild": "echo \"Building...\"",
"build": "bun scripts/build.ts"
}
}
```
Before:
```
$ echo "Building..." --production
Building... --production
```
After:
```
$ echo "Building..."
Building...
```
Thanks to [@nektro](https://github.com/nektro) for fixing this issue.
## []()[Fixed: Hang in `bun:sqlite`'s .get() method](bun-v1.0.12.html#fixed-hang-in-bun-sqlite-s-get-method)
Previously, the following code would potentially hang after being called about 5,000 times in quick succession:
```
import { Database } from "bun:sqlite";
const db = new Database(":memory:");
const query = db.prepare("SELECT 1");
for (let i = 0; i < 10000; i++) {
query.get();
}
```
This has been fixed.
#### What caused this?
The prototype used for SQLite statements had an incorrect `JSType` specified.
JavaScriptCore has an internal `JSType` tag associated with each heap-allocated value. This tag is used in many places, including the JIT. The SQLite statement used a `FunctionType` instead of an `ObjectType`, which caused the DFG JIT to incorrectly optimize the `.get()` method. This led to a hang after the function was executed enough times for the DFG JIT to optimize the function.
JavaScriptCore had an assertion that caught this bug, but we weren't running JavaScriptCore with assertions enabled in development. To catch these kinds of bugs in the future, we've enabled assertions in the debug build of JavaScriptCore (the engine) to be used for the debug build of Bun.
## []()[Fixed: `Set-Cookie` header capitalization with `headers.raw()`](bun-v1.0.12.html#fixed-set-cookie-header-capitalization-with-headers-raw)
We fixed an issue where `headers.raw()` from `node-fetch` would return the `Set-Cookie` header with the wrong capitalization.
Before:
```
import { Headers } from "node-fetch";
const headers = new Headers({
"User-Agent": "Bun",
"Set-Cookie": "foo=bar",
});
console.log(headers.raw());
// { "user-agent": "Bun", "Set-Cookie": ["foo=bar"] }
```
After:
```
import { Headers } from "node-fetch";
const headers = new Headers({
"Set-Cookie": "foo=bar",
});
console.log(headers.raw());
// { "user-agent": "Bun", "set-cookie": ["foo=bar"] }
```
Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this issue.
## []()[Fixed: `AsyncLocalStorage` could not be disabled multiple times](bun-v1.0.12.html#fixed-asynclocalstorage-could-not-be-disabled-multiple-times)
There was a bug where `AsyncLocalStorage` could not be disabled multiple times. This has been fixed.
Before:
```
import { AsyncLocalStorage } from "node:async_hooks";
const store = new AsyncLocalStorage();
store.enterWith(1);
store.disable();
console.log(store.getStore()); // undefined
store.enterWith(2);
store.disable();
console.log(store.getStore()); // 2
```
After:
```
import { AsyncLocalStorage } from "node:async_hooks";
const store = new AsyncLocalStorage();
store.enterWith(1);
store.disable();
console.log(store.getStore()); // undefined
store.enterWith(2);
store.disable();
console.log(store.getStore()); // undefined
```
Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this issue.
## []()[Fixed: `fs.read()` returned incorrect value when promisified](bun-v1.0.12.html#fixed-fs-read-returned-incorrect-value-when-promisified)
We fixed a bug where `fs.read()` would return an incorrect value when `util.promisify(fs.read)` was used.
Before:
```
import fs from "node:fs";
import { promisify } from "node:util";
const read = promisify(fs.read);
const fd = await fs.promises.open("hello.txt");
const buffer = new Uint8Array(16);
const result = await read(fd, buffer, 0, 16, 0);
console.log(result); // 16
```
After:
```
import fs from "node:fs";
import { promisify } from "node:util";
const read = promisify(fs.read);
const fd = await fs.promises.open("hello.txt");
const buffer = new Uint8Array(16);
const result = await read(fd, buffer, 0, 16, 0);
console.log(result); // { bytesRead: 16, buffer }
```
Thanks to [@nektro](https://github.com/nektro) for fixing this issue.
Along the way, we also fixed:
- `fs.write()` when promisified
- `fs.writev()` when promisified
- `fs.readv()` when promisified
## []()[Fixed: bug when missing certain headers in HTTP client responses](bun-v1.0.12.html#fixed-bug-when-missing-certain-headers-in-http-client-responses)
For HTTP/1.1, the `Content-Length` header and the `Transfer-Encoding` headers are both optional. When these headers are omitted, the HTTP client is supposed to wait until the connection is closed to determine the length of the response body (and implicitly, disable keep-alive).
Previously, Bun was not handling this case and treating these HTTP responses as malformed.
Now, Bun properly handles this scenario and disables keep-alive when the `Content-Length` & `Transfer-Encoding` headers are omitted. It is not recommended to omit these headers (keep-alive is an important optimization for HTTP/1.1 and particularly TLS), but Bun now handles this case.
## []()[Fixed: `bun install --yarn` would occasionally produce invalid YAML](bun-v1.0.12.html#fixed-bun-install-yarn-would-occasionally-produce-invalid-yaml)
There was a bug in Bun's yarn.lock file printer that would not properly escape identifiers in certain cases. This would cause `bun install --yarn` to produce a yarn.lock file that Yarn v1 was unable to parse. Note that technically yarn.lock is not a YAML file, it is a bespoke Yarn v1 specific format (but saying "YAML" is easier since it is very close to YAML).
## []()[Fixed: Allow `crypto.subtle` to be polyfilled](bun-v1.0.12.html#fixed-allow-crypto-subtle-to-be-polyfilled)
Previously, Bun would throw an error if `crypto.subtle` was polyfilled. There are some packages that depend on this behaviour, and it has been fixed.
## []()[Fixed: `bun init` would contain an invalid `.gitignore`](bun-v1.0.12.html#fixed-bun-init-would-contain-an-invalid-gitignore)
Ther was a bug where `bun init` would contain an invalid `.gitignore` file. This has been fixed thanks to [@Pierre-Mike](https://github.com/Pierre-Mike).
## []()[Fixed: crash in debugger](bun-v1.0.12.html#fixed-crash-in-debugger)
A crash could occur on start when using `bun --inspect` to debug an application, which has been fixed.
The crash was due to assuming a debugger was started when it might not have been started yet.
## []()[Fixed: sometimes bun install would binlink the wrong version](bun-v1.0.12.html#fixed-sometimes-bun-install-would-binlink-the-wrong-version)
In certain cases, bun install could have binlinked the wrong version of a package. We previously were not bin linking into `my-dependency/node_modules/.bin`, preferring the root `node_modules/.bin` instead. This has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
## []()[Miscellaneous](bun-v1.0.12.html#miscellaneous)
We upgraded to a later version of Zig.
## []()[Thanks to 19 contributors!](bun-v1.0.12.html#thanks-to-19-contributors)
- [@antongolub](https://github.com/antongolub)
- [@bh1337x](https://github.com/bh1337x)
- [@brettgoulder](https://github.com/brettgoulder)
- [@cdfzo](https://github.com/cdfzo)
- [@cirospaciari](https://github.com/cirospaciari)
- [@colinhacks](https://github.com/colinhacks)
- [@dottedmag](https://github.com/dottedmag)
- [@dylan-conway](https://github.com/@dylanconway)
- [@Electroid](https://github.com/Electroid)
- [@Hanaasagi](https://github.com/Hanaasagi)
- [@jaas666](https://github.com/jaas666)
- [@Jarred-Sumner](https://github.com/@JarredSumner)
- [@joseph082](https://github.com/joseph082)
- [@lorenzodonadio](https://github.com/lorenzodonadio)
- [@nektro](https://github.com/nektro)
- [@otgerrogla](https://github.com/otgerrogla)
- [@paperclover](https://github.com/paperclover)
- [@Pierre-Mike](https://github.com/@PierreMike)
- [@rupurt](https://github.com/rupurt)
- [@SeedyROM](https://github.com/SeedyROM)
You can also read the [full changelog](https://github.com/oven-sh/bun/compare/bun-v1.0.11...bun-v1.0.12).
* * *
#### [Bun v1.0.11](bun-v1.0.11.html)
#### [Bun v1.0.13](bun-v1.0.13.html)
On this page
- [`bun -e` evaluates a script](bun-v1.0.12.html#bun-e-evaluates-a-script)
- [`bun --env-file <path>` overrides the .env file to load](bun-v1.0.12.html#bun-env-file-path-overrides-the-env-file-to-load)
- [`server.url`](bun-v1.0.12.html#server-url)
- [`import.meta.env` for accessing environment variables](bun-v1.0.12.html#import-meta-env-for-accessing-environment-variables)
- [`expect.unreachable()`](bun-v1.0.12.html#expect-unreachable)
- [Improved CLI help output](bun-v1.0.12.html#improved-cli-help-output)
- [Macros now support builtin modules](bun-v1.0.12.html#macros-now-support-builtin-modules)
- [Read a file into a string at bundle-time](bun-v1.0.12.html#read-a-file-into-a-string-at-bundle-time)
- [Spawn a process at bundle-time](bun-v1.0.12.html#spawn-a-process-at-bundle-time)
- [`mock.module(...)` now supports default exports](bun-v1.0.12.html#mock-module-now-supports-default-exports)
- [`mock.module(...)` now supports re-exports](bun-v1.0.12.html#mock-module-now-supports-re-exports)
- [Fixed: transpiler preserves custom directives](bun-v1.0.12.html#fixed-transpiler-preserves-custom-directives)
- [Fixed: `Dirent.name` setter must be a string](bun-v1.0.12.html#fixed-dirent-name-setter-must-be-a-string)
- [Fixed: Assertion failures and crashes](bun-v1.0.12.html#fixed-assertion-failures-and-crashes)
- [Fixed: potential crash in `require()` after exception is thrown](bun-v1.0.12.html#fixed-potential-crash-in-require-after-exception-is-thrown)
- [Fixed: `ENOENT` when using `bun install` + `package-lock.json`](bun-v1.0.12.html#fixed-enoent-when-using-bun-install-package-lock-json)
- [Fixed: `bun install` with a package that contains `~`](bun-v1.0.12.html#fixed-bun-install-with-a-package-that-contains)
- [Fixed: Bun does not forward arguments to lifecycle scripts](bun-v1.0.12.html#fixed-bun-does-not-forward-arguments-to-lifecycle-scripts)
- [Fixed: Hang in `bun:sqlite`'s .get() method](bun-v1.0.12.html#fixed-hang-in-bun-sqlite-s-get-method)
- [Fixed: `Set-Cookie` header capitalization with `headers.raw()`](bun-v1.0.12.html#fixed-set-cookie-header-capitalization-with-headers-raw)
- [Fixed: `AsyncLocalStorage` could not be disabled multiple times](bun-v1.0.12.html#fixed-asynclocalstorage-could-not-be-disabled-multiple-times)
- [Fixed: `fs.read()` returned incorrect value when promisified](bun-v1.0.12.html#fixed-fs-read-returned-incorrect-value-when-promisified)
- [Fixed: bug when missing certain headers in HTTP client responses](bun-v1.0.12.html#fixed-bug-when-missing-certain-headers-in-http-client-responses)
- [Fixed: `bun install --yarn` would occasionally produce invalid YAML](bun-v1.0.12.html#fixed-bun-install-yarn-would-occasionally-produce-invalid-yaml)
- [Fixed: Allow `crypto.subtle` to be polyfilled](bun-v1.0.12.html#fixed-allow-crypto-subtle-to-be-polyfilled)
- [Fixed: `bun init` would contain an invalid `.gitignore`](bun-v1.0.12.html#fixed-bun-init-would-contain-an-invalid-gitignore)
- [Fixed: crash in debugger](bun-v1.0.12.html#fixed-crash-in-debugger)
- [Fixed: sometimes bun install would binlink the wrong version](bun-v1.0.12.html#fixed-sometimes-bun-install-would-binlink-the-wrong-version)
- [Miscellaneous](bun-v1.0.12.html#miscellaneous)
- [Thanks to 19 contributors!](bun-v1.0.12.html#thanks-to-19-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.13.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.13
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · November 18, 2023
[](../rss.xml)
Bun v1.0.13 fixes 6 bugs (addressing 317 👍 reactions), adds support for the `"node:http2"` module (unblocking gRPC in Bun). Vite 5 & Rollup 4 work now. Implements `process.report.getReport()`, improves support for ES5 `with` statements, fixes a regression in `bun install`, and fixes a crash when printing exceptions.
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun:
- [`v1.0.8`](bun-v1.0.8.html) - Fixes 138 bugs (addressing 257 👍 reactions), makes `require()` use 30% less memory, adds module mocking to `bun test`, fixes more `bun install` bugs
- [`v1.0.9`](bun-v1.0.9.html) - Fixes a glibc symbol version error, illegal instruction error, a Bun.spawn bug, an edgecase with peer dependency installs, and a JSX transpiler bugfix
- [`v1.0.10`](bun-v1.0.10.html) - Fixes 14 bugs (addressing 102 👍 reactions), node:http gets 14% faster, stability improvements to Bun for Linux ARM64, bun install bugfix, and node:http bugfixes
- [`v1.0.11`](bun-v1.0.11.html) - Fixes 5 bugs, adds `Bun.semver`, fixes a bug in bun install and fixes bugs impacting `astro` and `@google-cloud/storage`
- [`v1.0.12`](bun-v1.0.12.html) - Adds `bun -e` for evaluating scripts, `bun --env-file` for loading environment variables, `server.url`, `import.meta.env`, `expect.unreachable()`, improved CLI help output, and more
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
```
## []()[http2 client support](bun-v1.0.13.html#http2-client-support)
You can now use the `node:http2` module's client functions in Bun!
```
import { connect } from "node:http2";
const client = connect("https://example.com");
const req = client.request({ ":path": "/" });
req.on("response", (headers, flags) => {
for (const name in headers) {
console.log(`${name}: ${headers[name]}`);
}
});
```
Thanks to [@cirospaciari](https://github.com/cirospaciari)
### []()[gRPC works now](bun-v1.0.13.html#grpc-works-now)
Our `node:http2` implementation unblocks gRPC.js in Bun. `@grpc/grpc-js` is a popular gRPC client and server library for Node.js.
```
import { loadPackageDefinition } from "@grpc/grpc-js";
import { join } from "path";
const protoPath = join(__dirname, "protos/helloworld.proto");
const packageDefinition = loadPackageDefinition(protoPath);
const client = new packageDefinition.helloworld.Greeter(
"localhost:50051",
credentials.createInsecure(),
);
client.sayHello({ name: "world" }, (err, response) => {
console.log("Greeting:", response.message);
});
```
To prevent regressions, we've ported much of grpc's test suite to run on every commit to Bun.
Thanks to [@cirospaciari](https://github.com/cirospaciari)
## []()[Vite 5 & Rollup 4 work now](bun-v1.0.13.html#vite-5-rollup-4-work-now)
There were two bugs in Bun that prevented Vite 5 and Rollup 4 from working out of the gate. Both of these bugs have been fixed in Bun v1.0.13.
[](https://github.com/oven-sh/bun/assets/709451/830c6a28-08d1-45d5-841c-1faa8e35fbbb)
### []()[process.report.getReport() is now implemented](bun-v1.0.13.html#process-report-getreport-is-now-implemented)
The Node.js API [`process.report.getReport`](https://nodejs.org/api/process.html#process_process_report) is now implemented in Bun. Native addons frequently use this to get the current libc version and whether it is using glibc or musl on Linux.
That particular usecase - detecting libc - is what was blocking Rollup 4 (which Vite 5 depends on) from working in Bun. Now that `process.report.getReport()` is implemented, Rollup 4 works in Bun.
To prevent regressions, we've added an integration test that runs Rollup 4 in Bun on every commit.
### []()[Transpiler bug involing require and ternaries is fixed](bun-v1.0.13.html#transpiler-bug-involing-require-and-ternaries-is-fixed)
A transpiler bug when statically-known pure constants were used in ternaries that call `require()` was fixed. This bug was blocking Vite 5 from working in Bun. Thanks to [@dylan-conway](https://github.com/dylan-conway) for the fix.
## []()[Improved support for ES5 `with` statements](bun-v1.0.13.html#improved-support-for-es5-with-statements)
Before the days of destructuring, the `with` statement was a popular way to avoid typing out long object names.
For example, instead of writing
```
import { join } from "path";
join(__dirname, "foo");
```
You could write
```
with (require("path")) {
join(__dirname, "foo");
}
```
Today, a lot of developers would get mad at you for using `with`. But it is a part of JavaScript, and Bun must support it. Importantly, there are popular libraries people depend on that use `with`, and those must work in Bun.
### []()[Using `with` now makes the file CommonJS](bun-v1.0.13.html#using-with-now-makes-the-file-commonjs)
`with` statements are not supported in strict mode. ES Modules are strict mode-only.
Previously, Bun would throw an error like this when you used `with` without any other CommonJS syntax:
```
SyntaxError: 'with' statements are not valid in strict mode.
```
Now, Bun will automatically convert the file to CommonJS if you use `with`:
```
with (require("path")) {
join(__dirname, "foo");
}
```
## []()[`Bun.spawn` better errors](bun-v1.0.13.html#bun-spawn-better-errors)
Previously, `Bun.spawn` would silently fail on macOS when errors like the current working directory did not exist:
```
Bun.spawn({
cwd: "/i/dont/exist!",
cmd: ["ls"],
});
```
Now, it (correctly) will throw an error:
```
ENOENT: No such file or directory
path: "/opt/homebrew/opt/coreutils/libexec/gnubin/ls"
syscall: "posix_spawn"
errno: -2
```
This is fixed thanks to [@Electroid](https://github.com/Electroid).
### []()[Why did this happen?](bun-v1.0.13.html#why-did-this-happen)
Most C system call wrappers return `-1` and then expect the developer to check `errno`. `posix_spawn` is a little unusual. Instead, any non-zero value is an error, and the errno is returned directly. We were checking for errno, errno was reporting that everything was fine, and so we were not throwing an error.
We have added a test to check `posix_spawn` throws accordingly.
## []()[Regression in `bun install` fixed](bun-v1.0.13.html#regression-in-bun-install-fixed)
A regression that caused `"FileNotFound"` errors to appear in `bun install` in certain cases has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
### []()[A peer dependencies determinism issue is fixed](bun-v1.0.13.html#a-peer-dependencies-determinism-issue-is-fixed)
A bug sometimes caused `bun install` to non-deterministically choose which peer dependency version to install. This bug has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
## []()[Fixed: `The Stats.atime getter can only be used on instances of Stats`](bun-v1.0.13.html#fixed-the-stats-atime-getter-can-only-be-used-on-instances-of-stats)
The following error was fixed:
```
const { Stats } = require("node:fs");
const stat = Object.create(Stats.prototype);
stat.atime; // previously: threw "The Stats.atime getter can only be used on instances of Stats"
```
Some libraries create `Stats` objects using `Object.create(Stats.prototype)`. Previously, Bun would throw an error when you tried to access `atime` on a `Stats` object created this way (it is implemented as a class currently). Now, Bun will return `undefined` instead of throwing an error and allow the fields to be set.
This unblocks certain libraires.
## []()[Fixed: `new Server` in node:http](bun-v1.0.13.html#fixed-new-server-in-node-http)
The following error was fixed:
```
import { Server } from "http";
new Server({ key: "123" });
```
Previously, this would throw the following error:
```
TypeError: key argument must be an string, Buffer, TypedArray, BunFile or an array containing string, Buffer, TypedArray or BunFile
```
This error was incorrect. It no longer errors.
Thanks to [@HK-SHAO](https://github.com/HK-SHAO) for the fix.
## []()[Fixed: `napi_get_value_string_utf8` behaves like Node.js now](bun-v1.0.13.html#fixed-napi-get-value-string-utf8-behaves-like-node-js-now)
Bun's implementation of [`napi_get_value_string_utf8`](https://nodejs.org/api/n-api.html#napi_get_value_string_utf8) now more closely matches the behavior of Node.js, thanks to [@oguimbal](https://github.com/oguimbal).
## []()[Slightly fewer strings are allocated in CommonJS modules](bun-v1.0.13.html#slightly-fewer-strings-are-allocated-in-commonjs-modules)
CommonJS modules have `require` and `require.resolve` functions.
In Bun, these are implemented as the native code equivalent of a `.bind` call. Bound functions by default change the name, but code expects `require.name` to return `"require"` and `require.resolve.name` to return `"resolve"` - so we must manually set the name.
It turns out, the way we were manually setting the name caused the name to be a new string created every time any CommonJS module was loaded. These two strings are small, but if you load hundreds of modules, it adds up.
```
require("discord.js");
const { heapStats } = require("bun:jsc");
const { strings } = heapStats().objectTypeCounts;
console.log(strings, "+ strings allocated");
```
BeforeAfter`10,397` strings`9,628` strings
That's a **7.9% reduction in strings allocated when loading Discord.js**
Does this make a performance difference? Probably not. But it's a nice cleanup.
## []()[Thanks to 9 contributors!](bun-v1.0.13.html#thanks-to-9-contributors)
- [@cirospaciari](https://github.com/cirospaciari)
- [@Didas-git](https://github.com/Didas-git)
- [@dottedmag](https://github.com/dottedmag)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Electroid](https://github.com/Electroid)
- [@HK-SHAO](https://github.com/HK-SHAO)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@jhmaster2000](https://github.com/jhmaster2000)
- [@mathiasrw](https://github.com/mathiasrw)
- [@oguimbal](https://github.com/oguimbal)
* * *
#### [Bun v1.0.12](bun-v1.0.12.html)
#### [Bun v1.0.14](bun-v1.0.14.html)
On this page
- [http2 client support](bun-v1.0.13.html#http2-client-support)
- [gRPC works now](bun-v1.0.13.html#grpc-works-now)
- [Vite 5 & Rollup 4 work now](bun-v1.0.13.html#vite-5-rollup-4-work-now)
- [process.report.getReport() is now implemented](bun-v1.0.13.html#process-report-getreport-is-now-implemented)
- [Transpiler bug involing require and ternaries is fixed](bun-v1.0.13.html#transpiler-bug-involing-require-and-ternaries-is-fixed)
- [Improved support for ES5 `with` statements](bun-v1.0.13.html#improved-support-for-es5-with-statements)
- [Using `with` now makes the file CommonJS](bun-v1.0.13.html#using-with-now-makes-the-file-commonjs)
- [`Bun.spawn` better errors](bun-v1.0.13.html#bun-spawn-better-errors)
- [Why did this happen?](bun-v1.0.13.html#why-did-this-happen)
- [Regression in `bun install` fixed](bun-v1.0.13.html#regression-in-bun-install-fixed)
- [A peer dependencies determinism issue is fixed](bun-v1.0.13.html#a-peer-dependencies-determinism-issue-is-fixed)
- [Fixed: `The Stats.atime getter can only be used on instances of Stats`](bun-v1.0.13.html#fixed-the-stats-atime-getter-can-only-be-used-on-instances-of-stats)
- [Fixed: `new Server` in node:http](bun-v1.0.13.html#fixed-new-server-in-node-http)
- [Fixed: `napi_get_value_string_utf8` behaves like Node.js now](bun-v1.0.13.html#fixed-napi-get-value-string-utf8-behaves-like-node-js-now)
- [Slightly fewer strings are allocated in CommonJS modules](bun-v1.0.13.html#slightly-fewer-strings-are-allocated-in-commonjs-modules)
- [Thanks to 9 contributors!](bun-v1.0.13.html#thanks-to-9-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.14.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.14
* * *
[Ashcon Partovi](https://twitter.com/ashconpartovi) · November 22, 2023
[](../rss.xml)
Bun v1.0.14 introduces `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.
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun:
- [`v1.0.9`](bun-v1.0.9.html) - Fixes a glibc symbol version error, illegal instruction error, a Bun.spawn bug, an edgecase with peer dependency installs, and a JSX transpiler bugfix
- [`v1.0.10`](bun-v1.0.10.html) - Fixes 14 bugs (addressing 102 👍 reactions), node:http gets 14% faster, stability improvements to Bun for Linux ARM64, bun install bugfix, and node:http bugfixes
- [`v1.0.11`](bun-v1.0.11.html) - Fixes 5 bugs, adds `Bun.semver`, fixes a bug in bun install and fixes bugs impacting `astro` and `@google-cloud/storage`
- [`v1.0.12`](bun-v1.0.12.html) - Adds `bun -e` for evaluating scripts, `bun --env-file` for loading environment variables, `server.url`, `import.meta.env`, `expect.unreachable()`, improved CLI help output, and more
- [`v1.0.13`](bun-v1.0.13.html) - Fixes 6 bugs (addressing 317 👍 reactions). 'http2' module & gRPC.js work now. Vite 5 & Rollup 4 work. Implements process.report.getReport(), improves support for ES5 'with' statements, fixes a regression in bun install, fixes a crash when printing exceptions, fixes a Bun.spawn bug, and fixes a peer dependencies bug
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.Glob`](bun-v1.0.14.html#bun-glob)
`Bun.Glob` is a fast API for matching files and strings using glob patterns.
It's similar to popular Node.js libraries like `fast-glob` or `micromatch`, except it matches strings 3x faster.
[](https://github.com/oven-sh/bun/assets/709451/0214879d-6fae-4857-8665-e77e6d838b74)
Use `glob.scan()` to scan for files that match the glob, which returns an `AsyncIterator` that yields matching paths.
```
import { Glob } from "bun";
const glob = new Glob("**/*.ts");
for await (const path of glob.scan("src")) {
console.log(path); // "src/index.ts"
}
```
Use `glob.match()` to match a string against a glob pattern.
```
import { Glob } from "bun";
const glob = new Glob("**/*.ts");
const match = glob.match("src/index.ts");
console.log(match); // true
```
Thanks to [@zackradisic](https://github.com/zackradisic) for implementing this! Also, thanks to [@mrmlnc](https://github.com/mrmlnc) for `fast-glob` along with the contributors to `micromatch` & `picomatch`, which our tests were inspired by. Much of our Zig implementation was inspired by Devon Govett (@devongovett) and Stephen Gregoratto (@The-King-of-Toasters)'s glob implementations, which we are grateful for.
## []()[Fixed bug with missing dependencies using `bun install`](bun-v1.0.14.html#fixed-bug-with-missing-dependencies-using-bun-install)
Bun had a race condition that could cause `bun install` to occasionally fail to install a dependency when many different versions of the same package were being extracted concurrently. This was caused by a bug in how Bun created the temporary filename for installing dependencies. The path used was not unique enough, which could cause one build to overwrite another build's temporary folder, sometimes.
## []()[TypeScript module resolution changes in `node_modules`](bun-v1.0.14.html#typescript-module-resolution-changes-in-node-modules)
To mimick `tsc` behavior, Bun loads TypeScript files before JavaScript files. This works well in local development, but sometimes npm packages ship TypeScript source files that transpilers cannot transpile, such as:
- TypeScript transformer plugins.
- Using `import {Foo}` instead of `import {type Foo}`.
- Using `export {Foo}` instead of `export {type Foo}`.
Going forward, when inside `node_modules`, Bun will prefer JavaScript files over TypeScript files when both are present.
This fixes errors that looked like:
```
SyntaxError: Indirectly exported binding name 'Foo' is not found.
```
Bun continues to support TypeScript files in `node_modules`. When both `.ts` and `.js` files are present, Bun will prefer the `.js` file when inside `node_modules`. Otherwise, Bun continues to prefer `.ts` files.
## []()[More readable error messages when a build fails](bun-v1.0.14.html#more-readable-error-messages-when-a-build-fails)
Bun now shows better error messages when a build fails:
- Fixed a bug where it only highlighed the first character
- Trimmed extraneous newlines in the error message
- Made the styling for build errors match the styling for runtime errors
[](https://github.com/oven-sh/bun/assets/709451/8e344a23-3924-40fa-b110-0e2dca003cfc)
## []()[Better export & import error messages](bun-v1.0.14.html#better-export-import-error-messages)
> In the next version of Bun
>
> When you confuse a named import for a default import, it suggests using the named import instead [pic.twitter.com/UGIxbEeO7C](https://t.co/UGIxbEeO7C)
>
> — Jarred Sumner (@jarredsumner) [November 19, 2023](https://twitter.com/jarredsumner/status/1726115774673396194?ref_src=twsrc%5Etfw)
> In the next version of Bun
>
> When you confuse a default import for a named import, it suggests using the default import instead [pic.twitter.com/Tjx3px19pa](https://t.co/Tjx3px19pa)
>
> — Jarred Sumner (@jarredsumner) [November 19, 2023](https://twitter.com/jarredsumner/status/1726116117285122321?ref_src=twsrc%5Etfw)
## []()[Errors for unsupported ESM <> CommonJS features](bun-v1.0.14.html#errors-for-unsupported-esm-commonjs-features)
Bun supports both `require()` and `import` in the same file, but you cannot use import and `module.exports` in the same file. You also cannot use `exports`, `module`, `with`, or top-level return.
Previously, Bun relied on a runtime error message from JavaScriptCore for this, but the error message was a little confusing.
Now, these errors are detected at build-time and show a better error message. In this example, you cannot use `import` and `with` in the same file:
```
import "abc";
with (Bun) {
write("/tmp/file.txt", escapeHTML(file("/tmp/file.html").text()));
console.log({
contents: file("/tmp/file.txt").text(),
});
}
```
Before:
```
1 | import "abc";
2 |
3 | with (Bun) {
^
SyntaxError: Unexpected string literal "abc". import call expects one or two arguments.
at unsupported.js:3:0
```
After:
```
1 | import "abc";
^
error: Cannot use import statement with CommonJS-only features
at unsupported.js:1:8 7
note: Try require("abc") instead
note: This file is CommonJS because a "with" statement is used
```
## []()[Class name shown in `console.log`](bun-v1.0.14.html#class-name-shown-in-console-log)
`console.log()` now shows the class name of the object in more cases, which matches the behavior of Node.js.
```
class Foo {}
class Bar {
value = 1;
}
console.log(new Foo()); // Foo {}
console.log(new Bar()); // Bar { value: 1 }
```
Thanks to [@JibranKalia](https://github.com/JibranKalia) for implementing this!
## []()[Fixed signal using `process.kill()`](bun-v1.0.14.html#fixed-signal-using-process-kill)
A bug was fixed where `SIGKILL` and `SIGSTOP` were not supported by `process.kill()`.
```
process.kill("SIGKILL"); // or "SIGSTOP"
```
If you encountered the following error, it is now fixed:
```
RangeError: Unknown signal name
```
Thanks to [@antongolub](https://github.com/antongolub) for fixing this bug!
If you want to see the full changelog, you can find it [here](https://github.com/oven-sh/bun/compare/bun-v1.0.13...bun-v1.0.14).
## []()[Thanks to 7 contributors!](bun-v1.0.14.html#thanks-to-7-contributors)
- [@antongolub](https://github.com/@antongolub)
- [@dylan-conway](https://github.com/@dylan-conway)
- [@Jarred-Sumner](https://github.com/@Jarred-Sumner)
- [@jerome-benoit](https://github.com/@jerome-benoit)
- [@JibranKalia](https://github.com/@JibranKalia)
- [@liz3](https://github.com/@liz3)
- [@zackradisic](https://github.com/@zackradisic)
* * *
#### [Bun v1.0.13](bun-v1.0.13.html)
#### [Bun v1.0.15](bun-v1.0.15.html)
On this page
- [`Bun.Glob`](bun-v1.0.14.html#bun-glob)
- [Fixed bug with missing dependencies using `bun install`](bun-v1.0.14.html#fixed-bug-with-missing-dependencies-using-bun-install)
- [TypeScript module resolution changes in `node_modules`](bun-v1.0.14.html#typescript-module-resolution-changes-in-node-modules)
- [More readable error messages when a build fails](bun-v1.0.14.html#more-readable-error-messages-when-a-build-fails)
- [Better export & import error messages](bun-v1.0.14.html#better-export-import-error-messages)
- [Errors for unsupported ESM <> CommonJS features](bun-v1.0.14.html#errors-for-unsupported-esm-commonjs-features)
- [Class name shown in `console.log`](bun-v1.0.14.html#class-name-shown-in-console-log)
- [Fixed signal using `process.kill()`](bun-v1.0.14.html#fixed-signal-using-process-kill)
- [Thanks to 7 contributors!](bun-v1.0.14.html#thanks-to-7-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.15.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.15
* * *
[Ashcon Partovi](https://twitter.com/ashconpartovi) · December 2, 2023
[](../rss.xml)
Bun v1.0.15 fixes 23 bugs (addressing 117 👍 reactions), `tsc` starts 2x faster, prettier 40% faster. Stable `WebSocket` client, syntax-highlighted errors, cleaner stack traces, add custom test matchers with `expect.extend()` + additional expect matchers, TensorFlow.js support, and more.
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun:
- [`v1.0.12`](bun-v1.0.12.html) - Adds `bun -e` for evaluating scripts, `bun --env-file` for loading environment variables, `server.url`, `import.meta.env`, `expect.unreachable()`, improved CLI help output, and more
- [`v1.0.13`](bun-v1.0.13.html) - Fixes 6 bugs (addressing 317 👍 reactions). 'http2' module & gRPC.js work now. Vite 5 & Rollup 4 work. Implements process.report.getReport(), improves support for ES5 'with' statements, fixes a regression in bun install, fixes a crash when printing exceptions, fixes a Bun.spawn bug, and fixes a peer dependencies bug
- [`v1.0.14`](bun-v1.0.14.html) - `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.
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
```
## []()[Transpiler cache makes CLIs like `tsc` up to 2x faster](bun-v1.0.15.html#transpiler-cache-makes-clis-like-tsc-up-to-2x-faster)
Bun lets you run TypeScript and JSX files without a build step. This works by running Bun's JavaScript transpiler before files load. In this release, we're introducing a content-addressable cache for files larger than 50KB, to avoid the performance overhead of transpiling the same files repeatedly. This makes CLIs, such as `tsc`, run up to 2x faster.
`tsc --help` gets a 2x speedup compared to Bun v1.0.14:
```
Benchmark 1: bun --bun ./node_modules/.bin/tsc --help
Time (mean ± σ): 82.2 ms ± 2.6 ms [User: 70.1 ms, System: 14.3 ms]
Range (min … max): 78.4 ms … 87.1 ms 37 runs
Benchmark 2: bun-1.0.14 --bun ./node_modules/.bin/tsc --help
Time (mean ± σ): 197.0 ms ± 3.6 ms [User: 172.0 ms, System: 27.2 ms]
Range (min … max): 192.4 ms … 204.4 ms 14 runs
Benchmark 3: node ./node_modules/.bin/tsc --help
Time (mean ± σ): 113.8 ms ± 3.2 ms [User: 103.6 ms, System: 16.0 ms]
Range (min … max): 110.0 ms … 123.4 ms 23 runs
Summary
bun --bun ./node_modules/.bin/tsc --help ran
1.38 ± 0.06 times faster than node ./node_modules/.bin/tsc --help
2.40 ± 0.09 times faster than bun-1.0.14 --bun ./node_modules/.bin/tsc --help
```
### []()[Prettier gets up to 40% faster (compared to Bun v1.0.14)](bun-v1.0.15.html#prettier-gets-up-to-40-faster-compared-to-bun-v1-0-14)
```
Benchmark 1: bun --bun ./node_modules/.bin/prettier --write ./examples/hashing.js
Time (mean ± σ): 124.5 ms ± 3.2 ms [User: 144.5 ms, System: 23.4 ms]
Range (min … max): 119.9 ms … 131.8 ms 23 runs
Benchmark 2: bun-1.0.14 --bun ./node_modules/.bin/prettier --write ./examples/hashing.js
Time (mean ± σ): 184.4 ms ± 4.1 ms [User: 202.7 ms, System: 28.6 ms]
Range (min … max): 175.2 ms … 192.9 ms 15 runs
Benchmark 3: node ./node_modules/.bin/prettier --write ./examples/hashing.js
Time (mean ± σ): 162.9 ms ± 3.7 ms [User: 161.8 ms, System: 42.5 ms]
Range (min … max): 158.2 ms … 170.7 ms 17 runs
Summary
bun --bun ./node_modules/.bin/prettier --write ./examples/hashing.js ran
1.31 ± 0.04 times faster than node ./node_modules/.bin/prettier --write ./examples/hashing.js
1.48 ± 0.05 times faster than bun-1.0.14 --bun ./node_modules/.bin/prettier --write ./examples/hashing.js
```
To minimize disk usage, the transpiler cache is global and shared across all projects. It's safe to delete the cache at any time, and since it's content-addressable it will not contain duplicate entries. If you are running Bun with an emphemeral filesystem, such as Docker, it is recommended to disable the cache.
If you want to customize the path where these files are cached, you can set the `BUN_RUNTIME_TRANSPILER_CACHE_PATH` environment variable. You can also set the value to `0` to disable the cache entirely.
## []()[Stable `WebSocket` client](bun-v1.0.15.html#stable-websocket-client)
This release includes a (finally) stable [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket) client. Bun has supported `WebSocket` for a while, but it had various protocol bugs, such as disconnecting early or not handling message fragmentation properly. Now, it is stable and should work with most WebSocket servers.
```
const ws = new WebSocket("wss://echo.websocket.org/");
ws.addEventListener("message", ({ data }) => {
console.log("Received:", data);
});
ws.addEventListener("open", () => {
ws.send("Hello!");
});
```
To test compliance, we used the [Autobahn](https://www.google.com/search?q=autobahn%20websocket&sourceid=chrome&ie=UTF-8) test suite, which is the de-facto standard for testing WebSocket implementations. Bun passed 100% of Autobahn's tests, excluding those that test for compression. (our WebSocket client does not support compression yet, but will soon.)
[](https://github.com/oven-sh/bun/assets/3238291/a0d322fe-4deb-4970-a439-a179184559a0)
That means all of these [issues](https://github.com/oven-sh/bun/issues/6686), and more, have now been fixed.
[](https://github.com/oven-sh/bun/assets/3238291/aef6ec18-72ce-4ff1-821d-fac476510d48)
Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing these bugs and getting Autobahn test compliance!
## []()[`expect.extend()` and more matchers](bun-v1.0.15.html#expect-extend-and-more-matchers)
You can now defined custom test matchers using [`expect.extend()`](https://jestjs.io/docs/expect#expectextendmatchers). This is useful when you want to create a custom matcher that is reusable across multiple tests. For example, you can create a custom matcher that checks if a number is within a range:
```
import { test, expect } from "bun:test";
expect.extend({
toBeWithinRange(received, floor, ceiling) {
const pass = received >= floor && received <= ceiling;
if (pass) {
return {
message: () =>
`expected ${received} not to be within range ${floor} - ${ceiling}`,
pass: true,
};
} else {
return {
message: () =>
`expected ${received} to be within range ${floor} - ${ceiling}`,
pass: false,
};
}
},
});
test("toBeWithinRange()", () => {
expect(1).toBeWithinRange(1, 99); // ✅
expect(100).toBeWithinRange(1, 99); // ❌ expected 100 to be within range 1 - 99
});
```
Bun also supports more asymmetric matchers, including:
- [`expect.closeTo()`](https://jestjs.io/docs/expect#expectclosetonumber-numdigits)
- [`expect.objectContaining()`](https://jestjs.io/docs/expect#expectobjectcontainingobject)
In addition to the above asymetric matchers, Bun is introducing two new asymetric matchers that work for promises.
- `expect.resolvesTo`
- `expect.rejectsTo`
For example, you can use `expect.resolvedTo` to check for a promise that resolves to a value:
```
import { test, expect } from "bun:test";
import { getTempurature, getForecast } from "./weather";
test("expect.resolvedTo", async () => {
const weather = {
tempurature: getTempurature(),
forecast: getForecast(),
};
await expect(weather).toMatchObject({
tempurature: expect.resolvedTo.closeTo(10, 5),
forecast: expect.resolvedTo.stringMatching(/rain|snow|sleet/),
});
});
```
Thanks to [@otgerrogla](https://github.com/otgerrogla) for implementing these features and also fixing various bugs with `expect()`.
There are also more mock matchers available, including:
- [`expect().toHaveBeenCalledWith()`](https://jestjs.io/docs/expect#tohavebeencalledwitharg1-arg2-)
- [`expect().toHaveBeenLastCalledWith()`](https://jestjs.io/docs/expect#tohavebeenlastcalledwitharg1-arg2-)
- [`expect().toHaveBeenNthCalledWith()`](https://jestjs.io/docs/expect#tohavebeennthcalledwithnthcall-arg1-arg2-)
You can use these matchers to check if a function was called with certain arguments:
```
import { test, mock, expect } from "bun:test";
test("toHaveBeenCalledWith()", () => {
const fn = mock(() => {});
sum(1, 2, 3);
expect(fn).toHaveBeenCalledWith(1, 2, 3); // ✅
expect(fn).toHaveBeenCalledWith(1, 2); // ❌
});
```
Thanks to [@james-elicx](https://github.com/james-elicx) for implementing these matchers and making various error messages better.
## []()[Syntax-highlighting for errors](bun-v1.0.15.html#syntax-highlighting-for-errors)
When an exception occurs in Bun, it prints a stack trace to the console with a multi-line source code preview. Now that source code preview gets syntax highlighted, which makes it easier to read.
[](https://github.com/oven-sh/bun/assets/709451/a95254d0-2652-433c-80e7-7faac1e38c2a)
The syntax highlighter also extends to all other errors that include source code, such as this one when using `bun install` with multiple workspace packages sharing the same name.
[](https://github.com/oven-sh/bun/assets/24465214/0e7166bf-2fe2-40e8-9c20-98135ed8d691)
Thanks to [@paperclover](https://github.com/paperclover) for working on this!
## []()[Better `Error.stack` traces](bun-v1.0.15.html#better-error-stack-traces)
We've made several improvements to how `Error.stack` traces are formatted.
Stack traces now include less noise, such as internal functions that are not relevant to the error.
```
1 | throw new Error("Oops");
^
error: Oops
at /Users/jarred/Desktop/oops.js:1:7
- at globalThis (/Users/jarred/Desktop/oops.js:3:14)
- at overridableRequire (:1:20)
at /Users/jarred/Desktop/index.js:3:8
- at globalThis (/Users/jarred/Desktop/index.js:3:8)
```
We also fixed a bug where Bun would not detect if the `Error.stack` property was modified. This can happen if you use a library that modifies the stack trace, such as concatenating multiple traces together.
```
const err = new Error("Oops 1");
err.stack += "\n" + new Error("Oops 2").stack;
throw err;
```
Bun now re-parses `error.stack`, so that modified stack traces are properly detected and formatted.
## []()[`recursive` in `fs.readdir()` is 40x faster than Node.js](bun-v1.0.15.html#recursive-in-fs-readdir-is-40x-faster-than-node-js)
Bun now supports the `recursive` option in `fs.readdir()`, which is used to recursively read a directory.
```
import { readdir } from "fs/promises";
const results = await readdir(__dirname, { recursive: true });
console.log(results); // ["a.js", "b/c.js" ...
```
When running `readdir()` in the `test/` directory of Bun's repository, on Linux it's 40x faster than Node.js v21.2.0.
[](https://github.com/oven-sh/bun/assets/3238291/31feab1d-8dce-4aec-9909-0a197e1b37e9)
> Fixed.[https://t.co/WhuVBhNdc3](https://t.co/WhuVBhNdc3)
>
> — Jarred Sumner (@jarredsumner) [November 24, 2023](https://twitter.com/jarredsumner/status/1728042351010910323?ref_src=twsrc%5Etfw)
## []()[CommonJS modules get 1% faster](bun-v1.0.15.html#commonjs-modules-get-1-faster)
We made some improvements to how Bun loads CommonJS modules, which makes them 1% faster.
[](https://github.com/oven-sh/bun/assets/3238291/c22b6a4d-7b5c-4625-a192-22bc6244fa1d)
This is because we simplified our internal wraper functions for CommonJS. Previosuly, our wrapper functions were written in JavaScript, with some help from Bun's transpiler. Now, this is done in native code, so it's faster and uses less memory.
Thanks to [@paperclover](https://github.com/paperclover) for implementing this!
## []()[TensorFlow.js now works](bun-v1.0.15.html#tensorflow-js-now-works)
There was an outstanding bug in Bun's implementation of `napi_create_string_utf16` and `napi_create_arraybuffer` that prevented [TensorFlow.js](https://www.tensorflow.org/js) from working. This has now been fixed.
```
import * as tf from "@tensorflow/tfjs-node";
const model = tf.sequential({
layers: [
tf.layers.dense({ units: 128, activation: "relu", inputShape: [1] }),
tf.layers.dense({ units: 3 }),
tf.layers.softmax(),
],
});
model.compile({
optimizer: "adam",
loss: "categoricalCrossentropy",
metrics: ["categoricalAccuracy"],
});
const result = model.predict(tf.tensor([0]));
if (Array.isArray(result)) throw new Error("Expected a single tensor");
const prediction = await result.data();
console.log(prediction); // Float32Array(3) [...]
```
## []()[Support for `crypto.sign` and `crypto.verify`](bun-v1.0.15.html#support-for-crypto-sign-and-crypto-verify)
Bun now supports `sign` and `verify` in the `node:crypto` module, which can be used to sign and verify data using a private key.
```
import { sign, generateKeyPairSync } from "node:crypto";
const { privateKey } = generateKeyPairSync("ed25519");
const signature = sign(undefined, Buffer.from("foo"), privateKey);
console.log(signature); // Buffer(64) [ ... ]
```
Thanks to [@cirospaciari](https://github.com/cirospaciari) for implementing this feature!
## []()[`bun install` migration from `package-lock.json` v2](bun-v1.0.15.html#bun-install-migration-from-package-lock-json-v2)
Bun is now able to migrate `package-lock.json` files that have a `lockfileVersion` of `2`. This is useful if you are migrating from npm to Bun.
```
❯ cat package-lock.json | jq .lockfileVersion
2
❯ bun install
bun install v1.0.15
[3.57ms] migrated lockfile from package-lock.json
+ svelte@4.0.0 (v4.2.8 available)
21 packages installed [265.00ms]
```
## []()[`bun install` duplicate workspace bugfix](bun-v1.0.15.html#bun-install-duplicate-workspace-bugfix)
An error regarding duplicate workspace packages has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
## []()[Trailing commas with `console.log`](bun-v1.0.15.html#trailing-commas-with-console-log)
Bun now includes trailing commas for objects that are printed using `console.log`. This makes it easier to copy-paste the output from your console, do a search-and-replace, and matches what code formatters like `prettier` do.
```
console.log({ a: 1, b: 2, c: "3" });
{
a: 1,
b: 2,
- c: "3"
+ c: "3",
}
```
Thanks to [@hustLer2k](https://github.com/hustLer2k) for implementing this improvement, and to [@ArnaudBarre](https://github.com/ArnaudBarre) for the suggestion!
## []()[Implemented: `console.timeLog`](bun-v1.0.15.html#implemented-console-timelog)
There was a bug that prevented `console.timeLog` from working. This was fixed thanks to [@lqqyt2423](https://github.com/lqqyt2423).
## []()[Fixed: Detached usage of `ReadableStream`](bun-v1.0.15.html#fixed-detached-usage-of-readablestream)
There was a bug where a `undefined is not an object` error would throw when a `ReadableStream` was detached, which has now been fixed.
```
const { exited, stdout } = Bun.spawn(["echo", "hello"], {
stdout: "pipe",
});
await exited;
// Since the process has exited, the `stdout` ReadableStream is detached.
console.log(await Bun.readableStreamToText(stdout));
// Before: error: undefined is not an object
// After: "hello\n"
```
## []()[Fixed: `fs.opendir()` has `path` property](bun-v1.0.15.html#fixed-fs-opendir-has-path-property)
Previously, `fs.opendir()` did not have a `path` property, this has now been fixed thanks to [@samfundev](https://github.com/samfundev).
```
import { test, expect } from "bun:test";
import { opendir } from "fs/promises";
test("opendir() has `path` property", () => {
const result = await opendir(".");
expect(result).toHaveProperty("path", ".");
});
```
## []()[Fixed: Duplicate `Content-Range` header](bun-v1.0.15.html#fixed-duplicate-content-range-header)
There was a bug where Bun would send duplicate `Content-Range` headers.
```
const file = Bun.file("video.mp4");
const start = 0;
const end = 1000;
const range = file.slice(start, end);
return new Response(range, {
status: 206,
headers: {
"Content-Range": `bytes ${start}-${end}/${file.size}`,
},
});
```
Bun would not properly detect that a `Content-Range` header was already set, and would send a duplicate header.
```
content-range: bytes 0-1000/10000
- content-range: bytes 0-1000/*
```
This was fixed thanks to [@libersoft-org](https://github.com/libersoft-org).
## []()[Fixed: Various transpiler bugs](bun-v1.0.15.html#fixed-various-transpiler-bugs)
### []()[Hyphenated keys in `tsconfig.json`](bun-v1.0.15.html#hyphenated-keys-in-tsconfig-json)
There was a bug where if a `tsconfig.json` included a key that contained hyphens, parsing would fail. This was fixed thanks to [@DontBreakAlex](https://github.com/DontBreakAlex).
tsconfig.json
```
{
"key-with-hyphens": "value"
}
```
### []()[Spreading elements in JSX](bun-v1.0.15.html#spreading-elements-in-jsx)
There was a bug where spreading a child element into a parent element would cause an unexpected error. This was fixed thanks to [@rhyzx](https://github.com/rhyzx).
Input:
```
const a = <h1>{...[123]}</h1>;
```
Output:
```
- error: Unexpected ...
+ var a = jsx_dev_runtime.jsxDEV("h1", {
+ children: [...[123]]
+ }, undefined, true, undefined, this);
```
### []()[Stack Overflow in already-minified code](bun-v1.0.15.html#stack-overflow-in-already-minified-code)
"Stack Overflow" is not just a website. Programs execute code in a stack, and if the stack uses too much memory, it overflows.
Bun's parser is a recursive descent parser, which means it uses recursion to parse code. This makes the implementation simpler, but it can lead to stack overflow if the input source code is too deeply nested with binary expressions. This release fixes that.
For example, if you were to write a file with contents like this:
```
const chain =
`globalThis.a = {};` +
"\n" +
`globalThis.a + globalThis.a +`.repeat(1000000) +
`globalThis.a` +
"\n";
await Bun.write("stack-overflow.js", chain);
```
And then run it with `bun stack-overflow.js`, it would crash in bun's transpiler due to stack overflow.
This has now been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
This bug manifested when using Bun's runtime to format a TypeScript file with Prettier.
### []()[`override` keyword in TypeScript constructor](bun-v1.0.15.html#override-keyword-in-typescript-constructor)
There was a bug where the `override` keyword in a TypeScript constructor would cause an unexpected error.
```
class Foo {}
class Bar extends Foo {}
class Fizz {
constructor(readonly foo: Foo) {}
}
class Buzz extends Fizz {
constructor(override bar: Bar) {
super(foo);
}
}
new Buzz(new Bar());
```
```
- 10 | constructor(override foo: FooChild) {
- ^
- error: Expected ")" but found "foo"
- at example.ts:10:23
```
### []()[Fixed: Dynamicly loaded CommonJS modules in `bun build --compile`](bun-v1.0.15.html#fixed-dynamicly-loaded-commonjs-modules-in-bun-build-compile)
When the argument to `require` is not statically analyzable, `bun build` leaves it as is.
```
const dynamic = (name) => require(name);
console.log(dynamic("some-package"));
```
If you used this with `bun build --compile` and loaded a commonjs file this way, the transpiler would generate code with a syntax error. This has been fixed.
## []()[Thanks to 25 contributors!](bun-v1.0.15.html#thanks-to-25-contributors)
We're always excited to welcome new contributors to Bun. 12 new contributors made their first contribution in this release.
- [@adrienbrault](https://github.com/adrienbrault) made their first contribution in [#7350](https://github.com/oven-sh/bun/pull/7350)
- [@brianknight10](https://github.com/brianknight10) made their first contribution in [#7368](https://github.com/oven-sh/bun/pull/7368)
- [@DontBreakAlex](https://github.com/DontBreakAlex) made their first contribution in [#7316](https://github.com/oven-sh/bun/pull/7316)
- [@james-elicx](https://github.com/james-elicx) made their first contribution in [#7277](https://github.com/oven-sh/bun/pull/7277)
- [@joeyw](https://github.com/joeyw) made their first contribution in [#7364](https://github.com/oven-sh/bun/pull/7364)
- [@lqqyt2423](https://github.com/lqqyt2423) made their first contribution in [#7089](https://github.com/oven-sh/bun/pull/7089)
- [@mimikun](https://github.com/mimikun) made their first contribution in [#7378](https://github.com/oven-sh/bun/pull/7378)
- [@NReilingh](https://github.com/NReilingh) made their first contribution in [#7372](https://github.com/oven-sh/bun/pull/7372)
- [@rhyzx](https://github.com/rhyzx) made their first contribution in [#7294](https://github.com/oven-sh/bun/pull/7294)
- [@RiskyMH](https://github.com/RiskyMH) made their first contribution in [#7306](https://github.com/oven-sh/bun/pull/7306)
- [@stav](https://github.com/stav) made their first contribution in [#7327](https://github.com/oven-sh/bun/pull/7327)
- [@SukkaW](https://github.com/SukkaW) made their first contribution in [#7348](https://github.com/oven-sh/bun/pull/7348)
- [@yharaskrik](https://github.com/yharaskrik) made their first contribution in [#7409](https://github.com/oven-sh/bun/pull/7409)
Thanks to the 25 contributors who made this release possible:
- [@adrienbrault](https://github.com/adrienbrault)
- [@brianknight10](https://github.com/brianknight10)
- [@cirospaciari](https://github.com/cirospaciari)
- [@Didas-git](https://github.com/Didas-git)
- [@DontBreakAlex](https://github.com/DontBreakAlex)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Electroid](https://github.com/Electroid)
- [@Hanaasagi](https://github.com/Hanaasagi)
- [@hustLer2k](https://github.com/hustLer2k)
- [@james-elicx](https://github.com/james-elicx)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@jerome-benoit](https://github.com/jerome-benoit)
- [@joeyw](https://github.com/joeyw)
- [@lqqyt2423](https://github.com/lqqyt2423)
- [@mimikun](https://github.com/mimikun)
- [@NReilingh](https://github.com/NReilingh)
- [@otgerrogla](https://github.com/otgerrogla)
- [@paperclover](https://github.com/paperclover)
- [@rhyzx](https://github.com/rhyzx)
- [@RiskyMH](https://github.com/RiskyMH)
- [@samfundev](https://github.com/samfundev)
- [@stav](https://github.com/stav)
- [@SukkaW](https://github.com/SukkaW)
- [@WingLim](https://github.com/WingLim)
- [@yharaskrik](https://github.com/yharaskrik)
- [@zackradisic](https://github.com/zackradisic)
* * *
#### [Bun v1.0.14](bun-v1.0.14.html)
#### [Bun v1.0.16](bun-v1.0.16.html)
On this page
- [Transpiler cache makes CLIs like `tsc` up to 2x faster](bun-v1.0.15.html#transpiler-cache-makes-clis-like-tsc-up-to-2x-faster)
- [Prettier gets up to 40% faster (compared to Bun v1.0.14)](bun-v1.0.15.html#prettier-gets-up-to-40-faster-compared-to-bun-v1-0-14)
- [Stable `WebSocket` client](bun-v1.0.15.html#stable-websocket-client)
- [`expect.extend()` and more matchers](bun-v1.0.15.html#expect-extend-and-more-matchers)
- [Syntax-highlighting for errors](bun-v1.0.15.html#syntax-highlighting-for-errors)
- [Better `Error.stack` traces](bun-v1.0.15.html#better-error-stack-traces)
- [`recursive` in `fs.readdir()` is 40x faster than Node.js](bun-v1.0.15.html#recursive-in-fs-readdir-is-40x-faster-than-node-js)
- [CommonJS modules get 1% faster](bun-v1.0.15.html#commonjs-modules-get-1-faster)
- [TensorFlow.js now works](bun-v1.0.15.html#tensorflow-js-now-works)
- [Support for `crypto.sign` and `crypto.verify`](bun-v1.0.15.html#support-for-crypto-sign-and-crypto-verify)
- [`bun install` migration from `package-lock.json` v2](bun-v1.0.15.html#bun-install-migration-from-package-lock-json-v2)
- [`bun install` duplicate workspace bugfix](bun-v1.0.15.html#bun-install-duplicate-workspace-bugfix)
- [Trailing commas with `console.log`](bun-v1.0.15.html#trailing-commas-with-console-log)
- [Implemented: `console.timeLog`](bun-v1.0.15.html#implemented-console-timelog)
- [Fixed: Detached usage of `ReadableStream`](bun-v1.0.15.html#fixed-detached-usage-of-readablestream)
- [Fixed: `fs.opendir()` has `path` property](bun-v1.0.15.html#fixed-fs-opendir-has-path-property)
- [Fixed: Duplicate `Content-Range` header](bun-v1.0.15.html#fixed-duplicate-content-range-header)
- [Fixed: Various transpiler bugs](bun-v1.0.15.html#fixed-various-transpiler-bugs)
- [Hyphenated keys in `tsconfig.json`](bun-v1.0.15.html#hyphenated-keys-in-tsconfig-json)
- [Spreading elements in JSX](bun-v1.0.15.html#spreading-elements-in-jsx)
- [Stack Overflow in already-minified code](bun-v1.0.15.html#stack-overflow-in-already-minified-code)
- [`override` keyword in TypeScript constructor](bun-v1.0.15.html#override-keyword-in-typescript-constructor)
- [Fixed: Dynamicly loaded CommonJS modules in `bun build --compile`](bun-v1.0.15.html#fixed-dynamicly-loaded-commonjs-modules-in-bun-build-compile)
- [Thanks to 25 contributors!](bun-v1.0.15.html#thanks-to-25-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.16.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.16
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · December 10, 2023
[](../rss.xml)
Bun v1.0.16 fixes 49 bugs (addressing 38 👍 reactions). Rewritten IO for Bun.file, 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, and more.
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun:
- [`v1.0.12`](bun-v1.0.12.html) - Adds `bun -e` for evaluating scripts, `bun --env-file` for loading environment variables, `server.url`, `import.meta.env`, `expect.unreachable()`, improved CLI help output, and more
- [`v1.0.13`](bun-v1.0.13.html) - Fixes 6 bugs (addressing 317 👍 reactions). 'http2' module & gRPC.js work now. Vite 5 & Rollup 4 work. Implements process.report.getReport(), improves support for ES5 'with' statements, fixes a regression in bun install, fixes a crash when printing exceptions, fixes a Bun.spawn bug, and fixes a peer dependencies bug
- [`v1.0.14`](bun-v1.0.14.html) - `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`](bun-v1.0.15.html) - 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.
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.write` now creates the parent directory if it doesn't exist](bun-v1.0.16.html#bun-write-now-creates-the-parent-directory-if-it-doesn-t-exist)
Previously, `Bun.write` would throw an error if the directory didn't exist. Now, it will create the directory if it doesn't exist.
```
// script.ts
import { write } from "bun";
await write("i/dont/exist.txt", "Hello, world!");
```
Now, `i/dont` will be created if it doesn't exist.
```
$ bun script.ts
```
Previously, it would throw an error:
```
1 | import { write } from "bun";
2 | await write("i/dont/exist.txt", "heyyy");
^
ENOENT: No such file or directory
path: "i/dont/exist.txt"
syscall: "open"
errno: -2
```
### []()[To throw an error when the parent directory doesn't exist: `createPath: false`](bun-v1.0.16.html#to-throw-an-error-when-the-parent-directory-doesn-t-exist-createpath-false)
This behavior can be disabled by passing `createPath: false` to `Bun.write`.
```
// script.ts
import { write } from "bun";
await write("i/dont/exist.txt", "Hello, world!", { createPath: false });
```
Now, it will throw an error if the directory doesn't exist.
```
$ bun script.ts
```
```
1 | import { write } from "bun";
2 | await write("i/dont/exist.txt", "heyyy", { createPath: false });
^
ENOENT: No such file or directory
path: "i/dont/exist.txt"
syscall: "open"
errno: -2
```
> In the next version of Bun
>
> Bun.write() will automatically create parent directories if they do not exist [pic.twitter.com/jNgjZ5LAtl](https://t.co/jNgjZ5LAtl)
>
> — Jarred Sumner (@jarredsumner) [December 10, 2023](https://twitter.com/jarredsumner/status/1733680612819804494?ref_src=twsrc%5Etfw)
> You run
>
> await Bun.write(“/dir-doesnt-exist/file.txt”, “abc”)
>
> Do you expect the function to throw because “dir-doesn’t-exist” doesn’t exist?
>
> — Bun (@bunjavascript) [December 7, 2023](https://twitter.com/bunjavascript/status/1732710459583897674?ref_src=twsrc%5Etfw)
## []()[Rewritten IO for `Bun.file`](bun-v1.0.16.html#rewritten-io-for-bun-file)
The internals of `Bun.file` on Linux have been rewritten to use epoll instead of io\_uring, which improves compatibility in Docker and cloud hosts like Vercel and Google Cloud Run.
This addresses 11 issues related to `EBADF` when using `Bun.file`:
[](https://github.com/oven-sh/bun/assets/24465214/29076f9f-adff-42d0-9948-dc35b08b7036)
The impetus for this change was Docker disabled io\_uring by default in November 2023.
### []()[Bun.write() and Bun.file().text() gets 3x faster under concurrent load](bun-v1.0.16.html#bun-write-and-bun-file-text-gets-3x-faster-under-concurrent-load)
Along the way, we improved the performance of reading and writing files concurrently using Bun.file() and Bun.write().
Reading:
```
❯ N=100 hyperfine "bun ./read.js" "bun-1.0.15 read.js" --warmup=20
Benchmark 1: bun ./read.js
Time (mean ± σ): 40.9 ms ± 2.9 ms [User: 27.6 ms, System: 181.7 ms]
Range (min … max): 37.1 ms … 48.3 ms 73 runs
Benchmark 2: bun-1.0.15 read.js
Time (mean ± σ): 134.5 ms ± 19.0 ms [User: 24.8 ms, System: 82.5 ms]
Range (min … max): 98.8 ms … 161.2 ms 23 runs
Summary
bun ./read.js ran
3.29 ± 0.52 times faster than bun-1.0.15 read.js
```
Writing:
```
❯ N=100 hyperfine "bun ./write.js" "bun-1.0.15 write.js" --warmup=20
Benchmark 1: bun ./write.js
Time (mean ± σ): 35.0 ms ± 8.0 ms [User: 13.0 ms, System: 364.6 ms]
Range (min … max): 25.7 ms … 71.5 ms 83 runs
Benchmark 2: bun-1.0.15 write.js
Time (mean ± σ): 134.7 ms ± 13.6 ms [User: 23.6 ms, System: 193.3 ms]
Range (min … max): 117.8 ms … 171.2 ms 23 runs
Summary
bun ./write.js ran
3.85 ± 0.96 times faster than bun-1.0.15 write.js
```
read.js:
```
const promises = new Array(parseInt(process.env.N || "20"));
for (let i = 0; i < promises.length; i++) {
promises[i] = Bun.file("out.log." + i).text();
}
await Promise.all(promises);
```
write.js:
```
const toPipe = new Blob(["abc".repeat(1_000_000)]);
const promises = new Array(parseInt(process.env.N || "20"));
for (let i = 0; i < promises.length; i++) {
promises[i] = Bun.write("out.log." + i, toPipe);
}
await Promise.all(promises);
```
### []()[Fixed: Bun.stdin.text() incomplete reads](bun-v1.0.16.html#fixed-bun-stdin-text-incomplete-reads)
Previously, `Bun.stdin.text()` would sometimes not return all of the data from stdin.
```
import { stdin } from "bun";
console.log(await stdin.text());
```
```
$ echo "Hello, world!" | bun script.ts
```
Previously, sometimes it would print nothing:
```
```
Now, it prints the full input:
```
Hello, world!
```
## []()[`napi_create_object` gets 2.5x faster](bun-v1.0.16.html#napi-create-object-gets-2-5x-faster)
> in the next version of Bun
>
> napi\_create\_object gets 2.5x faster [pic.twitter.com/lXyj6koceT](https://t.co/lXyj6koceT)
>
> — Jarred Sumner (@jarredsumner) [December 5, 2023](https://twitter.com/jarredsumner/status/1731836157606940851?ref_src=twsrc%5Etfw)
## []()[`expect` and `expect.extend` in `--preload`](bun-v1.0.16.html#expect-and-expect-extend-in-preload)
Previously, `expect` was scoped to the indivdual test file, which would break `expect.extend` if it was called in a shared file. This is now fixed, and you can now use a shared file containing your custom matchers such as.
custom-matchers.ts
```
import { expect } from "bun:test";
// Based off of from Jest's example documentation
// https://jestjs.io/docs/expect#expectextendmatchers
function toBeWithinRange(actual, floor, ceiling) {
const pass = actual >= floor && actual <= ceiling;
return {
pass,
message: () =>
"expected " +
this.utils.printReceived(actual) +
" to " +
(pass ? "not " : "") +
"be within range " +
this.utils.printExpected(`${floor} - ${ceiling}`),
};
}
expect.extend({
toBeWithinRange,
});
```
Then configure `bunfig.toml` to load them during testing,
bunfig.toml
```
test.preload = "./custom-matchers.ts"
```
and run `bun test`:
example.test.ts
```
import { expect, test } from "bun:test";
test("example", () => {
expect(1234).toBeWithinRange(1000, 2000);
});
```
```
example.test.ts:
-TypeError: expect.extend is not a function. (In 'expect.extend({
- toBeWithinRange
-})', 'expect.extend' is undefined)
- at /custom-matchers.ts:21:1
+✓ example [1.31ms]
```
You can also use `expect()` outside of `test` callbacks.
```
-error: This function can only be used in a test.
- at /custom-matchers.ts:21:1
```
## []()[Fixed: module resolution bug with `"imports"` in `package.json`](bun-v1.0.16.html#fixed-module-resolution-bug-with-imports-in-package-json)
Packages can declare a list of internal-only imports in their `package.json` file, which Bun will use to resolve imports. This is useful for avoiding exposing internal files to users.
```
{
"name": "my-package",
"imports": {
"my-package": "./dist/index.js"
}
}
```
These imports are prefixed with `#`.
```
import { foo } from "#my-package";
```
This can also be used to rewrite imports from other packages. For example, if you wanted to rewrite all imports from `async-hooks` to `#async-hooks`, you could do:
```
{
"name": "my-package",
"imports": {
"async-hooks": "async-hooks"
}
}
```
Then, it will load the `async-hooks` package:
```
import { foo } from "#async-hooks";
```
Except, there was a bug that caused aliasing packages this way to not work in Bun. This has been fixed.
Notable packages this bug impacted:
- **Astro v4**
- **`p-limit`**
## []()[Fixed: holey arrays appearing as undefined in console.log](bun-v1.0.16.html#fixed-holey-arrays-appearing-as-undefined-in-console-log)
Previously, holey arrays would appear as `undefined` in `console.log`. This has been fixed.
```
console.log([1, , 3]);
```
Now:
```
[ 1, empty item, 3 ]
```
Previously:
```
[1, undefined, 3];
```
## []()[Fixed: file: URLs in createRequire() that contain spaces](bun-v1.0.16.html#fixed-file-urls-in-createrequire-that-contain-spaces)
Previously, `createRequire()` would throw an error when passed a `file:` URL which contained an unescaped space. This has been fixed.
```
import { createRequire } from "node:module";
const require = createRequire(import.meta.url);
require("file:///Users/jarred/My%20Folder/script.js");
```
Thanks to [@paperclover](https://github.com/paperclover) for fixing this.
## []()[Fixed: console.log was omiting the `length` property sometimes](bun-v1.0.16.html#fixed-console-log-was-omiting-the-length-property-sometimes)
Sometimes, `console.log` would omit the `length` property of an object. This has been fixed.
```
console.log({ length: 1, a: 1 });
```
Previously, it would print:
```
{
a: 1
}
```
Now, it prints:
```
{
length: 1,
a: 1,
}
```
## []()[Fixed: transpiler inconsistentcy with jsx key after spread](bun-v1.0.16.html#fixed-transpiler-inconsistentcy-with-jsx-key-after-spread)
The following input would behave differently in Bun versus in TypeScript:
```
const obj = {};
console.log(<div {...obj} key="after" />, <div key="before" {...obj} />);
```
This has been fixed, thanks to [@rhyzx](https://github.com/rhyzx).
## []()[Fixed: `console.log("%d", value)` bug](bun-v1.0.16.html#fixed-console-log-d-value-bug)
A bug causing `%d` to not handle non-numeric values correctly has been fixed.
```
console.log("%d", "1");
```
Previously, it would print:
```
0
```
Now, it prints:
```
1
```
## []()[Fixed: Syntax highlighter template string handling](bun-v1.0.16.html#fixed-syntax-highlighter-template-string-handling)
In the previous version of Bun, we added syntax-highlighting to the code shown in error messages, but it has a bug that caused some template strings to crash the highlighter. This has been fixed.
## []()[Fixed: jest.fn(jest.fn()) crash](bun-v1.0.16.html#fixed-jest-fn-jest-fn-crash)
A crash when calling `jest.fn(jest.fn(() => {}))` has been fixed, thanks to [@Hanassagi](https://github.com/Hanassagi).
## []()[Thanks to 16 contributors!](bun-v1.0.16.html#thanks-to-16-contributors)
We're always excited to welcome new contributors to Bun. 6 new contributors made their first contribution in this release.
- [@mkayander](https://github.com/@mkayander) made their first contribution in [#7453](https://github.com/oven-sh/bun/pull/7453)
- [@asilvas](https://github.com/@asilvas) made their first contribution in [#7446](https://github.com/oven-sh/bun/pull/7446)
- [@annervisser](https://github.com/@annervisser) made their first contribution in [#7289](https://github.com/oven-sh/bun/pull/7289)
- [@sstephant](https://github.com/@sstephant) made their first contribution in [#7477](https://github.com/oven-sh/bun/pull/7477)
- [@DaleSeo](https://github.com/@DaleSeo) made their first contribution in [#7532](https://github.com/oven-sh/bun/pull/7532)
- [@bradymadden97](https://github.com/@bradymadden97) made their first contribution in [#7529](https://github.com/oven-sh/bun/pull/7529)
- [@dfaio](https://github.com/@dfaio) made their first contribution in [#7542](https://github.com/oven-sh/bun/pull/7542)
Thanks to the 16 contributors who made this release possible:
- [@annervisser](https://github.com/annervisser)
- [@asilvas](https://github.com/asilvas)
- [@bradymadden97](https://github.com/bradymadden97)
- [@DaleSeo](https://github.com/DaleSeo)
- [@dfaio](https://github.com/dfaio)
- [@dylan-conway](https://github.com/dylan)
- [@Hanaasagi](https://github.com/Hanaasagi)
- [@ImBIOS](https://github.com/ImBIOS)
- [@Jarred-Sumner](https://github.com/Jarred)
- [@jerome-benoit](https://github.com/jerome)
- [@mkayander](https://github.com/mkayander)
- [@otgerrogla](https://github.com/otgerrogla)
- [@paperclover](https://github.com/paperclover)
- [@rhyzx](https://github.com/rhyzx)
- [@RiskyMH](https://github.com/RiskyMH)
- [@sirenkovladd](https://github.com/sirenkovladd)
- [@sstephant](https://github.com/sstephant)
* * *
#### [Bun v1.0.15](bun-v1.0.15.html)
#### [Bun v1.0.17](bun-v1.0.17.html)
On this page
- [`Bun.write` now creates the parent directory if it doesn't exist](bun-v1.0.16.html#bun-write-now-creates-the-parent-directory-if-it-doesn-t-exist)
- [To throw an error when the parent directory doesn't exist: `createPath: false`](bun-v1.0.16.html#to-throw-an-error-when-the-parent-directory-doesn-t-exist-createpath-false)
- [Rewritten IO for `Bun.file`](bun-v1.0.16.html#rewritten-io-for-bun-file)
- [Bun.write() and Bun.file().text() gets 3x faster under concurrent load](bun-v1.0.16.html#bun-write-and-bun-file-text-gets-3x-faster-under-concurrent-load)
- [Fixed: Bun.stdin.text() incomplete reads](bun-v1.0.16.html#fixed-bun-stdin-text-incomplete-reads)
- [`napi_create_object` gets 2.5x faster](bun-v1.0.16.html#napi-create-object-gets-2-5x-faster)
- [`expect` and `expect.extend` in `--preload`](bun-v1.0.16.html#expect-and-expect-extend-in-preload)
- [Fixed: module resolution bug with `"imports"` in `package.json`](bun-v1.0.16.html#fixed-module-resolution-bug-with-imports-in-package-json)
- [Fixed: holey arrays appearing as undefined in console.log](bun-v1.0.16.html#fixed-holey-arrays-appearing-as-undefined-in-console-log)
- [Fixed: file: URLs in createRequire() that contain spaces](bun-v1.0.16.html#fixed-file-urls-in-createrequire-that-contain-spaces)
- [Fixed: console.log was omiting the `length` property sometimes](bun-v1.0.16.html#fixed-console-log-was-omiting-the-length-property-sometimes)
- [Fixed: transpiler inconsistentcy with jsx key after spread](bun-v1.0.16.html#fixed-transpiler-inconsistentcy-with-jsx-key-after-spread)
- [Fixed: `console.log("%d", value)` bug](bun-v1.0.16.html#fixed-console-log-d-value-bug)
- [Fixed: Syntax highlighter template string handling](bun-v1.0.16.html#fixed-syntax-highlighter-template-string-handling)
- [Fixed: jest.fn(jest.fn()) crash](bun-v1.0.16.html#fixed-jest-fn-jest-fn-crash)
- [Thanks to 16 contributors!](bun-v1.0.16.html#thanks-to-16-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.17.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.17
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · December 12, 2023
[](../rss.xml)
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
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun:
- [`v1.0.13`](bun-v1.0.13.html) - Fixes 6 bugs (addressing 317 👍 reactions). 'http2' module & gRPC.js work now. Vite 5 & Rollup 4 work. Implements process.report.getReport(), improves support for ES5 'with' statements, fixes a regression in bun install, fixes a crash when printing exceptions, fixes a Bun.spawn bug, and fixes a peer dependencies bug
- [`v1.0.14`](bun-v1.0.14.html) - `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`](bun-v1.0.15.html) - 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`](bun-v1.0.16.html) - 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
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 install now runs lifecycle scripts for the top 500 npm packages](bun-v1.0.17.html#bun-install-now-runs-lifecycle-scripts-for-the-top-500-npm-packages)
In this release, we've added the top 500 most-downloaded npm packages in [a default allowlist](https://github.com/oven-sh/bun/blob/bun-v1.0.17/src/install/default-trusted-dependencies.txt#L1-L500) to run lifecycle scripts during `bun install`. This means that `bun install` will now run `preinstall`, `install`, and `postinstall` scripts for the top 500 npm packages which have them defined.
This addresses *many* issues with `bun install`:
[](https://github.com/oven-sh/bun/assets/709451/b66c452b-002e-4250-9ad4-f8b8c82e533f)
Thanks to [@dylan-conway](https://github.com/dylan-conway) and @paperclover for implementing this.
### []()[Lifecycle scripts now run in parallel](bun-v1.0.17.html#lifecycle-scripts-now-run-in-parallel)
As part of the above work, we also made lifecycle scripts run in parallel, which reduces the impact of lifecycle scripts on installation time.
[](https://github.com/oven-sh/bun/assets/709451/4ad72f2f-6152-4e4e-b1d1-d832cefdd8f8)
⚙️ emoji appears when the lifecycle script is running
#### Configuring concurency
You can configure the maximum number of concurrent lifecycle scripts that run at once either by
`bunfig.toml`:
```
# Only run 5 in parallel at max
install.concurrentScripts = 5
```
CLI argument:
```
bun install --concurrent-scripts=5
```
Environment variable:
```
GOMAXPROCS=2 bun install
```
Note: it is `$GOMAXPROCS` because we use that elsewhere and it's one less environment variable for us to make up a name for (it's what Go uses, but Bun doesn't use Go).
## []()[Error message improvement in bun install](bun-v1.0.17.html#error-message-improvement-in-bun-install)
When a permissions error occurs, bun install now shows a more helpful error message. Instead of just "Unexpected", it now provides more information when it can.
[](https://github.com/oven-sh/bun/assets/24465214/26e2f264-d468-4785-a48b-1be84188e4bd)
Left: before, Right: after
Thanks to [@paperclover](https://github.com/paperclover) for implementing this.
### []()[Fixed: Semver pre-release sorting bug](bun-v1.0.17.html#fixed-semver-pre-release-sorting-bug)
A crash that could occur when sorting many pre-release versions of specific input simultaneously has been fixed. This bug was fixed by [@dylan-conway](https://github.com/dylan-conway). This bug could be reproduced when installing 4 year old versions of Gatsby.
### []()[Fixed: lifecycle script dependency install order](bun-v1.0.17.html#fixed-lifecycle-script-dependency-install-order)
A bug where `bun install` would install lifecycle scripts without first ensuring all dependent lifecycle scripts were installed has been fixed. This bug was fixed by [@dylan-conway](https://github.com/dylan-conway).
## []()[`bunx supabase` starts 30x faster than `npx supabase`](bun-v1.0.17.html#bunx-supabase-starts-30x-faster-than-npx-supabase)
Since `bun install` now enables lifecycle scripts for popular packages by default, `bunx supabase` now works.
On Linux x64, `bun x supabase` starts 30x faster than `npx supabase`:
```
Benchmark 1: bun x supabase
Time (mean ± σ): 10.5 ms ± 1.0 ms [User: 8.0 ms, System: 5.5 ms]
Range (min … max): 8.5 ms … 13.1 ms 248 runs
Benchmark 2: npx supabase
Time (mean ± σ): 325.2 ms ± 30.6 ms [User: 272.6 ms, System: 117.9 ms]
Range (min … max): 291.0 ms … 389.9 ms 10 runs
Summary
bun x supabase ran
30.90 ± 4.17 times faster than npx supabase
```
## []()[`bunx esbuild` starts 50x faster than `npx esbuild`](bun-v1.0.17.html#bunx-esbuild-starts-50x-faster-than-npx-esbuild)
Now that `bun install` enables lifecycle scripts for popular packages by default, `bunx esbuild` now starts roughly 50x faster than `npx esbuild`:
```
Benchmark 1: bun x esbuild --help
Time (mean ± σ): 3.5 ms ± 0.3 ms [User: 1.8 ms, System: 1.6 ms]
Range (min … max): 2.8 ms … 4.3 ms 827 runs
Benchmark 2: npx esbuild --help
Time (mean ± σ): 295.7 ms ± 23.8 ms [User: 270.0 ms, System: 100.6 ms]
Range (min … max): 259.6 ms … 339.6 ms 10 runs
Summary
bun x esbuild --help ran
83.84 ± 9.31 times faster than npx esbuild --help
```
## []()[`-h` is now an alias of `--help`](bun-v1.0.17.html#h-is-now-an-alias-of-help)
`-h` is now an alias of `--help` for all commands. Thanks to [@hustLer2k](https://github.com/hustLer2k) for implementing this.
```
$ bun -h
Bun is a fast JavaScript runtime, package manager, bundler, and test runner. (1.0.16 (a2f595d3))
Usage: bun <command> [...flags] [...args]
Commands:
run ./my-script.ts Execute a file with Bun
lint Run a package.json script
test Run unit tests with Bun
x vite Execute a package binary (CLI), installing if needed (bunx)
repl Start a REPL session with Bun
install Install dependencies for a package.json (bun i)
add svelte Add a dependency to package.json (bun a)
remove babel-core Remove a dependency from package.json (bun rm)
update lodash Update outdated dependencies
link [<package>] Register or link a local npm package
unlink Unregister a local npm package
pm <subcommand> Additional package management utilities
build ./a.ts ./b.jsx Bundle TypeScript & JavaScript into a single file
init Start an empty Bun project from a blank template
create Create a new project from a template (bun c)
upgrade Upgrade to latest version of Bun.
<command> --help Print help text for command.
Flags:
--watch Automatically restart the process on file change
--hot Enable auto reload in the Bun runtime, test runner, or bundler
--smol Use less memory, but run garbage collection more often
-r, --preload Import a module before other modules are loaded
--inspect Activate Bun's debugger
--inspect-wait Activate Bun's debugger, wait for a connection before executing
--inspect-brk Activate Bun's debugger, set breakpoint on first line of code and wait
--if-present Exit without an error if the entrypoint does not exist
--no-install Disable auto install in the Bun runtime
--install Configure auto-install behavior. One of "auto" (default, auto-installs when no node_modules), "fallback" (missing packages only), "force" (always).
-i Auto-install dependencies during execution. Equivalent to --install=fallback.
-e, --eval Evaluate argument as a script
--prefer-offline Skip staleness checks for packages in the Bun runtime and resolve from disk
--prefer-latest Use the latest matching versions of packages in the Bun runtime, always checking npm
-p, --port Set the default port for Bun.serve
-b, --bun Force a script or package to use Bun's runtime instead of Node.js (via symlinking node)
--silent Don't print the script command
-v, --version Print version and exit
--revision Print version with revision and exit
--env-file Load environment variables from the specified file(s)
--cwd Absolute path to resolve files & entry points from. This just changes the process' cwd.
-c, --config Specify path to Bun config file. Default $cwd/bunfig.toml
-h, --help Display this menu and exit
(more flags in bun install --help, bun test --help, and bun build --help)
Learn more about Bun: https://bun.sh/docs
Join our Discord community: https://bun.sh/discord
```
## []()[Fixed: encoding argument in fs.createReadStream](bun-v1.0.17.html#fixed-encoding-argument-in-fs-createreadstream)
A bug where the `encoding` argument in `fs.createReadStream` was not handled correctly has been fixed. This bug was fixed by [@hustLer2k](https://github.com/hustLer2k).
## []()[Thanks to 6 contributors!](bun-v1.0.17.html#thanks-to-6-contributors)
- [@DaleSeo](https://github.com/DaleSeo)
- [@dylan-conway](https://github.com/dylan-conway)
- [@hustLer2k](https://github.com/hustLer2k)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@NReilingh](https://github.com/NReilingh)
- [@paperclover](https://github.com/paperclover)
* * *
#### [Bun v1.0.16](bun-v1.0.16.html)
#### [Bun v1.0.18](bun-v1.0.18.html)
On this page
- [bun install now runs lifecycle scripts for the top 500 npm packages](bun-v1.0.17.html#bun-install-now-runs-lifecycle-scripts-for-the-top-500-npm-packages)
- [Lifecycle scripts now run in parallel](bun-v1.0.17.html#lifecycle-scripts-now-run-in-parallel)
- [Error message improvement in bun install](bun-v1.0.17.html#error-message-improvement-in-bun-install)
- [Fixed: Semver pre-release sorting bug](bun-v1.0.17.html#fixed-semver-pre-release-sorting-bug)
- [Fixed: lifecycle script dependency install order](bun-v1.0.17.html#fixed-lifecycle-script-dependency-install-order)
- [`bunx supabase` starts 30x faster than `npx supabase`](bun-v1.0.17.html#bunx-supabase-starts-30x-faster-than-npx-supabase)
- [`bunx esbuild` starts 50x faster than `npx esbuild`](bun-v1.0.17.html#bunx-esbuild-starts-50x-faster-than-npx-esbuild)
- [`-h` is now an alias of `--help`](bun-v1.0.17.html#h-is-now-an-alias-of-help)
- [Fixed: encoding argument in fs.createReadStream](bun-v1.0.17.html#fixed-encoding-argument-in-fs-createreadstream)
- [Thanks to 6 contributors!](bun-v1.0.17.html#thanks-to-6-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.18.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.18
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · December 14, 2023
[](../rss.xml)
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 bugfixes.
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun:
- [`v1.0.13`](bun-v1.0.13.html) - Fixes 6 bugs (addressing 317 👍 reactions). 'http2' module & gRPC.js work now. Vite 5 & Rollup 4 work. Implements process.report.getReport(), improves support for ES5 'with' statements, fixes a regression in bun install, fixes a crash when printing exceptions, fixes a Bun.spawn bug, and fixes a peer dependencies bug
- [`v1.0.14`](bun-v1.0.14.html) - `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`](bun-v1.0.15.html) - 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`](bun-v1.0.16.html) - 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`](bun-v1.0.17.html) - 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
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
```
## []()[Fixed: Hang when reading from `process.stdin`](bun-v1.0.18.html#fixed-hang-when-reading-from-process-stdin)
A bug where `Bun.stdin.stream()` or `process.stdin` would sometimes hang after the first read has been fixed, thanks to [@paperclover](https://github.com/paperclover).
This bug impacted many packages, including `create-vite` and `create-next-app`. While it prompts for user input, the terminal would freeze at the second prompt.
[](https://github.com/oven-sh/bun/assets/709451/b8d855f5-765f-4faa-96b4-b1aa25771990)
Where bun would get stuck
This was caused by two bugs related to our implementation of `process.stdin`, which is built on top of [`Bun.stdin.stream()`](../guides/process/stdin.html):
1. We previously called `cancel` on the `ReadableStream` input, closing the stream and preventing the ability to recieve new data. The fix is to use [`releaseLock`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStreamDefaultReader/releaseLock) instead.
2. A bug where after calling `releaseLock`, Bun would think the stream is still "in use", which would keep the process alive forever.
This has been fixed, thanks to [@paperclover](https://github.com/paperclover).
## []()[Fixed: Lifecycle scripts running in the wrong working directory](bun-v1.0.18.html#fixed-lifecycle-scripts-running-in-the-wrong-working-directory)
A bug where lifecycle scripts would sometimes run in the wrong working directory has been fixed. This bug was fixed by [@dylan-conway](https://github.com/dylan-conway).
## []()[Fixed: Lifecycle scripts reporting command not found "node" or "node-gyp"](bun-v1.0.18.html#fixed-lifecycle-scripts-reporting-command-not-found-node-or-node-gyp)
Yesterday in Bun v1.0.17, we enabled lifecycle scripts for the top 500 packages on npm. While we did plenty of testing ourselves, we missed a few cases that were reported by users.
For example, what happens if `node-gyp` was not installed?
```
bun install
```
```
node-gyp rebuild
```
```
Command not found: node-gyp
```
That's no good. We've fixed this. Now, Bun will symlink `node-gyp` into running `bunx node-gyp` if `node-gyp` is not installed (which will lazily auto-install node-gyp).
Or what if a lifecycle script you're using depends on `node`, but you're running in Docker and the container does not have `node` installed?
```
bun install
```
```
node install.js
```
```
Command not found: node
```
That's not good either. Now Bun will symlink `node` into running `bun` if `node` is not installed.
These have been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
## []()[Symlinking `node` to `bun` works better](bun-v1.0.18.html#symlinking-node-to-bun-works-better)
Bun will automatically symlink `node` to `bun` when it is not available to ensure scripts that expect `node` to exist still work. However, Bun's CLI is very different from Node's, so when running a command like `node build` or `node install`, it is expected to find a file like `build.js`, not invoke a bundler or package manager.
Previously:
```
ln -s $(which bun) node && chmod +x node
```
```
./node build
```
```
bun build v1.0.18 (a648ed9e)
error: Missing entrypoints. What would you like to bundle?
Usage:
$ bun build <entrypoint> [...<entrypoints>] [...flags]
To see full documentation:
$ bun build --help
```
Now:
```
./node build
```
```
Hello! (Bun 1.0.18)
```
build.js
```
const isBun = typeof Bun !== 'undefined';
const name = isBun ? "Bun" : "Node";
const version = isBun ? Bun.version : process.version;
console.log(`Hello! (${name} ${version})`)
```
Thanks to [@paperclover](https://github.com/paperclover).
## []()[Reflinks on Linux](bun-v1.0.18.html#reflinks-on-linux)
Reflinks are copy-on-write copies of files. They make it faster to copy files. macOS has supported reflinks since APFS was released in 2017. Linux has supported reflinks with brtfs and more recently more filesystems have added support for reflinks.
Bun already used `copy_file_range` on Linux to make copying files faster, but some hypervisors (like gVisor) disable this system call. Now Bun will try to use `ioctl_ficlone`, which is a lower-level system call that internally does something very similar to `copy_file_range`. `ioctl_ficlone` is overall less well-supported than `copy_file_range`, but it's a useful fallback when `copy_file_range` is unavailable.
When `copy_file_range` is disabled but `ioctl_ficlone` is available, you will notice a speed improvement to:
- `bun install`
- `fs.copyFile`, `fs.copyFileSync`
- `fs.cp`, `fs.cpSync`
To force the usage of `ioctl_ficlone`, you can pass `constants.COPYFILE_FICLONE_FORCE` as the `flags` argument to `fs.copyFile` or `fs.cp`:
```
import { copyFileSync, constants } from "fs";
copyFileSync("src/index.js", "dest/index.js", constants.COPYFILE_FICLONE_FORCE);
```
This will throw an error if `ioctl_ficlone` is not available.
## []()[Fixed: Wildcard tsconfig path not including suffix](bun-v1.0.18.html#fixed-wildcard-tsconfig-path-not-including-suffix)
A bug where wildcard `tsconfig.json` `paths` would fail to resolve due to the suffix not being added has been fixed
```
error: Cannot find module "@faasjs/bar" from ".../test/js/bun/resolve/resolve-test.js"
```
Thanks to [@james-elicx](https://github.com/james-elicx) for fixing this.
## []()[Fixed: `expect().rejects.toThrow` works more like Jest](bun-v1.0.18.html#fixed-expect-rejects-tothrow-works-more-like-jest)
In Jest, `expect().toThrow` requires you pass a function to call. With `expect().rejects.toThrow`, they let you simply pass in the rejecting promise. Bun did not support this case.
The following test now passes in `bun:test`:
rejects-toThrow.test.js
```
test("rejects to octopus", async () => {
const rejection = Promise.reject(new Error("octopus"));
await expect(rejection).rejects.toThrow("octopus");
});
```
Thanks to [@paperclover](https://github.com/paperclover) for fixing this.
## []()[Thanks to 10 contributors!](bun-v1.0.18.html#thanks-to-10-contributors)
- [@ashoener](https://github.com/ashoener)
- [@baboon-king](https://github.com/baboon-king)
- [@chocolateboy](https://github.com/chocolateboy)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Hanaasagi](https://github.com/Hanaasagi)
- [@ImBIOS](https://github.com/ImBIOS)
- [@james-elicx](https://github.com/james-elicx)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@pacexy](https://github.com/pacexy)
- [@paperclover](https://github.com/paperclover)
* * *
#### [Bun v1.0.17](bun-v1.0.17.html)
#### [Bun v1.0.19](bun-v1.0.19.html)
On this page
- [Fixed: Hang when reading from `process.stdin`](bun-v1.0.18.html#fixed-hang-when-reading-from-process-stdin)
- [Fixed: Lifecycle scripts running in the wrong working directory](bun-v1.0.18.html#fixed-lifecycle-scripts-running-in-the-wrong-working-directory)
- [Fixed: Lifecycle scripts reporting command not found "node" or "node-gyp"](bun-v1.0.18.html#fixed-lifecycle-scripts-reporting-command-not-found-node-or-node-gyp)
- [Symlinking `node` to `bun` works better](bun-v1.0.18.html#symlinking-node-to-bun-works-better)
- [Reflinks on Linux](bun-v1.0.18.html#reflinks-on-linux)
- [Fixed: Wildcard tsconfig path not including suffix](bun-v1.0.18.html#fixed-wildcard-tsconfig-path-not-including-suffix)
- [Fixed: `expect().rejects.toThrow` works more like Jest](bun-v1.0.18.html#fixed-expect-rejects-tothrow-works-more-like-jest)
- [Thanks to 10 contributors!](bun-v1.0.18.html#thanks-to-10-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.19.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.19
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · December 22, 2023
[](../rss.xml)
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 — all in one. In case you missed it, here are some of the recent changes to Bun:
- [`v1.0.14`](bun-v1.0.14.html) - `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`](bun-v1.0.15.html) - 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`](bun-v1.0.16.html) - 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`](bun-v1.0.17.html) - 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`](bun-v1.0.18.html) - 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:
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
```
## []()[Re-introducing `@types/bun` (formerly `bun-types`)](bun-v1.0.19.html#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`:
```
bun add -d @types/bun
```
Or you can ue `bun init`:
```
bun init
```
## []()[bcrypt & argon2 packages now work](bun-v1.0.19.html#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.
[Bun.password](../docs/api/hashing.html#bun-password) also lets you hash and verify passwords using either bcrypt or argon2 without any dependencies to install.
> in the next version of bun
>
> the "bcrypt" npm package works [pic.twitter.com/IwDSTvKHA0](https://t.co/IwDSTvKHA0)
>
> — Jarred Sumner (@jarredsumner) [December 21, 2023](https://twitter.com/jarredsumner/status/1737799500029431863?ref_src=twsrc%5Etfw)
> In the next version of Bun
>
> the "node-argon2" package works [pic.twitter.com/gYxkXUgWBP](https://t.co/gYxkXUgWBP)
>
> — Jarred Sumner (@jarredsumner) [December 21, 2023](https://twitter.com/jarredsumner/status/1737782581259833532?ref_src=twsrc%5Etfw)
## []()[Fixed: "lockfile had changes, but is frozen" bug](bun-v1.0.19.html#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:
```
bun pm hash-string
```
View example output
```
-- 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--
```
## []()[`setTimeout` & `setInterval` get 4x higher throughput](bun-v1.0.19.html#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.
```
❯ 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?](bun-v1.0.19.html#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`](bun-v1.0.19.html#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](bun-v1.0.19.html#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.
```
❯ 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:
```
❯ 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](bun-v1.0.19.html#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.
[](https://github.com/oven-sh/bun/assets/709451/49a7167a-a31d-444b-ab00-1c209ddf4ed0)
## []()[`Bun.peek()` gets 90x faster](bun-v1.0.19.html#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](bun-v1.0.19.html#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-v1.0.19.html#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).
```
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](bun-v1.0.19.html#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.
```
bun add v1.0.19 (7e59f287)
installed re2@1.20.9
+warn: re2's install script took 57.7s
92 packages installed [58.20s]
```
This is now fixed. Thanks to [@paperclover](https://github.com/paperclover) for fixing this.
## []()[Fixed: crash in `bun init`](bun-v1.0.19.html#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`](bun-v1.0.19.html#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](bun-v1.0.19.html#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:
```
❯ bun -e 'console.log([1,,,2,1,3])' # After
[ 1, 2 x empty items, 2, 1, 3 ]
```
Before:
```
❯ 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()`](bun-v1.0.19.html#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 `===`.
```
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](bun-v1.0.19.html#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](bun-v1.0.19.html#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)
* * *
#### [Bun v1.0.18](bun-v1.0.18.html)
#### [Bun v1.0.20](bun-v1.0.20.html)
On this page
- [Re-introducing `@types/bun` (formerly `bun-types`)](bun-v1.0.19.html#re-introducing-types-bun-formerly-bun-types)
- [bcrypt & argon2 packages now work](bun-v1.0.19.html#bcrypt-argon2-packages-now-work)
- [Fixed: "lockfile had changes, but is frozen" bug](bun-v1.0.19.html#fixed-lockfile-had-changes-but-is-frozen-bug)
- [`setTimeout` & `setInterval` get 4x higher throughput](bun-v1.0.19.html#settimeout-setinterval-get-4x-higher-throughput)
- [Why is timer performance important?](bun-v1.0.19.html#why-is-timer-performance-important)
- [Fixed: `setInterval` sometimes still ran after `clearInterval`](bun-v1.0.19.html#fixed-setinterval-sometimes-still-ran-after-clearinterval)
- [Better error for using `await` outside an `async` function](bun-v1.0.19.html#better-error-for-using-await-outside-an-async-function)
- [Optimized `Bun.spawnSync` for large input on Linux](bun-v1.0.19.html#optimized-bun-spawnsync-for-large-input-on-linux)
- [`Bun.peek()` gets 90x faster](bun-v1.0.19.html#bun-peek-gets-90x-faster)
- [expect(map1).toEqual(map2) gets 100x faster](bun-v1.0.19.html#expect-map1-toequal-map2-gets-100x-faster)
- [module mocks in `bun:test` resolve specifiers](bun-v1.0.19.html#module-mocks-in-bun-test-resolve-specifiers)
- [Log slow postinstall scripts](bun-v1.0.19.html#log-slow-postinstall-scripts)
- [Fixed: potential hang when running post-install scripts](bun-v1.0.19.html#fixed-potential-hang-when-running-post-install-scripts)
- [`bun install --verbose` now streams post-install script output](bun-v1.0.19.html#bun-install-verbose-now-streams-post-install-script-output)
- [Fixed: missing progress bar in post-install script output](bun-v1.0.19.html#fixed-missing-progress-bar-in-post-install-script-output)
- [Fixed: stringifying SHA1, SHA256, MD5 hashes sometimes output too long of a string](bun-v1.0.19.html#fixed-stringifying-sha1-sha256-md5-hashes-sometimes-output-too-long-of-a-string)
- [Upgraded SQLite from v3.38.5 to v3.44.2](bun-v1.0.19.html#upgraded-sqlite-from-v3-38-5-to-v3-44-2)
- [Fixed: TypeScript parser edgecase](bun-v1.0.19.html#fixed-typescript-parser-edgecase)
- [Fixed: crash in `bun init`](bun-v1.0.19.html#fixed-crash-in-bun-init)
- [Fixed: regression with `$NODE_ENV`](bun-v1.0.19.html#fixed-regression-with-node-env)
- [Fixed: printing bug with holey arrays](bun-v1.0.19.html#fixed-printing-bug-with-holey-arrays)
- [New matcher in bun:test `expect().toContainEqual()`](bun-v1.0.19.html#new-matcher-in-bun-test-expect-tocontainequal)
- [Credits](bun-v1.0.19.html#credits)
- [Thanks to 18 contributors for making Bun v1.0.19 possible](bun-v1.0.19.html#thanks-to-18-contributors-for-making-bun-v1-0-19-possible)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.2.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.2
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · September 15, 2023
[](../rss.xml)
Bun v1.0.2 fixes numerous bugs and makes `bun --watch` faster.
Thank you for reporting issues. We are working hard to fix them as quickly as possible.
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. We've been releasing a lot of changes to Bun recently. Here's a recap of the last few releases. In case you missed it:
- [`v1.0.0`](../1.0.html) - Bun's first stable release!
- [`v1.0.1`](bun-v1.0.1.html) - Named imports for .json & .toml files, bugfixes to bun install, node:path, Buffer
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
```
### []()[`bunx <package>@latest` always fetches the latest](bun-v1.0.2.html#bunx-package-latest-always-fetches-the-latest)
Previously, `bunx package@latest` would only fetch the latest version of the package if it had not been installed previously in the `/tmp` folder (which is cleared every 3 days or on restart, dpending on your OS).
Now, `bunx package@latest` will always fetch the latest version of the package. If there is an `@` tag and that tag is not a number, it will fetch the query the npm registry for the matching version of the package.
[#5346](https://github.com/oven-sh/bun/pull/5346)
### []()[Faster `bun --watch`](bun-v1.0.2.html#faster-bun-watch)
`bun --watch <./path-to-file.ts>` lets you watch a file and re-run it when it or any of its imports change. This is useful for development.
Previously, `bun --watch` would enqueue a task to the event loop on change to reload the process. That means any blocking or long-running tasks would delay the reload.
Now, it reloads immediately.

In this gif, the current timestamp in milliseconds is printed to the console on restart.
### []()[`bun run --silent` no longer prints error messages](bun-v1.0.2.html#bun-run-silent-no-longer-prints-error-messages)
When running:
```
bun run --silent bash -c 'exit 1'
```
Before:
```
error: "bash" exited with code 1
```
After:
```
# nothing!
```
### []()[Bun now uses V8's `Date` parser](bun-v1.0.2.html#bun-now-uses-v8-s-date-parser)
Bun now uses V8's Date parser. This means that date parsing behaves the same in Bun as it does in Chrome and Node.js.
Previously:
```
Date.parse("2020-09-21 15:19:06 +00:00"); // Invalid Date
```
After:
```
Date.parse("2020-09-21 15:19:06 +00:00"); // 1600701546000
```
This fixes a number of bugs where date parsing would fail in Bun but work in Node.js.
### []()[`URL.canParse` is implemented](bun-v1.0.2.html#url-canparse-is-implemented)
The `URL` class now has a static `canParse` method, which returns `true` if the URL can be parsed, and `false` otherwise.
```
URL.canParse("https://example.com"); // true
URL.canParse("https://example.com:8080"); // true
URL.canParse("apoksd!"); // false
```
[`URL.canParse`](https://developer.mozilla.org/en-US/docs/Web/API/URL/canParse_static) is a relatively new addition to the Web Platform. At the time of writing, it is not available in Chrome or Firefox yet.
### []()[`URLSearchParams.prototype.size` is implemented](bun-v1.0.2.html#urlsearchparams-prototype-size-is-implemented)
The `URLSearchParams` class now has a `size` property, which returns the number of key/value pairs in the search params.
```
const params = new URLSearchParams("a=1&b=2&c=3");
params.size; // 3
```
[`URLSearchParams.prototype.size`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/size) is a relatively new addition to the Web Platform.
### []()[Bugfix to `bun run`](bun-v1.0.2.html#bugfix-to-bun-run)
Previously, `bun run` would always load tsconfig.json files. This meant that having an invalid tsconfig.json file could cause `bun run` to fail, which was completely unnecessary. THis has been fixed.
### []()[Bugfix to `node:stream`](bun-v1.0.2.html#bugfix-to-node-stream)
When `encoding` was passed to the `write` function, the `callback` would not be called. This has been fixed.
[#75b5c715405d49b5026c13143efecd580d27be1b](https://github.com/oven-sh/bun/commit/75b5c715405d49b5026c13143efecd580d27be1b)
### []()[Bugfix to fetch with a `data:` URL](bun-v1.0.2.html#bugfix-to-fetch-with-a-data-url)
Previously, invalid `data:` URLs would throw an exception in `fetch`. This was inconsistent with Node.js which would leave the incorrect data in the URL. This has been fixed, thanks to [@davidmhewitt](https://github.com/davidmhewitt).
[#c3455c0ceee6bbe399781819a42fff6cf24792e2](https://github.com/oven-sh/bun/commit/c3455c0ceee6bbe399781819a42fff6cf24792e2)
### []()[Bugfix to `node:readline` (arrow keys)](bun-v1.0.2.html#bugfix-to-node-readline-arrow-keys)
A bug in `node:readline` causing the terminal to hang on WSL has been fixed.
[#5345](https://github.com/oven-sh/bun/issues/5435)
### []()[Bugfix to `node:dns`](bun-v1.0.2.html#bugfix-to-node-dns)
A crash in `node:dns`'s `resolve` function has been fixed, thanks to [@Hanaasagi](https://github.com/Hanaasagi).
[#5200](https://github.com/oven-sh/bun/pull/5200)
### []()[`os.availableParallelism` is implemented](bun-v1.0.2.html#os-availableparallelism-is-implemented)
The `node:os` module now has an [`availableParallelism`](https://nodejs.org/api/os.html#os_os_availableparallelism) property, which returns the number of logical CPUs available to the process.
```
os.availableParallelism(); // 8
```
You can also use `navigator.hardwareConcurrency`.
### []()[Bugfixes to `Bun.serve()`](bun-v1.0.2.html#bugfixes-to-bun-serve)
A crash that could occur when a ReadableStream has enqueued all data before the stream has begun being read has been fixed. This crash happened because the code was missing a check for whether or not a JavaScript function was a callable object.
[#5321](https://github.com/oven-sh/bun/issues/5321)
A crash that could occur when calling `req.formData()` has been fixed
[#4966](https://github.com/oven-sh/bun/issues/4966)
### []()[Fix `set-cookie`](bun-v1.0.2.html#fix-set-cookie)
A bug causing the `set-cookie` header to be set incorrectly in `node:http` in some cases has been fixed. This causes issues with Express.js.
[#5183](https://github.com/oven-sh/bun/issues/5183)
### []()[`node:fs` functions are now concurrent](bun-v1.0.2.html#node-fs-functions-are-now-concurrent)
Previously, only a handful of `node:fs` functions were concurrent. Now, all of them are.
### []()[Deletable `setTimeout` & other globals](bun-v1.0.2.html#deletable-settimeout-other-globals)
Most globals are now configurable/deletable, which fixes issues impacting some libraries and ExecJS.
### []()[Bugfix for fastify](bun-v1.0.2.html#bugfix-for-fastify)
Fastify loops over `require.cache` during initialization. `require.cache` previously included ES Modules which have not finished evaluating yet and that partially broke Fastify. This has been fixed.
### []()[Bugfix for multiline string in CRLF terminated files](bun-v1.0.2.html#bugfix-for-multiline-string-in-crlf-terminated-files)
Thanks to [@tikotzky](https://github.com/tikotzky) for the fix.
[#5318](https://github.com/oven-sh/bun/pull/5318)
### []()[Bugfix for `Bun.file()`](bun-v1.0.2.html#bugfix-for-bun-file)
When the length of the file was less than the size of the `Bun.file()`, the file would sometimes not finish reading. This has been fixed, thanks to [@cirospaciari](https://github.com/cirospaciari).
[#5186](https://github.com/oven-sh/bun/pull/5186)
### []()[Bugfix for `node:tty`](bun-v1.0.2.html#bugfix-for-node-tty)
A bug causing `WritableStream.prototype.getColorDepth` to sometimes throw an exception has been fixed.
[#5468](https://github.com/oven-sh/bun/pull/5468)
### []()[Transpiler bugfix for escaping non-ascii `RegExp` literals to latin1](bun-v1.0.2.html#transpiler-bugfix-for-escaping-non-ascii-regexp-literals-to-latin1)
[#5468](https://github.com/oven-sh/bun/pull/5468)
### []()[Internal changes](bun-v1.0.2.html#internal-changes)
We upgraded from LLVM 15->16 & Clang 15->16.
## []()[Full changelog](bun-v1.0.2.html#full-changelog)
[`#5161`](https://github.com/oven-sh/bun/pull/5161)fix(bun-lambda) Fix API Gateway V1 events and expand on Lambda documentation by [@mkossoris](https://github.com/mkossoris)[`#5159`](https://github.com/oven-sh/bun/pull/5159)fix lifecycle docu by [@ximex](https://github.com/ximex)[`#5151`](https://github.com/oven-sh/bun/pull/5151)docs: fix typos by [@s-rigaud](https://github.com/s-rigaud)[`#5127`](https://github.com/oven-sh/bun/pull/5127)Updated Lambda readme by [@tsndr](https://github.com/tsndr)[`#5072`](https://github.com/oven-sh/bun/pull/5072)Add missing full stop on nodejs-apis.md by [@diogo405](https://github.com/diogo405)[`#5069`](https://github.com/oven-sh/bun/pull/5069)update dev build instruction for arch by [@mi4uu](https://github.com/mi4uu)[`#5046`](https://github.com/oven-sh/bun/pull/5046)fix typo and grammar errors in bunfig.toml by [@xNaCly](https://github.com/xNaCly)[`#4997`](https://github.com/oven-sh/bun/pull/4997)Update simple.md by [@tomredman](https://github.com/tomredman)[`#4990`](https://github.com/oven-sh/bun/pull/4990)Update hot.md by [@nazeelashraf](https://github.com/nazeelashraf)[`#5146`](https://github.com/oven-sh/bun/pull/5146)docs: fix typo in import.meta.resolve by [@jonathantneal](https://github.com/jonathantneal)[`#5143`](https://github.com/oven-sh/bun/pull/5143)\[Docs] Use git's `--global` flag for lockfile diffs instead of manually editing config files. by [@Southpaw1496](https://github.com/Southpaw1496)[`#5201`](https://github.com/oven-sh/bun/pull/5201)Various docs by [@colinhacks](https://github.com/colinhacks)[`#5120`](https://github.com/oven-sh/bun/pull/5120)docs: Made bun-types install as dev dependency in example by [@MasterGordon](https://github.com/MasterGordon)[`#4841`](https://github.com/oven-sh/bun/pull/4841)js/node/stream.js: call write() callback when encoding is not provided by [@cfal](https://github.com/cfal)[`#5234`](https://github.com/oven-sh/bun/pull/5234)Correct the configuration file names. by [@nathanhammond](https://github.com/nathanhammond)[`#5167`](https://github.com/oven-sh/bun/pull/5167)decode regex if needed by [@dylan-conway](https://github.com/dylan-conway)[`#5227`](https://github.com/oven-sh/bun/pull/5227)Update misleading documentation link by [@0x346e3730](https://github.com/0x346e3730)[`#5061`](https://github.com/oven-sh/bun/pull/5061)file.exists() needs to be awaited to get the value by [@amt8u](https://github.com/amt8u)[`#5243`](https://github.com/oven-sh/bun/pull/5243)docs(runtime): fix jsx FragmentFactory output example by [@zongzi531](https://github.com/zongzi531)[`#5248`](https://github.com/oven-sh/bun/pull/5248)Add informative message on `bun create react` by [@colinhacks](https://github.com/colinhacks)[`#5140`](https://github.com/oven-sh/bun/pull/5140)chore: make comment grammatically correct by [@G-Rath](https://github.com/G-Rath)[`#5250`](https://github.com/oven-sh/bun/pull/5250)docs(runtime): fix plugins loader extensions typo by [@zongzi531](https://github.com/zongzi531)[`#5057`](https://github.com/oven-sh/bun/pull/5057)avoid inserting extraneous"accept-encoding" header by [@iidebyo](https://github.com/iidebyo)[`#5126`](https://github.com/oven-sh/bun/pull/5126)fix(node/fetch): Make data URL fetch consistent with node by [@davidmhewitt](https://github.com/davidmhewitt)[`#5275`](https://github.com/oven-sh/bun/pull/5275)docs: update lockfile diff instructions by [@gtramontina](https://github.com/gtramontina)[`#5311`](https://github.com/oven-sh/bun/pull/5311)add uninstall instructions by [@browner12](https://github.com/browner12)[`#5294`](https://github.com/oven-sh/bun/pull/5294)docs(guide): fix expect assertion example in guide for `spyOn` by [@winghouchan](https://github.com/winghouchan)[`#5281`](https://github.com/oven-sh/bun/pull/5281)chore(docs): include missing links to Node.js APIs by [@styfle](https://github.com/styfle)[`#5262`](https://github.com/oven-sh/bun/pull/5262)Fixed api & cli docs typo. by [@jamesgordo](https://github.com/jamesgordo)[`#5233`](https://github.com/oven-sh/bun/pull/5233)fix(runtime): require cache should not include unevaluated ESM modules. by [@paperclover](https://github.com/paperclover)[`#5236`](https://github.com/oven-sh/bun/pull/5236)Make --watch instant by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#5109`](https://github.com/oven-sh/bun/pull/5109)feat(nodejs): implement `os.availableParallelism` by [@WingLim](https://github.com/WingLim)[`#5164`](https://github.com/oven-sh/bun/pull/5164)fix(console.log) fix printing long custom format by [@cirospaciari](https://github.com/cirospaciari)[`#5200`](https://github.com/oven-sh/bun/pull/5200)fix(node:dns): fix crash and compatibility issues with `resolve` by [@Hanaasagi](https://github.com/Hanaasagi)[`#5325`](https://github.com/oven-sh/bun/pull/5325)fix(doc): Add "compilerOptions" to bun-types README.md by [@philolo1](https://github.com/philolo1)[`#5186`](https://github.com/oven-sh/bun/pull/5186)fix(BunFile.slice) fix slice when length is greater than the size by [@cirospaciari](https://github.com/cirospaciari)[`#5229`](https://github.com/oven-sh/bun/pull/5229)More docs & helptext cleanup by [@colinhacks](https://github.com/colinhacks)[`#5285`](https://github.com/oven-sh/bun/pull/5285)doc(guides): update sveltekit guide by [@mroyme](https://github.com/mroyme)[`#5225`](https://github.com/oven-sh/bun/pull/5225)modules documentation didn't have correct import example by [@miccou](https://github.com/miccou)[`#5115`](https://github.com/oven-sh/bun/pull/5115)fix link to "local template" by [@desm](https://github.com/desm)[`#5244`](https://github.com/oven-sh/bun/pull/5244)chore: test for overwriting \_resolveFilename by [@paperclover](https://github.com/paperclover)[`#5318`](https://github.com/oven-sh/bun/pull/5318)Fix bug with multiline string in CRLF terminated files (#4893) by [@tikotzky](https://github.com/tikotzky)[`#5216`](https://github.com/oven-sh/bun/pull/5216)fix(runtime): make most globals configurable/deletable, allow resuming the console iterator by [@paperclover](https://github.com/paperclover)[`#5152`](https://github.com/oven-sh/bun/pull/5152)fix(Bun.serve) fix buffering edge case by [@cirospaciari](https://github.com/cirospaciari)[`#4905`](https://github.com/oven-sh/bun/pull/4905)Update nextjs.md by [@kryparnold](https://github.com/kryparnold)[`#4881`](https://github.com/oven-sh/bun/pull/4881)Update simple.md by [@TwanLuttik](https://github.com/TwanLuttik)[`#4452`](https://github.com/oven-sh/bun/pull/4452)Update nuxt.md by [@s0h311](https://github.com/s0h311)[`#5335`](https://github.com/oven-sh/bun/pull/5335)Remove the ability to configure lockfile location. by [@nathanhammond](https://github.com/nathanhammond)[`#5346`](https://github.com/oven-sh/bun/pull/5346)In `bunx`, always get latest version when @latest is explicitly passed by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#5376`](https://github.com/oven-sh/bun/pull/5376)Fix typo in HTTPThread name by [@chrisbodhi](https://github.com/chrisbodhi)[`#5379`](https://github.com/oven-sh/bun/pull/5379)docs - Add "workspace:\*" to workspace docs. by [@dylang](https://github.com/dylang)[`#4647`](https://github.com/oven-sh/bun/pull/4647)fix(docs): Fix the text that `bun run --bun` is the same as `bun` by [@DuGlaser](https://github.com/DuGlaser)[`#5419`](https://github.com/oven-sh/bun/pull/5419)fix warnings during bun run publish-layer by [@nangchan](https://github.com/nangchan)[`#5336`](https://github.com/oven-sh/bun/pull/5336)fix(runtime): emit `node:net` connect error event vs throw by [@paperclover](https://github.com/paperclover)[`#5332`](https://github.com/oven-sh/bun/pull/5332)v8 date parser tests by [@dylan-conway](https://github.com/dylan-conway)[`#5360`](https://github.com/oven-sh/bun/pull/5360)async-ify all node:fs functions by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#5439`](https://github.com/oven-sh/bun/pull/5439)fix dockerfile by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#5428`](https://github.com/oven-sh/bun/pull/5428)fix http set cookie headers by [@dylan-conway](https://github.com/dylan-conway)[`#5422`](https://github.com/oven-sh/bun/pull/5422)fix(nitro) fix sourcemaps and JSSink closing by [@cirospaciari](https://github.com/cirospaciari)[`#5425`](https://github.com/oven-sh/bun/pull/5425)Update docs/quickstart.md by [@sonyarianto](https://github.com/sonyarianto)[`#5341`](https://github.com/oven-sh/bun/pull/5341)dup and close file descriptors by [@dylan-conway](https://github.com/dylan-conway)[`#5459`](https://github.com/oven-sh/bun/pull/5459)Make `bun run --silent` omit `"error: "..." exited with code 1` by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#5452`](https://github.com/oven-sh/bun/pull/5452)Does not fix #4622 by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#5464`](https://github.com/oven-sh/bun/pull/5464)fix(proxy): allow empty string `http_proxy` env by [@Hanaasagi](https://github.com/Hanaasagi)[`#5463`](https://github.com/oven-sh/bun/pull/5463)Implement `URL.canParse` by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#5467`](https://github.com/oven-sh/bun/pull/5467)Fixes #5461 by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#5468`](https://github.com/oven-sh/bun/pull/5468)Fixes #5465 by [@Jarred-Sumner](https://github.com/Jarred-Sumner)
## []()[New contributors](bun-v1.0.2.html#new-contributors)
Thanks to Bun's newest contributors!
[`@mkossoris`](https://github.com/@mkossoris) [`@ximex`](https://github.com/@ximex) [`@s-rigaud`](https://github.com/@s-rigaud) [`@tsndr`](https://github.com/@tsndr) [`@mi4uu`](https://github.com/@mi4uu) [`@xNaCly`](https://github.com/@xNaCly) [`@tomredman`](https://github.com/@tomredman) [`@nazeelashraf`](https://github.com/@nazeelashraf) [`@jonathantneal`](https://github.com/@jonathantneal) [`@Southpaw1496`](https://github.com/@Southpaw1496) [`@MasterGordon`](https://github.com/@MasterGordon) [`@cfal`](https://github.com/@cfal) [`@nathanhammond`](https://github.com/@nathanhammond) [`@0x346e3730`](https://github.com/@0x346e3730) [`@amt8u`](https://github.com/@amt8u) [`@zongzi531`](https://github.com/@zongzi531) [`@G-Rath`](https://github.com/@G-Rath) [`@iidebyo`](https://github.com/@iidebyo) [`@gtramontina`](https://github.com/@gtramontina) [`@browner12`](https://github.com/@browner12) [`@winghouchan`](https://github.com/@winghouchan) [`@philolo1`](https://github.com/@philolo1) [`@mroyme`](https://github.com/@mroyme) [`@miccou`](https://github.com/@miccou) [`@desm`](https://github.com/@desm) [`@tikotzky`](https://github.com/@tikotzky) [`@kryparnold`](https://github.com/@kryparnold) [`@TwanLuttik`](https://github.com/@TwanLuttik) [`@s0h311`](https://github.com/@s0h311) [`@chrisbodhi`](https://github.com/@chrisbodhi) [`@dylang`](https://github.com/@dylang) [`@DuGlaser`](https://github.com/@DuGlaser) [`@nangchan`](https://github.com/@nangchan) [`@sonyarianto`](https://github.com/@sonyarianto)
* * *
#### [Bun v1.0.1](bun-v1.0.1.html)
#### [Bun v1.0.3](bun-v1.0.3.html)
On this page
- [Full changelog](bun-v1.0.2.html#full-changelog)
- [New contributors](bun-v1.0.2.html#new-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.20.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/blog/bun-v1.0.21.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/blog/bun-v1.0.22.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/blog/bun-v1.0.23.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/blog/bun-v1.0.24.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.24
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · January 20, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun.
This release fixes 9 bugs and adds Bun Shell, a fast cross-platform shell with seamless JavaScript interop. Fixes a socket timeout bug, a potential crash when socket closes, a Node.js compatibility issue with Hapi, a process.exit bug, and bun install binlinking bug, bun inspect regression, and bun:test expect().toContain bug.
#### Previous releases
- [`v1.0.23`](bun-v1.0.23.html) fixes 40 bugs (addressing 194 👍 reactions). import & embed sqlite databases in Bun, Resource Management ('using' TC39 stage3) support, bundler improvements when building for Node.js, bugfix for peer dependency resolution, semver bugfix, 4% faster TCP on linux, Node.js compatibility improvements and more"
- [`v1.0.22`](bun-v1.0.22.html) fixes 29 bugs (addressing 118 👍 reactions), fixes `bun install` issues on Vercel, adds `performance.mark()` APIs, adds `child_process` support for extra pipes, makes `Buffer.concat` faster, adds `toBeEmptyObject` and `toContainKeys` matchers, fixes `console.table` width using emojis, and support for `argv` and `execArgv` options in `worker_threads`, and supports Brotli in `fetch`.
- [`v1.0.21`](bun-v1.0.21.html) - Fixes 33 bugs (addressing 80 👍 reactions). `console.table()` support. `Bun.write`, Bun.file, and bun:sqlite use less memory. Large file uploads with FormData use less memory. bun:sqlite error messages get more detailed. Memory leak in errors from node:fs fixed. Node.js compatibility improvements, and many crashes fixed.
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 Shell](bun-v1.0.24.html#bun-shell)
The Bun Shell is an experimental embedded language & interpreter in Bun that allows you to run cross-platform shell scripts in JavaScript & TypeScript.
```
import { $, file } from "bun";
const resp = await fetch("https://example.com");
const stdout = await $`gzip -c < ${resp}`.arrayBuffer();
// as a file()
await $`ls *.js > ${file("output.txt")}`;
// or as a file path string, if you prefer:
await $`ls *.js > output.txt`;
await $`ls *.js > ${"output.txt"}`;
// Get the output as text
const combined = await $`cat ./1.txt ./2.txt`.text();
// iterate over the output line-by-line
for await (let line of $`cat ./1.txt ./2.txt`.lines()) {
console.log(line);
}
```
[Read more](the-bun-shell.html) about the Bun Shell in the blog post or [read the docs](../docs/runtime/shell.html).
## []()[Fixed: socket timeout behavior](bun-v1.0.24.html#fixed-socket-timeout-behavior)
In Node.js, when a `net.Socket` times out, it emits a `timeout` event. In Bun, we emitted the `timeout` event, but we also closed the socket. This is not the behavior of Node.js and is not what users expect, so we fixed it. This also applies to `Bun.connect()` and `Bun.listen()`.
## []()[Fixed: Potential crash when socket closes](bun-v1.0.24.html#fixed-potential-crash-when-socket-closes)
A crash that could occur when frequently connecting and disconnecting from sockets (usually a database client) has been fixed
## []()[Node.js compatiblity improvements for `"perf_hooks"`](bun-v1.0.24.html#node-js-compatiblity-improvements-for-perf-hooks)
Previously, Hapi (`@hapi/hapi`) was not working in Bun because the `perf_hooks.eventLoopUtilization` function was not defined. Bun now defines it, and returns empty values for all metrics which unblocks Hapi.
## []()[Fixed: process.exit threw "exitCode is not a number" in some cases](bun-v1.0.24.html#fixed-process-exit-threw-exitcode-is-not-a-number-in-some-cases)
`process.exit(eval("1.234 - 0.234"))` would throw an error in Bun, but not in Node.js. This has been fixed.
The bug was in how Bun was reading the `exitCode` argument within the `process.exit` function. JavaScriptCore's JSValue representation of `1.234 - 0.234` represents it as a 64-bit floating point number, even though it is technically just the signed 32-bit integer `1`. Bun's code was specifically checking if the representation was a signed 32 bit integer instead of being any integer number, which caused the error. The fix was to check if the value was an integer number instead of a signed 32-bit integer.
This bug impacted Prisma CLI, which uses `process.exit` to exit the process with a non-zero exit code when an error occurs.
## []()[Fixed: bin linking in bun install with dangling symlinks](bun-v1.0.24.html#fixed-bin-linking-in-bun-install-with-dangling-symlinks)
When a symlink already existed but pointed to a path which no longer exited, `bun install` would not overwrite the symlink. This has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
## []()[Fixed: regression with fully-qualified URL in `bun --inspect`](bun-v1.0.24.html#fixed-regression-with-fully-qualified-url-in-bun-inspect)
When using `bun --inspect` with a fully-qualified URL, the URL was not being parsed correctly. This has been fixed, thanks to [@Electroid](https://github.com/Electroid).
## []()[Fixed: expect().toContain("") behaved incorrectly](bun-v1.0.24.html#fixed-expect-tocontain-behaved-incorrectly)
A bug where `bun:test`'s implementation of `expect(a).toContain("")` behaved inconsistently with Jest has been fixed, thanks to [@DontBreakAlex](https://github.com/DontBreakAlex).
## []()[Fixed: path.parse edgecase](bun-v1.0.24.html#fixed-path-parse-edgecase)
Given the string `path.parse('.prettierrc')`, the `path.parse` function in Bun would return different results in Bun and Node.js.
Now Bun returns the same result as in Node.js, thanks to [@Aarav-Juneja](https://github.com/Aarav-Juneja).
## []()[Fixed: hang in recursive console.log](bun-v1.0.24.html#fixed-hang-in-recursive-console-log)
A hang when a function logs inside of console.* has been fixed, thanks to [@LukasKastern](https://github.com/LukasKastern).
## []()[Thanks to 14 contributors!](bun-v1.0.24.html#thanks-to-14-contributors)
- [@Aarav-Juneja](https://github.com/Aarav-Juneja)
- [@cena-ko](https://github.com/cena-ko)
- [@DontBreakAlex](https://github.com/DontBreakAlex)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Electroid](https://github.com/Electroid)
- [@guest271314](https://github.com/guest271314)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@keepdying](https://github.com/keepdying)
- [@LukasKastern](https://github.com/LukasKastern)
- [@maxmilton](https://github.com/maxmilton)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@RiskyMH](https://github.com/RiskyMH)
- [@yus-ham](https://github.com/yus-ham)
- [@zackradisic](https://github.com/zackradisic)
* * *
#### [Bun v1.0.23](bun-v1.0.23.html)
#### [Bun v1.0.25](bun-v1.0.25.html)
On this page
- [Bun Shell](bun-v1.0.24.html#bun-shell)
- [Fixed: socket timeout behavior](bun-v1.0.24.html#fixed-socket-timeout-behavior)
- [Fixed: Potential crash when socket closes](bun-v1.0.24.html#fixed-potential-crash-when-socket-closes)
- [Node.js compatiblity improvements for `"perf_hooks"`](bun-v1.0.24.html#node-js-compatiblity-improvements-for-perf-hooks)
- [Fixed: process.exit threw "exitCode is not a number" in some cases](bun-v1.0.24.html#fixed-process-exit-threw-exitcode-is-not-a-number-in-some-cases)
- [Fixed: bin linking in bun install with dangling symlinks](bun-v1.0.24.html#fixed-bin-linking-in-bun-install-with-dangling-symlinks)
- [Fixed: regression with fully-qualified URL in `bun --inspect`](bun-v1.0.24.html#fixed-regression-with-fully-qualified-url-in-bun-inspect)
- [Fixed: expect().toContain("") behaved incorrectly](bun-v1.0.24.html#fixed-expect-tocontain-behaved-incorrectly)
- [Fixed: path.parse edgecase](bun-v1.0.24.html#fixed-path-parse-edgecase)
- [Fixed: hang in recursive console.log](bun-v1.0.24.html#fixed-hang-in-recursive-console-log)
- [Thanks to 14 contributors!](bun-v1.0.24.html#thanks-to-14-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.25.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.25
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · January 21, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun.
This release fixes 4 bugs, adds vm.createScript. Fixes a crash in fs.readFile, a crash in Bun.file().text(), a crash in IPC, and a transpiler bug involving loose equals
#### Previous releases
- [`v1.0.24`](bun-v1.0.24.html) fixes 9 bugs and adds Bun Shell, a fast cross-platform shell with seamless JavaScript interop. Fixes a socket timeout bug, a potential crash when socket closes, a Node.js compatibility issue with Hapi, a process.exit bug, and bun install binlinking bug, bun inspect regression, and bun:test expect().toContain bug
- [`v1.0.23`](bun-v1.0.23.html) fixes 40 bugs (addressing 194 👍 reactions). import & embed sqlite databases in Bun, Resource Management ('using' TC39 stage3) support, bundler improvements when building for Node.js, bugfix for peer dependency resolution, semver bugfix, 4% faster TCP on linux, Node.js compatibility improvements and more"
- [`v1.0.22`](bun-v1.0.22.html) fixes 29 bugs (addressing 118 👍 reactions), fixes `bun install` issues on Vercel, adds `performance.mark()` APIs, adds `child_process` support for extra pipes, makes `Buffer.concat` faster, adds `toBeEmptyObject` and `toContainKeys` matchers, fixes `console.table` width using emojis, and support for `argv` and `execArgv` options in `worker_threads`, and supports Brotli in `fetch`.
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
```
## []()[Fixed: crash in fs.readFile](bun-v1.0.25.html#fixed-crash-in-fs-readfile)
In certain cases, Bun would crash when reading a file with `fs.readFile`, `fs.readFileSync`, or `fs.promises.readFile`. This was caused by an unintiailized memory access introduced when Bun added support for standalone modules.
## []()[Fixed: crash in Bun.file().text()](bun-v1.0.25.html#fixed-crash-in-bun-file-text)
A crash when reading a file with `Bun.file().text()` that had a Byte Order Mark has been fixed. This crash was introduced in Bun v1.0.24.
## []()[Fixed: crash in IPC](bun-v1.0.25.html#fixed-crash-in-ipc)
A crash in IPC that would occur 4-5 seconds after the process started has been fixed. This crash was introduced when upgrading our version of uSockets to gain "long timeout" support. The crash was a null-pointer dereference when calling the timeout callback.
## []()[Fixed: transpiler loose equality comparison bug](bun-v1.0.25.html#fixed-transpiler-loose-equality-comparison-bug)
The following input would be constant-folded incorrectly:
```
"" == 0;
"-0" == 0;
1234n == 5678n;
```
This has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
## []()[`vm.createScript`](bun-v1.0.25.html#vm-createscript)
The `node:vm` function `createScript` has been added. This calls `new vm.Script` with the same arguments.
## []()[Windows is coming soon](bun-v1.0.25.html#windows-is-coming-soon)
10 days away.
## []()[Thanks to 5 contributors!](bun-v1.0.25.html#thanks-to-5-contributors)
- [@bjon](https://github.com/bjon)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Hanaasagi](https://github.com/Hanaasagi)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@nektro](https://github.com/nektro)
* * *
#### [Bun v1.0.24](bun-v1.0.24.html)
#### [Bun v1.0.26](bun-v1.0.26.html)
On this page
- [Fixed: crash in fs.readFile](bun-v1.0.25.html#fixed-crash-in-fs-readfile)
- [Fixed: crash in Bun.file().text()](bun-v1.0.25.html#fixed-crash-in-bun-file-text)
- [Fixed: crash in IPC](bun-v1.0.25.html#fixed-crash-in-ipc)
- [Fixed: transpiler loose equality comparison bug](bun-v1.0.25.html#fixed-transpiler-loose-equality-comparison-bug)
- [`vm.createScript`](bun-v1.0.25.html#vm-createscript)
- [Windows is coming soon](bun-v1.0.25.html#windows-is-coming-soon)
- [Thanks to 5 contributors!](bun-v1.0.25.html#thanks-to-5-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.26.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.26
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · February 3, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun.
This release fixes 30 bugs, adds support for multi-statement queries in bun:sqlite, makes bun --watch more reliable in longer-running sessions, Bun.FileSystemRouter now supports more than 64 routes, fixes a bug with expect().toStrictEqual(), fixes 2 bugs with error.stack, fixes a bug with fileURLToPath, improves Node.js compatibility
#### Previous releases
- [`v1.0.25`](bun-v1.0.25.html) fixes 4 bugs, adds vm.createScript. Fixes a crash in fs.readFile, a crash in Bun.file().text(), a crash in IPC, and a transpiler bug involving loose equals
- [`v1.0.24`](bun-v1.0.24.html) fixes 9 bugs and adds Bun Shell, a fast cross-platform shell with seamless JavaScript interop. Fixes a socket timeout bug, a potential crash when socket closes, a Node.js compatibility issue with Hapi, a process.exit bug, and bun install binlinking bug, bun inspect regression, and bun:test expect().toContain bug
- [`v1.0.23`](bun-v1.0.23.html) fixes 40 bugs (addressing 194 👍 reactions). import & embed sqlite databases in Bun, Resource Management ('using' TC39 stage3) support, bundler improvements when building for Node.js, bugfix for peer dependency resolution, semver bugfix, 4% faster TCP on linux, Node.js compatibility improvements and more"
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
```
## []()[Multi-statement queries in bun:sqlite](bun-v1.0.26.html#multi-statement-queries-in-bun-sqlite)
[`bun:sqlite`](../docs/api/sqlite.html) gets support for multi-statement queries. This allows you to run multiple SQL statements in a single call to `db.run()` delimited by a `;`, similar to how it works in the `sqlite` command-line tool.
```
import { Database } from "bun:sqlite";
const db = new Database(":memory:");
db.run(`
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT
);
INSERT INTO users (name) VALUES ("Alice");
INSERT INTO users (name) VALUES ("Bob");
`);
const names = db
.query("SELECT name FROM users")
.all()
.map(({ name }) => name)
.join(", ");
console.log(names); // Alice, Bob
```
Only `Database.prototype.run` and \`\`Database.prototype.exec`support multi-statement queries.`db.query`and`db.prepare\` do not.
## []()[bun --watch reliability improvement](bun-v1.0.26.html#bun-watch-reliability-improvement)
`bun --watch` now defensively closes all file descriptors on reload. Filesystem watchers inherently need to keep many file descriptors open when watching many files, but keeping file descriptors open for a long time can lead to resource exhaustion and many other issues. Bun already set `O_CLOEXEC` internally, but that doesn't always mean all file descriptors closed.
Part of what makes `bun --watch` fast is we immediately reload the entire process when an imported file changes. There's very little work that happens between the file change and the process reload. This is in contrast to other tools that might recompile the file to check for changes, and only re-run the process on change.
On Linux, Bun now uses the [`close_range(2)`](https://man7.org/linux/man-pages/man2/close_range.2.html) system call to close all file descriptors > 8 before reloading the process. This reliably ensures that all file descriptors are closed (for those of you running modern Linux kernels).
On macOS, we use the `POSIX_SPAWN_CLOEXEC_DEFAULT` flag to close all file descriptors on spawn. We also fixed an issue where signals were not being reset to their default behavior on reload.
## []()[`abort-controller` polyfill now uses native `AbortController`](bun-v1.0.26.html#abort-controller-polyfill-now-uses-native-abortcontroller)
The popular `abort-controller` npm package polyfill now uses the native `AbortController` in Bun instead of the polyfill.
This fixes an issue where Bun would report an error like `"Expected signal to be an AbortSignal"` when a library used the `abort-controller` polyfill with `fetch` or `Request` or `Response`.
The `abort-controller` polyfill is a polyfill for the `AbortController` and `AbortSignal` web APIs
## []()[Fixed: Bun.FileSystemRouter now supports more than 64 routes](bun-v1.0.26.html#fixed-bun-filesystemrouter-now-supports-more-than-64-routes)
[Bun.FileSystemRouter](../docs/api/file-system-router.html) is Bun's built-in Next.js pages-inspired filesystem router. It now supports more than 64 routes.
Previously, Bun would throw an uncatchable exception when you tried to use more than 64 routes. This was caused by an assertion failure in JavascriptCore when an object is defined with more than 63 "inline" properties. This has been fixed.
## []()[Fixed: error.stack sometimes `undefined`](bun-v1.0.26.html#fixed-error-stack-sometimes-undefined)
Bun implements the [V8 Stack Trace API](https://v8.dev/docs/stack-trace-api) (despite Bun using the JavaScriptCore engine), which adds methods like `Error.prepareStackTrace` and `Error.captureStackTrace` to the `Error` object.
There was a bug where `error.stack` was sometimes `undefined` when it should have been a string. This has been fixed.
This bug impacted Firebase & Google Cloud libraries when they were about to log an error. It caused these libraries to throw a different error while trying to log the error, which was not helpful.
## []()[Fixed: error.stack CallSite lineNumber was sometimes negative](bun-v1.0.26.html#fixed-error-stack-callsite-linenumber-was-sometimes-negative)
The following would sometimes print negative numbers:
```
Error.prepareStackTrace = (error, stack) => {
return [stack[0].getLineNumber(), stack[0].getColumnNumber()];
};
const error = new Error();
console.log(error.stack);
```
Bun returned negative numbers when the line number was not available. This unfortunately broke the popular `source-map-support` library since it asserts that line and column numbers are positive integers. This has been "fixed" by never returning negative numbers.
## []()[Fixed: `Error.prepareStackTrace` is now a function by default](bun-v1.0.26.html#fixed-error-preparestacktrace-is-now-a-function-by-default)
In Node.js, `Error.prepareStackTrace` is a function by default. In Bun, it was `undefined` by default. This has been fixed.
The default `Error.prepareStackTrace` function does what you would expect: it returns a string of the stack trace. You can continue to set `Error.prepareStackTrace` to a custom function to customize the stack trace, or to `undefined` (in which case the default function is used).
## []()[Fixed: `module.path` is now `__dirname` instead of `module.id`](bun-v1.0.26.html#fixed-module-path-is-now-dirname-instead-of-module-id)
In Node.js, the `module` object has a `path` property which is supposed to be the directory of the module, equivalent to `__dirname`. In Bun, `module.path` was incorrectly an alias for `module.id`. This has been fixed.
## []()[Fixed: `expect(a).toStrictEqual(b)` with deleted properties](bun-v1.0.26.html#fixed-expect-a-tostrictequal-b-with-deleted-properties)
A bug in `bun:test`'s `expect.toStrictEqual` implementation caused it to behave incorrectly when comparing objects with deleted properties. This has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
```
import { test, expect } from "bun:test";
test("expect.toStrictEqual", () => {
const a = { a: 1, b: 2 };
const b = { a: 1, b: 2 };
delete b.b;
expect(a).toStrictEqual(b);
});
```
Previously, this would throw an error with a confusingly empty diff:
```
hey.test.ts:
2 |
3 | test("expect.toStrictEqual", () => {
4 | var obj1 = { a: 1 };
5 | var obj2 = {};
6 | delete obj1.a;
7 | expect(obj1).toStrictEqual(obj2);
^
error: expect(received).toStrictEqual(expected)
{}
- Expected - 0
+ Received + 0
at hey.test.ts:7:3
✗ expect.toStrictEqual [0.29ms]
```
Now it correctly passes.
This happened because toStrictEqual used a fast path that failed to handle deleted properties correctly in some cases.
## []()[Fixed: event loop scheduling bug in Bun.serve() websockets](bun-v1.0.26.html#fixed-event-loop-scheduling-bug-in-bun-serve-websockets)
We've made some infrastructure tweaks to ensure that microtasks are always drained after event loop callbacks are executed. There was a bug where we skipped doing this in websockets, in Bun.spawn(), and in IPC handlers. Neglecting to drain the microtask queue can cause very high memory growth until the microtasks get drained (imagine if you just kept adding to a queue without ever removing anything).
## []()[Fixed: new Response(Bun.file()) sometimes logged an error to stderr](bun-v1.0.26.html#fixed-new-response-bun-file-sometimes-logged-an-error-to-stderr)
When you passed a `Bun.file()` to `new Response()` to `Bun.serve()` connected to HTTP (not HTTPS), if the client aborted the request at the right time, Bun would log `Error: NOTCONN` to stderr with no way to suppress it. This was confusing and unhelpful. Aborting a request is a normal part of the web, and Bun should not log an unsupressable error when it happens.
## []()[Windows is happening on February 15th](bun-v1.0.26.html#windows-is-happening-on-february-15th)
78% of Bun's tests pass on Windows, but it's still not enough to release.
Most of the changes in this release were Windows-related, but this changelog excludes that since its not "released" yet.
## []()[Thanks to 28 contributors!](bun-v1.0.26.html#thanks-to-28-contributors)
- [@fneco](https://github.com/fneco)
- [@jcarpe](https://github.com/jcarpe)
- [@nektro](https://github.com/nektro)
- [@nullun](https://github.com/nullun)
- [@A-D-E-A](https://github.com/A-D-E-A)
- [@blimmer](https://github.com/blimmer)
- [@DaleSeo](https://github.com/DaleSeo)
- [@gvilums](https://github.com/gvilums)
- [@jdalton](https://github.com/jdalton)
- [@moznion](https://github.com/moznion)
- [@Primexz](https://github.com/Primexz)
- [@zack466](https://github.com/zack466)
- [@cyfdecyf](https://github.com/cyfdecyf)
- [@guarner8](https://github.com/guarner8)
- [@huseeiin](https://github.com/huseeiin)
- [@Didas-git](https://github.com/Didas-git)
- [@Electroid](https://github.com/Electroid)
- [@paperclover](https://github.com/paperclover)
- [@FireSquid6](https://github.com/FireSquid6)
- [@TiranexDev](https://github.com/TiranexDev)
- [@vinnichase](https://github.com/vinnichase)
- [@whygee-dev](https://github.com/whygee-dev)
- [@BeyondMagic](https://github.com/BeyondMagic)
- [@eliot-akira](https://github.com/eliot-akira)
- [@lukeingalls](https://github.com/lukeingalls)
- [@cirospaciari](https://github.com/cirospaciari)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
* * *
#### [Bun v1.0.25](bun-v1.0.25.html)
#### [Bun v1.0.27](bun-v1.0.27.html)
On this page
- [Multi-statement queries in bun:sqlite](bun-v1.0.26.html#multi-statement-queries-in-bun-sqlite)
- [bun --watch reliability improvement](bun-v1.0.26.html#bun-watch-reliability-improvement)
- [`abort-controller` polyfill now uses native `AbortController`](bun-v1.0.26.html#abort-controller-polyfill-now-uses-native-abortcontroller)
- [Fixed: Bun.FileSystemRouter now supports more than 64 routes](bun-v1.0.26.html#fixed-bun-filesystemrouter-now-supports-more-than-64-routes)
- [Fixed: error.stack sometimes `undefined`](bun-v1.0.26.html#fixed-error-stack-sometimes-undefined)
- [Fixed: error.stack CallSite lineNumber was sometimes negative](bun-v1.0.26.html#fixed-error-stack-callsite-linenumber-was-sometimes-negative)
- [Fixed: `Error.prepareStackTrace` is now a function by default](bun-v1.0.26.html#fixed-error-preparestacktrace-is-now-a-function-by-default)
- [Fixed: `module.path` is now `__dirname` instead of `module.id`](bun-v1.0.26.html#fixed-module-path-is-now-dirname-instead-of-module-id)
- [Fixed: `expect(a).toStrictEqual(b)` with deleted properties](bun-v1.0.26.html#fixed-expect-a-tostrictequal-b-with-deleted-properties)
- [Fixed: event loop scheduling bug in Bun.serve() websockets](bun-v1.0.26.html#fixed-event-loop-scheduling-bug-in-bun-serve-websockets)
- [Fixed: new Response(Bun.file()) sometimes logged an error to stderr](bun-v1.0.26.html#fixed-new-response-bun-file-sometimes-logged-an-error-to-stderr)
- [Windows is happening on February 15th](bun-v1.0.26.html#windows-is-happening-on-february-15th)
- [Thanks to 28 contributors!](bun-v1.0.26.html#thanks-to-28-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.27.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.27
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · February 17, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one.
This release fixes 72 bugs (addressing 192 👍 reactions), Bun Shell supports throwing on non-zero exit codes, stream Response bodies using async generators, improves reliability of fetch(), http2 client, Bun.Glob fixes. Fixes a regression with bun --watch on Linux. Improves Node.js compatibility
#### Previous releases
- [`v1.0.26`](bun-v1.0.26.html) fixes 30 bugs (addressing 60 👍 reactions), adds support for multi-statement queries in bun:sqlite, makes bun --watch more reliable in longer-running sessions, Bun.FileSystemRouter now supports more than 64 routes, fixes a bug with expect().toStrictEqual(), fixes 2 bugs with error.stack, improves Node.js compatibility
- [`v1.0.25`](bun-v1.0.25.html) fixes 4 bugs, adds vm.createScript. Fixes a crash in fs.readFile, a crash in Bun.file().text(), a crash in IPC, and a transpiler bug involving loose equals
- [`v1.0.24`](bun-v1.0.24.html) fixes 9 bugs and adds Bun Shell, a fast cross-platform shell with seamless JavaScript interop. Fixes a socket timeout bug, a potential crash when socket closes, a Node.js compatibility issue with Hapi, a process.exit bug, and bun install binlinking bug, bun inspect regression, and bun:test expect().toContain bug
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 Shell supports throwing on non-zero exit codes](bun-v1.0.27.html#bun-shell-supports-throwing-on-non-zero-exit-codes)
When we released Bun Shell, we made a small API design mistake. In Bash, shell scripts by default continue running even if a command fails. This is often the cause of subtle bugs in shell scripts. For compatibility, Bun Shell also does this -- but that's not what JavaScript developers expect.
This release adds support for throwing on non-zero exit codes
```
import { $ } from "bun";
$.throws(true);
await $`cat /not-found`;
```
It will throw an error like this:
```
ShellError: Failed with exit code 1
info: {
"stderr": "cat: /not-found: No such file or directory\n",
"exitCode": 1,
"stdout": ""
}
```
There is an issue with not showing a complete stacktrace in this Error and we are investigating how to fix that.
### []()[Upcoming breaking change](bun-v1.0.27.html#upcoming-breaking-change)
After lots of feedback, in Bun v1.1 (not this release), Bun Shell will by default throw on non-zero exit codes - making this the default behavior (a breaking change). We mention in the API docs that Bun Shell is an unstable API and this is a good example of why.
## []()[More robust escaping in Bun.Shell](bun-v1.0.27.html#more-robust-escaping-in-bun-shell)
In this release, we made the escaping logic more robust in Bun Shell in situations like this:
```
import { $ } from "bun";
const str = "cookies & creme";
await $`echo "${str}"`;
```
Previously, this would escape like so:
```
await $`echo ""cookies & creme ""`;
```
Which would lead to the following error:
```
1 | import { $ } from "bun";
2 | const str = "cookies & creme";
3 | await $`echo "${str}"`;
^
error: expected a command or assignment but got: "Ampersand"
at BunShell (:117:69)
at /private/tmp/sh.js:3:7
```
Now it correctly escapes like so:
```
await $`echo "cookies & creme"`;
```
## []()[Stream Response bodies using async generators](bun-v1.0.27.html#stream-response-bodies-using-async-generators)
This release adds support for streaming Response bodies using async generators
```
Bun.serve({
async fetch(req) {
return new Response(
// using an async generator* function
async function* stream() {
yield "Hello, ";
yield Buffer.from("world!");
},
);
},
});
Bun.serve({
async fetch(req) {
return new Response({
// You can also pass async iterables
async *[Symbol.asyncIterator]() {
yield "Hello, ";
yield Buffer.from("world!");
},
});
},
});
```
You can pass an async generator function or an async iterable to the `Response` constructor. You can yield `string` or any TypedArray (like `Buffer`). Passing a string automatically converts it to a UTF-8 string.
Internally, this becomes a [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream). Bun continues to support ReadableStream directly.
### []()[Node.js Readable streams in Bun.serve()](bun-v1.0.27.html#node-js-readable-streams-in-bun-serve)
Since Node.js Readable implements `[Symbol.asyncIterator]`, you can now also pass a Node.js Readable stream to the `Response` constructor.
```
import { Readable } from "stream";
import { serve } from "bun";
serve({
port: 3001,
fetch(req) {
const r = new Readable();
r.push("your text here");
r.push(null);
return new Response(r);
},
});
```
### []()[Fixed: Astro v4.4 rendering empty pages](bun-v1.0.27.html#fixed-astro-v4-4-rendering-empty-pages)
In Astro v4.4, they switched to using an async generator function to render pages. This caused a bug in Bun where it would render empty pages. This has been fixed.
## []()[Fixed: ctrl+c in bun --watch on Linux](bun-v1.0.27.html#fixed-ctrl-c-in-bun-watch-on-linux)
A regression in Bun v1.0.26 caused `bun --watch` to not exit when pressing ctrl+c on Linux. This has been fixed. Sorry about this.
Thanks to [@gvilums](https://github.com/gvilums) for fixing this.
## []()[Fixed: "ShortRead" in fetch()](bun-v1.0.27.html#fixed-shortread-in-fetch)
In Bun v1.0.21, we added Brotli streaming support to `fetch()` -- but there was a bug in the implementation when consuming streaming chunks of data to JavaScript. It would throw "error: ShortRead" in some cases. This release fixes that bug, thanks to [@argosphil](https://github.com/argosphil).
## []()[Fixed: http2 client hangs](bun-v1.0.27.html#fixed-http2-client-hangs)
A bug where the http2 client would sometimes hang has been fixed. This was most noticeable when using Firebase or Firestore.
## []()[Fixed: crash when calling Bun.$ as a function without a template tag](bun-v1.0.27.html#fixed-crash-when-calling-bun-as-a-function-without-a-template-tag)
A crash would occur in code like this:
```
import { $ } from "bun";
await $("i should've used a template tag instead :(");
```
Now it correctly throws an error.
Thanks to [@zackradisic](https://github.com/zackradisic) for fixing this
## []()[Fixed: bug with Glob matching `**` sometimes returning an empty list](bun-v1.0.27.html#fixed-bug-with-glob-matching-sometimes-returning-an-empty-list)
A bug where Bun.Glob with `**` would sometimes return an empty list has been fixed, thanks to [@zackradisic](https://github.com/zackradisic).
## []()[Fixed: support `_` in HTTP header names](bun-v1.0.27.html#fixed-support-in-http-header-names)
Previously, Bun.serve() considered header names containing underscores to be invalid. This has been fixed, thanks to [@uNetworkingAB](https://github.com/uNetworkingAB).
## []()[Fixed: symlink entry points reported import.meta.main as false](bun-v1.0.27.html#fixed-symlink-entry-points-reported-import-meta-main-as-false)
In Bun, you can find out if the current module is the entry point using `import.meta.main`. This was not working correctly when the entry point was a symlink. This has been fixed, thanks to [@paperclover](https://github.com/paperclover).
## []()[Fixed: async module mocks in bun:test](bun-v1.0.27.html#fixed-async-module-mocks-in-bun-test)
A bug where using async or promises inside module mocks was not working correctly has been fixed.
This test now passes:
```
import { mock, test, expect } from "bun:test";
test("mock.module async", async () => {
mock.module("i-am-async-and-mocked", async () => {
await 42;
await Bun.sleep(0);
return { a: 123 };
});
expect((await import("i-am-async-and-mocked")).a).toBe(123);
});
```
## []()[Fixed: potential crash in node:crypto](bun-v1.0.27.html#fixed-potential-crash-in-node-crypto)
A crash in node:crypto that could potentially occur when using KeyObject has been fixed, thanks to [@cirospaciari](https://github.com/cirospaciari).
## []()[Fixed: path.win32 Node.js tests now pass](bun-v1.0.27.html#fixed-path-win32-node-js-tests-now-pass)
The implementation of `path.win32` has been rewritten and now passes all Node.js tests, thanks to [@jdalton](https://github.com/jdalton).
## []()[Fixed: edgecase in tsconfig.json path mapping](bun-v1.0.27.html#fixed-edgecase-in-tsconfig-json-path-mapping)
A bug where the `tsconfig.json` path mapping would not work correctly when multiple possible paths could potentially match and one was longer than the other has been fixed, thanks to [@james-elicx](https://github.com/james-elicx).
## []()[Fixed: potential crash in Bun.$ when removing lots of files](bun-v1.0.27.html#fixed-potential-crash-in-bun-when-removing-lots-of-files)
A potential crash has been fixed when using `rm -rf` with a large number of files. This was most noticeable on Linux when using in-memory filesystems.
## []()[Fixed: potential crash in fetch() after a redirect](bun-v1.0.27.html#fixed-potential-crash-in-fetch-after-a-redirect)
A bug in our code for handling redirects in `fetch()` has been fixed, thanks to [@cirospaciari](https://github.com/cirospaciari).
## []()[Fixed: bun test -t 'pattern' where pattern matched at start](bun-v1.0.27.html#fixed-bun-test-t-pattern-where-pattern-matched-at-start)
A bug where `bun test -t 'pattern'` would not match tests where the pattern matched at the start of the test name has been fixed, thanks to [@argosphil](https://github.com/argosphil).
## []()[Fixed: potential crash in Bun.stdin, Bun.stdout, Bun.stderr](bun-v1.0.27.html#fixed-potential-crash-in-bun-stdin-bun-stdout-bun-stderr)
A bug where using `Bun.stdin`, `Bun.stdout`, and `Bun.stderr` could sometimes crash has been fixed, thanks to [@argosphil](https://github.com/argosphil). This was a regression introduced in Bun v1.0.24.
## []()[Bundows is soon](bun-v1.0.27.html#bundows-is-soon)
Despite all the non-Windows specific fixes in this release -- most of the code changes are to make Bun work better on Windows (and just not mentioned here since it's not released yet).
We will ship Windows once more of the test suite passes on Windows. 85% of tests pass right now. We are working on getting that to 100% as quickly as possible.
## []()[Thanks to 27 contributors!](bun-v1.0.27.html#thanks-to-27-contributors)
- [@jakeg](https://github.com/jakeg)
- [@nektro](https://github.com/nektro)
- [@jcarpe](https://github.com/jcarpe)
- [@7f8ddd](https://github.com/7f8ddd)
- [@lei-rs](https://github.com/lei-rs)
- [@tobycm](https://github.com/tobycm)
- [@gvilums](https://github.com/gvilums)
- [@risu729](https://github.com/risu729)
- [@DaleSeo](https://github.com/DaleSeo)
- [@jdalton](https://github.com/jdalton)
- [@kantuni](https://github.com/kantuni)
- [@ZTL-UwU](https://github.com/ZTL-UwU)
- [@sroussey](https://github.com/sroussey)
- [@paperclover](https://github.com/paperclover)
- [@argosphil](https://github.com/argosphil)
- [@Electroid](https://github.com/Electroid)
- [@dmitri-gb](https://github.com/dmitri-gb)
- [@AugusDogus](https://github.com/AugusDogus)
- [@guest271314](https://github.com/guest271314)
- [@zackradisic](https://github.com/zackradisic)
- [@james-elicx](https://github.com/james-elicx)
- [@cirospaciari](https://github.com/cirospaciari)
- [@dylan-conway](https://github.com/dylan-conway)
- [@traviscooper](https://github.com/traviscooper)
- [@masterujjval](https://github.com/masterujjval)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@FortyGazelle700](https://github.com/FortyGazelle700)
* * *
#### [Bun v1.0.26](bun-v1.0.26.html)
#### [Bun v1.0.28](bun-v1.0.28.html)
On this page
- [Bun Shell supports throwing on non-zero exit codes](bun-v1.0.27.html#bun-shell-supports-throwing-on-non-zero-exit-codes)
- [Upcoming breaking change](bun-v1.0.27.html#upcoming-breaking-change)
- [More robust escaping in Bun.Shell](bun-v1.0.27.html#more-robust-escaping-in-bun-shell)
- [Stream Response bodies using async generators](bun-v1.0.27.html#stream-response-bodies-using-async-generators)
- [Node.js Readable streams in Bun.serve()](bun-v1.0.27.html#node-js-readable-streams-in-bun-serve)
- [Fixed: Astro v4.4 rendering empty pages](bun-v1.0.27.html#fixed-astro-v4-4-rendering-empty-pages)
- [Fixed: ctrl+c in bun --watch on Linux](bun-v1.0.27.html#fixed-ctrl-c-in-bun-watch-on-linux)
- [Fixed: "ShortRead" in fetch()](bun-v1.0.27.html#fixed-shortread-in-fetch)
- [Fixed: http2 client hangs](bun-v1.0.27.html#fixed-http2-client-hangs)
- [Fixed: crash when calling Bun.$ as a function without a template tag](bun-v1.0.27.html#fixed-crash-when-calling-bun-as-a-function-without-a-template-tag)
- [Fixed: bug with Glob matching `**` sometimes returning an empty list](bun-v1.0.27.html#fixed-bug-with-glob-matching-sometimes-returning-an-empty-list)
- [Fixed: support `_` in HTTP header names](bun-v1.0.27.html#fixed-support-in-http-header-names)
- [Fixed: symlink entry points reported import.meta.main as false](bun-v1.0.27.html#fixed-symlink-entry-points-reported-import-meta-main-as-false)
- [Fixed: async module mocks in bun:test](bun-v1.0.27.html#fixed-async-module-mocks-in-bun-test)
- [Fixed: potential crash in node:crypto](bun-v1.0.27.html#fixed-potential-crash-in-node-crypto)
- [Fixed: path.win32 Node.js tests now pass](bun-v1.0.27.html#fixed-path-win32-node-js-tests-now-pass)
- [Fixed: edgecase in tsconfig.json path mapping](bun-v1.0.27.html#fixed-edgecase-in-tsconfig-json-path-mapping)
- [Fixed: potential crash in Bun.$ when removing lots of files](bun-v1.0.27.html#fixed-potential-crash-in-bun-when-removing-lots-of-files)
- [Fixed: potential crash in fetch() after a redirect](bun-v1.0.27.html#fixed-potential-crash-in-fetch-after-a-redirect)
- [Fixed: bun test -t 'pattern' where pattern matched at start](bun-v1.0.27.html#fixed-bun-test-t-pattern-where-pattern-matched-at-start)
- [Fixed: potential crash in Bun.stdin, Bun.stdout, Bun.stderr](bun-v1.0.27.html#fixed-potential-crash-in-bun-stdin-bun-stdout-bun-stderr)
- [Bundows is soon](bun-v1.0.27.html#bundows-is-soon)
- [Thanks to 27 contributors!](bun-v1.0.27.html#thanks-to-27-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.28.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.28
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · February 19, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one.
This release fixes 6 bugs (addressing 26 👍 reactions). Fixes bugs impacting Prisma and Astro, `node:events`, `node:readline`, and `node:http2`. Fixes a bug in Bun Shell involving stdin redirection and fixes bugs in `bun:test` with `test.each` and `describe.only`.
#### Previous releases
- [`v1.0.27`](bun-v1.0.27.html) fixes 72 bugs (addressing 192 👍 reactions), Bun Shell supports throwing on non-zero exit codes, stream Response bodies using async generators, improves reliability of fetch(), http2 client, Bun.Glob fixes. Fixes a regression with bun --watch on Linux. Improves Node.js compatibility
- [`v1.0.26`](bun-v1.0.26.html) fixes 30 bugs (addressing 60 👍 reactions), adds support for multi-statement queries in bun:sqlite, makes bun --watch more reliable in longer-running sessions, Bun.FileSystemRouter now supports more than 64 routes, fixes a bug with expect().toStrictEqual(), fixes 2 bugs with error.stack, improves Node.js compatibility
- [`v1.0.25`](bun-v1.0.25.html) fixes 4 bugs, adds vm.createScript. Fixes a crash in fs.readFile, a crash in Bun.file().text(), a crash in IPC, and a transpiler bug involving loose equals
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
```
## []()[Fixed: Crash when using Prisma](bun-v1.0.28.html#fixed-crash-when-using-prisma)
A crash when using Prisma with multiple simultaneous N-API calls from different modules has been fixed. This crash would reproduce when using Prisma and `@napi-rs/canvas` in the same microtask tick.
This crash was caused by an incorrect implementation of `napi_create_reference`. Previously, we assumed that only one napi reference would be associated with an individual object created from napi, but that assumption was incorrect. This led to a crash when creating a napi reference for the same object multiple times.
Thanks to [@camero2734](https://github.com/camero2734) for fixing this.
## []()[Fixed: Astro v4.4 throwing an error](bun-v1.0.28.html#fixed-astro-v4-4-throwing-an-error)
In Bun v1.0.27, we fixed a bug where Astro v4.4 would render empty pages – but our fix was incomplete. An error would occur when multiple pages were being rendered simultaneosly.
This occurred because we made an incorrect assumption. We assumed that the `[Symbol.asyncIterator]` function could be called in `pull` of the ReadableStream, but Astro expected it to be called immediately. This bug manifested when multiple pages were being rendered simultaneously.
Thanks to [@paperclover](https://github.com/paperclover) for fixing this.
## []()[Fixed: describe.only + nested describe/test](bun-v1.0.28.html#fixed-describe-only-nested-describe-test)
Previously, the test `my test here` would not run in the following code:
```
describe.only("outer", () => {
describe("inner", () => {
test("my test here", () => {
expect(1).toBe(1);
});
});
});
```
The bug was that `describe.only` was not propagating to nested non-describe.only blocks. This has been fixed.
## []()[Fixed: `--only` flag with test.each](bun-v1.0.28.html#fixed-only-flag-with-test-each)
Previously, the test.each block would run in the following code:
```
describe.only("outer", () => {});
test.each([1, 2, 3])("my test %d here should never run!", () => {
expect(1).toBe(1);
});
```
This was a bug! test.each should not have run. This bug has been fixed.
## []()[node:readline & node:events.on bugfixes](bun-v1.0.28.html#node-readline-node-events-on-bugfixes)
Thanks to [@yschroe](https://github.com/yschroe), this release includes 3 bugfixes for node:readline and node:events.on:
- Fixes a bug in events.on which causes events to be skipped
- Fixes readline does not read all line when looping with iterator
- Fixes readline module yields wrong and incomplete values with a bad performance
## []()[node:http2 bugfix](bun-v1.0.28.html#node-http2-bugfix)
Previously, passing a header that can only be one value (like `Authorization`) via an array of one element (like `['Bearer token']`) would throw an error in node:http2. This has been fixed. Now it only throws if truly multiple values are passed in.
This bug impacted Firebase & Firestore. There are still bugs blocking Firebase & Firestore from being usable in Bun, but this gets us closer.
## []()[Bun Shell stdin redirect bugfix](bun-v1.0.28.html#bun-shell-stdin-redirect-bugfix)
Bun Shell was not handling stdin redirection to file paths correctly. Thanks to [@zackradisic](https://github.com/zackradisic) for fixing this.
## []()[Windows is not ready yet](bun-v1.0.28.html#windows-is-not-ready-yet)
We are still working on Windows. There's a big PR we aim to merge on Wednesday, which will get us closer.
## []()[Thanks to 8 contributors!](bun-v1.0.28.html#thanks-to-8-contributors)
- [@camero2734](https://github.com/camero2734)
- [@DaleSeo](https://github.com/DaleSeo)
- [@eliot-akira](https://github.com/eliot-akira)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@risu729](https://github.com/risu729)
- [@yschroe](https://github.com/yschroe)
- [@zackradisic](https://github.com/zackradisic)
[**Full Changelog**](https://github.com/oven-sh/bun/compare/bun-v1.0.27...bun-v1.0.28)
* * *
#### [Bun v1.0.27](bun-v1.0.27.html)
#### [Bun v1.0.29](bun-v1.0.29.html)
On this page
- [Fixed: Crash when using Prisma](bun-v1.0.28.html#fixed-crash-when-using-prisma)
- [Fixed: Astro v4.4 throwing an error](bun-v1.0.28.html#fixed-astro-v4-4-throwing-an-error)
- [Fixed: describe.only + nested describe/test](bun-v1.0.28.html#fixed-describe-only-nested-describe-test)
- [Fixed: `--only` flag with test.each](bun-v1.0.28.html#fixed-only-flag-with-test-each)
- [node:readline & node:events.on bugfixes](bun-v1.0.28.html#node-readline-node-events-on-bugfixes)
- [node:http2 bugfix](bun-v1.0.28.html#node-http2-bugfix)
- [Bun Shell stdin redirect bugfix](bun-v1.0.28.html#bun-shell-stdin-redirect-bugfix)
- [Windows is not ready yet](bun-v1.0.28.html#windows-is-not-ready-yet)
- [Thanks to 8 contributors!](bun-v1.0.28.html#thanks-to-8-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.29.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.29
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · February 23, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one.
This release fixes 8 bugs. `Bun.stringWidth(a)` is a ~6,756x faster drop-in replacement for the popular `"string-width"` package. bunx now checks for updates more frequently. Adds `expect().toBeOneOf()` in `bun:test`. Memory leak impacting Prisma is fixed. Shell now supports advanced redirects like `2>&1`, `&>`. Reliability improvements to bunx, bun install, WebSocket client, and Bun Shell
#### Previous releases
- [`v1.0.28`](bun-v1.0.28.html) fixes 6 bugs (addressing 26 👍 reactions). Fixes bugs impacting Prisma and Astro, `node:events`, `node:readline`, and `node:http2`. Fixes a bug in Bun Shell involving stdin redirection and fixes bugs in `bun:test` with `test.each` and `describe.only`.
- [`v1.0.27`](bun-v1.0.27.html) fixes 72 bugs (addressing 192 👍 reactions), Bun Shell supports throwing on non-zero exit codes, stream Response bodies using async generators, improves reliability of fetch(), http2 client, Bun.Glob fixes. Fixes a regression with bun --watch on Linux. Improves Node.js compatibility
- [`v1.0.26`](bun-v1.0.26.html) fixes 30 bugs (addressing 60 👍 reactions), adds support for multi-statement queries in bun:sqlite, makes bun --watch more reliable in longer-running sessions, Bun.FileSystemRouter now supports more than 64 routes, fixes a bug with expect().toStrictEqual(), fixes 2 bugs with error.stack, improves Node.js compatibility
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
```
## []()[bunx checks for updates more frequently](bun-v1.0.29.html#bunx-checks-for-updates-more-frequently)
`bunx` is like `npx` except powered by `bun install`. It starts [100x faster than npx](https://twitter.com/jarredsumner/status/1606163655527059458?lang=en).
A cache invalidation bug in `bunx` caused it to not check for updates as frequently as it should. Now we rely on the timestamp from `stat` to determine if it's been 24 hours since the last check, which is more reliable.
We've also made it so explicitly using a tag like `bunx create-vite@latest` will always check for the latest version and delete the previously installed version if it existed.
Thanks to [@paperclover](https://github.com/paperclover) for fixing this.
## []()[Bun.stringWidth() ~6,756x faster `"string-width"` replacement](bun-v1.0.29.html#bun-stringwidth-6-756x-faster-string-width-replacement)
`Bun.stringWidth(string)` returns the visible width of a string in a terminal. This is useful when you want to know how many columns a string will take up in a terminal.
```
import { stringWidth } from "bun";
// text
console.log(stringWidth("hello")); // => 5
// emoji
console.log(stringWidth("👋")); // => 2
// ansi colors
console.log(stringWidth("\u001b[31mhello\u001b[39m")); // => 5
// fullwidth characters
console.log(stringWidth("你好")); // => 4
// graphemes
console.log(stringWidth("👩👩👧👦")); // => 2
```
It accounts for [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code), [fullwidth characters](https://en.wikipedia.org/wiki/Halfwidth_and_fullwidth_forms), graphemes, and emojis. It supports Latin1, UTF-16, and UTF-8 encodings, with optimized implementations for each.
The [`string-width`](https://www.npmjs.com/package/string-width) package gets over 100m downloads/week. Making it a built-in function in Bun means you don't need to install an extra package for this common use case, and lets us optimize it. Huge thanks to [@sindresorhus](https://github.com/sindresorhus) for creating `string-width` and for the inspiration to include it in Bun.
[In this benchmark](https://github.com/oven-sh/bun/blob/f75306db0fc6ab6e0755128d062d7451266d4f0d/bench/snippets/string-width.mjs#L1-L40), `Bun.stringWidth` performs ~6,756x faster than `string-width` for ascii input > 500 characters. The range is from 48x faster in the worst-case scenario to 137,623x faster for 25,000 ascii or ansi characters.
```
❯ bun string-width.mjs
cpu: 13th Gen Intel(R) Core(TM) i9-13900
runtime: bun 1.0.29 (x64-linux)
benchmark time (avg) (min … max) p75 p99 p995
------------------------------------------------------------------------------------- -----------------------------
Bun.stringWidth 500 chars ascii 37.09 ns/iter (36.77 ns … 41.11 ns) 37.07 ns 38.84 ns 38.99 ns
❯ node string-width.mjs
cpu: 13th Gen Intel(R) Core(TM) i9-13900
runtime: node v21.4.0 (x64-linux)
benchmark time (avg) (min … max) p75 p99 p995
------------------------------------------------------------------------------------- -----------------------------
npm/string-width 500 chars ascii 249,710 ns/iter (239,970 ns … 293,180 ns) 250,930 ns 276,700 ns 281,450 ns
```
To make `Bun.stringWidth` fast, we've implemented it in Zig using optimized SIMD instructions, accounting for Latin1, UTF-16, and UTF-8 encodings. It implements the same API as `string-width` and passes their tests. This also fixes an edgecase in `console.table`. Thanks to [@nektro](https://github.com/nektro) for implementing this!
View full benchmark
As a reminder, 1 nanosecond (ns) is 1 billionth of a second. Here's a quick reference for converting between units:
UnitPer 1 Millisecondns1 / 1,000,000µs1 / 1,000ms1s1000
Bun:
```
❯ bun string-width.mjs
cpu: 13th Gen Intel(R) Core(TM) i9-13900
runtime: bun 1.0.29 (x64-linux)
benchmark time (avg) (min … max) p75 p99 p995
------------------------------------------------------------------------------------- -----------------------------
Bun.stringWidth 5 chars ascii 16.52 ns/iter (16.28 ns … 20.3 ns) 16.5 ns 17.44 ns 17.57 ns
Bun.stringWidth 50 chars ascii 20.02 ns/iter (19.19 ns … 28.14 ns) 19.99 ns 21.96 ns 22.22 ns
Bun.stringWidth 500 chars ascii 37.31 ns/iter (36.69 ns … 40.7 ns) 37.1 ns 39.21 ns 39.27 ns
Bun.stringWidth 5,000 chars ascii 216.34 ns/iter (215.71 ns … 228.52 ns) 216.22 ns 228.05 ns 228.48 ns
Bun.stringWidth 25,000 chars ascii 1.01 µs/iter (1.01 µs … 1.06 µs) 1.01 µs 1.06 µs 1.06 µs
Bun.stringWidth 9 chars ascii+ansi 20.59 ns/iter (20.35 ns … 22.48 ns) 20.55 ns 21.72 ns 21.83 ns
Bun.stringWidth 90 chars ascii+ansi 23.87 ns/iter (23.61 ns … 26.56 ns) 23.84 ns 25.43 ns 26.55 ns
Bun.stringWidth 900 chars ascii+ansi 53.74 ns/iter (53.42 ns … 56.88 ns) 53.64 ns 56.73 ns 56.76 ns
Bun.stringWidth 9,000 chars ascii+ansi 377.62 ns/iter (377.22 ns … 379.05 ns) 377.73 ns 378.96 ns 379.05 ns
Bun.stringWidth 45,000 chars ascii+ansi 1.82 µs/iter (1.81 µs … 1.92 µs) 1.82 µs 1.92 µs 1.92 µs
Bun.stringWidth 7 chars ascii+emoji 54.06 ns/iter (53.43 ns … 55.01 ns) 54.21 ns 54.74 ns 54.8 ns
Bun.stringWidth 70 chars ascii+emoji 355.6 ns/iter (350.89 ns … 378.26 ns) 356.72 ns 375.33 ns 378.26 ns
Bun.stringWidth 700 chars ascii+emoji 3.3 µs/iter (3.28 µs … 3.38 µs) 3.3 µs 3.38 µs 3.38 µs
Bun.stringWidth 7,000 chars ascii+emoji 32.72 µs/iter (32.23 µs … 815.5 µs) 32.73 µs 33.85 µs 33.95 µs
Bun.stringWidth 35,000 chars ascii+emoji 163.83 µs/iter (161.33 µs … 177.04 µs) 163.99 µs 174.15 µs 175.94 µs
Bun.stringWidth 8 chars ansi+emoji 67.94 ns/iter (67.31 ns … 69.56 ns) 68.09 ns 68.56 ns 68.68 ns
Bun.stringWidth 80 chars ansi+emoji 495.47 ns/iter (488.47 ns … 524.57 ns) 496.08 ns 523.26 ns 524.57 ns
Bun.stringWidth 800 chars ansi+emoji 4.72 µs/iter (4.7 µs … 4.82 µs) 4.72 µs 4.82 µs 4.82 µs
Bun.stringWidth 8,000 chars ansi+emoji 46.84 µs/iter (46.35 µs … 56.24 µs) 46.92 µs 47.91 µs 48.07 µs
Bun.stringWidth 40,000 chars ansi+emoji 235.04 µs/iter (231.83 µs … 249.74 µs) 234.89 µs 247.96 µs 248.18 µs
Bun.stringWidth 19 chars ansi+emoji+ascii 136.22 ns/iter (135.02 ns … 139.89 ns) 136.47 ns 139.26 ns 139.56 ns
Bun.stringWidth 190 chars ansi+emoji+ascii 1.17 µs/iter (1.16 µs … 1.23 µs) 1.17 µs 1.23 µs 1.23 µs
Bun.stringWidth 1,900 chars ansi+emoji+ascii 11.45 µs/iter (11.25 µs … 16.09 µs) 11.45 µs 12.09 µs 12.15 µs
Bun.stringWidth 19,000 chars ansi+emoji+ascii 114 µs/iter (112.86 µs … 120.02 µs) 114.18 µs 116.39 µs 116.68 µs
Bun.stringWidth 95,000 chars ansi+emoji+ascii 571.82 µs/iter (564.88 µs … 605.42 µs) 572.04 µs 603.22 µs 603.9 µs
```
Node.js:
```
❯ node string-width.mjs
cpu: 13th Gen Intel(R) Core(TM) i9-13900
runtime: node v21.4.0 (x64-linux)
benchmark time (avg) (min … max) p75 p99 p995
-------------------------------------------------------------------------------------- -----------------------------
npm/string-width 5 chars ascii 3.16 µs/iter (3.05 µs … 3.42 µs) 3.19 µs 3.42 µs 3.42 µs
npm/string-width 50 chars ascii 20.12 µs/iter (18.89 µs … 415.35 µs) 19.5 µs 21.95 µs 22.77 µs
npm/string-width 500 chars ascii 250.09 µs/iter (240.33 µs … 2.07 ms) 250.36 µs 276.33 µs 284.44 µs
npm/string-width 5,000 chars ascii 6.74 ms/iter (6.63 ms … 6.85 ms) 6.76 ms 6.85 ms 6.85 ms
npm/string-width 25,000 chars ascii 144.36 ms/iter (143.2 ms … 146.15 ms) 144.78 ms 146.15 ms 146.15 ms
npm/string-width 9 chars ascii+ansi 4.66 µs/iter (4.55 µs … 5.01 µs) 4.71 µs 5.01 µs 5.01 µs
npm/string-width 90 chars ascii+ansi 36.15 µs/iter (34.42 µs … 513.73 µs) 35.42 µs 39.33 µs 149.33 µs
npm/string-width 900 chars ascii+ansi 508.56 µs/iter (490.99 µs … 540.08 µs) 515.87 µs 533.68 µs 536.92 µs
npm/string-width 9,000 chars ascii+ansi 19.33 ms/iter (18.92 ms … 19.55 ms) 19.4 ms 19.55 ms 19.55 ms
npm/string-width 45,000 chars ascii+ansi 451.84 ms/iter (444.37 ms … 458.41 ms) 454.91 ms 458.41 ms 458.41 ms
npm/string-width 7 chars ascii+emoji 3.75 µs/iter (3.64 µs … 4.2 µs) 3.9 µs 4.2 µs 4.2 µs
npm/string-width 70 chars ascii+emoji 23.78 µs/iter (22.25 µs … 395.2 µs) 23.01 µs 25.39 µs 28.46 µs
npm/string-width 700 chars ascii+emoji 251.04 µs/iter (237.56 µs … 469.57 µs) 254.47 µs 334.36 µs 407.38 µs
npm/string-width 7,000 chars ascii+emoji 4.6 ms/iter (4.45 ms … 6.45 ms) 4.61 ms 5.48 ms 6.45 ms
npm/string-width 35,000 chars ascii+emoji 92.82 ms/iter (91.79 ms … 95.1 ms) 92.7 ms 95.1 ms 95.1 ms
npm/string-width 8 chars ansi+emoji 4.3 µs/iter (3.76 µs … 4.82 µs) 4.56 µs 4.82 µs 4.82 µs
npm/string-width 80 chars ansi+emoji 24.26 µs/iter (22.67 µs … 652.98 µs) 23.45 µs 25.91 µs 27.83 µs
npm/string-width 800 chars ansi+emoji 259.56 µs/iter (244.07 µs … 490.51 µs) 257.48 µs 348.52 µs 410.1 µs
npm/string-width 8,000 chars ansi+emoji 5.33 ms/iter (5.15 ms … 5.56 ms) 5.47 ms 5.55 ms 5.56 ms
npm/string-width 40,000 chars ansi+emoji 104.32 ms/iter (102.36 ms … 110.73 ms) 104.94 ms 110.73 ms 110.73 ms
npm/string-width 19 chars ansi+emoji+ascii 6.55 µs/iter (6.36 µs … 6.77 µs) 6.58 µs 6.77 µs 6.77 µs
npm/string-width 190 chars ansi+emoji+ascii 55.18 µs/iter (52.49 µs … 317.03 µs) 53.88 µs 81.87 µs 171.48 µs
npm/string-width 1,900 chars ansi+emoji+ascii 699.56 µs/iter (650.96 µs … 933.47 µs) 720.99 µs 817.92 µs 847.01 µs
npm/string-width 19,000 chars ansi+emoji+ascii 25.99 ms/iter (25.6 ms … 27.59 ms) 26.12 ms 27.59 ms 27.59 ms
npm/string-width 95,000 chars ansi+emoji+ascii 3.7 s/iter (3.68 s … 3.73 s) 3.71 s 3.73 s 3.73 s
```
## []()[`expect(a).toBeOneOf([a, b, c])` in `bun:test`](bun-v1.0.29.html#expect-a-tobeoneof-a-b-c-in-bun-test)
[`bun:test`](../docs/cli/test.html) gets a new matcher: `toBeOneOf`. This is useful when you want to check if a value is one of a list of values.
```
import { test, expect } from "bun:test";
test("my test here", () => {
expect(1).toBeOneOf([1, 2, 3]);
});
```
This matcher is also supported by the popular [`jest-extended`](https://jest-extended.jestcommunity.dev/docs/matchers/toBeOneOf) package.
> looks like expect().toBeOneOf() is 500x faster in bun test compared to Jest [pic.twitter.com/0sAGJ8um8v](https://t.co/0sAGJ8um8v)
>
> — Jarred Sumner (@jarredsumner) [February 22, 2024](https://twitter.com/jarredsumner/status/1760779425371836771?ref_src=twsrc%5Etfw)
##### How is this different than expect(a).toInclude(b)?
`expect(a).toInclude(b)` checks if `a` includes `b`. `expect(a).toBeOneOf([a, b, c])` checks if `a` is one of `[a, b, c]`. `toBeOneOf` operates on the actual value, while `toInclude` operates on the expected value.
```
import { test, expect } from "bun:test";
test("my test here", () => {
expect([1, 2, 3]).toInclude(1);
expect(1).toBeOneOf([1, 2, 3]);
});
```
When the goal is to check if a value is one of a list of values, `toBeOneOf` is more readable and gives a better error message when it fails.
## []()[Shell supports advanced redirects like `2>&1`, `&>`](bun-v1.0.29.html#shell-supports-advanced-redirects-like-2-1)
Bun Shell now supports advanced redirects like `2>&1` and `&>`
To output stderr to stdout, you can use `2>&1`:
```
import { $ } from "bun";
await $`vite build 2>&1 output.txt`;
```
To redirect both stdout and stderr, you can use `&>`:
```
import { $ } from "bun";
await $`next build &> output.txt`;
```
We've also added support for `2>>` to append stderr.
Thanks to [@zackradisic](https://github.com/zackradisic) for implementing this.
## []()[Fixed: bun install semver pre-release bug](bun-v1.0.29.html#fixed-bun-install-semver-pre-release-bug)
An edgecase where `bun install` would sometimes fail to resolve a pre-release version that `node-semver` resolved correctly has been fixed.
This bug impacted the `svelte-eslint-parser` package with an error like:
```
error: No version matching ">=0.34.0-next.4 <1.0.0" found for specifier "svelte-eslint-parser"
```
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this.
## []()[Fixed: WebSocket client short messages bug](bun-v1.0.29.html#fixed-websocket-client-short-messages-bug)
A bug where a message with a payload of 1 or 2 bytes would sometimes cause timeouts in the WebSocket client has been fixed. This bug did not impact the WebSocket server. Thanks to [@lithdew](https://github.com/lithdew) for fixing this. This was @lithdew's first PR to Bun, but we've been using @lithdew's open source code in many places throughout Bun for awhile now.
## []()[Fixed: Memory leak in napi impacting Prisma](bun-v1.0.29.html#fixed-memory-leak-in-napi-impacting-prisma)
A memory leak in napi (which impacted Prisma) has been fixed.
[In a microbenchmark](https://github.com/oven-sh/bun/pull/9035), it reduced memory usage from 1720 megabytes to 275 megabytes (a 6x reduction).
Thanks to [@camero2734](https://github.com/camero2734) for fixing this.
## []()[Fixed: Memory leak regression in response.blob()](bun-v1.0.29.html#fixed-memory-leak-regression-in-response-blob)
A regression introduced in Bun v1.0.26 causing a memory leak in `response.blob()` has been fixed. Thanks to [@nektro](https://github.com/nektro) for fixing this!
## []()[Fixed: Bun.password.verify on long passwords with bcrypt](bun-v1.0.29.html#fixed-bun-password-verify-on-long-passwords-with-bcrypt)
bcrypt has a maximum password length of 72 characters. This is part of the reason why `Bun.password.hash` defaults to the more modern [`Argon2`](https://en.wikipedia.org/wiki/Argon2) algorithm.
To compensate for the max password length in bcrypt, when `algorithm` is set to `bcrypt` and the password is longer than 72 characters, `Bun.password.hash` uses SHA-512 on the password input and sends the SHA-512 hash to bcrypt (the choice of SHA-512 was suggested by the author of the popular [libsodium](https://github.com/jedisct1/libsodium) cryptography library).
But, we weren't doing this for `Bun.password.verify` when the password was longer than 72 characters and the algorithm was set to `bcrypt`. This meant you could run into situations where `Bun.password.verify` would return `false` for a password that was previously hashed with `Bun.password.hash`.
This has been fixed so that `Bun.password.verify` now behaves the same as `Bun.password.hash` when the password is longer than 72 characters when using bcrypt. Thanks to [@argosphil](https://github.com/argosphil) for fixing this.
## []()[Fixed: bun install vendored node\_modules with hardlinks](bun-v1.0.29.html#fixed-bun-install-vendored-node-modules-with-hardlinks)
Occasionally, packages published to npm include a vendored `node_modules` directory in a subdirectory (often by accident). Previously, `bun install` would ignore these vendored node\_modules folders when using hardlinks to install, which broke packages relying on this behavior. We've fixed it so `bun install` no longer ignores vendored node\_modules folders.
Thanks to [@eemelipa](https://github.com/eemelipa) for fixing this.
## []()[Fixed: Shell substitution bug adding extra space character](bun-v1.0.29.html#fixed-shell-substitution-bug-adding-extra-space-character)
Previously, the following code in Bun Shell would add an extra space character:
```
echo $(echo id)/$(echo region) # => "id / region"
```
Now it correctly outputs:
```
echo $(echo id)/$(echo region) # => "id/region"
```
Thanks to [@zackradisic](https://github.com/zackradisic).
## []()[Fixed: Shell latin1 template encoding bug](bun-v1.0.29.html#fixed-shell-latin1-template-encoding-bug)
A bug where Bun Shell would sometimes handle non-ascii latin1 characters incorrectly has been fixed. Thanks to [@zackradisic](https://github.com/zackradisic).
## []()[Fixed: bunx with multiple users on the same machine](bun-v1.0.29.html#fixed-bunx-with-multiple-users-on-the-same-machine)
bunx now works correctly when multiple users on the same machine use it. Since bunx stores its cache in the temporary directory, multiple users on the same machine share the same cache directory. This sometimes caused permissions issues. We've fixed this by including the `uid` in the cache key so that different users don't share the same cache.
Thanks to [@paperclover](https://github.com/paperclover) for fixing this.
## []()[Bundows is soon](bun-v1.0.29.html#bundows-is-soon)
We continue to work on Windows support. Windows will be supported in Bun v1.1.
## []()[Thanks to 8 contributors!](bun-v1.0.29.html#thanks-to-8-contributors)
- [@argosphil](https://github.com/argosphil)
- [@camero2734](https://github.com/camero2734)
- [@dylan-conway](https://github.com/dylan-conway)
- [@eemelipa](https://github.com/eemelipa)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@lithdew](https://github.com/lithdew)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@zackradisic](https://github.com/zackradisic)
* * *
#### [Bun v1.0.28](bun-v1.0.28.html)
#### [Bun v1.0.30](bun-v1.0.30.html)
On this page
- [bunx checks for updates more frequently](bun-v1.0.29.html#bunx-checks-for-updates-more-frequently)
- [Bun.stringWidth() ~6,756x faster `"string-width"` replacement](bun-v1.0.29.html#bun-stringwidth-6-756x-faster-string-width-replacement)
- [`expect(a).toBeOneOf([a, b, c])` in `bun:test`](bun-v1.0.29.html#expect-a-tobeoneof-a-b-c-in-bun-test)
- [Shell supports advanced redirects like `2>&1`, `&>`](bun-v1.0.29.html#shell-supports-advanced-redirects-like-2-1)
- [Fixed: bun install semver pre-release bug](bun-v1.0.29.html#fixed-bun-install-semver-pre-release-bug)
- [Fixed: WebSocket client short messages bug](bun-v1.0.29.html#fixed-websocket-client-short-messages-bug)
- [Fixed: Memory leak in napi impacting Prisma](bun-v1.0.29.html#fixed-memory-leak-in-napi-impacting-prisma)
- [Fixed: Memory leak regression in response.blob()](bun-v1.0.29.html#fixed-memory-leak-regression-in-response-blob)
- [Fixed: Bun.password.verify on long passwords with bcrypt](bun-v1.0.29.html#fixed-bun-password-verify-on-long-passwords-with-bcrypt)
- [Fixed: bun install vendored node\_modules with hardlinks](bun-v1.0.29.html#fixed-bun-install-vendored-node-modules-with-hardlinks)
- [Fixed: Shell substitution bug adding extra space character](bun-v1.0.29.html#fixed-shell-substitution-bug-adding-extra-space-character)
- [Fixed: Shell latin1 template encoding bug](bun-v1.0.29.html#fixed-shell-latin1-template-encoding-bug)
- [Fixed: bunx with multiple users on the same machine](bun-v1.0.29.html#fixed-bunx-with-multiple-users-on-the-same-machine)
- [Bundows is soon](bun-v1.0.29.html#bundows-is-soon)
- [Thanks to 8 contributors!](bun-v1.0.29.html#thanks-to-8-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.3.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.3
* * *
[Colin McDonnell](https://twitter.com/colinhacks) · September 22, 2023
[](../rss.xml)
Bun v1.0.3 fixes numerous bugs, adds support for metadata reflection via TypeScript's [`emitDecoratorMetadata`](https://www.typescriptlang.org/tsconfig#emitDecoratorMetadata), improves `fetch` compatibility, unblocks private registries like Azure Artifacts and Artifactory, bunx bugfix, console.log() depth 8 -> 2, Node.js compatibility improvements, and more.
Thank you for reporting issues. We are working hard to fix them as quickly as possible.
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. We've been releasing a lot of changes to Bun recently. Here's a recap of the last few releases. In case you missed it:
- [`v1.0.0`](../1.0.html) - Bun's first stable release!
- [`v1.0.1`](bun-v1.0.1.html) - Named imports for .json & .toml files, bugfixes to bun install, node:path, Buffer
- [`v1.0.2`](bun-v1.0.2.html) - Make `--watch` faster, plus bug fixes
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
```
## []()[`emitDecoratorMetadata` (used by Nest.js, TypeORM, and more)](bun-v1.0.3.html#emitdecoratormetadata-used-by-nest-js-typeorm-and-more)
Bun now supports metadata reflection via TypeScript's [`emitDecoratorMetadata`](https://www.typescriptlang.org/tsconfig#emitDecoratorMetadata). This means that you can use Nest.js with Bun, and it will work out of the box.
tsconfig.json
```
{
"compilerOptions": {
"emitDecoratorMetadata": true,
"experimentalDecorators": true
}
}
```
The `emitDecoratorMetadata` is a TypeScript compiler option that enables the generation of metadata for decorators via [reflect-metadata](https://www.npmjs.com/package/reflect-metadata).
## []()[Improved Nest.js support](bun-v1.0.3.html#improved-nest-js-support)
The addition of `emitDecoratorMetadata` dramatically improves Nest.js support, as it relies on custom ["Reflectors"](https://docs.nestjs.com/fundamentals/execution-context#reflection-and-metadata) to attach metadata and middleware to route handlers.
```
@Post()
@Roles(['admin']) // custom authentication decorator
async create(@Body() createCatDto: CreateCatDto) {
this.catsService.create(createCatDto);
}
```
## []()[`module.parent` support](bun-v1.0.3.html#module-parent-support)
In Node, the CommonJS `module.parent` getter is a reference to the parent module that required the current module. This is useful for determining whether a module was run directly or required by another module.
```
if (module.parent) {
// this module was required by another module
} else {
// this module was run directly
}
```
Bun now supports `module.parent` in the same way that Node does.
For ES modules, you can use `import.meta.main` to find out if the current module started the Bun process.
## []()[Bugfixes for private npm registries](bun-v1.0.3.html#bugfixes-for-private-npm-registries)
Improvements to [`fetch`](https://github.com/oven-sh/bun/pull/5729) unblock the usage of `bun install` with popular private package registries like Azure Artifacts and JFrog Artifactory.
You can configure a private registry using `bunfig.toml` instead of `.npmrc`. Provide values for `url`, `username`, and `password` under the `[install.registry]` section of your `bunfig.toml` file.
bunfig.toml
```
[install.registry]
url = "https://pkgs.dev.azure.com/my-azure-artifacts-user/_packaging/my-azure-artifacts-user/npm/registry"
username = "my-azure-artifacts-user"
# Bun v1.0.3+ supports using an environment variable here
password = "$NPM_PASSWORD"
```
Alternatively, specify a token instead of a username and password. This is useful for Artifactory.
bunfig.toml
```
[install.registry]
url = "https://my-artifactory-server.com/artifactory/api/npm/npm-virtual"
token = "$NPM_TOKEN"
```
For more complete information, refer to our new guides:
- [Using `bun install` with Artifactory](../guides/install/jfrog-artifactory.html)
- [Using `bun install` with Azure Artifacts](../guides/install/azure-artifacts.html)
## []()[`[0.5ms] env` message is now silent by default](bun-v1.0.3.html#0-5ms-env-message-is-now-silent-by-default)
Many people asked for this, so @colinhacks made it happen. The `[0.5ms] env loaded` message is now silent by default. You can still see it by setting `logLevel` to `"debug"` in `bunfig.toml`
> in the next version of bun
>
> \[0.1ms] ".env" is silenced by default [pic.twitter.com/F7V6hGZvrV](https://t.co/F7V6hGZvrV)
>
> — Jarred Sumner (@jarredsumner) [September 22, 2023](https://twitter.com/jarredsumner/status/1705102614793474448?ref_src=twsrc%5Etfw)
## []()[Node.js compatiblity improvements](bun-v1.0.3.html#node-js-compatiblity-improvements)
The work on Node.js compatibility continues. Here are some of the improvements in this release:
### []()[Implement `console.Console` constructor](bun-v1.0.3.html#implement-console-console-constructor)
The Node.js `console.Console` constructor has been implemented.
```
import { Console } from "console";
import { createWriteStream } from "fs";
const writer = new Console({ stdout: createWriteStream("log.txt") });
writer.log("hello");
writer.log("world", { x: 2 });
```
This fixes [`vitest`](https://github.com/oven-sh/bun/issues/4145) and webpack's [`ts-loader`](https://github.com/oven-sh/bun/issues/5558) when executed with the Bun runtime—though consider using `bun test` and `bun build` instead! Of course, there are a lot of tools and codebases that rely on these technologies which will now work with Bun.
#### Empty environment variables now appear as an empty string (`""`)
In `process.env` and `Bun.env`, empty environment variables appeared as `undefined` instead of an empty string. This is fixed, thanks to [@liz3](https://github.com/liz3).
#### `dns.lookupService` is now implemented
The `node:dns` function `dns.lookupService` is now implemented. Thanks to [@Hanaasagi](https://github.com/Hanaasagi).
#### console.log() depth is now 2 instead of 8
8 was nice, but caused issues with large objects filling up your terminal screen. Thanks to [@JibranKalia](https://github.com/JibranKalia). This aligns the behavior with Node.js.
#### node\_api\_create\_external\_string\_latin1 and node\_api\_create\_external\_string\_utf16
The node\_api functions `node_api_create_external_string_latin1` and `node_api_create_external_string_utf16` are now implemented
#### listen() in `node:http` callback bugfix
The error event was not emitting to the event listener correctly. Thanks to [@SuperAuguste](https://github.com/SuperAuguste) for fixing this.
## []()[Bugfixes](bun-v1.0.3.html#bugfixes)
#### Crash in `request.json()` fixed
A crash that could occur when calling `request.json()` was fixed. It was caused by incorrect exception handling in native code.
#### `bun pm rm cache` now works
The `bun pm rm cache` command now deletes the cache directory. Thanks to [@WingLim](https://github.com/WingLim).
#### Max redirect URL length is now 8192 instead of 4096
This fixes an issue with certain private npm registries.
#### bunx choosing version from $PATH instead of @version tag bugfix
A bug causing `bunx` to choose the version of the executable from `$PATH` instead of the `@version` tag was fixed
> in the next version of bun
>
> bunx foo@tag will always load the @tag version when a @tag is present, instead of choosing the version in [$PATH](https://twitter.com/search?q=%24PATH&src=ctag&ref_src=twsrc%5Etfw) [pic.twitter.com/eCMVa0gSxF](https://t.co/eCMVa0gSxF)
>
> — Jarred Sumner (@jarredsumner) [September 20, 2023](https://twitter.com/jarredsumner/status/1704390982534594744?ref_src=twsrc%5Etfw)
## []()[Full changelog](bun-v1.0.3.html#full-changelog)
[`#4652`](https://github.com/oven-sh/bun/pull/4652)VSCode Extension Bunlock Syntax-Highlighting and Docs Improvements by [@JeremyFunk](https://bun.sh/blog/JeremyFunk)[`#5451`](https://github.com/oven-sh/bun/pull/5451)docs(runtime): fix some typo. by [@zongzi531](https://bun.sh/blog/zongzi531)[`#5531`](https://github.com/oven-sh/bun/pull/5531)Update development.md by [@sonyarianto](https://bun.sh/blog/sonyarianto)[`#5525`](https://github.com/oven-sh/bun/pull/5525)fix(corking) uncork if needed by [@cirospaciari](https://bun.sh/blog/cirospaciari)[`#5503`](https://github.com/oven-sh/bun/pull/5503)fix(request) handle undefined/null/empty signal on request by [@cirospaciari](https://bun.sh/blog/cirospaciari)[`#5521`](https://github.com/oven-sh/bun/pull/5521)fix(bundler): Add a space before minified require by [@davidmhewitt](https://bun.sh/blog/davidmhewitt)[`#5505`](https://github.com/oven-sh/bun/pull/5505)fix(node/fs.watch): Check first char before trimming event filenames by [@davidmhewitt](https://bun.sh/blog/davidmhewitt)[`#5535`](https://github.com/oven-sh/bun/pull/5535)webkit upgrade by [@dylan-conway](https://bun.sh/blog/dylan-conway)[`#5555`](https://github.com/oven-sh/bun/pull/5555)Follow-up for workspace docs #5379 and #5229 by [@bdenham](https://bun.sh/blog/bdenham)[`#5579`](https://github.com/oven-sh/bun/pull/5579)fix: `ArrayBufferConstructor` type signature by [@52](https://bun.sh/blog/52)[`#5580`](https://github.com/oven-sh/bun/pull/5580)fix: `array-buffer.test-d.ts` test by [@52](https://bun.sh/blog/52)[`#4693`](https://github.com/oven-sh/bun/pull/4693)fix: node compatibility with empty path string (stat, exist, ...) by [@coratgerl](https://bun.sh/blog/coratgerl)[`#5603`](https://github.com/oven-sh/bun/pull/5603)Make error message when importing a node: module in a browser bundle clearer by [@Jarred-Sumner](https://bun.sh/blog/Jarred-Sumner)[`#5576`](https://github.com/oven-sh/bun/pull/5576)docs: fix typo in lockflie nav by [@Vilsol](https://bun.sh/blog/Vilsol)[`#5593`](https://github.com/oven-sh/bun/pull/5593)Docs: path aliases fix by [@e253](https://bun.sh/blog/e253)[`#5496`](https://github.com/oven-sh/bun/pull/5496)fix(fetch) handle 100 continue by [@cirospaciari](https://bun.sh/blog/cirospaciari)[`#5387`](https://github.com/oven-sh/bun/pull/5387)feat(encoding): TextDecoder support undefined by [@WingLim](https://bun.sh/blog/WingLim)[`#5481`](https://github.com/oven-sh/bun/pull/5481)fix(child\_process) unref next tick so exit/close event can be fired before application exits by [@cirospaciari](https://bun.sh/blog/cirospaciari)[`#5529`](https://github.com/oven-sh/bun/pull/5529)Implement VSCode tasks for bun by [@JeremyFunk](https://bun.sh/blog/JeremyFunk)[`#5610`](https://github.com/oven-sh/bun/pull/5610)fix(install): Return NotSupported when errno == XDEV by [@pan93412](https://bun.sh/blog/pan93412)[`#5510`](https://github.com/oven-sh/bun/pull/5510)Fix ZLS commit hash in the document by [@shinichy](https://bun.sh/blog/shinichy)[`#5628`](https://github.com/oven-sh/bun/pull/5628)Added .DS\_Store to gitignore-for-init by [@Cilooth](https://bun.sh/blog/Cilooth)[`#5615`](https://github.com/oven-sh/bun/pull/5615)Workaround #5604 by [@Jarred-Sumner](https://bun.sh/blog/Jarred-Sumner)[`#5626`](https://github.com/oven-sh/bun/pull/5626)Fix a TypeError in the documentation by [@LapsTimeOFF](https://bun.sh/blog/LapsTimeOFF)[`#5656`](https://github.com/oven-sh/bun/pull/5656)Add a way to disable the GC timer by [@Jarred-Sumner](https://bun.sh/blog/Jarred-Sumner)[`#5660`](https://github.com/oven-sh/bun/pull/5660)Remove hardcoded references to zig in Makefile by [@xbjfk](https://bun.sh/blog/xbjfk)[`#5595`](https://github.com/oven-sh/bun/pull/5595)feat(console.log): Print anonymous when class name is unknown by [@JibranKalia](https://bun.sh/blog/JibranKalia)[`#5572`](https://github.com/oven-sh/bun/pull/5572)feat(test): Implement `arrayContaining` by [@WingLim](https://bun.sh/blog/WingLim)[`#5655`](https://github.com/oven-sh/bun/pull/5655)In `bun:sqlite`, make sure we set the number tag correctly when creating the JSValue by [@Jarred-Sumner](https://bun.sh/blog/Jarred-Sumner)[`#5662`](https://github.com/oven-sh/bun/pull/5662)fix(config): support for registry url without trailing slash by [@Hanaasagi](https://bun.sh/blog/Hanaasagi)[`#5685`](https://github.com/oven-sh/bun/pull/5685)fix(docs): update formatting by [@rauny-brandao](https://bun.sh/blog/rauny-brandao)[`#5638`](https://github.com/oven-sh/bun/pull/5638)docs: add missing options from bun init by [@jumoog](https://bun.sh/blog/jumoog)[`#5594`](https://github.com/oven-sh/bun/pull/5594)change circles for color-blinds by [@Hamcker](https://bun.sh/blog/Hamcker)[`#5689`](https://github.com/oven-sh/bun/pull/5689)Fix HTTP listen behavior being non-compliant with node by [@paperclover](https://bun.sh/blog/paperclover)[`#5448`](https://github.com/oven-sh/bun/pull/5448)feat(runtime): Implement `console.Console` by [@paperclover](https://bun.sh/blog/paperclover)[`#5675`](https://github.com/oven-sh/bun/pull/5675)Implement `node_api_create_external_string_latin1` by [@Jarred-Sumner](https://bun.sh/blog/Jarred-Sumner)[`#5699`](https://github.com/oven-sh/bun/pull/5699)fix(runtime/node): Allow `new Buffer.alloc()` + Upgrade WebKit by [@paperclover](https://bun.sh/blog/paperclover)[`#5684`](https://github.com/oven-sh/bun/pull/5684)fix: remove unneeded branch in toJSONWithBytes by [@liz3](https://bun.sh/blog/liz3)[`#5696`](https://github.com/oven-sh/bun/pull/5696)update llvm version from 15 to 16 in makefile by [@nithinkjoy-tech](https://bun.sh/blog/nithinkjoy-tech)[`#5679`](https://github.com/oven-sh/bun/pull/5679)fix: provide empty string to 0 length process environment variables by [@liz3](https://bun.sh/blog/liz3)[`#5025`](https://github.com/oven-sh/bun/pull/5025)`bun run` fix missing script error on empty file by [@Parzival-3141](https://bun.sh/blog/Parzival-3141)[`#5444`](https://github.com/oven-sh/bun/pull/5444)Add navigator type definition by [@ruihe774](https://bun.sh/blog/ruihe774)[`#5716`](https://github.com/oven-sh/bun/pull/5716)Encode slashes in package names in the registry manifest request by [@Jarred-Sumner](https://bun.sh/blog/Jarred-Sumner)[`#5726`](https://github.com/oven-sh/bun/pull/5726)Make bun install --verbose more verbose by [@Jarred-Sumner](https://bun.sh/blog/Jarred-Sumner)[`#5730`](https://github.com/oven-sh/bun/pull/5730)Fixes #3712 by [@Jarred-Sumner](https://bun.sh/blog/Jarred-Sumner)[`#5729`](https://github.com/oven-sh/bun/pull/5729)Align fetch() redirect behavior with spec by [@Jarred-Sumner](https://bun.sh/blog/Jarred-Sumner)[`#5744`](https://github.com/oven-sh/bun/pull/5744)Get artifactory to work by [@Jarred-Sumner](https://bun.sh/blog/Jarred-Sumner)[`#5702`](https://github.com/oven-sh/bun/pull/5702)docs: Update Remix guide by [@brookslybrand](https://bun.sh/blog/brookslybrand)[`#5620`](https://github.com/oven-sh/bun/pull/5620)Added react installation to react.md by [@jt3k](https://bun.sh/blog/jt3k)[`#5597`](https://github.com/oven-sh/bun/pull/5597)remind users of the latest version by [@jumoog](https://bun.sh/blog/jumoog)[`#5562`](https://github.com/oven-sh/bun/pull/5562)docs: update `net` node documentation by [@weyert](https://bun.sh/blog/weyert)[`#5513`](https://github.com/oven-sh/bun/pull/5513)docs(development): typo which would lead to wrong llvm installation by [@sum117](https://bun.sh/blog/sum117)[`#5759`](https://github.com/oven-sh/bun/pull/5759)Doc updates by [@colinhacks](https://bun.sh/blog/colinhacks)[`#4571`](https://github.com/oven-sh/bun/pull/4571)fix(cli): `bun pm cache rm` command not work by [@WingLim](https://bun.sh/blog/WingLim)[`#5762`](https://github.com/oven-sh/bun/pull/5762)fix(Makefile) by [@cirospaciari](https://bun.sh/blog/cirospaciari)[`#5775`](https://github.com/oven-sh/bun/pull/5775)Fixes #5769 by [@Jarred-Sumner](https://bun.sh/blog/Jarred-Sumner)[`#5447`](https://github.com/oven-sh/bun/pull/5447)add warning to Ensure correct placement of the '--watch' flag by [@a4addel](https://bun.sh/blog/a4addel)[`#5456`](https://github.com/oven-sh/bun/pull/5456)Updated modules.md to address issue #5420 by [@h2210316651](https://bun.sh/blog/h2210316651)[`#4810`](https://github.com/oven-sh/bun/pull/4810)docs: add Qwik guide by [@sanyamkamat](https://bun.sh/blog/sanyamkamat)
## []()[New contributors](bun-v1.0.3.html#new-contributors)
Thanks to Bun's newest contributors!
- @52 made their first contribution in https://github.com/oven-sh/bun/pull/5579
- @a4addel made their first contribution in https://github.com/oven-sh/bun/pull/5447
- @AaronDewes made their first contribution in https://github.com/oven-sh/bun/pull/4779
- @bdenham made their first contribution in https://github.com/oven-sh/bun/pull/5555
- @brookslybrand made their first contribution in https://github.com/oven-sh/bun/pull/5702
- @Brooooooklyn made their first contribution in https://github.com/oven-sh/bun/pull/5788
- @Cilooth made their first contribution in https://github.com/oven-sh/bun/pull/5628
- @coratgerl made their first contribution in https://github.com/oven-sh/bun/pull/4693
- @ggobbe made their first contribution in https://github.com/oven-sh/bun/pull/5786
- @h2210316651 made their first contribution in https://github.com/oven-sh/bun/pull/5456
- @Hamcker made their first contribution in https://github.com/oven-sh/bun/pull/5594
- @igorshapiro made their first contribution in https://github.com/oven-sh/bun/pull/5873
- @ImBIOS made their first contribution in https://github.com/oven-sh/bun/pull/5885
- @JeremyFunk made their first contribution in https://github.com/oven-sh/bun/pull/4652
- @JibranKalia made their first contribution in https://github.com/oven-sh/bun/pull/5595
- @jonahsnider made their first contribution in https://github.com/oven-sh/bun/pull/5104
- @jt3k made their first contribution in https://github.com/oven-sh/bun/pull/5620
- @jumoog made their first contribution in https://github.com/oven-sh/bun/pull/5638
- @liz3 made their first contribution in https://github.com/oven-sh/bun/pull/5684
- @nithinkjoy-tech made their first contribution in https://github.com/oven-sh/bun/pull/5696
- @pan93412 made their first contribution in https://github.com/oven-sh/bun/pull/5610
- @rauny-brandao made their first contribution in https://github.com/oven-sh/bun/pull/5685
- @ruihe774 made their first contribution in https://github.com/oven-sh/bun/pull/5444
- @sanyamkamat made their first contribution in https://github.com/oven-sh/bun/pull/4810
- @shinichy made their first contribution in https://github.com/oven-sh/bun/pull/5510
- @sum117 made their first contribution in https://github.com/oven-sh/bun/pull/5513
- @Vilsol made their first contribution in https://github.com/oven-sh/bun/pull/5576
- @weyert made their first contribution in https://github.com/oven-sh/bun/pull/5562
- @xbjfk made their first contribution in https://github.com/oven-sh/bun/pull/5660
- @yadav-saurabh made their first contribution in https://github.com/oven-sh/bun/pull/5270
* * *
#### [Bun v1.0.2](bun-v1.0.2.html)
#### [Bun v1.0.4](bun-v1.0.4.html)
On this page
- [`emitDecoratorMetadata` (used by Nest.js, TypeORM, and more)](bun-v1.0.3.html#emitdecoratormetadata-used-by-nest-js-typeorm-and-more)
- [Improved Nest.js support](bun-v1.0.3.html#improved-nest-js-support)
- [`module.parent` support](bun-v1.0.3.html#module-parent-support)
- [Bugfixes for private npm registries](bun-v1.0.3.html#bugfixes-for-private-npm-registries)
- [`[0.5ms] env` message is now silent by default](bun-v1.0.3.html#0-5ms-env-message-is-now-silent-by-default)
- [Node.js compatiblity improvements](bun-v1.0.3.html#node-js-compatiblity-improvements)
- [Implement `console.Console` constructor](bun-v1.0.3.html#implement-console-console-constructor)
- [Bugfixes](bun-v1.0.3.html#bugfixes)
- [Full changelog](bun-v1.0.3.html#full-changelog)
- [New contributors](bun-v1.0.3.html#new-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.30.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.30
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · March 4, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one.
This release fixes 27 bugs (addressing 103 👍 reactions), fixes an 8x perf regression to Bun.serve(), adds a new `--conditions` flag to `bun build` and Bun's runtime, adds support for `expect.assertions()` and `expect.hasAssertions()` in Bun's test runner, fixes crashes and improves Node.js compatibility.
#### Previous releases
- [`v1.0.29`](bun-v1.0.29.html) fixes 8 bugs. Bun.stringWidth(a) is a ~6,756x faster drop-in replacement for the popular 'string-width' package. bunx checks for updates more frequently. Adds expect().toBeOneOf() in bun:test. Memory leak impacting Prisma is fixed. Shell now supports advanced redirects like '2>&1', '&>'. Reliability improvements to bunx, bun install, WebSocket client, and Bun Shell
- [`v1.0.28`](bun-v1.0.28.html) fixes 6 bugs (addressing 26 👍 reactions). Fixes bugs impacting Prisma and Astro, `node:events`, `node:readline`, and `node:http2`. Fixes a bug in Bun Shell involving stdin redirection and fixes bugs in `bun:test` with `test.each` and `describe.only`.
- [`v1.0.27`](bun-v1.0.27.html) fixes 72 bugs (addressing 192 👍 reactions), Bun Shell supports throwing on non-zero exit codes, stream Response bodies using async generators, improves reliability of fetch(), http2 client, Bun.Glob fixes. Fixes a regression with bun --watch on Linux. Improves Node.js compatibility
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
```
## []()[Fixed: 8x performance regression in `Bun.serve()` in certain cases](bun-v1.0.30.html#fixed-8x-performance-regression-in-bun-serve-in-certain-cases)
A performance regression when using streams to write exactly one chunk of data to the response body in a single tick of the event loop has been fixed in `Bun.serve()`. This regression was introduced in v1.0.4.
The following code sometimes reproduces the issue:
```
Bun.serve({
async fetch(req) {
return new Response(
new ReadableStream({
type: "direct",
async pull(controller) {
controller.write("hello");
await controller.end();
},
}),
);
},
});
```
Tip: when using nginx with Bun, make sure to set `proxy_http_version 1.1` in your nginx configuration. HTTP Keep-Alive is important for performance, and nginx by default disables it.
## []()[New flag: `--conditions`](bun-v1.0.30.html#new-flag-conditions)
The `--conditions` flag allows you to specify a list of conditions to use when resolving packages from package.json `"exports"`.
This flag is supported in both `bun build` and Bun's runtime.
```
# Use it with bun build:
```
```
bun build --conditions="react-server" --target=bun ./app/foo/route.js
```
```
# Use it with bun's runtime:
```
```
bun --conditions="react-server" ./app/foo/route.js
```
Bun already supported package.json `"exports"`, this release adds support for adding additional conditions to target.
You can also use `conditions` programmatically with `Bun.build`:
```
await Bun.build({
conditions: ["react-server"],
target: "bun",
entryPoints: ["./app/foo/route.js"],
});
```
This CLI flag is also supported by Node.js with the same syntax.
Thanks to [@igorwessel](https://github.com/igorwessel) for implementing this feature!
## []()[`expect.assertions()` and `expect.hasAssertions()` are now supported](bun-v1.0.30.html#expect-assertions-and-expect-hasassertions-are-now-supported)
`expect.assertions()` and `expect.hasAssertions()` are now supported in Bun's test runner.
```
test("expect.assertions()", () => {
expect.assertions(1);
expect(true).toBe(true);
});
test("expect.hasAssertions()", () => {
expect.hasAssertions();
expect(true).toBe(true);
});
```
Thanks to [@Yash-Singh1](https://github.com/Yash-Singh1) for implementing this feature!
## []()[`Bun.fileURLToPath(url)` now supports strings](bun-v1.0.30.html#bun-fileurltopath-url-now-supports-strings)
`Bun.fileURLToPath(url)` now supports strings as well as URL objects.
```
// new:
Bun.fileURLToPath("file:///path/to/file.txt");
// old (still works):
Bun.fileURLToPath(new URL("file:///path/to/file.txt"));
```
## []()[Bun Shell better stacktraces on error](bun-v1.0.30.html#bun-shell-better-stacktraces-on-error)
Bun Shell now provides better stacktraces on error.
Previously, Bun Shell would not include the full stacktrace when an error occurred. This has been fixed, thanks to [@zackradisic](https://github.com/zackradisic).
## []()[Fixed: potential crash in `Bun.serve()` with delayed request bodies](bun-v1.0.30.html#fixed-potential-crash-in-bun-serve-with-delayed-request-bodies)
A crash that could potentially occur when sending a buffered response after receiving a request body has been fixed.
The following code sometimes reproduces the issue:
```
Bun.serve({
development: true,
async fetch(request: Request): Promise<Response> {
await Bun.sleep(200 + Math.random() * 100);
const body = await (async function () {
return await request.json();
})();
return new Response(JSON.stringify(body));
},
});
```
This crash occurred because Bun will automatically reject pending Promises that consume requests when the request aborts, and Bun's code was not checking that the Promise to read the request body was still pending before attempting to reject the Promise. Rejecting the Promise triggered an assertion failure internally, which led to the crash.
## []()[Fixed: Headers with underscores and uppercase names in `Bun.serve()`](bun-v1.0.30.html#fixed-headers-with-underscores-and-uppercase-names-in-bun-serve)
Bun v1.0.28 added support for receiving headers with underscores in Bun.serve(). For several reasons, Bun.serve() automatically lowercases all incoming header names (HTTP headers are case insensitive by the spec). A bug in the HTTP server's code for lowercasing header names caused the underscore to be invalid in the header name, leading to unexpected behavior. This has been fixed.
## []()[Fixed: `textEncoder.encode()` JIT bug under certain conditions](bun-v1.0.30.html#fixed-textencoder-encode-jit-bug-under-certain-conditions)
A bug in the side effects configuration in `TextEncoder.prototype.encode` caused it to potentially return unexpected results when called thousands of times in a short loop when no allocations occur between calls. This has been fixed.
## []()[Fixed: Crash when printing error stacks with mocked functions](bun-v1.0.30.html#fixed-crash-when-printing-error-stacks-with-mocked-functions)
A bug in Bun's implementation of mock functions caused a crash when printing error stack traces that contain an anonymous mock function. This has been fixed.
The following test reproduces the crash:
```
test("#8794", () => {
const target = {
a() {
throw new Error("a");
return 1;
},
method() {
return target.a();
},
};
spyOn(target, "method");
for (let i = 0; i < 20; i++) {
try {
target.method();
expect.unreachable();
} catch (e) {
e.stack;
expect(e.stack).toContain("at method ");
expect(e.stack).toContain("at a ");
}
Bun.gc(false);
}
});
```
## []()[Fixed: crash in `expect(undefined).toContainKeys(a)`](bun-v1.0.30.html#fixed-crash-in-expect-undefined-tocontainkeys-a)
`expect(undefined).toContainKeys(array)` no longer crashes the test runner. This crash occurred due to missing a check for an object-like expect() value in the `toContainKeys` matcher.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this bug.
## []()[Fixed: Potential crash with timers in event loop](bun-v1.0.30.html#fixed-potential-crash-with-timers-in-event-loop)
An uninitialized memory access in the event loop library used by Bun could lead to a crash after about 16 minutes in certain cases. This crash could be reproduced most frequently on Linux ARM64 builds of Bun. Thanks to [@argosphil](https://github.com/argosphil) for fixing this bug.
## []()[Node.js compatiblity improvements](bun-v1.0.30.html#node-js-compatiblity-improvements)
This release includes several Node.js compatibility improvements.
### []()[`isKeyObject` in `util/types` is implemented](bun-v1.0.30.html#iskeyobject-in-util-types-is-implemented)
The `isKeyObject` function in `node:util/types` is implemented. This function returns true if the input is a KeyObject.
```
import { isKeyObject } from "node:util/types";
import { generateKeyPairSync } from "node:crypto";
isKeyObject({}); // false
isKeyObject(generateKeyPairSync("ed25519").publicKey); // true
```
### []()[`fdatasync` in node:fs is implemented](bun-v1.0.30.html#fdatasync-in-node-fs-is-implemented)
Bun now implements `fdatasync` in `node:fs`. This function synchronously writes all changes made to the file to disk.
```
import { fdatasync } from "node:fs";
fdatasync(fd);
```
### []()[`require.main` with symlinks behaves like Node.js](bun-v1.0.30.html#require-main-with-symlinks-behaves-like-node-js)
Bun now behaves like Node.js when using `require.main` with symlinks.
```
ln -s /path/to/real.js /path/to/symlink.js
```
```
// symlink.js
console.log(require.main === module); // true
```
This helps address a compatibility issue when running `prisma generate` using Bun.
### []()[Fixed: crash in `napi_get_buffer_info`](bun-v1.0.30.html#fixed-crash-in-napi-get-buffer-info)
When using the `napi_get_buffer_info` function in a native addon and passing a null pointer for the size argument, Bun no longer crashes.
### []()[Fixed: Emit end-of-file correctly in Node.js Readable](bun-v1.0.30.html#fixed-emit-end-of-file-correctly-in-node-js-readable)
A bug in our `node:stream` implementation caused the `readable` event to be emitted in a microtask instead of `process.nextTick`. This has been fixed, thanks to [@camero2734](https://github.com/camero2734).
This bug impacted `prisma generate` and other tools that use Node.js streams.
### []()[Fixed: missing event in node:streams impacting `node-fetch`](bun-v1.0.30.html#fixed-missing-event-in-node-streams-impacting-node-fetch)
A bug in our `node:streams` implementation where we called `destroy` on the stream on the next tick after calling `this.push(null)` led to `node:streams` not destroying the stream correctly. This bug caused `node-fetch` to never finish reading the response body. This bug impacted `prisma generate` and other tools that bundle `node-fetch` into their package.
Bun internally overrides `node-fetch` to use the `fetch` global provided by Bun, so packages using `node-fetch` directly were not impacted by this bug.
Thanks to [@camero2734](https://github.com/camero2734) for fixing this bug.
### []()[Fixed: 'request.endsWith is not a function' error in Next.js](bun-v1.0.30.html#fixed-request-endswith-is-not-a-function-error-in-next-js)
When using Bun to run a Next.js app, after a large number of requests you might run into an error like this:
```
57 | }).bind(null, resolveFilename, hookPropertyMap);
58 | // This is a hack to make sure that if a user requires a Next.js module that wasn't bundled
59 | // that needs to point to the rendering runtime version, it will point to the correct one.
60 | // This can happen on `pages` when a user requires a dependency that uses next/image for example.
61 | mod.prototype.require = function(request) {
62 | if (request.endsWith(".shared-runtime")) {
^
TypeError: request.endsWith is not a function. (In 'request.endsWith(".shared-runtime")', 'request.endsWith' is undefined)
at node_modules/next/dist/server/require-hook.js:62:9
at getMiddleware (node_modules/next/dist/server/next-server.js:904:26)
at node_modules/next/dist/server/base-server.js:173:32
at node_modules/next/dist/server/base-server.js:172:50
at node_modules/next/dist/server/base-server.js:275:34
```
This bug has been fixed. Our implementation of `require` was incorrectly using the tailcall intrinsic in JavaScriptCore which sometimes led to arguments in the function being forwarded to bound functions incorrectly.
### []()[Fixed: `cp` function in `node:fs` with relative paths](bun-v1.0.30.html#fixed-cp-function-in-node-fs-with-relative-paths)
A regression in v1.0.27 intended for Windows support caused the `cp` function in `node:fs` to not handle relative paths correctly. This bug has been fixed, thanks to [@argosphil](https://github.com/argosphil).
### []()[Fixed: `process.stdin` ends too early](bun-v1.0.30.html#fixed-process-stdin-ends-too-early)
Given a large enough input, the following code would incorrectly lose one of the last chunks of data:
```
const { Transform } = require("node:stream");
let totalChunkSize = 0;
const uppercase = new Transform({
transform(chunk, _encoding, callback) {
totalChunkSize += chunk.length;
callback(null, "");
},
});
process.stdin.pipe(uppercase).pipe(process.stdout);
process.stdin.on("end", () => console.log(totalChunkSize));
```
This impacted `prisma generate`, amongst others. Thanks to [@camero2734](https://github.com/camero2734) for fixing it.
## []()[Windows support is coming in Bun v1.1.0](bun-v1.0.30.html#windows-support-is-coming-in-bun-v1-1-0)
We are still working on Windows support. We are making progress, but it's not ready yet. You will see a release with Windows support soon.
## []()[Thanks to 14 contributors!](bun-v1.0.30.html#thanks-to-14-contributors)
- [@kyr0](https://github.com/kyr0)
- [@nektro](https://github.com/nektro)
- [@almmiko](https://github.com/almmiko)
- [@lgarron](https://github.com/lgarron)
- [@paperclover](https://github.com/paperclover)
- [@Electroid](https://github.com/Electroid)
- [@argosphil](https://github.com/argosphil)
- [@camero2734](https://github.com/camero2734)
- [@igorwessel](https://github.com/igorwessel)
- [@lucasmichot](https://github.com/lucasmichot)
- [@marvinruder](https://github.com/marvinruder)
- [@Yash-Singh1](https://github.com/Yash-Singh1)
- [@zackradisic](https://github.com/zackradisic)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
* * *
#### [Bun v1.0.29](bun-v1.0.29.html)
#### [Bun v1.0.31](bun-v1.0.31.html)
On this page
- [Fixed: 8x performance regression in `Bun.serve()` in certain cases](bun-v1.0.30.html#fixed-8x-performance-regression-in-bun-serve-in-certain-cases)
- [New flag: `--conditions`](bun-v1.0.30.html#new-flag-conditions)
- [`expect.assertions()` and `expect.hasAssertions()` are now supported](bun-v1.0.30.html#expect-assertions-and-expect-hasassertions-are-now-supported)
- [`Bun.fileURLToPath(url)` now supports strings](bun-v1.0.30.html#bun-fileurltopath-url-now-supports-strings)
- [Bun Shell better stacktraces on error](bun-v1.0.30.html#bun-shell-better-stacktraces-on-error)
- [Fixed: potential crash in `Bun.serve()` with delayed request bodies](bun-v1.0.30.html#fixed-potential-crash-in-bun-serve-with-delayed-request-bodies)
- [Fixed: Headers with underscores and uppercase names in `Bun.serve()`](bun-v1.0.30.html#fixed-headers-with-underscores-and-uppercase-names-in-bun-serve)
- [Fixed: `textEncoder.encode()` JIT bug under certain conditions](bun-v1.0.30.html#fixed-textencoder-encode-jit-bug-under-certain-conditions)
- [Fixed: Crash when printing error stacks with mocked functions](bun-v1.0.30.html#fixed-crash-when-printing-error-stacks-with-mocked-functions)
- [Fixed: crash in `expect(undefined).toContainKeys(a)`](bun-v1.0.30.html#fixed-crash-in-expect-undefined-tocontainkeys-a)
- [Fixed: Potential crash with timers in event loop](bun-v1.0.30.html#fixed-potential-crash-with-timers-in-event-loop)
- [Node.js compatiblity improvements](bun-v1.0.30.html#node-js-compatiblity-improvements)
- [`isKeyObject` in `util/types` is implemented](bun-v1.0.30.html#iskeyobject-in-util-types-is-implemented)
- [`fdatasync` in node:fs is implemented](bun-v1.0.30.html#fdatasync-in-node-fs-is-implemented)
- [`require.main` with symlinks behaves like Node.js](bun-v1.0.30.html#require-main-with-symlinks-behaves-like-node-js)
- [Fixed: crash in `napi_get_buffer_info`](bun-v1.0.30.html#fixed-crash-in-napi-get-buffer-info)
- [Fixed: Emit end-of-file correctly in Node.js Readable](bun-v1.0.30.html#fixed-emit-end-of-file-correctly-in-node-js-readable)
- [Fixed: missing event in node:streams impacting `node-fetch`](bun-v1.0.30.html#fixed-missing-event-in-node-streams-impacting-node-fetch)
- [Fixed: 'request.endsWith is not a function' error in Next.js](bun-v1.0.30.html#fixed-request-endswith-is-not-a-function-error-in-next-js)
- [Fixed: `cp` function in `node:fs` with relative paths](bun-v1.0.30.html#fixed-cp-function-in-node-fs-with-relative-paths)
- [Fixed: `process.stdin` ends too early](bun-v1.0.30.html#fixed-process-stdin-ends-too-early)
- [Windows support is coming in Bun v1.1.0](bun-v1.0.30.html#windows-support-is-coming-in-bun-v1-1-0)
- [Thanks to 14 contributors!](bun-v1.0.30.html#thanks-to-14-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.31.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.31
* * *
[Ashcon Partovi](https://twitter.com/ashconpartovi) · March 14, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one.
Bun v1.0.31 fixes 54 bugs (addresses 113 👍 reactions), introduces `bun --print`, `<stdin> | bun run -`, `bun add --trust`, `fetch()` with Unix sockets, fixes macOS binary size regression, fixes high CPU usage bug in spawn() on older linux, adds `util.styleText`, Node.js compatibiltiy improvements, bun install bugfixes, and bunx bugfixes.
#### Previous releases
- [`v1.0.30`](bun-v1.0.30.html) fixes 27 bugs (addressing 103 👍 reactions), fixes an 8x perf regression to Bun.serve(), adds a new `--conditions` flag to `bun build` and Bun's runtime, adds support for `expect.assertions()` and `expect.hasAssertions()` in Bun's test runner, fixes crashes and improves Node.js compatibility.
- [`v1.0.29`](bun-v1.0.29.html) fixes 8 bugs. Bun.stringWidth(a) is a ~6,756x faster drop-in replacement for the popular 'string-width' package. bunx checks for updates more frequently. Adds expect().toBeOneOf() in bun:test. Memory leak impacting Prisma is fixed. Shell now supports advanced redirects like '2>&1', '&>'. Reliability improvements to bunx, bun install, WebSocket client, and Bun Shell
- [`v1.0.28`](bun-v1.0.28.html) fixes 6 bugs (addressing 26 👍 reactions). Fixes bugs impacting Prisma and Astro, `node:events`, `node:readline`, and `node:http2`. Fixes a bug in Bun Shell involving stdin redirection and fixes bugs in `bun:test` with `test.each` and `describe.only`.
#### 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
```
## []()[New: `bun --print`](bun-v1.0.31.html#new-bun-print)
You can now use `bun --print` to evaluate the provided code and print the result using `console.log`. It's the same as `node --print`, except it supports top-level await, ESM, CommonJS, TypeScript, and JSX.
[](https://github.com/oven-sh/bun/assets/3238291/785a956a-a446-47b8-8835-dcd3af1ad6db)
Bun will also await dangling promises so you don't need to append `await` to your code.
[](https://github.com/oven-sh/bun/assets/3238291/619e3b3a-ec11-47ab-8723-c9a5c1bf4879)
For reference, here is an equivalent output using `node --print`:
[](https://github.com/oven-sh/bun/assets/3238291/6e782e85-21c0-4539-81ec-76c29a4e4873)
We implemented this because many npm packages have `postinstall` scripts that call `node --print`, and we don't want `bun install` to have any issues when you don't have Node.js installed.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for implementing this!
## []()[New: Run code from stdin](bun-v1.0.31.html#new-run-code-from-stdin)
You can now pipe stdin into Bun using `bun run -`. This is useful for running code from a file or a script.
[](https://github.com/oven-sh/bun/assets/3238291/5c063b3c-a522-4ea8-803c-078cc76659f4)
echo 'console.log("Hello")' | bun run -
```
cat file.js | bun run -
bun run - < file.js
```
As usual in Bun, this works with top-level await, ESM, CommonJS, TypeScript, and JSX.
Thanks to [@nektro](https://github.com/nektro) for adding this feature!
## []()[New: `bun add --trust <package>`](bun-v1.0.31.html#new-bun-add-trust-package)
We've made improvements to how Bun handles [`trustedDependencies`](../docs/install/lifecycle.html#trusteddependencies) in your package.json. By default, Bun does not run `postinstall` scripts for packages that are not trusted. This is a security feature to prevent malicious code from running on your machine.
When you first add a package, Bun will tell you if the package had a `postinstall` script that did not run.
```
bun add v1.0.31
Saved lockfile
installed @biomejs/biome@1.6.1 with binaries:
- biome
1 package installed [55.00ms]
Blocked 1 postinstall. Run `bun pm untrusted` for details.
```
## []()[New: `bun pm untrusted`](bun-v1.0.31.html#new-bun-pm-untrusted)
If you want to see which scripts were blocked, you can run `bun pm untrusted`.
```
bun pm untrusted v1.0.31
./node_modules/@biomejs/biome @1.6.1
» [postinstall]: node scripts/postinstall.js
These dependencies had their lifecycle scripts blocked during install.
If you trust them and wish to run their scripts, use `bun pm trust`.
```
## []()[New: `bun pm trust`](bun-v1.0.31.html#new-bun-pm-trust)
If you trust the package, you can run `bun pm trust [package]`. If you want to trust every package, you can also run `bun pm trust --all`.
```
bun pm trust v1.0.31
./node_modules/@biomejs/biome @1.6.1
✓ [postinstall]: node scripts/postinstall.js
1 script ran across 1 package [71.00ms]
```
The most popular packages are already trusted by default. You can see the list of trusted packages by running `bun pm default-trusted`.
If you already know you want to trust a dependency, you can add it using `bun add --trust [package]`. This will add the package and it's transitive dependencies to your `trustedDependencies` list so you don't need to run `bun pm trust` for that package.
```
{
"dependencies": {
"@biomejs/biome": "1.6.1"
},
"trustedDependencies": [
"@biomejs/biome"
]
}
```
Thanks to [@dylan-conway](https://github.com/dylan-conway) for improving this feature!
## []()[New: Unix sockets in `fetch()`](bun-v1.0.31.html#new-unix-sockets-in-fetch)
Bun now supports sending HTTP requests over a Unix socket.
```
const response = await fetch("http://localhost/info", {
// a file path to a Unix socket
unix: "/var/run/docker.sock",
});
const { ID } = await response.json();
console.log("Docker ID:", ID);
```
This means you can send `fetch()` request to services that speak HTTP but communicate using Unix sockets, like the Docker daemon.
This feature works with `fetch` and with `node:http`.
Ordinarily, unix sockets have a file path limit of around 108 characters, but on Linux we've added a workaround to support longer paths.
### []()[Abstract domain sockets in `fetch()`](bun-v1.0.31.html#abstract-domain-sockets-in-fetch)
We also added support for a obscure Linux feature called "abstract domain sockets".
Unlike Unix sockets, abstract sockets do not exist on the filesystem and get cleaned up automatically when both ends are closed. They are useful in environments where one process might not share filesystem permissions with the parent.
```
import { $, serve } from "bun";
const unix = "\0much-abstract-very-domain";
const server = serve({
unix,
fetch(req) {
return new Response("hello from abstract socket!");
},
});
// abstract domain sockets don't exist in the filesystem
// and they don't run on a port
await $`rm -rf ${unix.slice(1)}`;
// but we can still make requests to them
await $`curl --abstract-unix-socket ${unix.slice(1)} http://anything/hello`;
await fetch(`http://a:1234/b`, { unix });
server.stop();
```
Abstract sockets works using `fetch()`, `Bun.serve()`, and `socketPath` in `node:http`.
## []()[Fixed: Bun.spawn() 100% CPU usage bug on older Linux kernels](bun-v1.0.31.html#fixed-bun-spawn-100-cpu-usage-bug-on-older-linux-kernels)
Correctly spawning processes and monitoring when they exit is extremely complicated.
For Linux, Bun has two implementations for monitoring when a spawned process exits:
1. Using `pidfd_open(2)` which was fully added to the Linux Kernel in v5.10 (Dec 2020). pidfd is the most efficient way to monitor when a process exits because it can be used with epoll or io\_uring, like other file descriptors.
2. A fallback implementation using `SIGCHLD` which is supported on all Linux kernels
In psuedocode, the fallback implementation used to look something like this:
```
// in a dedicated thread:
while (true) {
for (const pid of pids) {
if (wait4(pid, WNOHANG, ...) === pid) {
pids.delete(pid);
tellBunThatProcessExited(pid);
}
}
sleepUntilNewPidsOrAnyProcessExits(eventfd, signalfd);
}
```
There was a bug where the equivalent of `sleepUntilNewPidsOrAnyProcessExits` would immediately resolve when it should've slept, causing Bun to consume 100% CPU on this thread.
There were two causes of this bug:
- We were not calling `read()` on the underlying `eventfd`, leading it to always be ready to read (and thus never sleep)
- The signal handler for `SIGCHLD` was not being installed correctly, leading the thread to never receive the signal
The first bug prevented the second bug from being noticed. Since it never slept, it never needed to wake up to handle the signal.
To prevent this from regressing in the future, we added a test that checks CPU usage when spawning `sleep infinity` and killing the subprocess after 1 second. If the CPU time is greater than 1/2 a second, the test fails.
### []()[Fixed: missing resourceUsage stats in Bun.spawn() on older Linux kernels](bun-v1.0.31.html#fixed-missing-resourceusage-stats-in-bun-spawn-on-older-linux-kernels)
Bun supports tracking how much memory, CPU time, and more stats a spawned process consumes. In the fallback implementation on older Linux kernels, we were not able to track these stats. Now we can.
```
const proc = Bun.spawn({
cmd: ["sleep", "1"],
});
await proc.exited;
console.log(proc.resourceUsage);
// Before: all 0s
```
## []()[Fixed: bun executable size regression on macOS](bun-v1.0.31.html#fixed-bun-executable-size-regression-on-macos)
In Bun v1.0.28 (last month), we added `Bun.stringWidth` which used more functions from the ICU internationalization library. A mistake in Bun's build process led to statically-linking the entire ICU library into the Bun executable on macOS. This increased the size of Bun's executable by 32.7 MB.
size on macOSBun version47.8 MBBun v1.0.3180.4 MBBun v1.0.3080.4 MBBun v1.0.2947.7 MBBun v1.0.28
This regression has been fixed, and we will add monitoring to prevent this from happening again.
## []()[Node.js compatibility improvements](bun-v1.0.31.html#node-js-compatibility-improvements)
### []()[New: `util.styleText()`](bun-v1.0.31.html#new-util-styletext)
Node.js recently added the [`util.styleText()`](https://nodejs.org/api/util.html#utilstyletextformat-text) API that allows you to style text using ANSI escape codes. We added this to Bun.
```
import { styleText } from "node:util";
console.log(styleText("red", "This is a failure!"));
console.log(styleText("yellow", "This is a warning!"));
console.log(styleText("green", "This is a success!"));
```
The code above will print the following output:
```
This is a failure!
This is a warning!
This is a success!
```
Thanks to [@paperclover](https://github.com/paperclover) for working on this!
### []()[New: `socketPath` option in `node:http`](bun-v1.0.31.html#new-socketpath-option-in-node-http)
We added support for the [`socketPath`](https://nodejs.org/api/http.html#httprequesturl-options-callback) option in `node:http`. This allows you to send HTTP requests using a Unix socket or an abstract domain socket.
```
import { request } from "node:http";
request(
{
socketPath: "/var/run/docker.sock",
path: "/info",
},
(res) => {
let data = "";
res.on("data", (chunk) => (data += chunk));
res.on("end", () => console.log(JSON.parse(data)));
},
);
```
### []()[New: `domainToASCII` and `domainToUnicode`](bun-v1.0.31.html#new-domaintoascii-and-domaintounicode)
We added support for the [`url.domainToASCII`](https://nodejs.org/api/url.html#urldomaintoasciidomain) and [`url.domainToUnicode`](https://nodejs.org/api/url.html#urldomaintounicodedomain) APIs. These are legacy Node.js APIs that useful for converting domain names to and from their ASCII and Unicode representations.
```
import { domainToASCII, domainToUnicode } from "node:url";
console.log(domainToASCII("www.🍕.com")); // => www.xn--xj8h.com
console.log(domainToUnicode("www.xn--xj8h.com")); // => www.🍕.com
```
Thanks to [@nektro](https://github.com/nektro) for adding these APIs!
### []()[Fixed: `child_process` could timeout early](bun-v1.0.31.html#fixed-child-process-could-timeout-early)
We fixed a bug where spawned `child_process` would timeout early when timeout was defined. This did not affect code where the timeout was not defined.
```
import { spawn } from "node:child_process";
const start = performance.now();
await new Promise((resolve, reject) => {
const child = spawn("sleep", ["1000"], { timeout: 1000 });
child.on("error", reject);
child.on("exit", resolve);
});
const duration = performance.now() - start;
console.log(duration); // ~10ms instead of ~1000ms
```
Thanks to [@Electroid](https://github.com/Electroid) for fixing this bug!
### []()[Fixed: `socket` event not firing in `node:http`](bun-v1.0.31.html#fixed-socket-event-not-firing-in-node-http)
We fixed a bug where the `socket` event would not fire in `node:http` when a client connected to a server.
```
import { request } from "http";
const request = request("http://localhost:8080");
await new Promise((resolve, reject) => {
request.on("error", reject);
request.on("socket", function onSocket(socket) {
request.destroy();
console.log(socket);
resolve();
});
});
```
## []()[Fixed: Crash with invalid arguments to `Bun.serve()`](bun-v1.0.31.html#fixed-crash-with-invalid-arguments-to-bun-serve)
We fixed a bug where `Bun.serve()` would crash if the `Bun.serve()` options were invalid in some cases. It should have thrown an error instead.
Thanks to [@paperclover](https://github.com/paperclover) for fixing this bug!
## []()[Fixed: Crash with `expect()` outside a test](bun-v1.0.31.html#fixed-crash-with-expect-outside-a-test)
We fixed a bug where `expect()` using an async resolver would crash if it was called outside of a test.
```
import { expect } from "bun:test";
expect(Bun.sleep(1000)).resolves.toBeTruthy();
```
Thanks to [@paperclover](https://github.com/paperclover) for fixing this bug!
## []()[Fixed: Potential crash when fetch() received an invalid `Location` header](bun-v1.0.31.html#fixed-potential-crash-when-fetch-received-an-invalid-location-header)
If the `Location` header received by `fetch()` pointed to an invalid URL, Bun would potentially crash. This has now been fixed.
Thanks to [@nektro](https://github.com/nektro) for fixing this bug!
## []()[Implemented: 2nd argument for `URLSearchParams.delete` & `URLSearchParams.has`](bun-v1.0.31.html#implemented-2nd-argument-for-urlsearchparams-delete-urlsearchparams-has)
The [`URLSearchParams.prototype.delete`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/delete) and [`URLSearchParams.prototype.has`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams/has) methods get support for a second `"value"` argument. This allows you to delete or check for a specific value in a URLSearchParams.
```
const params = new URLSearchParams("a=1&a=2&b=3");
params.delete("a", 1);
params.delete("b", undefined);
params + ""; // => actual='' expected='a=2'
```
This feature was a recent addition to the Web Platform, and we've added it to Bun.
## []()[Fixed: `.test.env` not loading when `NODE_ENV=test`](bun-v1.0.31.html#fixed-test-env-not-loading-when-node-env-test)
We found a bug where the `.test.env` file would not load when `NODE_ENV=test` and a `.production.env` file also existed. This has been fixed, thanks to [@nektro](https://github.com/nektro).
## []()[Fixed: Errors not buffered to stderr](bun-v1.0.31.html#fixed-errors-not-buffered-to-stderr)
We found a performance bug where Bun would not buffer writes when printing stack traces to stderr. This has now been fixed.
## []()[bun install bugfixes](bun-v1.0.31.html#bun-install-bugfixes)
### []()[Fixed: Various bugs with `bunx`](bun-v1.0.31.html#fixed-various-bugs-with-bunx)
We also fixed various bugs with `bunx`:
- `bunx --bun` would sometimes ignore the `--bun` flag, depending on the flag order.
- `bun x --bun` would forward the `--bun` flag to the script, instead of Bun.
- `bun --bun create` would crash and not work properly.
- `bunx <github>` would sometimes hang.
Thanks to [@paperclover](https://github.com/paperclover) for fixing these bugs!
### []()[Fixed: `node-gyp` would sometimes not run](bun-v1.0.31.html#fixed-node-gyp-would-sometimes-not-run)
A bug where `bun install` would not run lifecycle scripts when a package.json had both a `postinstall` script and a `bindings.gyp` file has been fixed. This bug impacted `node-pty`, among other packages.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this bug!
### []()[Fixed: `bun pm cache rm` now removes bunx cache](bun-v1.0.31.html#fixed-bun-pm-cache-rm-now-removes-bunx-cache)
Previously, `bun pm cache rm` would not remove the `node_modules` cache for `bunx`. This has been fixed.
## []()[Internal: I/O architecture changes](bun-v1.0.31.html#internal-i-o-architecture-changes)
In this release, we've reimplemented how Bun:
- Spawns processes
- Reads files (streaming)
- Writes files (streaming)
These new implementations do a better job of preventing reads/writes from blocking the main thread, without paying the cost of moving all I/O to a threadpool. Peak memory usage should be lower, especially with `node:stream` & `node:fs`.
Please report any bugs you find when using Bun.file(path).stream(), `fs.createReadStream`, `fs.createWriteStream`, or `Bun.spawn()`.
## []()[Windows support is close](bun-v1.0.31.html#windows-support-is-close)
We are close to shipping Windows support with Bun v1.1. Once Bun for Windows passes 95% of Bun's test suite, we will announce the release date.
> Bun for Windows currently passes 92.51% of Bun's test suite
>
> ████████████░ 92.51%
>
> — Bun (@bunjavascript) [March 12, 2024](https://twitter.com/bunjavascript/status/1767644565581017580?ref_src=twsrc%5Etfw)
## []()[Thank you to 18 contributors!](bun-v1.0.31.html#thank-you-to-18-contributors)
- [@BrookJeynes](https://github.com/BrookJeynes)
- [@camero2734](https://github.com/camero2734)
- [@cirospaciari](https://github.com/cirospaciari)
- [@cyfung1031](https://github.com/cyfung1031)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Electroid](https://github.com/Electroid)
- [@ErikOnBike](https://github.com/ErikOnBike)
- [@eventualbuddha](https://github.com/eventualbuddha)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@jdalton](https://github.com/jdalton)
- [@Marukome0743](https://github.com/Marukome0743)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@ryands17](https://github.com/ryands17)
- [@sequencerr](https://github.com/sequencerr)
- [@sharpobject](https://github.com/sharpobject)
- [@Yash-Singh1](https://github.com/Yash-Singh1)
- [@zieka](https://github.com/zieka)
[**Full Changelog**](https://github.com/oven-sh/bun/compare/bun-v1.0.30...bun-v1.0.31)
* * *
#### [Bun v1.0.30](bun-v1.0.30.html)
#### [Bun v1.0.32](bun-v1.0.32.html)
On this page
- [New: `bun --print`](bun-v1.0.31.html#new-bun-print)
- [New: Run code from stdin](bun-v1.0.31.html#new-run-code-from-stdin)
- [New: `bun add --trust <package>`](bun-v1.0.31.html#new-bun-add-trust-package)
- [New: `bun pm untrusted`](bun-v1.0.31.html#new-bun-pm-untrusted)
- [New: `bun pm trust`](bun-v1.0.31.html#new-bun-pm-trust)
- [New: Unix sockets in `fetch()`](bun-v1.0.31.html#new-unix-sockets-in-fetch)
- [Abstract domain sockets in `fetch()`](bun-v1.0.31.html#abstract-domain-sockets-in-fetch)
- [Fixed: Bun.spawn() 100% CPU usage bug on older Linux kernels](bun-v1.0.31.html#fixed-bun-spawn-100-cpu-usage-bug-on-older-linux-kernels)
- [Fixed: missing resourceUsage stats in Bun.spawn() on older Linux kernels](bun-v1.0.31.html#fixed-missing-resourceusage-stats-in-bun-spawn-on-older-linux-kernels)
- [Fixed: bun executable size regression on macOS](bun-v1.0.31.html#fixed-bun-executable-size-regression-on-macos)
- [Node.js compatibility improvements](bun-v1.0.31.html#node-js-compatibility-improvements)
- [New: `util.styleText()`](bun-v1.0.31.html#new-util-styletext)
- [New: `socketPath` option in `node:http`](bun-v1.0.31.html#new-socketpath-option-in-node-http)
- [New: `domainToASCII` and `domainToUnicode`](bun-v1.0.31.html#new-domaintoascii-and-domaintounicode)
- [Fixed: `child_process` could timeout early](bun-v1.0.31.html#fixed-child-process-could-timeout-early)
- [Fixed: `socket` event not firing in `node:http`](bun-v1.0.31.html#fixed-socket-event-not-firing-in-node-http)
- [Fixed: Crash with invalid arguments to `Bun.serve()`](bun-v1.0.31.html#fixed-crash-with-invalid-arguments-to-bun-serve)
- [Fixed: Crash with `expect()` outside a test](bun-v1.0.31.html#fixed-crash-with-expect-outside-a-test)
- [Fixed: Potential crash when fetch() received an invalid `Location` header](bun-v1.0.31.html#fixed-potential-crash-when-fetch-received-an-invalid-location-header)
- [Implemented: 2nd argument for `URLSearchParams.delete` & `URLSearchParams.has`](bun-v1.0.31.html#implemented-2nd-argument-for-urlsearchparams-delete-urlsearchparams-has)
- [Fixed: `.test.env` not loading when `NODE_ENV=test`](bun-v1.0.31.html#fixed-test-env-not-loading-when-node-env-test)
- [Fixed: Errors not buffered to stderr](bun-v1.0.31.html#fixed-errors-not-buffered-to-stderr)
- [bun install bugfixes](bun-v1.0.31.html#bun-install-bugfixes)
- [Fixed: Various bugs with `bunx`](bun-v1.0.31.html#fixed-various-bugs-with-bunx)
- [Fixed: `node-gyp` would sometimes not run](bun-v1.0.31.html#fixed-node-gyp-would-sometimes-not-run)
- [Fixed: `bun pm cache rm` now removes bunx cache](bun-v1.0.31.html#fixed-bun-pm-cache-rm-now-removes-bunx-cache)
- [Internal: I/O architecture changes](bun-v1.0.31.html#internal-i-o-architecture-changes)
- [Windows support is close](bun-v1.0.31.html#windows-support-is-close)
- [Thank you to 18 contributors!](bun-v1.0.31.html#thank-you-to-18-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.32.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.32
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · March 17, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one.
Bun v1.0.32 fixes 13 bugs and improves Node.js compatibility. 'ws' package can now send & receive ping/pong events. util.promisify'd setTimeout setInterval, setImmediate work now. FileHandle methods have been implemented.
#### Previous releases
- [`v1.0.31`](bun-v1.0.31.html) fixes 54 bugs (addresses 113 👍 reactions), introduces `bun --print`, `<stdin> | bun run -`, `bun add --trust`, `fetch()` with Unix sockets, fixes macOS binary size regression, fixes high CPU usage bug in spawn() on older linux, adds `util.styleText`, Node.js compatibiltiy improvements, bun install bugfixes, and bunx bugfixes
- [`v1.0.30`](bun-v1.0.30.html) fixes 27 bugs (addressing 103 👍 reactions), fixes an 8x perf regression to Bun.serve(), adds a new `--conditions` flag to `bun build` and Bun's runtime, adds support for `expect.assertions()` and `expect.hasAssertions()` in Bun's test runner, fixes crashes and improves Node.js compatibility.
- [`v1.0.29`](bun-v1.0.29.html) fixes 8 bugs. Bun.stringWidth(a) is a ~6,756x faster drop-in replacement for the popular 'string-width' package. bunx checks for updates more frequently. Adds expect().toBeOneOf() in bun:test. Memory leak impacting Prisma is fixed. Shell now supports advanced redirects like '2>&1', '&>'. Reliability improvements to bunx, bun install, WebSocket client, and Bun Shell
- [`v1.0.28`](bun-v1.0.28.html) fixes 6 bugs (addressing 26 👍 reactions). Fixes bugs impacting Prisma and Astro, `node:events`, `node:readline`, and `node:http2`. Fixes a bug in Bun Shell involving stdin redirection and fixes bugs in `bun:test` with `test.each` and `describe.only`.
#### 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
```
## []()[Fixed: GitHub actions timeout with bun install](bun-v1.0.32.html#fixed-github-actions-timeout-with-bun-install)
In Bun v1.0.31, we rewrote how a lot of I/O works in Bun in preparation for Windows support. This has led to a few regressions.
When more than 16 lifecycle scripts were invoked at the very end of the install process, `bun install` could potentially hang. To prevent system instability, bun install sets a maximum number of lifecycle scripts to execute concurrently. Due to a bug, the counter which increments the number of active lifecycle scripts was never decremented. This has been fixed.
Thanks to [@farreldarian](https://github.com/farreldarian) for providing an easy reproduction.
## []()[Fixed: bun install --production regression](bun-v1.0.32.html#fixed-bun-install-production-regression)
Bun v1.0.31 incorrectly changed the order of how `--frozen-lockfile` and `--production` flags were handled.
These flags are supposed to block installs that change the lockfile, but in v1.0.31, the install process would still occur. The exit code would still be correct (causing CI to fail), but the packages were still installed.
Now it correctly verifies the lockfile and does not install packages when `--frozen-lockfile` is passed before installing packages.
We've expanded our test suite to prevent this from regressing.
## []()[Fixed: Shell hanging with || &&](bun-v1.0.32.html#fixed-shell-hanging-with)
In certain cases the following command would hang:
```
import { $ } from "bun";
await $`echo 1 && echo 1`;
```
This was a regression caused by our I/O rewrite. We were not closing a file descriptor. This has been fixed, thanks to [@zackradisic](https://github.com/zackradisic). We have expanded our test suite to prevent this from regressing.
## []()[Fixed: Using bun shell instead of system shell](bun-v1.0.32.html#fixed-using-bun-shell-instead-of-system-shell)
In Bun v1.0.31, we unintentionally enabled the bun shell as the package.json script runner for posix. This was only meant to be enabled for Windows. We have written tests to prevent this from happening again.
We've also added the `--shell` flag that lets you opt-in to using either the `"bun"` shell or the `"system"` shell:
```
bun --shell=bun run my-package-json-script
```
## []()[Fixed: import.meta.url query string parameters](bun-v1.0.32.html#fixed-import-meta-url-query-string-parameters)
Bun was returning the encoded query string params in `import.meta.url` instead of the decoded query string params.
For the following code:
index.mjs
```
import './test?param=value'
```
test.mjs
```
console.log(import.meta.url);
```
Previously, Bun would return the following incorrect string:
run.sh
```
bun-1.0.31 ./index.mjs
```
```
file:///Users/jarred/test.mjs%3Fparam=value
```
Now Bun returns the correct string:
run.sh
```
bun ./index.mjs
```
```
file:///Users/jarred/test.mjs?param=value
```
Thanks to [@paperclover](https://github.com/paperclover) for fixing this.
## []()[Fixed: Subprocess.kill(undefined)](bun-v1.0.32.html#fixed-subprocess-kill-undefined)
The argument-coercion code for Bun.spawn().kill has been tweaked to match the behavior of Node.
Previously, this snippet would hang forever:
```
import { spawn } from "bun";
const proc = spawn({
cmd: ["sleep", "infinity"],
});
proc.kill(undefined);
```
Now `undefined` will coerce to the equivalent of not passing it any arguments -- `SIGTERM`. Similarly, `null`, `""`, `false` coerce to `SIGTERM`. This aligns the behavior with Node's child\_process.kill and honestly feels more like JavaScript.
## []()[Node.js compatiblity improvements](bun-v1.0.32.html#node-js-compatiblity-improvements)
This release also includes a few Node.js compatiblity improvements
### []()["ws" module can send & receive `ping` and `pong`](bun-v1.0.32.html#ws-module-can-send-receive-ping-and-pong)
The `"ws"` WebSocket client & server can now send and receive `"ping"` and `"pong"` events when using Bun.
output
ping.mjs
output
```
bun ping.mjs
```
```
Server is listening
Ping received on server side hello
Pong received on client side hello
Pong received on client side hello
```
```
bun-1.0.31 ping.mjs # Before
```
```
Server is listening
Pong received on client side hello
```
```
node ping.mjs # Node, for comparison
```
```
Server is listening
Ping received on server side hello
Pong received on client side hello
Pong received on client side hello
```
ping.mjs
```
import WebSocket, { WebSocketServer } from "ws";
const wss = new WebSocketServer({ port: 8080 });
wss.on("connection", (ws) => {
ws.on("ping", (data) => {
console.log("Ping received on server side", data.toString());
ws.pong(data);
});
});
// test client
const ws = new WebSocket("ws://localhost:8080");
ws.on("pong", (data) => {
console.log("Pong received on client side", data.toString());
});
ws.on("open", () => {
ws.ping(Buffer.from("hello"));
});
// listen for the server
wss.on("listening", () => {
console.log("Server is listening");
});
```
### []()[FileHandle read & write methods](bun-v1.0.32.html#filehandle-read-write-methods)
The Node `FileHandle` class implementation in Bun is implemented more correctly. You can call `.read` or `.write` and it returns the expected result instead of just a number.
We've also fixed a bug that could cause it to not call `close` on the file descriptor when it should have.
Thanks to [@eventualbuddha](https://github.com/eventualbuddha) for their help with this
### []()[util.promisify + setTimeout, setInterval, setImmediate](bun-v1.0.32.html#util-promisify-settimeout-setinterval-setimmediate)
When using `util.promisify` on timers in Bun, they now behave like they do in Node.js. This includes:
- `setTimeout`
- `setInterval`
- `setImmediate`
```
import { promisify } from "util";
const setTimeoutAsync = promisify(setTimeout);
await setTimeoutAsync(1000);
// await Bun.sleep(1000)
```
## []()[Windows support is close](bun-v1.0.32.html#windows-support-is-close)
We are close to shipping Windows support with Bun v1.1. Once Bun for Windows passes 95% of Bun's test suite, we will announce the release date.
> Bun for Windows currently passes 92.51% of Bun's test suite
>
> ████████████░ 92.51%
>
> — Bun (@bunjavascript) [March 12, 2024](https://twitter.com/bunjavascript/status/1767644565581017580?ref_src=twsrc%5Etfw)
## []()[Thank you to 8 contributors!](bun-v1.0.32.html#thank-you-to-8-contributors)
- [@cirospaciari](https://github.com/cirospaciari)
- [@dylan-conway](https://github.com/dylan-conway)
- [@eventualbuddha](https://github.com/eventualbuddha)
- [@fmajestic](https://github.com/fmajestic)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@zackradisic](https://github.com/zackradisic)
[**Full Changelog**](https://github.com/oven-sh/bun/compare/bun-v1.0.31...bun-v1.0.32)
* * *
#### [Bun v1.0.31](bun-v1.0.31.html)
#### [Bun v1.0.33](bun-v1.0.33.html)
On this page
- [Fixed: GitHub actions timeout with bun install](bun-v1.0.32.html#fixed-github-actions-timeout-with-bun-install)
- [Fixed: bun install --production regression](bun-v1.0.32.html#fixed-bun-install-production-regression)
- [Fixed: Shell hanging with || &&](bun-v1.0.32.html#fixed-shell-hanging-with)
- [Fixed: Using bun shell instead of system shell](bun-v1.0.32.html#fixed-using-bun-shell-instead-of-system-shell)
- [Fixed: import.meta.url query string parameters](bun-v1.0.32.html#fixed-import-meta-url-query-string-parameters)
- [Fixed: Subprocess.kill(undefined)](bun-v1.0.32.html#fixed-subprocess-kill-undefined)
- [Node.js compatiblity improvements](bun-v1.0.32.html#node-js-compatiblity-improvements)
- ["ws" module can send & receive `ping` and `pong`](bun-v1.0.32.html#ws-module-can-send-receive-ping-and-pong)
- [FileHandle read & write methods](bun-v1.0.32.html#filehandle-read-write-methods)
- [util.promisify + setTimeout, setInterval, setImmediate](bun-v1.0.32.html#util-promisify-settimeout-setinterval-setimmediate)
- [Windows support is close](bun-v1.0.32.html#windows-support-is-close)
- [Thank you to 8 contributors!](bun-v1.0.32.html#thank-you-to-8-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.33.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.33
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · March 17, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one.
Bun v1.0.33 fixes 2 bugs, including a bug with the mv command in Bun Shell and in node:crypto creating & verifying signatures
#### Previous releases
- [`v1.0.32`](bun-v1.0.32.html) fixes 13 bugs and improves Node.js compatibility. 'ws' package can now send & receive ping/pong events. util.promisify'd setTimeout setInterval, setImmediate work now. FileHandle methods have been implemented.
- [`v1.0.31`](bun-v1.0.31.html) fixes 54 bugs (addresses 113 👍 reactions), introduces `bun --print`, `<stdin> | bun run -`, `bun add --trust`, `fetch()` with Unix sockets, fixes macOS binary size regression, fixes high CPU usage bug in spawn() on older linux, adds `util.styleText`, Node.js compatibiltiy improvements, bun install bugfixes, and bunx bugfixes
- [`v1.0.30`](bun-v1.0.30.html) fixes 27 bugs (addressing 103 👍 reactions), fixes an 8x perf regression to Bun.serve(), adds a new `--conditions` flag to `bun build` and Bun's runtime, adds support for `expect.assertions()` and `expect.hasAssertions()` in Bun's test runner, fixes crashes and improves Node.js compatibility.
- [`v1.0.29`](bun-v1.0.29.html) fixes 8 bugs. Bun.stringWidth(a) is a ~6,756x faster drop-in replacement for the popular 'string-width' package. bunx checks for updates more frequently. Adds expect().toBeOneOf() in bun:test. Memory leak impacting Prisma is fixed. Shell now supports advanced redirects like '2>&1', '&>'. Reliability improvements to bunx, bun install, WebSocket client, and Bun Shell
#### 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
```
## []()[Fixed: mv command in Bun Shell](bun-v1.0.33.html#fixed-mv-command-in-bun-shell)
In Bun v1.0.31, the `mv` command in Bun Shell regressed and in several scenarios would not move files and instead throw an error.
This has been fixed thanks to [@zackradisic](https://github.com/zackradisic), and we've added tests to prevent this from happening again.
## []()[Fixed: node:crypto id values for sign function](bun-v1.0.33.html#fixed-node-crypto-id-values-for-sign-function)
Our `node:crypto` implementation was missing the `id` values for the `sign` functions. This has been fixed.
The `node-forge` and `acme-client` npm packages now work in Bun, thanks to [@zenshixd](https://github.com/zenshixd).
## []()[Windows support is close](bun-v1.0.33.html#windows-support-is-close)
We are close to shipping Windows support with Bun v1.1. Once Bun for Windows passes 95% of Bun's test suite, we will announce the release date.
> Bun for Windows currently passes 92.51% of Bun's test suite
>
> ████████████░ 92.51%
>
> — Bun (@bunjavascript) [March 12, 2024](https://twitter.com/bunjavascript/status/1767644565581017580?ref_src=twsrc%5Etfw)
## []()[Thank you to 4 contributors!](bun-v1.0.33.html#thank-you-to-4-contributors)
- [@nellfs](https://github.com/nellfs)
- [@zenshixd](https://github.com/zenshixd)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@zackradisic](https://github.com/zackradisic)
[**Full Changelog**](https://github.com/oven-sh/bun/compare/bun-v1.0.32...bun-v1.0.33)
* * *
#### [Bun v1.0.32](bun-v1.0.32.html)
#### [Bun v1.0.34](bun-v1.0.34.html)
On this page
- [Fixed: mv command in Bun Shell](bun-v1.0.33.html#fixed-mv-command-in-bun-shell)
- [Fixed: node:crypto id values for sign function](bun-v1.0.33.html#fixed-node-crypto-id-values-for-sign-function)
- [Windows support is close](bun-v1.0.33.html#windows-support-is-close)
- [Thank you to 4 contributors!](bun-v1.0.33.html#thank-you-to-4-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.34.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.34
* * *
[Ashcon Partovi](https://twitter.com/ashconpartovi) · March 22, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one.
Bun v1.0.34 fixes 7 bugs, bunx uses less memory, bun install gets faster on Docker & WSL, a conflicting devDependency hoisting bug is fixed, a cyclical CommonJS & ESM import crash is fixed, cross-mount fs.cp & fs.copyFile get 50% faster on Linux, and reliability improvements for bun install & bun's runtime.
#### Previous releases
- [`v1.0.33`](bun-v1.0.33.html) fixes 2 bugs, including a bug with the mv command in Bun Shell and in node:crypto creating & verifying signatures
- [`v1.0.32`](bun-v1.0.32.html) fixes 13 bugs and improves Node.js compatibility. 'ws' package can now send & receive ping/pong events. util.promisify'd setTimeout setInterval, setImmediate work now. FileHandle methods have been implemented.
- [`v1.0.31`](bun-v1.0.31.html) fixes 54 bugs (addresses 113 👍 reactions), introduces `bun --print`, `<stdin> | bun run -`, `bun add --trust`, `fetch()` with Unix sockets, fixes macOS binary size regression, fixes high CPU usage bug in spawn() on older linux, adds `util.styleText`, Node.js compatibiltiy improvements, bun install bugfixes, and bunx bugfixes
- [`v1.0.30`](bun-v1.0.30.html) fixes 27 bugs (addressing 103 👍 reactions), fixes an 8x perf regression to Bun.serve(), adds a new `--conditions` flag to `bun build` and Bun's runtime, adds support for `expect.assertions()` and `expect.hasAssertions()` in Bun's test runner, fixes crashes and improves Node.js compatibility.
#### 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
```
### []()[Runtime improvements](bun-v1.0.34.html#runtime-improvements)
## []()[50% faster cross-mount fs.cp & fs.copyFile on Linux](bun-v1.0.34.html#50-faster-cross-mount-fs-cp-fs-copyfile-on-linux)
We've optimized system calls used in `fs.cp` and `fs.copyFile` to make copying files across filesystems 50% faster on Linux. Bun now adds `sendfile` to its repertoire of system calls used to copy files.
This will likely have the most impact for Docker users and Windows Subsystem for Linux users.
> in the next version of bun
>
> copying large files on linux from /tmp or other mounts gets 50% faster [pic.twitter.com/PTTPm18UHy](https://t.co/PTTPm18UHy)
>
> — Jarred Sumner (@jarredsumner) [March 20, 2024](https://twitter.com/jarredsumner/status/1770454575079977460?ref_src=twsrc%5Etfw)
## []()[Fixed: CommonJS <> ESM cylical import crash](bun-v1.0.34.html#fixed-commonjs-esm-cylical-import-crash)
A crash that sometimes occurred involving cyclical ESM & CommonJS imports has been fixed.
Here's what went wrong:
1. You run `bun foo.ts`
`foo.ts` looks something like this:
```
import "./boop"; // <-- concurrently fetch "boop"
import "./baz"; // <-- concurrently fetch "baz"
```
1. `baz.ts` is a CommonJS module that requires `boop`. It loads synchronously.
```
require("./boop"); // <-- we already started fetching "boop"
```
1. `boop` is an ES module that imports `foo.ts`. Boop began loading asynchronously, but now it must load synchronously.
```
import "./foo";
```
CommonJS and ES Modules have different rules for cyclical imports. In CommonJS, the module is evaluated twice with exports memoized. In ES Modules, the module is only evaluated once but you can run into "Uninitialized variable" errors.
A crash sometimes occurred when the ES module finished loading after the CommonJS version had already been evaluated. We were missing a check to prevent the ES module from evaluating after the reference to it was stale. This caused a crash because the Promise was freed immediately after there were no longer any strong references to it. The strong reference gets cleared immediately before the Promise is fulfilled. The fix was to check if we had already evaluated the module and choose not to evaluate it again.
## []()[Fixed: Crash when asset import has a query parameter](bun-v1.0.34.html#fixed-crash-when-asset-import-has-a-query-parameter)
A crash that sometimes occurred when importing modules with query string parameters in the specifier has been fixed.
The following is an example that could reproduce the crash:
```
for (let i = 0; i < 100_000; i++>) {
const {default: MyIcon} = await import(`./MyIcon-${i}.svg?foo=${i}`);
}
```
## []()[Fixed: `Bun.sleep` not handling negative values](bun-v1.0.34.html#fixed-bun-sleep-not-handling-negative-values)
We fixed a bug where `Bun.sleep` would not handle negative values correctly. This would cause Bun to hang, when it should have exited immediately.
```
for (const timeout of [
-0, -0.1, -0.0000000000000001, -999999999999999,
-999999999999999.999999999999999,
]) {
await Bun.sleep(timeout);
}
```
The cause of this bug was an incorrect integer conversion to `i32`.
## []()[Module imports coalescing](bun-v1.0.34.html#module-imports-coalescing)
When possible, Bun transpiles CommonJS & ES module imports concurrently on another thread. Previously, when you import 1,000 modules in Bun and they finish fetching, Bun would allocate 1,000 individual event loop tasks to tell the event loop to to tell JavaScriptCore to parse the imports. Each task costs memory and CPU time. Instead of doing that, Bun now coalesces fetched modules into a single task that drains all of the fetched imports at once.
For example, if you were to send 100 fetch() requests to localhost and 100 imports in parallell, previously those 100 fetch() requests and 100 imports would potentially finish 1 by 1 and each would allocate a task internally. Now the completed imports would be executed sooner than the completed fetch() requests. This is similar to timers in Bun, which are also coalesced.
This is unlikely to have much impact on your application, but it felt worth mentioning.
### []()[bun install improvements](bun-v1.0.34.html#bun-install-improvements)
## []()[on macOS, bunx now replaces the current process](bun-v1.0.34.html#on-macos-bunx-now-replaces-the-current-process)
When you run `bunx <package>` on macOS, it will now replace the current process with the executable for the package. This saves you memory and CPU time because the `bunx` process stops running as soon as the new process is started instead of waiting for the old process to exit first.
> In the next version of Bun
>
> on macOS, bunx replaces itself with the command you ran
>
> compared to npx, this saves you about 120 MB of ram [pic.twitter.com/lL9mi3jokz](https://t.co/lL9mi3jokz)
>
> — Jarred Sumner (@jarredsumner) [March 22, 2024](https://twitter.com/jarredsumner/status/1771112354719396133?ref_src=twsrc%5Etfw)
## []()[bun installs gets a little faster on Docker & WSL](bun-v1.0.34.html#bun-installs-gets-a-little-faster-on-docker-wsl)
We've applied the same optimization for copying files across filesystems used in `fs.cp` and `fs.copyFile` to make copying files in `bun install` faster.
This mostly applies to Docker and WSL, where a remote filesystem is used or a filesystem like `overlayfs` where `renameat(2)` is not supported.
## []()[Fixed: Conflicting devDependency + dependency hoisting bug](bun-v1.0.34.html#fixed-conflicting-devdependency-dependency-hoisting-bug)
We introduced a regression in Bun v1.0.32 where `devDependencies` would be hoisted above regular `dependencies`, to better support when a package was present in both. However, this caused issued with packages like `eslint`.
Now, `devDependencies` are only hoisted if the dependency to hoist is from the same dependency tree. This prevents bugs where a dependency is hoisted, but the parent `node_modules` has a dev dependency with the same name but a different version.
## []()[Fixed: `bun pm trust` could hang in some cases](bun-v1.0.34.html#fixed-bun-pm-trust-could-hang-in-some-cases)
We found a bug where `bun pm trust` could hang if there were enough lifecycle scripts were being run. This has been fixed thanks to [@dylan-conway](https://github.com/dylan-conway).
## []()[Fixed: High CPU usage with lifecycle scripts on some Linux systems](bun-v1.0.34.html#fixed-high-cpu-usage-with-lifecycle-scripts-on-some-linux-systems)
A bug where `bun install` would use up to 100% CPU and block execution when running lifecycle scripts on some Linux systems has been fixed. This was caused by a missing check.
## []()[Windows support is close](bun-v1.0.34.html#windows-support-is-close)
We are close to shipping Windows support with Bun v1.1. Once Bun for Windows passes 95% of Bun's test suite, we will announce the release date.
Here's a summary of the changes we've made to Bun for Windows in this release:
#### Fixed: `process.stdout` is synchronous on Windows
We fixed a bug where `process.stdout` and `process.stderr` were asynchronous on Windows. This would cause issues where Bun would exit before all output was written to the terminal. To match the behavior of Node.js, we have made both synchronous on Windows.
#### Fixed: Default `trustedDependencies` not working on Windows
We fixed a bug where the default `trustedDependencies` were not working on Windows. This was because Bun was not properly checking for `\r` carriage returns in `bun.lockb`.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this bug!
#### Fixed: Various `bun install` bugs on Windows
- `bunx` was not locating `bin` files properly, causing it to not find executables
- `bun install` would not always detect tarballs correctly
- `bun install` would not always format relative paths correctly
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing these bugs!
> Bun for Windows currently passes 94.53% of Bun's test suite.
>
> ████████████░ 94.53%
>
> — Bun (@bunjavascript) [March 20, 2024](https://twitter.com/bunjavascript/status/1770298099833151867?ref_src=twsrc%5Etfw)
## []()[Thank you to 6 contributors!](bun-v1.0.34.html#thank-you-to-6-contributors)
- [@hustLer2k](https://github.com/hustLer2k)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@dylan-conway](https://github.com/dylan-conway)
- [@eroblaze](https://github.com/eroblaze)
- [@gnuns](https://github.com/gnuns)
- [@nektro](https://github.com/nektro)
[**Full Changelog**](https://github.com/oven-sh/bun/compare/bun-v1.0.33...bun-v1.0.34)
* * *
#### [Bun v1.0.33](bun-v1.0.33.html)
#### [Bun v1.0.36](bun-v1.0.36.html)
On this page
- [50% faster cross-mount fs.cp & fs.copyFile on Linux](bun-v1.0.34.html#50-faster-cross-mount-fs-cp-fs-copyfile-on-linux)
- [Fixed: CommonJS <> ESM cylical import crash](bun-v1.0.34.html#fixed-commonjs-esm-cylical-import-crash)
- [Fixed: Crash when asset import has a query parameter](bun-v1.0.34.html#fixed-crash-when-asset-import-has-a-query-parameter)
- [Fixed: `Bun.sleep` not handling negative values](bun-v1.0.34.html#fixed-bun-sleep-not-handling-negative-values)
- [Module imports coalescing](bun-v1.0.34.html#module-imports-coalescing)
- [bun install improvements](bun-v1.0.34.html#bun-install-improvements)
- [on macOS, bunx now replaces the current process](bun-v1.0.34.html#on-macos-bunx-now-replaces-the-current-process)
- [bun installs gets a little faster on Docker & WSL](bun-v1.0.34.html#bun-installs-gets-a-little-faster-on-docker-wsl)
- [Fixed: Conflicting devDependency + dependency hoisting bug](bun-v1.0.34.html#fixed-conflicting-devdependency-dependency-hoisting-bug)
- [Fixed: `bun pm trust` could hang in some cases](bun-v1.0.34.html#fixed-bun-pm-trust-could-hang-in-some-cases)
- [Fixed: High CPU usage with lifecycle scripts on some Linux systems](bun-v1.0.34.html#fixed-high-cpu-usage-with-lifecycle-scripts-on-some-linux-systems)
- [Windows support is close](bun-v1.0.34.html#windows-support-is-close)
- [Thank you to 6 contributors!](bun-v1.0.34.html#thank-you-to-6-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.36.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.36
* * *
[Ashcon Partovi](https://twitter.com/ashconpartovi) · March 29, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one.
Bun v1.0.36 fixes 13 bugs. Adds support for `fs.openAsBlob` and `fs.opendir`, fixes edgecase in bun install with multiple `bin` entries in `package.json`, fixes `bun build --target bun` encoding, fixes bug with process.stdin & process.stdout, fixes bug in http2, fixes bug with .env in bun run, fixes various Bun shell bugs and improves Node.js compatibility.
[Bun v1.1](https://www.youtube.com/watch?v=yXTFOeGly9o) (Bundows) is coming April 1st.
#### Previous releases
- `v1.0.35` fixed a regression from Bun v1.0.34
- [`v1.0.34`](bun-v1.0.34.html) fixes 7 bugs, bunx uses less memory, bun install gets faster on Docker & WSL, a conflicting devDependency hoisting bug is fixed, a cyclical CommonJS & ESM import crash is fixed, cross-mount fs.cp & fs.copyFile get 50% faster on Linux, and reliability improvements for bun install & bun's runtime.
- [`v1.0.33`](bun-v1.0.33.html) fixes 2 bugs, including a bug with the mv command in Bun Shell and in node:crypto creating & verifying signatures
- [`v1.0.32`](bun-v1.0.32.html) fixes 13 bugs and improves Node.js compatibility. 'ws' package can now send & receive ping/pong events. util.promisify'd setTimeout setInterval, setImmediate work now. FileHandle methods have been implemented.
#### 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
```
### []()[Node.js compatibility improvements](bun-v1.0.36.html#node-js-compatibility-improvements)
## []()[New: `fs.openAsBlob`](bun-v1.0.36.html#new-fs-openasblob)
Bun now supports the recently added [`fs.openAsBlob()`](https://nodejs.org/api/fs.html#fsopenasblobpath-options) API, which allows you to open a file as a Blob. This returns the same underlying `Blob` as `Bun.file`.
```
import { openAsBlob } from "node:fs";
const blob = await openAsBlob("hello.txt");
console.log(await blob.text()); // "Hello, world!"
```
## []()[New: `fs.opendir`](bun-v1.0.36.html#new-fs-opendir)
We also added support for [`fs.opendir()`](https://nodejs.org/api/fs.html#fsopendirpath-options-callback), which allows you to open a directory and read its contents.
```
import { opendir } from "node:fs";
const dir = await opendir(".");
for await (const dirent of dir) {
console.log(dirent.name); // "hello.txt", "world.txt"
}
```
## []()[Fixed: Hang piping process.stdin to process.stdout](bun-v1.0.36.html#fixed-hang-piping-process-stdin-to-process-stdout)
When at least 16 KB was piped to process.stdout, the process would sometimes hang. This has been fixed.
## []()[Fixed: Crash in http2](bun-v1.0.36.html#fixed-crash-in-http2)
A crash that could occur when using the `http2` client has been fixed. This crash was related to unimplemented HTTP2 features.
## []()[Fixed: Readable.toWeb(process.stdin)](bun-v1.0.36.html#fixed-readable-toweb-process-stdin)
The `Readable.toWeb()` function was not working correctly when reading from `process.stdin`. This has been fixed.
Now `Readable.toWeb(process.stdin)` is effectively the same as `Bun.stdin.stream()`.
## []()[Fixed: Regression using `process.stdout.moveCursor()`](bun-v1.0.36.html#fixed-regression-using-process-stdout-movecursor)
A regression in Bun v1.0.34 caused `process.stdout.moveCursor()` to throw `ReferenceError: Can't find variable: readline`. This has been fixed.
## []()[Fixed: TextDecoder error missing `code` property](bun-v1.0.36.html#fixed-textdecoder-error-missing-code-property)
When decoding an invalid UTF-8 string with `TextDecoder`, the error object would not have a `code` property. The Web API doesn't return a `code` property for invalid UTF-8 strings, but Node.js does. For compatiblity, we now return the same `code` property as Node.js.
This fixes a bug blocking `@angular/cli new` from running using Bun.
## []()[Fixed: non-blocking fs.readv & fs.writev](bun-v1.0.36.html#fixed-non-blocking-fs-readv-fs-writev)
The node:fs APIs `fs.readv` and `fs.writev` were running in a blocking manner. This has been fixed. We now enqueue the readv & writev functions to the threadpool when their `sync` versions are not called.
## []()[Fixed: Edgecase with multiple `bin` entries in `package.json`](bun-v1.0.36.html#fixed-edgecase-with-multiple-bin-entries-in-package-json)
Previously, there was a bug when:
1. exactly one version of a package had a `bin` entry in the NPM Registry API
2. all other versions did not have a `bin` entry
3. `bin` object had multiple entries
This bug caused `bun install` to fail to link the binaries properly.
package.json
```
{
"bin": {
"a": "bin",
"b": "bin",
}
}
```
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this issue.
## []()[Fixed: missing `terminate` method in `ws` server](bun-v1.0.36.html#fixed-missing-terminate-method-in-ws-server)
The `ws` polyfill in Bun was missing the `terminate` method on the WebSocketServer's WebSocket instance. This has been fixed.
Thanks to [@paperclover](https://github.com/paperclover) for fixing this issue.
### []()[Runtime improvements](bun-v1.0.36.html#runtime-improvements)
## []()[File descriptor leak prevention mechanism](bun-v1.0.36.html#file-descriptor-leak-prevention-mechanism)
POSIX defaults file descriptors to be inherited by child processes. This frequently causes file descriptor leaks in all sorts of ways. Bun has always used the `O_CLOEXEC` flag to prevent file descriptors from being inherited, but there were cases where this was not enough.
On modern Linux kernels, Bun now uses the `close_range` system call to prevent file descriptors from being inherited without the O\_CLOEXEC flag. This is a much more reliable way to prevent file descriptor leaks.
On macOS, Bun exclusively uses posix\_spawn to spawn child processes which has an equivalent mechanism to prevent file descriptor leaks which makes this harder to happen in the first place.
## []()[Restore stdin/stdout to their original state on SIGINT/SIGTERM](bun-v1.0.36.html#restore-stdin-stdout-to-their-original-state-on-sigint-sigterm)
Previously, Bun would not always restore stdin/stdout to their original state on SIGINT/SIGTERM. This has been fixed.
## []()[Non-blocking TTY reads](bun-v1.0.36.html#non-blocking-tty-reads)
On POSIX, Bun now reads from stdin in a non-blocking manner. Normally, this would cause the other end of the pipe to also be non-blocking, but we have a workaround (thanks to reading some code from libuv). We use [`ttyname_r`](https://man7.org/linux/man-pages/man3/ttyname_r.3.html) to open the TTY as a non-blocking file descriptor without affecting the other end of the pipe.
## []()[Fixed: Crash using `Bun.escapeHTML`](bun-v1.0.36.html#fixed-crash-using-bun-escapehtml)
We fixed a crash where specific input could crash `Bun.escapeHTML`, which was caused by an off-by-one bug.
Thanks to Querijn Voet for reporting this issue.
## []()[Fixed: Edgecase with WebSocket handshake](bun-v1.0.36.html#fixed-edgecase-with-websocket-handshake)
A bug in our `WebSocket` client implementation could cause non-101 status codes to be treated as a WebSocket upgrade request. This bug was not known to ever exist in the wild, but we fixed it anyway.
## []()[Fixed: potential file descriptor redirection bug in Bun.spawn](bun-v1.0.36.html#fixed-potential-file-descriptor-redirection-bug-in-bun-spawn)
A bug that could cause redirecting `stdin`, `stdout`, or `stderr` led to Bun closing the file descriptors before the child process finished starting. This bug was caused by misunderstanding how the `dup2` libc function works. When `dup2` receives the same file descriptor as the destination, it does nothing. Now when redirecting the same file descriptor, Bun will instead remove the `O_CLOEXEC` flag from the file descriptor which allows the child process to inherit the file descriptor. This bug only impacted linux, and was more difficult to reproduce than just inheriting file descriptors.
## []()[Fixed: incorrect .env propagation in `bun run`](bun-v1.0.36.html#fixed-incorrect-env-propagation-in-bun-run)
A regression caused `.env` files to be loaded unexpectedly when using `bun run` before the script is run. This regression has been fixed and we've improved our test suite to prevent this from occurring again.
## []()[Shell (Bun.$) stability improvements](bun-v1.0.36.html#shell-bun-stability-improvements)
We fixed various bugs and regressions with the Bun shell, including:
- A race condition where the shell would hang.
- A possible crash when the subprocess exited before the event loop was ready.
- A possible crash when stdin was over 128kb in size.
- When spawning a subprocess that uses interactive mode, user input would not be sent to the subprocess. This affected packages like `@inquirer/prompts`.
shell.js
prompt.js
input.js
shell.js
```
import { $ } from "bun";
await $`bun input.js | bun prompt.js`;
```
prompt.js
```
const { select } = require("@inquirer/prompts");
async function run() {
const foobar = await select({
message: "Foo or Bar",
choices: [
{ name: "Foo", value: "foo" },
{ name: "Bar", value: "bar" },
],
});
console.error("Choice:", foobar);
}
run();
```
input.js
```
// Simulate pressing the down arrow key
const writer = Bun.stdout.writer();
await Bun.sleep(100);
writer.write("\\x1b[B");
// Simulate pressing the enter key
await Bun.sleep(100);
writer.write("\\x0D");
writer.flush();
```
Thanks to [@zackradisic](https://github.com/zackradisic) for fixing these issue.
## []()[Fixed: `bun build --target bun` used wrong encoding](bun-v1.0.36.html#fixed-bun-build-target-bun-used-wrong-encoding)
Bun transpiles files to latin1 because the file size is reduced when being stored as utf-16. There was a bug where `bun build --target bun` would encode as utf-8 instead, which caused issues with non-latin1 characters. This has been fixed.
Given the following file, previously it would have been encoded as-is in utf-8.
```
console.log({ 我: "a" });
```
Now, it is encoded properly in latin1.
```
// @bun
console.log({ "\u{6211}": "a" });
```
Thanks to [@pfgithub](https://github.com/pfgithub) for fixing this issue.
## []()[Bundows (Bun v1.1) is April 1st](bun-v1.0.36.html#bundows-bun-v1-1-is-april-1st)
[Bun v1.1](https://www.youtube.com/watch?v=yXTFOeGly9o) will ship on April 1st.
## []()[Thank you to 13 contributors!](bun-v1.0.36.html#thank-you-to-13-contributors)
- [@buhrmi](https://github.com/buhrmi)
- [@cirospaciari](https://github.com/cirospaciari)
- [@davlgd](https://github.com/davlgd)
- [@dylan-conway](https://github.com/dylan-conway)
- [@eduardvercaemer](https://github.com/eduardvercaemer)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@kucukkanat](https://github.com/kucukkanat)
- [@kunokareal](https://github.com/kunokareal)
- [@nshen](https://github.com/nshen)
- [@paperclover](https://github.com/paperclover)
- [@pfgithub](https://github.com/pfgithub)
- [@sequencerr](https://github.com/sequencerr)
- [@zackradisic](https://github.com/zackradisic)
* * *
#### [Bun v1.0.34](bun-v1.0.34.html)
On this page
- [New: `fs.openAsBlob`](bun-v1.0.36.html#new-fs-openasblob)
- [New: `fs.opendir`](bun-v1.0.36.html#new-fs-opendir)
- [Fixed: Hang piping process.stdin to process.stdout](bun-v1.0.36.html#fixed-hang-piping-process-stdin-to-process-stdout)
- [Fixed: Crash in http2](bun-v1.0.36.html#fixed-crash-in-http2)
- [Fixed: Readable.toWeb(process.stdin)](bun-v1.0.36.html#fixed-readable-toweb-process-stdin)
- [Fixed: Regression using `process.stdout.moveCursor()`](bun-v1.0.36.html#fixed-regression-using-process-stdout-movecursor)
- [Fixed: TextDecoder error missing `code` property](bun-v1.0.36.html#fixed-textdecoder-error-missing-code-property)
- [Fixed: non-blocking fs.readv & fs.writev](bun-v1.0.36.html#fixed-non-blocking-fs-readv-fs-writev)
- [Fixed: Edgecase with multiple `bin` entries in `package.json`](bun-v1.0.36.html#fixed-edgecase-with-multiple-bin-entries-in-package-json)
- [Fixed: missing `terminate` method in `ws` server](bun-v1.0.36.html#fixed-missing-terminate-method-in-ws-server)
- [Runtime improvements](bun-v1.0.36.html#runtime-improvements)
- [File descriptor leak prevention mechanism](bun-v1.0.36.html#file-descriptor-leak-prevention-mechanism)
- [Restore stdin/stdout to their original state on SIGINT/SIGTERM](bun-v1.0.36.html#restore-stdin-stdout-to-their-original-state-on-sigint-sigterm)
- [Non-blocking TTY reads](bun-v1.0.36.html#non-blocking-tty-reads)
- [Fixed: Crash using `Bun.escapeHTML`](bun-v1.0.36.html#fixed-crash-using-bun-escapehtml)
- [Fixed: Edgecase with WebSocket handshake](bun-v1.0.36.html#fixed-edgecase-with-websocket-handshake)
- [Fixed: potential file descriptor redirection bug in Bun.spawn](bun-v1.0.36.html#fixed-potential-file-descriptor-redirection-bug-in-bun-spawn)
- [Fixed: incorrect .env propagation in `bun run`](bun-v1.0.36.html#fixed-incorrect-env-propagation-in-bun-run)
- [Shell (Bun.$) stability improvements](bun-v1.0.36.html#shell-bun-stability-improvements)
- [Fixed: `bun build --target bun` used wrong encoding](bun-v1.0.36.html#fixed-bun-build-target-bun-used-wrong-encoding)
- [Bundows (Bun v1.1) is April 1st](bun-v1.0.36.html#bundows-bun-v1-1-is-april-1st)
- [Thank you to 13 contributors!](bun-v1.0.36.html#thank-you-to-13-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.4.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.4
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · October 3, 2023
[](../rss.xml)
Bun v1.0.4 fixes 62 bugs, adds `server.requestIP`, supports virtual modules in runtime plugins, and reduces memory consumption in `Bun.serve()`. Thank you for reporting issues. We are working hard to fix them as quickly as possible.
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. We've been releasing a lot of changes to Bun recently. Here's a recap of the last few releases. In case you missed it:
- [`v1.0.0`](../1.0.html) - Bun's first stable release!
- [`v1.0.1`](bun-v1.0.1.html) - Named imports for .json & .toml files, bugfixes to bun install, node:path, Buffer
- [`v1.0.2`](bun-v1.0.2.html) - Make `--watch` faster, plus bug fixes
- [`v1.0.3`](bun-v1.0.3.html) - `emitDecoratorMetadata`, Nest.js support, private registry fixes, and many bugfixes
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
```
## []()[Features](bun-v1.0.4.html#features)
### []()[Reduced memory usage in `Bun.serve()`](bun-v1.0.4.html#reduced-memory-usage-in-bun-serve)
`Bun.serve()` now reports manually-managed per-request memory usage to JavaScriptCore's garbage collector. This reduces memory usage of `Bun.serve()` by 50% in some cases.
> In the next version of Bun
>
> Bun.serve() uses less memory
>
> After 800k requests
>
> Elysia
> v1.0.4: 47 MB
> v1.0.3: 71 MB
>
> Fastify
> v1.0.4: 114 MB
> v1.0.3: 267 MB
>
> Express
> v1.0.4: 116 MB
> v1.0.3: 167 MB [pic.twitter.com/XSjyo3aR9G](https://t.co/XSjyo3aR9G)
>
> — Jarred Sumner (@jarredsumner) [September 28, 2023](https://twitter.com/jarredsumner/status/1707355427904860475?ref_src=twsrc%5Etfw)
### []()[Implement `server.requestIP()`](bun-v1.0.4.html#implement-server-requestip)
With [`#6165`](https://github.com/oven-sh/bun/pull/6165), the IP address of a given `Request` can now be retrieved using `server.requestIP()`.
```
Bun.serve({
port: 3000,
handler: (req, res) => {
console.log(server.requestIP(req));
},
});
```
This does not read headers like `X-Forwarded-For` or `X-Real-IP`. It simply returns the IP address of the socket, which may correspond to the IP address of a proxy.
We've also added support to `node:http` for getting the socket address. `net.Socket().address` now returns an object with `address`, `port`, and `family` properties.
### []()[Virtual modules in `Bun.plugin`](bun-v1.0.4.html#virtual-modules-in-bun-plugin)
With [`#6167`](https://github.com/oven-sh/bun/pull/6167), Bun's plugin system gets more flexible and esbuild-compatible. It now supports fully virtual modules (`import stuff from "foo"`), in addition to custom loaders (`import stuff from "./stuff.foo"`).
You can register a virtual module by [registering a plugin](../docs/runtime/plugins.html#usage).
```
import { plugin } from "bun";
plugin({
name: "my plugin",
setup(builder) {
builder.module("my-virtual-module", () => {
return {
exports: {
hello: "world",
},
loader: "object",
};
});
},
});
```
This virtual module can then be consumed like a normal module:
```
import { hello } from "my-virtual-module";
console.log(hello); // "world"
// require("my-virtual-module") also works
// await import("my-virtual-module") also works
// require.resolve("my-virtual-module") also works
```
This feature is currently only supported for runtime plugins, not `bun build`.
### []()[Support parameters in `console.dir`](bun-v1.0.4.html#support-parameters-in-console-dir)
Thanks to [@liz3](https://github.com/liz3) for adding support for the second params object to `console.dir()` in [`#6059`](https://github.com/oven-sh/bun/pull/6059)
```
console.dir({ 1: { 2: { 3: 3 } } }, { depth: 0, colors: false });
```
## []()[Potentially breaking changes](bun-v1.0.4.html#potentially-breaking-changes)
**`fetch()` & `bun install` now have a network timeout of 5 minutes instead of 30 seconds**
After a number of reports about `fetch()` & `bun install` timeout being too quick, we've increased the default timeout for `fetch()` from 30 seconds to 5 minutes. This aligns the default with Google Chrome and should help with high-latency connections. It also applies to `bun install`. Note that this timeout is not for the cumulative time of the request, but rather the time between each chunk of data received. If you want to disable the timeout entirely, you can pass `timeout: false` to `fetch()`.
**`bun install` now stores the package.json `"version"` field of workspace member packages in the lockfile**
Previously, `bun install` would infer the package.json versions from other existing data when retrieved next, but this turned out to not work very well because you don't always need the package.json version of workspace member packages (they might not have one). The lockfile now stores the package.json version of workspace member packages, which helps address an issue where having a dependency using the npm version in the package.json but referencing the local workspace version would cause `bun install` to fail.
This is an incremental update to the existing lockfile in-place, it should have no impact other than a dirty git status the next time a lockfile which has workspace member packages with a `version` set. This is not technically a breaking change because this didn't work before, but it feels worth noting.
## []()[`bun install` bugfixes](bun-v1.0.4.html#bun-install-bugfixes)
Several stability improvements, including to workspaces, have been made to `bun install`:
- Fix `bun add <package>` when run inside a workspace member package [`#6092`](https://github.com/oven-sh/bun/pull/6092)
- Fix `bun install` "forgetting" about the existence of a workspace after the initial install
- Fixed a bug impacting Git/GitHub dependencies when the branch name contained a slash [`#5941`](https://github.com/oven-sh/bun/pull/5941).
- Fix occasional hang in `bun install` [`#6192`](https://github.com/oven-sh/bun/pull/6192)
- Support local `.tgz` dependency [`#5812`](https://github.com/oven-sh/bun/issues/5812)
- Fix a determinism bug that could happen when saving a lockfile, causing `git status` to report a dirty working tree when nothing actually changed.
## []()[Major bugfixes](bun-v1.0.4.html#major-bugfixes)
### []()[Fix a bug causing `fetch` to timeout in some cases with 3xx status codes](bun-v1.0.4.html#fix-a-bug-causing-fetch-to-timeout-in-some-cases-with-3xx-status-codes)
There was a bug where `fetch` would timeout in certain cases involving 3xx status codes and empty bodies when some headers were not included. The request would complete, but would eventually timeout instead of reporting success. This also impacted `bun install` in certain cases.
### []()[Fix `captureStackTrace` for subclasses of `Error` without `super()`](bun-v1.0.4.html#fix-capturestacktrace-for-subclasses-of-error-without-super)
[#6063](https://github.com/oven-sh/bun/pull/6063) fixes a crash when using `captureStackTrace` inside a constructor without `super()` in extended classes.
```
class ExtendedError extends Error {
constructor() {
super();
Error.captureStackTrace(this, ExtendedError);
}
}
class AnotherError extends ExtendedError {}
throw new AnotherError();
```
### []()[Fix a DNS resolution bug causing "Connection Refused" errors](bun-v1.0.4.html#fix-a-dns-resolution-bug-causing-connection-refused-errors)
Our usage of `getaddrinfo` was incorrect when the first returned result would fail to connect. `getaddrinfo` returns a linked list of results, but we were only looking at the first one. Now we look at all of them.
### []()[Implement `isBinary` in `'connection'` callback for `ws`](bun-v1.0.4.html#implement-isbinary-in-connection-callback-for-ws)
Per [`#5944`](https://github.com/oven-sh/bun/pull/5944):
```
import WebSocket, { WebSocketServer } from "ws";
const wss = new WebSocketServer({
port: 3000,
});
wss.on("connection", (ws) => {
ws.on("message", (data, isBinary) => {
// isBinary is now implemented
console.log("received", data, isBinary);
});
});
```
## []()[Node.js compatibilitiy improvements](bun-v1.0.4.html#node-js-compatibilitiy-improvements)
- Several bugs impacting Next.js pages router have been fixed, thanks to [@paperclover](https://github.com/paperclover)
- `util.inspect` has been rewritten to be more compatible with Node.js, thanks to [@jhmaster](https://github.com/jhmaster)
- A bug on macOS where `fs.rm` would not remove write-protected files has been fixed
- A bug where the callback version of `fs.exists` would mistakenly include an `error` parameter has been fixed, thanks to [@Hanaasagi](https://github.com/Hanaasagi)
## []()[Changelog](bun-v1.0.4.html#changelog)
[`#5903`](https://github.com/oven-sh/bun/pull/5903)fix(runtime): exclude unevaluated module in `require.cache` by [@Hanaasagi](https://github.com/Hanaasagi)[`#5941`](https://github.com/oven-sh/bun/pull/5941)\[install] fix GitHub dependency bugs by [@dylan-conway](https://github.com/dylan-conway)[`#5944`](https://github.com/oven-sh/bun/pull/5944)isBinary by [@dylan-conway](https://github.com/dylan-conway)[`#5986`](https://github.com/oven-sh/bun/pull/5986)Fixes #5985 by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#5950`](https://github.com/oven-sh/bun/pull/5950)Use c-ares function for checking if a string is an IP address by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#6000`](https://github.com/oven-sh/bun/pull/6000)Correctly fix #5888 by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#6001`](https://github.com/oven-sh/bun/pull/6001)Do not use removefileat() by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#6026`](https://github.com/oven-sh/bun/pull/6026)fix latest dev build panic by [@Hanaasagi](https://github.com/Hanaasagi)[`#6013`](https://github.com/oven-sh/bun/pull/6013)Fix create command with template prefixed with @ char #6007 by [@axlEscalada](https://github.com/axlEscalada)[`#6030`](https://github.com/oven-sh/bun/pull/6030)Add fs.statfs{Sync} to missing fs apis by [@techvlad](https://github.com/techvlad)[`#6032`](https://github.com/oven-sh/bun/pull/6032)Make error message for `new URL(invalid)` better by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#5998`](https://github.com/oven-sh/bun/pull/5998)Add `Module._extensions` by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#6036`](https://github.com/oven-sh/bun/pull/6036)Drain microtasks at end of abort() if called into JS by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#6063`](https://github.com/oven-sh/bun/pull/6063)fix `captureStackTrace` inside constructor without `super` in extended by [@dylan-conway](https://github.com/dylan-conway)[`#5771`](https://github.com/oven-sh/bun/pull/5771)Improve Docker images by [@Electroid](https://github.com/Electroid)[`#6090`](https://github.com/oven-sh/bun/pull/6090)fix: Docker - Include `bunx` symlink in distroless variant by [@polarathene](https://github.com/polarathene)[`#6086`](https://github.com/oven-sh/bun/pull/6086)fix(fetch/server) fix server end of stream, fix fetch not streaming without content-length or chunked encoding, fix case when stream do not return a promise on pull by [@cirospaciari](https://github.com/cirospaciari)[`#6059`](https://github.com/oven-sh/bun/pull/6059)fix: support console.dir options object correctly by [@liz3](https://github.com/liz3)[`#6092`](https://github.com/oven-sh/bun/pull/6092)fix workspace dependency install by [@dylan-conway](https://github.com/dylan-conway)[`#6097`](https://github.com/oven-sh/bun/pull/6097)fix(node:fs): fix `fs.exists` callback parameters by [@Hanaasagi](https://github.com/Hanaasagi)[`#6100`](https://github.com/oven-sh/bun/pull/6100)fix: Docker - Apply workaround with `RUN` to symlink `bunx` by [@polarathene](https://github.com/polarathene)[`#5825`](https://github.com/oven-sh/bun/pull/5825)fix: implement correct behaviour for urls with blob: scheme by [@liz3](https://github.com/liz3)[`#6122`](https://github.com/oven-sh/bun/pull/6122)fix(bun install): Handle vercel and github tarball path dependencies by [@booniepepper](https://github.com/booniepepper)[`#6123`](https://github.com/oven-sh/bun/pull/6123)revert fix for passing empty env vars to `bun run` by [@dylan-conway](https://github.com/dylan-conway)[`#5932`](https://github.com/oven-sh/bun/pull/5932)`deadCodeElimination` toggle for Bun.Transpiler by [@jhmaster2000](https://github.com/jhmaster2000)[`#6130`](https://github.com/oven-sh/bun/pull/6130)fix typescript metadata for import identifiers by [@dylan-conway](https://github.com/dylan-conway)[`#4493`](https://github.com/oven-sh/bun/pull/4493)Complete rework of the majority of `node:util`, primarily `util.inspect` by [@jhmaster2000](https://github.com/jhmaster2000)[`#6095`](https://github.com/oven-sh/bun/pull/6095)Get Next.js Pages Router to work by [@paperclover](https://github.com/paperclover)[`#6135`](https://github.com/oven-sh/bun/pull/6135)Reduce memory usage of HTTP server by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#6118`](https://github.com/oven-sh/bun/pull/6118)Add local tarball install #5812 by [@axlEscalada](https://github.com/axlEscalada)[`#6158`](https://github.com/oven-sh/bun/pull/6158)Upgrade to latest Node.js version by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#6162`](https://github.com/oven-sh/bun/pull/6162)Fixes #6053 by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#6165`](https://github.com/oven-sh/bun/pull/6165)feat(runtime): implement `server.requestIp` + node:http `socket.address()` by [@paperclover](https://github.com/paperclover)[`#5766`](https://github.com/oven-sh/bun/pull/5766)fix(resolver): support encoded file urls by [@paperclover](https://github.com/paperclover)[`#5945`](https://github.com/oven-sh/bun/pull/5945)fix(runtime): Socket.prototype is undefined by [@paperclover](https://github.com/paperclover)[`#6154`](https://github.com/oven-sh/bun/pull/6154)fix: don't set default request method when creating a Request from another by [@liz3](https://github.com/liz3)[`#6185`](https://github.com/oven-sh/bun/pull/6185)fix(runtime): followup for `server.requestIP` by [@paperclover](https://github.com/paperclover)[`#6167`](https://github.com/oven-sh/bun/pull/6167)Implement virtual module support in `Bun.plugin` by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#6192`](https://github.com/oven-sh/bun/pull/6192)Fix hang in `bun install` by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#6195`](https://github.com/oven-sh/bun/pull/6195)tweak github actions by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#6206`](https://github.com/oven-sh/bun/pull/6206)Fix bug causing "Connection Refused" errors by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#6207`](https://github.com/oven-sh/bun/pull/6207)fix(node:process): fix return value of `process.kill` by [@Hanaasagi](https://github.com/Hanaasagi)[`#6219`](https://github.com/oven-sh/bun/pull/6219)Slightly reduce number of open file descriptors in `bun install` by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#6231`](https://github.com/oven-sh/bun/pull/6231)Added the fileExtensions field to file-system-router.md by [@cornedor](https://github.com/cornedor)[`#6242`](https://github.com/oven-sh/bun/pull/6242)Warn at start when using AVX build of Bun without AVX support by [@Jarred-Sumner](https://github.com/Jarred-Sumner)[`#6247`](https://github.com/oven-sh/bun/pull/6247)Fix `bun install` reading Github API from wrong environment variable by [@Electroid](https://github.com/Electroid)[`#6217`](https://github.com/oven-sh/bun/pull/6217)Set `fetch` timeout to 5 minutes by [@Jarred-Sumner](https://github.com/Jarred-Sumner)
Thanks to Bun's newest contributors!
[@meck93](https://github.com/meck93) [@aszenz](https://github.com/aszenz) [@cyfung1031](https://github.com/cyfung1031) [@axlEscalada](https://github.com/axlEscalada) [@techvlad](https://github.com/techvlad) [@Dawntraoz](https://github.com/Dawntraoz) [@polarathene](https://github.com/polarathene) [@DarthDanAmesh](https://github.com/DarthDanAmesh) [@DevinJohw](https://github.com/DevinJohw) [@cornedor](https://github.com/cornedor) [@ciceropablo](https://github.com/ciceropablo)
**Full Changelog**: https://github.com/oven-sh/bun/compare/bun-v1.0.3...bun-v1.0.4
* * *
#### [Bun v1.0.3](bun-v1.0.3.html)
#### [Bun v1.0.5](bun-v1.0.5.html)
On this page
- [Features](bun-v1.0.4.html#features)
- [Reduced memory usage in `Bun.serve()`](bun-v1.0.4.html#reduced-memory-usage-in-bun-serve)
- [Implement `server.requestIP()`](bun-v1.0.4.html#implement-server-requestip)
- [Virtual modules in `Bun.plugin`](bun-v1.0.4.html#virtual-modules-in-bun-plugin)
- [Support parameters in `console.dir`](bun-v1.0.4.html#support-parameters-in-console-dir)
- [Potentially breaking changes](bun-v1.0.4.html#potentially-breaking-changes)
- [`bun install` bugfixes](bun-v1.0.4.html#bun-install-bugfixes)
- [Major bugfixes](bun-v1.0.4.html#major-bugfixes)
- [Fix a bug causing `fetch` to timeout in some cases with 3xx status codes](bun-v1.0.4.html#fix-a-bug-causing-fetch-to-timeout-in-some-cases-with-3xx-status-codes)
- [Fix `captureStackTrace` for subclasses of `Error` without `super()`](bun-v1.0.4.html#fix-capturestacktrace-for-subclasses-of-error-without-super)
- [Fix a DNS resolution bug causing "Connection Refused" errors](bun-v1.0.4.html#fix-a-dns-resolution-bug-causing-connection-refused-errors)
- [Implement `isBinary` in `'connection'` callback for `ws`](bun-v1.0.4.html#implement-isbinary-in-connection-callback-for-ws)
- [Node.js compatibilitiy improvements](bun-v1.0.4.html#node-js-compatibilitiy-improvements)
- [Changelog](bun-v1.0.4.html#changelog)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.5.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.5
* * *
[Ashcon Partovi](https://twitter.com/ashconpartovi) · October 11, 2023
[](../rss.xml)
Bun v1.0.5 fixes 41 bugs (addressing 248 👍 reactions), including a memory leak in `fetch()`, adds `KeyObject` support in `crypto` module, `bun install` can import package-lock.json files, and install peer dependencies. We've also added a `bun pm migrate` subcommand, and more bugfixes.
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun:
- [`v1.0.0`](../1.0.html) - First stable release!
- [`v1.0.1`](bun-v1.0.1.html) - Named imports for .json and .toml files, fixes to `bun install`, `node:path`, and `Buffer`
- [`v1.0.2`](bun-v1.0.2.html) - Make `--watch` faster and lots of bug fixes
- [`v1.0.3`](bun-v1.0.3.html) - `emitDecoratorMetadata` and Nest.js support, fixes for private registries and more
- [`v1.0.4`](bun-v1.0.4.html) - `server.requestIP`, virtual modules in runtime plugins, and more
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
```
## []()[Fixed memory leak with `fetch()`](bun-v1.0.5.html#fixed-memory-leak-with-fetch)
We fixed a memory leak in Bun [caused](https://github.com/oven-sh/bun/pull/6350) by responses with gzip/delate encoding not properly being closed. This makes `fetch()` use less memory and more reliable.
> in the next version of Bun
>
> A memory leak impacting fetch() is fixed
>
> left: bun v1.0.4
> right: bun v1.0.5 [pic.twitter.com/x3dNkPTh5O](https://t.co/x3dNkPTh5O)
>
> — Jarred Sumner (@jarredsumner) [October 7, 2023](https://twitter.com/jarredsumner/status/1710477837516595313?ref_src=twsrc%5Etfw)
This fix also reduces the overall memory consumption of `fetch()`.
## []()[`KeyObject` support in `node:crypto` module](bun-v1.0.5.html#keyobject-support-in-node-crypto-module)
Bun now supports the `KeyObject` class in the `crypto` module, thanks to [@cirospaciari](https://github.com/cirospaciari). This class is used to represent public and private keys, and is used by various crypto packages which now work, including:
- [`jsonwebtoken`](https://github.com/auth0/node-jsonwebtoken)
- [`jose`](https://github.com/panva/jose)
- [`@nestjs/jwt`](https://github.com/nestjs/jwt)
- [`firebase-admin`](https://github.com/firebase/firebase-admin-node)
That's because the following crypto APIs are now implemented in Bun:
- [`KeyObject`](https://nodejs.org/api/crypto.html#static-method-keyobjectfromkey)
- [`crypto.createSecretKey()`](https://nodejs.org/api/crypto.html#cryptocreatesecretkeykey-encoding)
- [`crypto.createPublicKey()`](https://nodejs.org/api/crypto.html#cryptocreatepublickeykey)
- [`crypto.createPrivateKey()`](https://nodejs.org/api/crypto.html#cryptocreateprivatekeykey)
- [`crypto.generateKeyPairSync()`](https://nodejs.org/api/crypto.html#cryptogeneratekeypairsynctype-options)
- [`crypto.generateKeySync()`](https://nodejs.org/api/crypto.html#cryptogeneratekeysynctype-options)
- [`crypto.generateKeyPair()`](https://nodejs.org/api/crypto.html#cryptogeneratekeypairtype-options)
- [`crypto.generateKey()`](https://nodejs.org/api/crypto.html#cryptogeneratekeytype-options)
- [`crypto.sign()`](https://nodejs.org/api/crypto.html#cryptosignalgorithm-data-key-callback)
- [`crypto.verify()`](https://nodejs.org/api/crypto.html#cryptoverifyalgorithm-data-key-signature-callback)
### []()[`expect().toEqualIgnoringWhitespace` in `bun:test`](bun-v1.0.5.html#expect-toequalignoringwhitespace-in-bun-test)
`bun:test` gets a new test matcher: `toEqualIgnoringWhitespace`, thanks to @EladBezalel.
```
import { expect, test } from "bun:test";
test("it works", () => {
expect(" hello ").toEqualIgnoringWhitespace("hello");
});
```
## []()[`bun run --if-present` flag](bun-v1.0.5.html#bun-run-if-present-flag)
`bun run` now has a `--if-present` flag, which only runs the script if it exists. This is useful for running the same script in many different folders, like workspaces.
```
bun run --if-present my-script
```
```
# runs "my-script" if it exists in package.json "scripts"
```
Thanks to [@Electroid](https://github.com/Electroid) for implementing this.
## []()[Import dependencies from `package-lock.json`](bun-v1.0.5.html#import-dependencies-from-package-lock-json)
If Bun does not detect a `bun.lockb` file, `bun install` will now automatically import dependencies from `package-lock.json` if it exists. This makes it easier to migrate from `npm` to `bun`. This preserves the same dependency versions from `package-lock.json`.
[](https://github.com/oven-sh/bun/assets/3238291/fea8d229-8736-4596-b4dd-ae31bae1ee82)
Thanks to [@paperclover](https://github.com/paperclover) for implementing this.
### []()[`bun pm migrate` subcommand](bun-v1.0.5.html#bun-pm-migrate-subcommand)
bun v1.0.5 introduces a new `bun pm migrate` subcommand.
To use it, run the following command in the same directory as your `package-lock.json` file:
```
bun pm migrate
```
This subcommand converts from an npm `package-lock.json` file to a `bun.lockb` file, preserving the same dependency versions from `package-lock.json`.
[](https://github-production-user-asset-6210df.s3.amazonaws.com/709451/274208726-7bd4e7a1-5b53-4eb4-9a2c-b7a793f808af.png)
You don't typically have to run this command because `bun install` will automatically run it if it detects a `package-lock.json` file and no `bun.lockb` file, but it's useful if you want to migrate from `npm` to `bun` without running `bun install`.
## []()[Install peer dependencies](bun-v1.0.5.html#install-peer-dependencies)
`bun install` now automatically installs unmet peer dependencies by default. This means that if you install a package that has peer dependencies, Bun will automatically install those peer dependencies if they were not already present. This aligns the behavior of `bun install` with `npm install` and `pnpm install`.
If you don't want this behavior, you can disable it by passing the `--no-peer` flag to `bun install`.
You can also disable this behavior by default by adding the following to your `bunfig.toml` file:
```
# Disable installing peer dependencies
install.peer = false
```
Thanks to [@dylan-conway](https://github.com/dylan-conway) for implementing this.
### []()[What are peer dependencies?](bun-v1.0.5.html#what-are-peer-dependencies)
Peer dependencies are dependencies that are required by a package, but preferred to be installed by the user.
For example, if you install `react-router-dom` without `react`, it probably won't work. `react-router-dom` has `react` as a peer dependency, which means that it requires `react` to be installed, but it's preferred that the user installs `react` themselves so that you can have more control over which version of `react` is installed. It's a way for a package to say, "I need this library to work, but it should use your version of the dependency instead of mine".
Previously, Bun would not install peer dependencies, which meant that you had to install them yourself. This caused issues where packages would not work out of the box, and you would have to manually install peer dependencies. Now, Bun will automatically install peer dependencies for you.
## []()[`"trustedDependencies"` lifecycle scripts bugfix](bun-v1.0.5.html#trusteddependencies-lifecycle-scripts-bugfix)
A bug caused lifecycle scripts from `"trustedDependencies"` to not be re-run on `bun install`. This has been fixed, \[thanks to [@Arden144](https://github.com/Arden144)](https://github.com/oven-sh/bun/issues/5472).
## []()[Fixed `bun install` bugs](bun-v1.0.5.html#fixed-bun-install-bugs)
We've been working hard to fix bugs in `bun install`. Here are some of the bugs we fixed:
- [#6258](https://github.com/oven-sh/bun/pull/6258) - Fixed issues with `workspace` dependencies not resolving.
- [#4066](https://github.com/oven-sh/bun/issues/4066) - Fixed `ConnectionRefused` errors or scenarios where `bun install` would take too long.
- More support for `git` dependencies, including `git@<url>` and `bitbucket:<url>`.
- [#6219](https://github.com/oven-sh/bun/pull/6219) - micro-optimization in `bun install` to open fewer file descriptors.
- Fixed a bug where pre-releases would cause the wrong version to be resolved.
## []()[Other changes and fixes](bun-v1.0.5.html#other-changes-and-fixes)
- [#6207](https://github.com/oven-sh/bun/pull/6207) - `process.kill()` now returns a boolean, to match Node.js. (thanks @Hanaasagi!)
- [#6042](https://github.com/oven-sh/bun/pull/6042) - `bunx` now works with Github packages, e.g. `bunx github:piuccio/cowsay` (thanks @axlEscalada!)
- [#6259](https://github.com/oven-sh/bun/pull/6259) - `Blob.slice` sets offset correctly (thanks @Hanaasagi!)
- [#6074](https://github.com/oven-sh/bun/pull/6074) - `TextEncoder.ignoreBOM` is now supported (thanks @WingLim!)
- bun install now persists relative workspace paths in the `bun.lockb` file.
- bun install now persists `trustedDependencies` in the `bun.lockb` file.
- The `query` property in `node:url` is now an object instead of a `URLSearchParams` instance, matching Node.js behavior
- Exit codes in `process.exit` can now be > 127, thanks to [@liz3](https://github.com/liz3).
- A bug in `node:buffer` where positional arguments were incorrectly required has been fixed, thanks to [@kitsuned](https://github.com/kitsuned).
## []()[New Contributors](bun-v1.0.5.html#new-contributors)
Thanks to our 16 new contributors 🎉
- [@mathiasrw](https://github.com/mathiasrw) made their first contribution in #6255
- [@wbjohn](https://github.com/wbjohn) made their first contribution in #6256
- [@jsparkdev](https://github.com/jsparkdev) made their first contribution in #6222
- [@kitsuned](https://github.com/kitsuned) made their first contribution in #4911
- [@Pandapip1](https://github.com/Pandapip1) made their first contribution in #6298
- [@panva](https://github.com/panva) made their first contribution in #6294
- [@2hu12](https://github.com/2hu12) made their first contribution in #6379
- [@Cadienvan](https://github.com/Cadienvan) made their first contribution in #6331
- [@Longju000](https://github.com/Longju000) made their first contribution in #6291
- [@babarkhuroo](https://github.com/babarkhuroo) made their first contribution in #6314
- [@otterDeveloper](https://github.com/otterDeveloper) made their first contribution in #6359
- [@RaresAil](https://github.com/RaresAil) made their first contribution in #6400
- [@yukulele](https://github.com/yukulele) made their first contribution in #6399
- [@vthemelis](https://github.com/vthemelis) made their first contribution in #6307
- [@EladBezalel](https://github.com/EladBezalel) made their first contribution in #6293
- [@Arden144](https://github.com/Arden144) made their first contribution in #6376
To view the full list of changes, check out the [Bun changelog](https://github.com/oven-sh/bun/compare/bun-v1.0.4...bun-v1.0.5).
* * *
#### [Bun v1.0.4](bun-v1.0.4.html)
#### [Bun v1.0.6](bun-v1.0.6.html)
On this page
- [Fixed memory leak with `fetch()`](bun-v1.0.5.html#fixed-memory-leak-with-fetch)
- [`KeyObject` support in `node:crypto` module](bun-v1.0.5.html#keyobject-support-in-node-crypto-module)
- [`expect().toEqualIgnoringWhitespace` in `bun:test`](bun-v1.0.5.html#expect-toequalignoringwhitespace-in-bun-test)
- [`bun run --if-present` flag](bun-v1.0.5.html#bun-run-if-present-flag)
- [Import dependencies from `package-lock.json`](bun-v1.0.5.html#import-dependencies-from-package-lock-json)
- [`bun pm migrate` subcommand](bun-v1.0.5.html#bun-pm-migrate-subcommand)
- [Install peer dependencies](bun-v1.0.5.html#install-peer-dependencies)
- [What are peer dependencies?](bun-v1.0.5.html#what-are-peer-dependencies)
- [`"trustedDependencies"` lifecycle scripts bugfix](bun-v1.0.5.html#trusteddependencies-lifecycle-scripts-bugfix)
- [Fixed `bun install` bugs](bun-v1.0.5.html#fixed-bun-install-bugs)
- [Other changes and fixes](bun-v1.0.5.html#other-changes-and-fixes)
- [New Contributors](bun-v1.0.5.html#new-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.6.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.6
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · October 11, 2023
[](../rss.xml)
Bun v1.0.6 fixes 3 bugs (addressing 85 👍 reactions), including a regression impacting Docker usage with Bun and implements support for the `overrides` & `resolutions` fields in `package.json`.
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun:
- [`v1.0.0`](../1.0.html) - First stable release!
- [`v1.0.1`](bun-v1.0.1.html) - Named imports for .json and .toml files, fixes to `bun install`, `node:path`, and `Buffer`
- [`v1.0.2`](bun-v1.0.2.html) - Make `--watch` faster and lots of bug fixes
- [`v1.0.3`](bun-v1.0.3.html) - `emitDecoratorMetadata` and Nest.js support, fixes for private registries and more
- [`v1.0.4`](bun-v1.0.4.html) - `server.requestIP`, virtual modules in runtime plugins, and more
- [`v1.0.5`](bun-v1.0.5.html) - Fixed memory leak with `fetch()`, `KeyObject` support in `node:crypto` module, `expect().toEqualIgnoringWhitespace` in `bun:test`, and more
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
```
## []()[Docker "abort" regression bugfix](bun-v1.0.6.html#docker-abort-regression-bugfix)
In Bun v1.0.5 (released earlier today), we introduced a regression that caused Bun to `abort()` at start when used in Docker on some systems that lack support for the v1 version of cgroups. This has been fixed in Bun v1.0.6.
## []()[`overrides` & `resolutions` support](bun-v1.0.6.html#overrides-resolutions-support)
This release implements support for [`"overrides"` in package.json](https://docs.npmjs.com/cli/v9/configuring-npm/package-json#overrides). `"overrides"` lets you override the version of a dependency to a specific package version. This is useful when you want to force a dependency to use a specific version, or point to a different package
One usecase is to ensure only a single version of a package is used in a project. For example:
```
{
"dependencies": {
"react": "^17.0.0",
"react-dom": "^17.0.0",
"some-other-package": "^1.0.0"
},
"overrides": {
"react": "17.0.0",
"react-dom": "17.0.0"
}
}
```
Now, even if `"some-other-package"` specifies `"react-dom": "^16.0.0"`, Bun will use `"react-dom": "17.0.0"` instead.
In Bun's implementation, only one level deep is supported, meaning the version you set applies to every package in the dependency tree. In the future, we may implement support for nested overrides.
Yarn implements a similar field called [`"resolutions"`](https://classic.yarnpkg.com/en/docs/selective-version-resolutions/), which is also supported in Bun:
```
{
"dependencies": {
"something-depending-on-typescript": "^1.0.0"
},
"resolutions": {
"**/typescript": "5.2.2"
}
}
```
We want Bun to be easily adoptable, and that philosophy is why we decided to support both `"overrides"` and `"resolutions"`.
Another use case of this is to assign completely different specifiers. This makes it possible to use a patched version of a dependency, or replace it with something completely different.
```
{
"overrides": {
// override any package that uses "react-native" with "react-native-web"
"react-native": "npm:react-native-web@0.19.9",
// create a symlink to the given directory instead of installing from npm
"lodash": "file:./not-lodash",
// or a tarball (can be a url or local path)
"hello": "file:./some-package.tgz"
}
}
```
These specifiers work the same way as the ones in `"dependencies"`, but forces all dependencies to use the version you specified.
Thanks to [@paperclover](https://github.com/paperclover) for implementing this feature!
## []()[Bug impacting pre-release tags with latest version](bun-v1.0.6.html#bug-impacting-pre-release-tags-with-latest-version)
A bug causing Bun to choose an incorrect version when using a pre-release tag (e.g. `-0`) that was marked as the latest version has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
To view the full list of changes, check out the [Bun changelog](https://github.com/oven-sh/bun/compare/bun-v1.0.5...bun-v1.0.6).
* * *
#### [Bun v1.0.5](bun-v1.0.5.html)
#### [Bun v1.0.7](bun-v1.0.7.html)
On this page
- [Docker "abort" regression bugfix](bun-v1.0.6.html#docker-abort-regression-bugfix)
- [`overrides` & `resolutions` support](bun-v1.0.6.html#overrides-resolutions-support)
- [Bug impacting pre-release tags with latest version](bun-v1.0.6.html#bug-impacting-pre-release-tags-with-latest-version)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.7.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.7
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · October 20, 2023
[](../rss.xml)
Bun v1.0.7 fixes 59 bugs (addressing 78 👍 reactions), implements optional peer dependencies in `bun install`, and makes improvements to Node.js compatibility.
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun:
- [`v1.0.0`](../1.0.html) - First stable release!
- [`v1.0.1`](bun-v1.0.1.html) - Named imports for .json and .toml files, fixes to `bun install`, `node:path`, and `Buffer`
- [`v1.0.2`](bun-v1.0.2.html) - Make `--watch` faster and lots of bug fixes
- [`v1.0.3`](bun-v1.0.3.html) - `emitDecoratorMetadata` and Nest.js support, fixes for private registries and more
- [`v1.0.4`](bun-v1.0.4.html) - `server.requestIP`, virtual modules in runtime plugins, and more
- [`v1.0.5`](bun-v1.0.5.html) - Fixed memory leak with `fetch()`, `KeyObject` support in `node:crypto` module, `expect().toEqualIgnoringWhitespace` in `bun:test`, and more
- [`v1.0.6`](bun-v1.0.6.html) - Fixes 3 bugs (addressing 85 👍 reactions), implements `overrides` & `resolutions` in `package.json`, and fixes regression impacting Docker usage with Bun
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 install` improvements](bun-v1.0.7.html#bun-install-improvements)
This release includes several bugfixes to `bun install`, such as:
### []()[New: Optional `peerDependencies`](bun-v1.0.7.html#new-optional-peerdependencies)
This release adds support for optional peer dependencies, which addresses a bug where `bun install` would potentially install more packages than `npm install`.
An optional peer dependency appears in a package.json looks like this:
package.json
```
{
"peerDependencies": {
"node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
},
"peerDependenciesMeta": {
"node-notifier": {
"optional": true
}
}
}
```
This tells the npm client to not install `node-notifier`, unless it is explicitly listed in the `dependencies` or `devDependencies` of the root project's `package.json`.
In the previous release, Bun would install `node-notifier` even if it wasn't listed in the root project's `package.json`. This would increase the size of node\_modules and potentially could cause issues where Bun would intall the same package under multiple versions. In Bun v1.0.7, this has been fixed.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for implementing optional peer dependencies in Bun!
### []()[Fixed: Edgecase where wrong version of packages were installed](bun-v1.0.7.html#fixed-edgecase-where-wrong-version-of-packages-were-installed)
There was a bug where `bun install` would sometimes choose older versions of packages when matching the semver range. This has been fixed, thanks to [@dylang](https://github.com/dylang).
Specifically, we assumed the npm registry API returned the list of package versions in semver order. The official registry API *usually* does, but not always. Moreover, not everyone uses the official registry API. This caused `bun install` to sometimes choose older versions of packages that still matched the semver range.
Bun will now sort the versions retreived from the registry, before choosing the best version that matches.
### []()[Fixed: `bun install github:foo/foo` could save multiple times to package.json](bun-v1.0.7.html#fixed-bun-install-github-foo-foo-could-save-multiple-times-to-package-json)
A bug caused `bun install github:foo/foo` to save multiple times to package.json. If you ran it twice, the dependency would appear multiple times in package.json. This bug has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
### []()[Fixed: Edgecase causing non-deterministic `bun.lockb` on Linux](bun-v1.0.7.html#fixed-edgecase-causing-non-deterministic-bun-lockb-on-linux)
A determinism issue caused `bun.lockb` to sometimes have differing contents on Linux. This has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
### []()[Fixed: npm alias edgecase bugfix](bun-v1.0.7.html#fixed-npm-alias-edgecase-bugfix)
A bug causing `npm:` aliases in dependencies to not always be respected has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
## []()[Node.js compatibility improvements](bun-v1.0.7.html#node-js-compatibility-improvements)
This release also includes several Node.js compatibility improvements.
### []()[Fixed: `child_process` IPC reliability](bun-v1.0.7.html#fixed-child-process-ipc-reliability)
A reliability issue causing IPC messages to not send all their contents has been fixed, thanks to [@paperclover](https://github.com/paperclover). This helps Next.js work more reliably in Bun, though there is still have more work to be done there.
### []()[Fixed: Hanging socket without `end` event](bun-v1.0.7.html#fixed-hanging-socket-without-end-event)
A bug causing `node:net` sockets to not correctly emit an `end` event in all cases has been fixed, thanks to [@cirospaciari](https://github.com/cirospaciari).
This bug impacted the `pg` and `sequelize` packages, among others.
### []()[Fixed: `napi` memory leak](bun-v1.0.7.html#fixed-napi-memory-leak)
A memory leak in napi has been fixed, thanks to [@alangecker](https://github.com/alangecker). The root cause was a reference count that started at `1` instead of `0`.
### []()[Fixed: `node:stream` crash](bun-v1.0.7.html#fixed-node-stream-crash)
A crash that could potentially occur when writing many small chunks to a `node:stream` has been fixed, thanks to [@paperclover](https://github.com/paperclover).
### []()[Fixed: `server.address()` for Unix sockets](bun-v1.0.7.html#fixed-server-address-for-unix-sockets)
A bug causing `server.address()` in `node:http` to return incorrect values for unix sockets has been fixed, thanks to [@Hanaasagi](https://github.com/Hanaasagi).
### []()[Fixed: `threadId` was unset in `Worker`](bun-v1.0.7.html#fixed-threadid-was-unset-in-worker)
A bug causing `threadId` to not be set in the `Worker` instance returned in `node:worker_threads` has been fixed, thanks to [@jerome-benoit](https://github.com/jerome-benoit).
### []()[Fixed: `Buffer.write` with 'binary' truncated to ascii instead of latin1](bun-v1.0.7.html#fixed-buffer-write-with-binary-truncated-to-ascii-instead-of-latin1)
A bug causing `Buffer.write` with `'binary'` encoding to truncate to ascii rather than latin1 has been fixed, thanks to [@Electroid](https://github.com/Electroid).
### []()[Fixed: `Buffer.concat(buffers, undefined)` threw an error](bun-v1.0.7.html#fixed-buffer-concat-buffers-undefined-threw-an-error)
A bug where the following code would throw an error has been fixed, thanks to [@Hanaasagi](https://github.com/Hanaasagi).
```
Buffer.concat([Buffer(1), Buffer(1)], undefined);
```
The following code would not throw an error:
```
Buffer.concat([Buffer(1), Buffer(1)]);
Buffer.concat([Buffer(1), Buffer(1)], 2);
```
The bug was checking for the native code equivalent of `arguments.length` instead of whether or not `arguments[1]` was `undefined`.
### []()[Fixed: `node:dns` lookup returned wrong address for family](bun-v1.0.7.html#fixed-node-dns-lookup-returned-wrong-address-for-family)
A bug causing `node:dns`'s `lookup` function to return the wrong address type when `family` was set has been fixed, thanks to [@Electroid](https://github.com/Electroid). For example, `dns.lookup('localhost', { family: 6 })` could have returned an IPv4 address instead of an IPv6 address.
## []()[Runtime fixes](bun-v1.0.7.html#runtime-fixes)
We also fixed several bugs in the Bun runtime.
### []()[Fixed: Bug causing docker container to throw incorrect "port in use" errors](bun-v1.0.7.html#fixed-bug-causing-docker-container-to-throw-incorrect-port-in-use-errors)
A bug causing Bun to throw incorrect "port in use" errors when running in a Docker container has been fixed, thanks to [@Hanaasagi](https://github.com/Hanaasagi).
When binding to IPv6 address failed, Bun would immediately return an error. Now, it also attempts to bind to IPv4 addresses and only returns an error if that also fails. This is because of a [long-standing issue](https://github.com/moby/moby/issues/35954) where Docker would contain IPv6 entries in `/etc/hosts`, even when IPv6 was disabled.
### []()[Fixed: `request.url` would sometimes have incorrect port](bun-v1.0.7.html#fixed-request-url-would-sometimes-have-incorrect-port)
An edgecase causing `request.url` to sometimes have an incorrect port has been fixed, thanks to [@Electroid](https://github.com/Electroid).
### []()[Fixed: Missing `statusText` in `Response`](bun-v1.0.7.html#fixed-missing-statustext-in-response)
A bug causing `response.statusText` to be missing has been fixed, thanks to [@toshok](https://github.com/toshok).
### []()[Fixed: WebSocket client Host header missing port](bun-v1.0.7.html#fixed-websocket-client-host-header-missing-port)
A bug where the port number was not included in the `Host` header sent by the WebSocket client has been fixed, thanks to [@Electroid](https://github.com/Electroid).
### []()[Fixed: `Bun.write` reported wrong path in error message](bun-v1.0.7.html#fixed-bun-write-reported-wrong-path-in-error-message)
A bug causing `Bun.write` to report the wrong path in error messages has been fixed, thanks to [@Hanaasagi](https://github.com/Hanaasagi).
### []()[Fixed: `statement.all()` in SQLite sometimes returned a number instead of an array](bun-v1.0.7.html#fixed-statement-all-in-sqlite-sometimes-returned-a-number-instead-of-an-array)
In certain cases `bun:sqlite`'s `statement.all()` function returned a number instead of an array. This was very confusing and has been fixed to always return an array, thanks to [@HForGames](https://github.com/HForGames).
### []()[Fixed: `describe.only` didn't work for nested describe scopes](bun-v1.0.7.html#fixed-describe-only-didn-t-work-for-nested-describe-scopes)
A bug in `bun:test` causing `describe.only` to not work for nested describe scopes has been fixed, thanks to [@igorshapiro](https://github.com/igorshapiro).
## []()[Preperation for regular Windows builds](bun-v1.0.7.html#preperation-for-regular-windows-builds)
We are making changes to our build system in preparation for regular Windows builds.
Bun will soon switch to use `cmake` and `ninja` for builds, rather than a 2000+ line `Makefile`. Bun will also start using the debug builds of JavaScriptCore, which enables various assertions that help us catch bugs earlier. This release implements most of the changes necessary for that, thanks to [@paperclover](https://github.com/paperclover).
Bun will also upgrade from LLVM 16 to LLVM 17 in the next release.
## []()[New Contributors](bun-v1.0.7.html#new-contributors)
Thanks to our 17 new contributors 🎉
- [`@clay-curry`](https://github.com/clay-curry) made their first contribution in [`#6479`](https://github.com/oven-sh/bun/pull/6479)
- [`@jerome-benoit`](https://github.com/jerome-benoit) made their first contribution in [`#6521`](https://github.com/oven-sh/bun/pull/6521)
- [`@Voldemat`](https://github.com/Voldemat) made their first contribution in [`#6128`](https://github.com/oven-sh/bun/pull/6128)
- [`@toshok`](https://github.com/toshok) made their first contribution in [`#6151`](https://github.com/oven-sh/bun/pull/6151)
- [`@HForGames`](https://github.com/HForGames) made their first contribution in [`#5946`](https://github.com/oven-sh/bun/pull/5946)
- [`@yschroe`](https://github.com/yschroe) made their first contribution in [`#5485`](https://github.com/oven-sh/bun/pull/5485)
- [`@Connormiha`](https://github.com/Connormiha) made their first contribution in [`#4975`](https://github.com/oven-sh/bun/pull/4975)
- [`@aralroca`](https://github.com/aralroca) made their first contribution in [`#6558`](https://github.com/oven-sh/bun/pull/6558)
- [`@pierre-cm`](https://github.com/pierre-cm) made their first contribution in [`#6563`](https://github.com/oven-sh/bun/pull/6563)
- [`@klatka`](https://github.com/klatka) made their first contribution in [`#6153`](https://github.com/oven-sh/bun/pull/6153)
- [`@mountainash`](https://github.com/mountainash) made their first contribution in [`#6579`](https://github.com/oven-sh/bun/pull/6579)
- [`@owlcode`](https://github.com/owlcode) made their first contribution in [`#6587`](https://github.com/oven-sh/bun/pull/6587)
- [`@nygmaaa`](https://github.com/nygmaaa) made their first contribution in [`#6581`](https://github.com/oven-sh/bun/pull/6581)
- [`@vladaman`](https://github.com/vladaman) made their first contribution in [`#6208`](https://github.com/oven-sh/bun/pull/6208)
- [`@PaulaBurgheleaGithub`](https://github.com/PaulaBurgheleaGithub) made their first contribution in [`#6620`](https://github.com/oven-sh/bun/pull/6620)
- [`@alangecker`](https://github.com/alangecker) made their first contribution in [`#6598`](https://github.com/oven-sh/bun/pull/6598)
- [`@imcatwhocode`](https://github.com/imcatwhocode) made their first contribution in [`#6590`](https://github.com/oven-sh/bun/pull/6590)
* * *
#### [Bun v1.0.6](bun-v1.0.6.html)
#### [Bun v1.0.8](bun-v1.0.8.html)
On this page
- [`bun install` improvements](bun-v1.0.7.html#bun-install-improvements)
- [New: Optional `peerDependencies`](bun-v1.0.7.html#new-optional-peerdependencies)
- [Fixed: Edgecase where wrong version of packages were installed](bun-v1.0.7.html#fixed-edgecase-where-wrong-version-of-packages-were-installed)
- [Fixed: `bun install github:foo/foo` could save multiple times to package.json](bun-v1.0.7.html#fixed-bun-install-github-foo-foo-could-save-multiple-times-to-package-json)
- [Fixed: Edgecase causing non-deterministic `bun.lockb` on Linux](bun-v1.0.7.html#fixed-edgecase-causing-non-deterministic-bun-lockb-on-linux)
- [Fixed: npm alias edgecase bugfix](bun-v1.0.7.html#fixed-npm-alias-edgecase-bugfix)
- [Node.js compatibility improvements](bun-v1.0.7.html#node-js-compatibility-improvements)
- [Fixed: `child_process` IPC reliability](bun-v1.0.7.html#fixed-child-process-ipc-reliability)
- [Fixed: Hanging socket without `end` event](bun-v1.0.7.html#fixed-hanging-socket-without-end-event)
- [Fixed: `napi` memory leak](bun-v1.0.7.html#fixed-napi-memory-leak)
- [Fixed: `node:stream` crash](bun-v1.0.7.html#fixed-node-stream-crash)
- [Fixed: `server.address()` for Unix sockets](bun-v1.0.7.html#fixed-server-address-for-unix-sockets)
- [Fixed: `threadId` was unset in `Worker`](bun-v1.0.7.html#fixed-threadid-was-unset-in-worker)
- [Fixed: `Buffer.write` with 'binary' truncated to ascii instead of latin1](bun-v1.0.7.html#fixed-buffer-write-with-binary-truncated-to-ascii-instead-of-latin1)
- [Fixed: `Buffer.concat(buffers, undefined)` threw an error](bun-v1.0.7.html#fixed-buffer-concat-buffers-undefined-threw-an-error)
- [Fixed: `node:dns` lookup returned wrong address for family](bun-v1.0.7.html#fixed-node-dns-lookup-returned-wrong-address-for-family)
- [Runtime fixes](bun-v1.0.7.html#runtime-fixes)
- [Fixed: Bug causing docker container to throw incorrect "port in use" errors](bun-v1.0.7.html#fixed-bug-causing-docker-container-to-throw-incorrect-port-in-use-errors)
- [Fixed: `request.url` would sometimes have incorrect port](bun-v1.0.7.html#fixed-request-url-would-sometimes-have-incorrect-port)
- [Fixed: Missing `statusText` in `Response`](bun-v1.0.7.html#fixed-missing-statustext-in-response)
- [Fixed: WebSocket client Host header missing port](bun-v1.0.7.html#fixed-websocket-client-host-header-missing-port)
- [Fixed: `Bun.write` reported wrong path in error message](bun-v1.0.7.html#fixed-bun-write-reported-wrong-path-in-error-message)
- [Fixed: `statement.all()` in SQLite sometimes returned a number instead of an array](bun-v1.0.7.html#fixed-statement-all-in-sqlite-sometimes-returned-a-number-instead-of-an-array)
- [Fixed: `describe.only` didn't work for nested describe scopes](bun-v1.0.7.html#fixed-describe-only-didn-t-work-for-nested-describe-scopes)
- [Preperation for regular Windows builds](bun-v1.0.7.html#preperation-for-regular-windows-builds)
- [New Contributors](bun-v1.0.7.html#new-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.8.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.8
* * *
[Ashcon Partovi](https://twitter.com/ashconpartovi) · November 2, 2023
[](../rss.xml)
Bun v1.0.8 fixes 138 bugs (addressing 257 👍 reactions), makes `require()` use 30% less memory, adds module mocking to `bun test`, fixes more `bun install` bugs, and fixes more runtime bugs.
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun:
- [`v1.0.0`](../1.0.html) - First stable release!
- [`v1.0.1`](bun-v1.0.1.html) - Named imports for .json and .toml files, fixes to `bun install`, `node:path`, and `Buffer`
- [`v1.0.2`](bun-v1.0.2.html) - Make `--watch` faster and lots of bug fixes
- [`v1.0.3`](bun-v1.0.3.html) - `emitDecoratorMetadata` and Nest.js support, fixes for private registries and more
- [`v1.0.4`](bun-v1.0.4.html) - `server.requestIP`, virtual modules in runtime plugins, and more
- [`v1.0.5`](bun-v1.0.5.html) - Fixed memory leak with `fetch()`, `KeyObject` support in `node:crypto` module, `expect().toEqualIgnoringWhitespace` in `bun:test`, and more
- [`v1.0.6`](bun-v1.0.6.html) - Fixes 3 bugs (addressing 85 👍 reactions), implements `overrides` & `resolutions` in `package.json`, and fixes regression impacting Docker usage with Bun
- [`v1.0.7`](bun-v1.0.7.html) - Fixes 59 bugs (addressing 78 👍 reactions), implements optional peer dependencies in `bun install`, and makes improvements to Node.js compatibility.
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
```
## []()[`require()` uses up to 30% less memory](bun-v1.0.8.html#require-uses-up-to-30-less-memory)
We discovered a memory leak when using `require()`, which was introduced when some of Bun's built-in modules were refactored from ESM to CommonJS. We've also added a small performance optimization to Bun's JavaScript parser for large files that create many scopes.
Bun v1.0.7: (before)
```
❯ bun discordy.js
[92.39ms] require("discord.js")
Memory: 73.5625 MB
```
Bun v1.0.8: (after)
```
❯ bun discordy.js
[90.22ms] require("discord.js")
Memory: 55.1875 MB
```
> In the next version of Bun
>
> A memory leak in require() is fixed [pic.twitter.com/gYDBK0Uwti](https://t.co/gYDBK0Uwti)
>
> — Jarred Sumner (@jarredsumner) [October 30, 2023](https://twitter.com/jarredsumner/status/1718825180443849123?ref_src=twsrc%5Etfw)
## []()[Module mocking in `bun test`](bun-v1.0.8.html#module-mocking-in-bun-test)
`bun test` now supports module mocking.
- Module mocks support both ESM and CJS.
- Existing imports are updated in-place. This means module mocks work at runtime (unlike other test runners, which do it at build time).
- You can override builtins, local files, and packages.
```
import { mock, test, expect } from "bun:test";
import { fn, iCallFn, variable } from "./mock-module-fixture";
test("mocking a local file", async () => {
expect(fn()).toEqual(42);
expect(variable).toEqual(7);
mock.module("./mock-module-fixture.ts", () => {
return {
fn: () => 1,
variable: 8,
};
});
expect(fn()).toEqual(1);
expect(variable).toEqual(8);
mock.module("./mock-module-fixture.ts", () => {
return {
fn: () => 2,
variable: 9,
};
});
expect(fn()).toEqual(2);
expect(variable).toEqual(9);
mock.module("./mock-module-fixture.ts", () => {
return {
fn: () => 3,
variable: 10,
};
});
expect(fn()).toEqual(3);
expect(variable).toEqual(10);
expect(require("./mock-module-fixture").fn()).toBe(3);
expect(require("./mock-module-fixture").variable).toBe(10);
expect(iCallFn()).toBe(3);
});
```
## []()[`bun install` peer dependency duplicate version bugfix](bun-v1.0.8.html#bun-install-peer-dependency-duplicate-version-bugfix)
Previously, `bun install` would always resolve the most recent version of a peer dependency, even if it was already installed. This could cause duplicate versions of the same package to be installed, which would increase the size of `node_modules` and potentially cause conflicts. This has been fixed thanks to [@dylan-conway](https://github.com/dylan-conway).
```
bar@1.0.1
foo@1.0.0
bar@^1.0.1
```
Bun v1.0.7: (before)
```
bar@1.0.1
bar@1.0.2
```
Bun v1.0.8: (after)
```
bar@1.0.1
```
## []()[`bun install` respects ordering of pre-release tags](bun-v1.0.8.html#bun-install-respects-ordering-of-pre-release-tags)
A bug causing `bun install` to not respect the ordering of pre-release tags has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway). Previously, Bun would only sort the pre-release tag lexicographically, but now it also sorts by semver presedence, if one exists.
package.json
```
{
"dependencies": {
"foo": "^1.0.0-beta.0.0.1"
}
}
```
## []()[Bug fixes](bun-v1.0.8.html#bug-fixes)
### []()[Fixed: `Bun.spawn` not working in Google Cloud, Vercel, and older Linux kernels](bun-v1.0.8.html#fixed-bun-spawn-not-working-in-google-cloud-vercel-and-older-linux-kernels)
`Bun.spawn` is implemented using a syscall, `pidfd_open`, which is not implemented by gVisor (includes Google Cloud Platform and Vercel) and by older Linux kernels. We implemented a workaround where Bun spawns a thread, enqueue concurrent tasks, then calls `waitpid` on each pid. This workaround is loosely based on libuv's default behavior.
If you encountered this error, upgrade to Bun v1.0.7 and it should now work.
```
// This error is fixed:
error: "pidfd_open(2)" system call is not supported by your Linux kernel
```
### []()[Fixed: `Bun.spawn` on macOS sometimes not detecting process exit](bun-v1.0.8.html#fixed-bun-spawn-on-macos-sometimes-not-detecting-process-exit)
A longstanding bug in `Bun.spawn` on macOS has been fixed. Previously, `Bun.spawn()` on macOS might fail to detect when the process exited when the event came shortly before a signal was sent. This was due to a race condition in event notifications from kqueue where the process might receive a notification from the operating system, but has not exited yet and then when we subscribe to notifications from the operating to detect when the process exits, it would tell us it exited.
In text-speak, the bug was this:
**macOS**: "hey something happened with process 123456"
**bun**: "cool, did process 123456 exit?"
**macOS**: "no"
**bun**: "ok...tell me when process 123456 exits"
**macOS**: "i can't tell u because it already exited"
**bun**: "???"
Now, we handle this case by recognizing when macOS reports it already exited after previously reporting it hadn't exited yet.
### []()[Fixed: `process.stdin` not sending `close` event](bun-v1.0.8.html#fixed-process-stdin-not-sending-close-event)
When Bun was done reading from `process.stdin`, it would not send a `close` event. This has been fixed, thanks to [@liz3](https://github.com/liz3).
### []()[Fixed: `setTimeout(cb, 0)` behaved incorrectly](bun-v1.0.8.html#fixed-settimeout-cb-0-behaved-incorrectly)
`setTimeout` now has a minimum duration of `1`, which aligns with the behaviour of Node.js and browsers. Previously, `setTimeout` with `0` would cause weird behavior, such as infinite loops when the task queue was being drained before moving on to the next tick.
### []()[Fixed: `setImmediate()` behaved incorrectly](bun-v1.0.8.html#fixed-setimmediate-behaved-incorrectly)
`setImmediate` now has a separate task queue, which aligns `setImmediate` with what Node.js does. Previously, `setImmediate` was similar to `queueMicrotask` which was incorrect.
### []()[Fixed: `server.requestIP` sometimes returning bad IP addresses](bun-v1.0.8.html#fixed-server-requestip-sometimes-returning-bad-ip-addresses)
A bug causing `server.requestIP` to sometimes return malformed IP addresses has been fixed, thanks to [@Hanaasagi](https://github.com/Hanaasagi).
Bun v1.0.7: (before)
```
{
"address": "4294967232.4294967208.68.57",
"family": "IPv4",
"port": 40174
}
```
Bun v1.0.8: (after)
```
{
"address": "192.168.68.57",
"family": "IPv4",
"port": 40174
}
```
### []()[Fixed: Edgecase with `util.promisify` and `node:dns`](bun-v1.0.8.html#fixed-edgecase-with-util-promisify-and-node-dns)
A bug causing `util.promisify` to not work correctly with `node:dns` has been fixed, thanks to [@antongolub](https://github.com/antongolub).
Bun v1.0.7: (incorrect)
```
const { promisify } = require("node:util");
const { lookup } = require("node:dns");
await promisify(lookup)("example.com"); // "45.33.20.235"
```
Bun v1.0.8: (correct)
```
const { promisify } = require("node:util");
const { lookup } = require("node:dns");
await promisify(lookup)("example.com"); // { address: "45.33.20.235", family: 4 }
```
### []()[Fixed: Crash when calling `Script` or `File` without `new`](bun-v1.0.8.html#fixed-crash-when-calling-script-or-file-without-new)
Thanks to [@krk](https://github.com/krk) for fixing a crash when invoking certain classes without `new`. We have plans to mitigate this class of bug by improving our API bindings.
Bun v1.0.7: (before)
```
File(); // <crash>
Script(); // <crash>
```
Bun v1.0.8: (after)
```
File(); // "Class constructor File cannot be invoked without 'new'"
Script(); // "Class constructor Script cannot be invoked without 'new'"
```
### []()[Fixed: Minifier printing bug with `case undefined`](bun-v1.0.8.html#fixed-minifier-printing-bug-with-case-undefined)
Thanks to [@krk](https://github.com/krk) for fixing a bug where `case undefined` was minified to have a missing whitespace, causing invalid JavaScript syntax.
```
switch (true) {
case undefined: {
}
}
```
Bun v1.0.7: (before)
```
switch(true){caseundefined:{}} // SyntaxError: Unexpected token 'caseundefined'
```
Bun v1.0.8: (after)
```
switch(true){case undefined:{}}
```
### []()[Fixed: Edgecases with macros causing a crash](bun-v1.0.8.html#fixed-edgecases-with-macros-causing-a-crash)
There were some edgecases when using macros that would cause a crash, instead of showing the underlying error. This has been fixed, thanks to [@I-A-S](https://github.com/I-A-S).
### []()[Fixed: Incorrect behviour for `Buffer.readUintBE`](bun-v1.0.8.html#fixed-incorrect-behviour-for-buffer-readuintbe)
There was an decoding bug that caused `Buffer.readUintBE` to return incorrect values in certain cases. Thanks to [@Hanaasagi](https://github.com/Hanaasagi) for fixing this issue.
### []()[Fixed: `fetch()` not throwing an error for untrusted certificates](bun-v1.0.8.html#fixed-fetch-not-throwing-an-error-for-untrusted-certificates)
A bug in error handling code for BoringSSL in fetch led to Bun not throwing an error when server certificates in `fetch()` failed to verify and inadvertently ignoring some errors from BoringSSL.
Thanks to [@ansg191](https://github.com/ansg191) for discovering and reporting this issue. Thanks to [@cirospaciari](https://github.com/cirospaciari) for implementing a fix and improving our test coverage.
### []()[New: Support for printing `Map` and `Set` iterators](bun-v1.0.8.html#new-support-for-printing-map-and-set-iterators)
Bun will now print `Map` and `Set` iterators in `console.log`, thanks to [@liz3](https://github.com/liz3).
```
const set = new Set([1, "123", { a: [], str: "123123132", nr: 3453 }]);
console.log(set.keys());
```
```
SetIterator {
1,
"123",
{
a: [],
str: "123123132",
nr: 3453
},
}
```
### []()[New Contributors](bun-v1.0.8.html#new-contributors)
- [@Pedromdsn](https://github.com/Pedromdsn) made their first contribution in [#6626](https://github.com/oven-sh/bun/pull/6626)
- [@yamcodes](https://github.com/yamcodes) made their first contribution in [#6656](https://github.com/oven-sh/bun/pull/6656)
- [@nxzq](https://github.com/nxzq) made their first contribution in [#6673](https://github.com/oven-sh/bun/pull/6673)
- [@jasperkelder](https://github.com/jasperkelder) made their first contribution in [#6703](https://github.com/oven-sh/bun/pull/6703)
- [@thapasusheel](https://github.com/thapasusheel) made their first contribution in [#6718](https://github.com/oven-sh/bun/pull/6718)
- [@RaisinTen](https://github.com/RaisinTen) made their first contribution in [#6745](https://github.com/oven-sh/bun/pull/6745)
- [@rohanmayya](https://github.com/rohanmayya) made their first contribution in [#6679](https://github.com/oven-sh/bun/pull/6679)
- [@perpetualsquid](https://github.com/perpetualsquid) made their first contribution in [#6774](https://github.com/oven-sh/bun/pull/6774)
- [@Smoothieewastaken](https://github.com/Smoothieewastaken) made their first contribution in [#6772](https://github.com/oven-sh/bun/pull/6772)
- [@gamedevsam](https://github.com/gamedevsam) made their first contribution in [#6788](https://github.com/oven-sh/bun/pull/6788)
- [@kingofdreams777](https://github.com/kingofdreams777) made their first contribution in [#6787](https://github.com/oven-sh/bun/pull/6787)
- [@RohitKaushal7](https://github.com/RohitKaushal7) made their first contribution in [#6739](https://github.com/oven-sh/bun/pull/6739)
- [@I-A-S](https://github.com/I-A-S) made their first contribution in [#6756](https://github.com/oven-sh/bun/pull/6756)
- [@krk](https://github.com/krk) made their first contribution in [#6808](https://github.com/oven-sh/bun/pull/6808)
- [@antongolub](https://github.com/antongolub) made their first contribution in [#6748](https://github.com/oven-sh/bun/pull/6748)
- [@Marukome0743](https://github.com/Marukome0743) made their first contribution in [#6819](https://github.com/oven-sh/bun/pull/6819)
### []()[Thanks to 26 contributors](bun-v1.0.8.html#thanks-to-26-contributors)
Thanks to the following 26 people for contributing to this release of Bun:
- [@antongolub](https://github.com/antongolub)
- [@ansg191](https://github.com/ansg191)
- [@cirospaciari](https://github.com/cirospaciari)
- [@colinhacks](https://github.com/colinhacks)
- [@dylan-conway](https://github.com/dylan-conway)
- [@gamedevsam](https://github.com/gamedevsam)
- [@Hanaasagi](https://github.com/Hanaasagi)
- [@I-A-S](https://github.com/I-A-S)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@jasperkelder](https://github.com/jasperkelder)
- [@jerome-benoit](https://github.com/jerome-benoit)
- [@kingofdreams777](https://github.com/kingofdreams777)
- [@krk](https://github.com/krk)
- [@liz3](https://github.com/liz3)
- [@Marukome0743](https://github.com/Marukome0743)
- [@nxzq](https://github.com/nxzq)
- [@o-az](https://github.com/o-az)
- [@paperclover](https://github.com/paperclover)
- [@Pedromdsn](https://github.com/Pedromdsn)
- [@perpetualsquid](https://github.com/perpetualsquid)
- [@pierre-cm](https://github.com/pierre-cm)
- [@RaisinTen](https://github.com/RaisinTen)
- [@rohanmayya](https://github.com/rohanmayya)
- [@RohitKaushal7](https://github.com/RohitKaushal7)
- [@Smoothieewastaken](https://github.com/Smoothieewastaken)
- [@thapasusheel](https://github.com/thapasusheel)
- [@yamcodes](https://github.com/yamcodes)
**Full Changelog**: [https://github.com/oven-sh/bun/compare/bun-v1.0.7...bun-v1.0.8](https://github.com/oven-sh/bun/compare/bun-v1.0.7...bun-v1.0.8)
* * *
#### [Bun v1.0.7](bun-v1.0.7.html)
#### [Bun v1.0.9](bun-v1.0.9.html)
On this page
- [`require()` uses up to 30% less memory](bun-v1.0.8.html#require-uses-up-to-30-less-memory)
- [Module mocking in `bun test`](bun-v1.0.8.html#module-mocking-in-bun-test)
- [`bun install` peer dependency duplicate version bugfix](bun-v1.0.8.html#bun-install-peer-dependency-duplicate-version-bugfix)
- [`bun install` respects ordering of pre-release tags](bun-v1.0.8.html#bun-install-respects-ordering-of-pre-release-tags)
- [Bug fixes](bun-v1.0.8.html#bug-fixes)
- [Fixed: `Bun.spawn` not working in Google Cloud, Vercel, and older Linux kernels](bun-v1.0.8.html#fixed-bun-spawn-not-working-in-google-cloud-vercel-and-older-linux-kernels)
- [Fixed: `Bun.spawn` on macOS sometimes not detecting process exit](bun-v1.0.8.html#fixed-bun-spawn-on-macos-sometimes-not-detecting-process-exit)
- [Fixed: `process.stdin` not sending `close` event](bun-v1.0.8.html#fixed-process-stdin-not-sending-close-event)
- [Fixed: `setTimeout(cb, 0)` behaved incorrectly](bun-v1.0.8.html#fixed-settimeout-cb-0-behaved-incorrectly)
- [Fixed: `setImmediate()` behaved incorrectly](bun-v1.0.8.html#fixed-setimmediate-behaved-incorrectly)
- [Fixed: `server.requestIP` sometimes returning bad IP addresses](bun-v1.0.8.html#fixed-server-requestip-sometimes-returning-bad-ip-addresses)
- [Fixed: Edgecase with `util.promisify` and `node:dns`](bun-v1.0.8.html#fixed-edgecase-with-util-promisify-and-node-dns)
- [Fixed: Crash when calling `Script` or `File` without `new`](bun-v1.0.8.html#fixed-crash-when-calling-script-or-file-without-new)
- [Fixed: Minifier printing bug with `case undefined`](bun-v1.0.8.html#fixed-minifier-printing-bug-with-case-undefined)
- [Fixed: Edgecases with macros causing a crash](bun-v1.0.8.html#fixed-edgecases-with-macros-causing-a-crash)
- [Fixed: Incorrect behviour for `Buffer.readUintBE`](bun-v1.0.8.html#fixed-incorrect-behviour-for-buffer-readuintbe)
- [Fixed: `fetch()` not throwing an error for untrusted certificates](bun-v1.0.8.html#fixed-fetch-not-throwing-an-error-for-untrusted-certificates)
- [New: Support for printing `Map` and `Set` iterators](bun-v1.0.8.html#new-support-for-printing-map-and-set-iterators)
- [New Contributors](bun-v1.0.8.html#new-contributors)
- [Thanks to 26 contributors](bun-v1.0.8.html#thanks-to-26-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.9.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.0.9
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · November 5, 2023
[](../rss.xml)
Bun v1.0.9 fixes regressions impacting usage in Vercel & older CPUs, a `Bun.spawn` bug, an edgecase with peer dependency installs, and a JSX transpiler bugfix.
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one. In case you missed it, here are some of the recent changes to Bun:
- [`v1.0.0`](../1.0.html) - First stable release!
- [`v1.0.1`](bun-v1.0.1.html) - Named imports for .json and .toml files, fixes to `bun install`, `node:path`, and `Buffer`
- [`v1.0.2`](bun-v1.0.2.html) - Make `--watch` faster and lots of bug fixes
- [`v1.0.3`](bun-v1.0.3.html) - `emitDecoratorMetadata` and Nest.js support, fixes for private registries and more
- [`v1.0.4`](bun-v1.0.4.html) - `server.requestIP`, virtual modules in runtime plugins, and more
- [`v1.0.5`](bun-v1.0.5.html) - Fixed memory leak with `fetch()`, `KeyObject` support in `node:crypto` module, `expect().toEqualIgnoringWhitespace` in `bun:test`, and more
- [`v1.0.6`](bun-v1.0.6.html) - Fixes 3 bugs (addressing 85 👍 reactions), implements `overrides` & `resolutions` in `package.json`, and fixes regression impacting Docker usage with Bun
- [`v1.0.7`](bun-v1.0.7.html) - Fixes 59 bugs (addressing 78 👍 reactions), implements optional peer dependencies in `bun install`, and makes improvements to Node.js compatibility.
- [`v1.0.8`](bun-v1.0.8.html) - Fixes 138 bugs (addressing 257 👍 reactions), makes `require()` use 30% less memory, adds module mocking to `bun test`, fixes more `bun install` bugs
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
```
## []()["Illegal instruction" and glibc symbol version regression from v1.0.8 is fixed](bun-v1.0.9.html#illegal-instruction-and-glibc-symbol-version-regression-from-v1-0-8-is-fixed)
In Bun v1.0.8, we moved our internal build-system from a bespoke 2,000 line `Makefile` to CMake & Ninja. This was to simplify our build system for contributors and to make it easier to build Bun on Windows.
Along the way, there were three regressions:
1. Bun v1.0.8 would crash with an "Illegal instruction" error on older CPUs (e.g. Intel Xeon E5-2670 v1) and some Linux arm64 CPUs. This impacted Docker users and users of older CPUs.
2. Bun v1.0.8 would crash with a "symbol not found" error for those using < glibc 2.28. This impacted Vercel users and users of older Linux distributions.
3. `bun init` would incorrectly print the version number in the `README.md`
These regressions are fixed, but they are embarassing for a post 1.0 product and I am sorry.
Here's what we're doing to prevent this from happening again:
1. We are adding a CI job that runs on a machine with an older CPU to test Bun on older CPUs
2. We are adding a CI job to check the minimum required version of glibc used by Bun's final executable and throw an error if it requests a version that is too new
3. We added a test to ensure `bun init` prints the correct version number in the `README.md`
## []()[Bun.spawn bugfixes](bun-v1.0.9.html#bun-spawn-bugfixes)
This release fixes two bugs in `Bun.spawn`. We've also added more tests to `Bun.spawn`.
### []()[Fixed: `await spawn(...).exited` sometimes returned a string](bun-v1.0.9.html#fixed-await-spawn-exited-sometimes-returned-a-string)
`await child.exited` sometimes returned a string instead of a number. The string was the signal that caused the process to exit.
```
import { spawn } from "bun";
const child = spawn(["sleep", "1"]);
child.kill();
const code = await child.exited;
// Before:
console.log(code); // "SIGHUP"
// After:
console.log(code); // 129
```
Instead of returning a string, `await child.exited` now returns a number. This is consistent with what our TypeScript types declared, what our documentation said, and what bash's exit codes do.
If the process exited normally, it returns `0`. If the process exited due to a signal, it returns `128` + signal number. For example, if the process exited due to `SIGTERM`, it would return `128 + 15 = 143`.
### []()[Fixed: edgecase causing `await spawn(...).exited` to not resolve](bun-v1.0.9.html#fixed-edgecase-causing-await-spawn-exited-to-not-resolve)
An edgecase that could cause `await spawn(...).exited` to not resolve has been fixed.
## []()[`bun install` peer dependency too many versions bugfix](bun-v1.0.9.html#bun-install-peer-dependency-too-many-versions-bugfix)
In this release, we began porting some tests from other package managers to Bun.
One of the tests uncovered an issue where Bun would not re-use a peer dependency's version from the existing project. This is fixed to align with the behavior of npm.
We've also added a warning when a peer dependency's chosen version is incompatible with the version range specified in the `package.json`.
## []()[JSX transpiler bugfix](bun-v1.0.9.html#jsx-transpiler-bugfix)
Either of the following lines of code would previously cause a runtime panic due to an assertion failure:
```
<A key={() => {}} b={class {}} />
<A key={() => {}} b={() => {}} />
```
This is fixed.
The bug was due to special handling of the `key` prop causing the AST nodes to not be visited in the order they were parsed. This bug could occur if the `key` prop created a scope, such as defining a function or class.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this bug!
* * *
#### [Bun v1.0.8](bun-v1.0.8.html)
#### [Bun v1.0.10](bun-v1.0.10.html)
On this page
- ["Illegal instruction" and glibc symbol version regression from v1.0.8 is fixed](bun-v1.0.9.html#illegal-instruction-and-glibc-symbol-version-regression-from-v1-0-8-is-fixed)
- [Bun.spawn bugfixes](bun-v1.0.9.html#bun-spawn-bugfixes)
- [Fixed: `await spawn(...).exited` sometimes returned a string](bun-v1.0.9.html#fixed-await-spawn-exited-sometimes-returned-a-string)
- [Fixed: edgecase causing `await spawn(...).exited` to not resolve](bun-v1.0.9.html#fixed-edgecase-causing-await-spawn-exited-to-not-resolve)
- [`bun install` peer dependency too many versions bugfix](bun-v1.0.9.html#bun-install-peer-dependency-too-many-versions-bugfix)
- [JSX transpiler bugfix](bun-v1.0.9.html#jsx-transpiler-bugfix)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.0.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun 1.0
* * *
[Jarred Sumner](https://twitter.com/jarredsumner), [Ashcon Partovi](https://twitter.com/ashconpartovi), [Colin McDonnell](https://twitter.com/colinhacks) · September 8, 2023
[](../rss.xml)
Bun 1.0 is finally here.
Bun is a fast, all-in-one toolkit for running, building, testing, and debugging JavaScript and TypeScript, from a single file to a full-stack application. Today, Bun is stable and production-ready.
**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
```
**Upgrade Bun**
```
bun upgrade
```
## []()[Bun is an all-in-one toolkit](../1.0.html#bun-is-an-all-in-one-toolkit)
We love JavaScript. It's mature, it moves fast, and its developer community is vibrant and passionate. It's awesome.
However, since Node.js debuted 14 years ago, layers and layers of tooling have accumulated on top of each other. And like any system that grows and evolves without centralized planning, JavaScript tooling has become slow and complex.
### []()[Why Bun exists](../1.0.html#why-bun-exists)
Bun's goal is simple: eliminate slowness and complexity *without* throwing away everything that's great about JavaScript. Your favorite libraries and frameworks should still work, and you shouldn't need to unlearn the conventions you're familiar with.
You *will* however need to unlearn the many tools that Bun makes unnecessary:
**Node.js** — Bun is a drop-in replacement for Node.js, so you don't need:
- `node`
- `npx` — `bunx` is 5x faster
- `dotenv`, `cross-env` — Bun reads `.env` files by default
- `nodemon`, `pm2` — built-in watch mode
- `ws` — built-in WebSocket server
- `node-fetch`, `isomorphic-fetch` — built-in `fetch`
**Transpilers** — Bun can run `.js`, `.ts`, `.cjs`, `.mjs`, `.jsx`, and `.tsx` files, which can replace:
- `tsc` — (but you can keep it for typechecking!)
- `babel`, `.babelrc`, `@babel/preset-*`
- `ts-node`, `ts-node-esm`
- `tsx`
**Bundlers** — Bun is a JavaScript bundler with best-in-class performance and an esbuild-compatible plugin API, so you don't need:
- `esbuild`
- `webpack`
- `parcel`, `.parcelrc`
- `rollup`, `rollup.config.js`
**Package managers** — Bun is an npm-compatible package manager with familiar commands. It reads your `package.json` and writes to `node_modules`, just like other package managers, so you can replace:
- `npm`, `.npmrc`, `package-lock.json`
- `yarn`, `yarn.lock`
- `pnpm`, `pnpm.lock`, `pnpm-workspace.yaml`
- `lerna`
**Testing libraries** — Bun is a Jest-compatible test runner with support for snapshot testing, mocking, and code coverage, so you no longer need:
- `jest`, `jest.config.js`
- `ts-jest`, `@swc/jest`, `babel-jest`
- `jest-extended`
- `vitest`, `vitest.config.ts`
While these tools are each good in their own right (mostly), using them all together inevitably creates fragility and a slow developer experience. They perform a lot of redundant work; when you run `jest`, your code will be parsed 3+ times by various tools! And the duct tape, plugins, and adapters required to stitch everything together always frays eventually.
Bun is a single integrated toolkit that avoids these integration problems. Each tool in this toolkit provides a best-in-class developer experience, from performance to API design.
## []()[Bun is a JavaScript runtime](../1.0.html#bun-is-a-javascript-runtime)
Bun is a fast JavaScript runtime. Its goal is to make the experience of building software faster, less frustrating, and more fun.
### []()[Node.js compatibility](../1.0.html#node-js-compatibility)
Bun is a drop-in replacement for Node.js. That means existing Node.js applications and npm packages *just work* in Bun. Bun has built-in support for Node APIs, including:
- built-in modules like `fs`, `path`, and `net`,
- globals like `__dirname` and `process`,
- and the Node.js module resolution algorithm. (e.g. `node_modules`)
While *perfect* compatibility with Node.js isn't possible — looking at you `node:v8` — Bun can run virtually any Node.js application in the wild.
Bun is tested against test suites of the most popular Node.js packages on npm. Server frameworks like Express, Koa, and Hono just work. As do applications built using the most popular full-stack frameworks. Collectively, these libraries and frameworks touch every part of Node.js's API surface that matters.
[](https://github.com/oven-sh/bun/assets/3084745/e4c4ee5d-a859-4a7b-97f7-9fb477939fe6)
Full-stack applications built with Next.js, Remix, Nuxt, Astro, SvelteKit, Nest, SolidStart, and Vite work in Bun.
**Note** — For a detailed breakdown of Node.js compatibility, check out: [bun.sh/nodejs](../nodejs.html).
### []()[Speed](../1.0.html#speed)
Bun is fast, starting up to 4x [faster](https://twitter.com/jarredsumner/status/1499225725492076544) than Node.js. This difference is only magnified when running a TypeScript file, which requires transpilation before it can be run by Node.js.
[](https://github.com/oven-sh/bun/assets/3084745/e65fa63c-99c7-4bcf-950b-e2fe9408a942)
Bun runs a "hello world" TypeScript file 5x faster than esbuild with Node.js.
Unlike Node.js and other runtimes that are built using Google's V8 engine, Bun is built using Apple's [WebKit](https://webkit.org/) engine. WebKit is the engine that powers Safari and is used by billions of devices every day. It's fast, efficient, and has been battle-tested for decades.
### []()[TypeScript and JSX support](../1.0.html#typescript-and-jsx-support)
Bun has a JavaScript transpiler that's baked into the runtime. That means you can run JavaScript, TypeScript, and even JSX/TSX files, no dependencies needed.
```
bun index.ts
```
```
bun index.jsx
```
```
bun index.tsx
```
### []()[ESM & CommonJS compatibility](../1.0.html#esm-commonjs-compatibility)
The transition from CommonJS to ES modules has been slow and full of terrors. After ESM was introduced, Node.js took 5 years before supporting it without an `--experimental-modules` flag. Regardless, the ecosystem is still full of CommonJS.
Bun supports both module systems, all the time. No need to worry about file extensions, `.js` vs `.cjs` vs `.mjs`, or including `"type": "module"` in your `package.json`.
You can even use `import` and `require()`, *in the same file.* It just works.
```
import lodash from "lodash";
const _ = require("underscore");
```
### []()[Web APIs](../1.0.html#web-apis)
Bun has built-in support for the Web standard APIs that are available in browsers, such as `fetch`, `Request`, `Response`, `WebSocket`, and `ReadableStream`.
```
const response = await fetch("https://example.com/");
const text = await response.text();
```
You no longer need to install packages like `node-fetch` and `ws`. Bun's built-in Web APIs are implemented in native code, and are faster and more reliable than the third-party alternatives.
### []()[Hot reloading](../1.0.html#hot-reloading)
Bun makes it easier for you to be productive as a developer. You can run Bun with `--hot` to enable hot reloading, which reloads your application when files change.
```
bun --hot server.ts
```
Unlike tools that hard-restart the entire process, like `nodemon`, Bun reloads your code without terminating the old process. That means HTTP and WebSocket connections don't disconnect and state isn't lost.
[](../hot.gif)
### []()[Plugins](../1.0.html#plugins)
Bun is designed to be highly-customizable.
You can define plugins to intercept imports and perform custom loading logic. A plugin can add support for additional file types, like `.yaml` or `.png`. The [Plugin API](../docs/runtime/plugins.html) is inspired by esbuild, which means that most esbuild plugins will just work in Bun.
```
import { plugin } from "bun";
plugin({
name: "YAML",
async setup(build) {
const { load } = await import("js-yaml");
const { readFileSync } = await import("fs");
build.onLoad({ filter: /\.(yaml|yml)$/ }, (args) => {
const text = readFileSync(args.path, "utf8");
const exports = load(text) as Record<string, any>;
return { exports, loader: "object" };
});
},
});
```
## []()[Bun APIs](../1.0.html#bun-apis)
Bun ships with highly-optimized, standard-library APIs for the things you need most as a developer.
In contrast to Node.js APIs, which exist for backwards compatibility, these *Bun-native* APIs are designed to be fast and easy-to-use.
### []()[`Bun.file()`](../1.0.html#bun-file)
Use `Bun.file()` to lazily load a `File` at a particular path.
```
const file = Bun.file("package.json");
const contents = await file.text();
```
It returns a `BunFile`, which extends the Web standard [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File). The file contents can be lazily loaded in various formats.
```
const file = Bun.file("package.json");
await file.text(); // string
await file.arrayBuffer(); // ArrayBuffer
await file.blob(); // Blob
await file.json(); // {...}
```
Bun reads files up to 10x times [faster](https://twitter.com/jarredsumner/status/1513878964531519494) than Node.js.
### []()[`Bun.write()`](../1.0.html#bun-write)
Use `Bun.write()` is a single, flexible API for writing almost anything to disk — string, binary data, `Blobs`, even a `Response` object.
```
await Bun.write("index.html", "<html/>");
await Bun.write("index.html", Buffer.from("<html/>"));
await Bun.write("index.html", Bun.file("home.html"));
await Bun.write("index.html", await fetch("https://example.com/"));
```
Bun writes files up to 3x [faster](https://twitter.com/jarredsumner/status/1551003252920946688) than Node.js.
### []()[`Bun.serve()`](../1.0.html#bun-serve)
Use `Bun.serve()` to spin up an HTTP server, WebSocket server, or both. It's based on familiar Web-standard APIs like `Request` and `Response`.
```
Bun.serve({
port: 3000,
fetch(request) {
return new Response("Hello from Bun!");
},
});
```
Bun can serve 4x [more](https://github.com/oven-sh/bun/tree/main/bench/react-hello-world) requests per second than Node.js.
You can also configure TLS using the `tls` option.
```
Bun.serve({
port: 3000,
fetch(request) {
return new Response("Hello from Bun!");
},
tls: {
key: Bun.file("/path/to/key.pem"),
cert: Bun.file("/path/to/cert.pem"),
}
});
```
To support WebSockets alongside HTTP, simply define an event handler inside `websocket`. Compare this with Node.js, which doesn't provide a built-in WebSocket API and requires a third-party dependency like `ws`.
```
Bun.serve({
fetch() { ... },
websocket: {
open(ws) { ... },
message(ws, data) { ... },
close(ws, code, reason) { ... },
},
});
```
Bun can serve 5x [more](https://github.com/oven-sh/bun/tree/main/bench/websocket-server) messages per second than `ws` on Node.js.
### []()[`bun:sqlite`](../1.0.html#bun-sqlite)
Bun has built-in support for SQLite. It has an API that's inspired by `better-sqlite3`, but is written in native code to be faster.
```
import { Database } from "bun:sqlite";
const db = new Database(":memory:");
const query = db.query("select 'Bun' as runtime;");
query.get(); // => { runtime: "Bun" }
```
Bun can query SQLite up to 4x [faster](https://github.com/oven-sh/bun/tree/main/bench/sqlite) than `better-sqlite3` on Node.js.
### []()[`Bun.password`](../1.0.html#bun-password)
Bun also supports APIs for common, but complex things you wouldn't want to implement yourself.
You can use `Bun.password` to hash and verify passwords using bcrypt or argon2, no external dependencies required.
```
const password = "super-secure-pa$$word";
const hash = await Bun.password.hash(password);
// => $argon2id$v=19$m=65536,t=2,p=1$tFq+9AVr1bfPxQdh...
const isMatch = await Bun.password.verify(password, hash);
// => true
```
## []()[Bun is a package manager](../1.0.html#bun-is-a-package-manager)
Even if you don't use Bun as a runtime, Bun's built-in package manager can speed up your development workflow. Gone are the days of staring at that `npm` spinner as your dependencies install.
Bun may *look* like the package managers you're used to —
```
bun install
```
```
bun add <package> [--dev|--production|--peer]
```
```
bun remove <package>
```
```
bun update <package>
```
— but it doesn't *feel* like them.
> Wow, bun install is ridiculously fast
>
> So fast I didn't believe it worked. I had to stare at the console for a while to fully believe that the package install actually happened
>
> Feels really nice to use, huge kudos to [@jarredsumner](https://twitter.com/jarredsumner?ref_src=twsrc%5Etfw)
>
> — Steve (Builder.io) (@Steve8708) [August 21, 2022](https://twitter.com/Steve8708/status/1561412958722306049?ref_src=twsrc%5Etfw)
### []()[Install speeds](../1.0.html#install-speeds)
Bun is orders of magnitude faster than `npm`, `yarn`, and `pnpm`. It uses a global module cache to avoid redundant downloads from the npm registry and uses the fastest system calls available on each operating system.
[](https://github.com/oven-sh/bun/assets/3084745/23cbde35-b859-41b5-9480-98b88bf40c44)
Installing dependencies for a starter Remix project from cache.
### []()[Running scripts](../1.0.html#running-scripts)
Chances are, you haven't ran a script directly with `node` in a while. Instead, we often use our package managers to interface with the frameworks and CLIs to build our apps.
```
npm run dev
```
You can replace `npm run` with `bun run` to save 150ms milliseconds *every time* you run a command.
These numbers may all seem small, but when running CLIs, the perceptual difference is huge. Running `npm run` is noticably laggy—
[](https://github-production-user-asset-6210df.s3.amazonaws.com/3084745/265893417-fbfb4172-5a91-4158-904f-55f2dbb0acde.gif)
—whereas `bun run` feels instantaneous.
[](https://github-production-user-asset-6210df.s3.amazonaws.com/3084745/265893406-6d7e0e3f-cd70-409c-8c1e-9b5493d18e51.gif)
And we're not just picking on npm. In fact, `bun run <command>` is [faster](https://gist.github.com/colinhacks/436b6836cd13291a79dd50dcde2d45bf) than the equivalent in `yarn` and `pnpm`.
Script runnerAvg. time`npm run``176ms``yarn run``131ms``pnpm run``259ms``bun run``7ms` 🚀
## []()[Bun is a test runner](../1.0.html#bun-is-a-test-runner)
If you’ve written tests in JavaScript before, you’re probably familiar with Jest, which pioneered the "expect"-style APIs.
Bun has a built-in testing module `bun:test` that is fully Jest-compatible.
```
import { test, expect } from "bun:test";
test("2 + 2", () => {
expect(2 + 2).toBe(4);
});
```
You can run your tests with the `bun test` command.
```
bun test
```
You also get all the benefits of the Bun runtime, including TypeScript and JSX support.
Migration from Jest or Vitest is easy. Any imports from `@jest/globals` or `vitest` will be internally re-mapped to `bun:test`, so everything works, even without code changes.
index.test.ts
```
import { test } from "@jest/globals";
describe("test suite", () => {
// ...
});
```
In a benchmark against the test suite for [`zod`](https://github.com/colinhacks/zod), Bun was 13x faster than Jest and 8x faster than than Vitest.
[](https://github.com/oven-sh/bun/assets/3084745/05148dc1-eb42-419b-8c92-8c1b574447e4)
Running the test suite for Zod
Bun's matchers are implemented in fast native code — `expect().toEqual()` in Bun is 100x [faster](https://twitter.com/jarredsumner/status/1595681235606585346) than Jest and 10x faster than Vitest.
To get started, you can speed up your CI using `bun test`. In Github Actions, use the official [`oven-sh/setup-bun`](https://github.com/oven-sh/setup-bun) action.
.github/workflows/ci.yml
```
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: oven-sh/setup-bun@v1
- run: bun test
```
And to make things that even nicer, Bun automatically adds annotations to your test failures, so your CI logs are easy to read.
[](https://github.com/oven-sh/bun/assets/3238291/cb8c6070-4f9c-423c-88bc-6f392adaf66d)
## []()[Bun is a bundler](../1.0.html#bun-is-a-bundler)
Bun is a JavaScript and TypeScript bundler and minifier that can be used to bundle code for the browser, Node.js, and other platforms.
CLI
```
bun build ./index.tsx --outdir ./build
```
It's heavily inspired by [esbuild](https://esbuild.github.io/api/) and provides a compatible plugin API.
```
import mdx from "@mdx-js/esbuild";
Bun.build({
entrypoints: ["index.tsx"],
outdir: "build",
plugins: [mdx()],
});
```
Bun's plugin API is universal, meaning it works for both the bundler *and* the runtime. So that `.yaml` plugin from earlier can be used here to support `.yaml` imports during bundling.
Using esbuild's own benchmarks, Bun is 1.75x faster than esbuild, 150x faster than Parcel 2, 180x times faster than Rollup + Terser, and 220x times faster than Webpack.
[](https://github.com/oven-sh/bun/assets/3084745/49fe1da7-b3d7-4b7c-9c9b-26d532c6a57b)
Bundling 10 copies of three.js from scratch, with sourcemaps and minification.
Since Bun's runtime and bundler are integrated, it means that Bun can do things that no other bundler can do.
Bun introduces JavaScript macros, a mechanism for running JavaScript functions at *bundle*-time. The value returned from these functions are directly inlined into your bundle.
index.ts
release.ts
index.ts
```
import { getRelease } from "./release.ts" with { type: "macro" };
// The value of `release` is evaluated at bundle-time,
// and inlined into the bundle, not run-time.
const release = await getRelease();
```
release.ts
```
export async function getRelease(): Promise<string> {
const response = await fetch(
"https://api.github.com/repos/oven-sh/bun/releases/latest"
);
const { tag_name } = await response.json();
return tag_name;
}
```
CLI
```
bun build index.ts
```
```
// index.ts
var release = await "bun-v1.0.0";
```
This is a new paradigm for bundling JavaScript, and we're excited to see what you build with it.
## []()[Bun more thing...](../1.0.html#bun-more-thing)
Bun provides native builds for macOS and Linux, but there's been one notable absence: Windows. Previously, to run Bun on Windows, you would need to install Windows Subsystem for Linux... but not anymore.
For the first time, we're excited to release an experimental, native build of Bun for Windows.
[](https://github.com/oven-sh/bun/assets/3084745/42e0657e-4421-42de-88bc-61a9ec9fa8a7)
While the macOS and Linux builds of Bun are production-ready, **the Windows build is highly experimental**. At the moment, only the JavaScript runtime is supported; the package manager, test runner, and bundler have been disabled until they are more stable. The performance has also not been optimized — yet.
We'll be rapidly improving support for Windows over the coming weeks. If you're excited about Bun for Windows, we'd encourage you to join the `#windows` channel on our [Discord](../discord.html) for updates.
## []()[Thank you](../1.0.html#thank-you)
Bun's journey to 1.0 would have not been possible without Bun's amazing team of engineers and the growing community of contributors.
We'd like to thank those who helped us get here.
- Node.js & its contributors: Software is built on the shoulder of giants.
- WebKit & its contributors, especially [Constellation](https://twitter.com/Constellation): Thank you for making WebKit faster, you're amazing.
- The [nearly 300 contributors](https://github.com/oven-sh/bun/graphs/contributors) who have helped build Bun over the past two years!
## []()[What's next?](../1.0.html#what-s-next)
Bun 1.0 is just the beginning.
We’re developing a new way to deploy JavaScript and TypeScript to production. And we’re [hiring](../careers.html) low-level systems engineers if you want to help us build the future of JavaScript.
You can also:
- [Join](../discord.html) our Discord server to hear the latest about Bun.
- [Follow](https://twitter.com/bunjavascript) us on X/Twitter for JavaScript memes and daily updates from Jarred and the team.
- [Star](https://github.com/oven-sh/bun) us on Github — it pays the bills! (/s)
* * *
**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
```
**Upgrade Bun**
```
bun upgrade
```
* * *
### []()[Changelog since v0.8](../1.0.html#changelog-since-v0-8)
If you were using Bun *before* 1.0, there are a few changes since Bun 0.8.
- Next.js, Astro, and Nest.js are now supported!
- The deprecated `bun dev` command has been removed. Running `bun dev` will now run the `"dev"` script in your package.json.
Bun now supports the following Node.js APIs:
- [`child_process.fork()`](https://nodejs.org/api/child_process.html#child_processforkmodulepath-args-options) and IPC.
- [`fs.cp()`](https://nodejs.org/api/fs.html#fscpsrc-dest-options-callback) and [`fs.cpSync()`](https://nodejs.org/api/fs.html#fscpsyncsrc-dest-options).
- [`fs.watchFile()`](https://nodejs.org/api/fs.html#fswatchfilefilename-options-listener) and [`fs.unwatchFile()`](https://nodejs.org/api/fs.html#fsunwatchfilefilename-listener).
- Unix sockets in `node:http`.
Hot reloading now supports `Bun.serve()`. Previously, this was only possible if the server was defined as a `default export`.
server.ts
```
Bun.serve({
fetch(request) {
return new Response("Reload!");
},
})
```
CLI
```
bun --hot server.ts
```
* * *
#### [Bun v1.0.1](bun-v1.0.1.html)
On this page
- [Bun is an all-in-one toolkit](../1.0.html#bun-is-an-all-in-one-toolkit)
- [Why Bun exists](../1.0.html#why-bun-exists)
- [Bun is a JavaScript runtime](../1.0.html#bun-is-a-javascript-runtime)
- [Node.js compatibility](../1.0.html#node-js-compatibility)
- [Speed](../1.0.html#speed)
- [TypeScript and JSX support](../1.0.html#typescript-and-jsx-support)
- [ESM & CommonJS compatibility](../1.0.html#esm-commonjs-compatibility)
- [Web APIs](../1.0.html#web-apis)
- [Hot reloading](../1.0.html#hot-reloading)
- [Plugins](../1.0.html#plugins)
- [Bun APIs](../1.0.html#bun-apis)
- [`Bun.file()`](../1.0.html#bun-file)
- [`Bun.write()`](../1.0.html#bun-write)
- [`Bun.serve()`](../1.0.html#bun-serve)
- [`bun:sqlite`](../1.0.html#bun-sqlite)
- [`Bun.password`](../1.0.html#bun-password)
- [Bun is a package manager](../1.0.html#bun-is-a-package-manager)
- [Install speeds](../1.0.html#install-speeds)
- [Running scripts](../1.0.html#running-scripts)
- [Bun is a test runner](../1.0.html#bun-is-a-test-runner)
- [Bun is a bundler](../1.0.html#bun-is-a-bundler)
- [Bun more thing...](../1.0.html#bun-more-thing)
- [Thank you](../1.0.html#thank-you)
- [What's next?](../1.0.html#what-s-next)
- [Changelog since v0.8](../1.0.html#changelog-since-v0-8)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.1.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.1
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · April 4, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one.
Bun v1.1.1 fixes 20 bugs (addressing 60 👍 reactions). Add subshell and positional argument support to Bun Shell, fixing an issue with bun install + sharp on Windows. Printed source code in errors no longer fill up your terminal. Upgrades JavaScriptCore, which includes performance improvements to RegExp, typed arrays, String indexOf and String replace. Error objects and JIT'd function calls use less memory. Fixes several bugs with bun install on Windows. Fixes a bug with Bun.serve() on Windows. Fixes a TOML parser bug impacting escape sequences and windows paths in .toml files.
#### Previous releases
- [`v1.1.0`](bun-v1.1.html) Bundows. Windows support is here! Plus, JSON IPC Node <-> Bun.
- [`v1.0.36`](bun-v1.0.36.html) Fixes 13 bugs. Adds support for `fs.openAsBlob` and `fs.opendir`, fixes edgecase in bun install with multiple `bin` entries in `package.json`, fixes `bun build --target bun` encoding, fixes bug with process.stdin & process.stdout, fixes bug in http2, fixes bug with .env in bun run, fixes various Bun shell bugs and improves Node.js compatibility.
#### To install Bun:
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
### []()[Windows support improvements](bun-v1.1.1.html#windows-support-improvements)
## []()[Fixed: `bun install` failed to install sharp on Windows](bun-v1.1.1.html#fixed-bun-install-failed-to-install-sharp-on-windows)
Sharp would not install correctly on Windows due to an unimplemented feature in Bun Shell (which powers lifecycle scripts on Windows). This unimplemented feature has been implemented! Subshells are now supported in Bun Shell.
Our test suite will catch this bug in the future
## []()[Fixed: bun install hanging on Windows](bun-v1.1.1.html#fixed-bun-install-hanging-on-windows)
A bug that could cause `bun install` to hang for awhile has been fixed.
This bug happened when `ERROR_DELETE_PENDING` was returned by a Windows API. When a folder or file is being deleted but hasn't been fully deleted yet, Windows sometimes returns `ERROR_DELETE_PENDING`. The zig standard library handled this by sleeping for 1ms and then retrying the delete. This causes a race condition when one thread has the handle open and another thread is trying to delete the file. The other thread goes to sleep in a loop forever, and the other thread never gets the chance to delete the file.
Thanks to [@gvilums](https://github.com/gvilums) for fixing this issue.
## []()[Fixed: spurious "Install failed" errors in `bun install` on Windows](bun-v1.1.1.html#fixed-spurious-install-failed-errors-in-bun-install-on-windows)
A bug that could cause spurious "Install failed" errors in `bun install` has been fixed. This most frequently occurred when installing many packages simultaneously.
A similar bug involving `@scoped/package` scoped packages was also fixed.
#### Why did this happen?
Permissions in Windows are a bit weird. Opened file handles have a "Sharing Mode", which prevents other file handles from being opened on the same file without the same permissions. In the zig standard library, the `ERROR_SHARING_VIOLATION` error was not handled correctly. Separately, certain functions were also not requesting the same "Sharing Mode", which causes the `ERROR_SHARING_VIOLATION` error. If you've been unable to delete a file on Windows without closing applications, this is frequently the cause.
Thanks to [@gvilums](https://github.com/gvilums) for fixing this issue.
## []()[Fixed: Workspace linking bug on Windows](bun-v1.1.1.html#fixed-workspace-linking-bug-on-windows)
A bug where `bun install` could return `error: Unexpected` while linking a workspace has been fixed.
This was caused by passing an incorrectly formatted filesystem path to a Windows API.
## []()[Fixed: "unable to find executable" in bunx](bun-v1.1.1.html#fixed-unable-to-find-executable-in-bunx)
A bug where running `bunx <package>` sometimes returned `error: unable to find executable` when it definitely should have been able to find the executable has been fixed.
The bug was caused by a cache invalidation bug in `bunx`. `bunx` was checking the `package.json` of the target package instead of the generated package.json that adds the target package as a dependency. The filesystem's creation time for that file may come from the original time the package was published to npm, which means it would virtually always invalidate the executable. Separately, there was another bug where `bunx` would check the creation time of the `package.json` *twice*, first when trying to use the cached verison and a second time after newly installing the package. Checking that second time is unnecessary because it was newly created.
## []()[Fixed: "Failed to install" error with Git dependencies](bun-v1.1.1.html#fixed-failed-to-install-error-with-git-dependencies)
A bug where `bun install` would fail to clone or checkout a git repository with a dependency that was a Git repository has been fixed. This bug was caused by assuming the current working directory of the target package continued to have a valid file descriptor when the `git clone` or `git checkout` command was run. We switched it to use an absolute filesystem path instead, via the `-C` flag in `git`.
Thanks to [@gvilums](https://github.com/gvilums) for fixing this issue.
## []()[Fixed: Spurious error when pressing CTRL+C in `bun init`](bun-v1.1.1.html#fixed-spurious-error-when-pressing-ctrl-c-in-bun-init)
An error that would occur when pressing CTRL+C in `bun init` has been fixed.
## []()[Fixed: `npm install -g bun` should work now on Windows](bun-v1.1.1.html#fixed-npm-install-g-bun-should-work-now-on-windows)
Sorry. Please let us know if you're still having issues with `npm install -g bun` on Windows.
### []()[Runtime improvements](bun-v1.1.1.html#runtime-improvements)
## []()[Truncated source code previews in error traces](bun-v1.1.1.html#truncated-source-code-previews-in-error-traces)
When a top-level exception is thrown, Bun prints relevant source code to help you debug the error faster.
Normally, it looks like this:
```
1 | function oops() {
2 | throw new Error("Woopsie woops!");
^
error: Woopsie woops!
at oops (woopsie.js:2:9)
at woopsie.js:5:1
```
However, what happens if the error is in a minified file? It would look something like this:
```
1 | function oops() {
2 | var h=1,t=2,m=3,x=4,m={o:{n:{t:{a:[{n: a}, {b: "uffalos"},() => {throw new Error("Woopsie woops!")}]}}}},j=q.u.e.r.y[0];such();minified();
error: Woopsie woops!
at oops (woopsie.js:2:9)
at woopsie.js:5:1
```
Some libraries publish minified source code. Most minifiers try to pack as much code as possible on a single line to reduce the byte count over the wire. Trying to print that to your terminal is...messy.
Previously, Bun would just dump the nearest 4 line(s) to your terminal. Now, we truncate the source code up to 1024 bytes per line. If the code is longer than 512 bytes, we also hide the divot `^` character since that ends up being quite a lot of whitespace. This makes it easier to read the error message.
## []()[JavaScriptCore upgrade](bun-v1.1.1.html#javascriptcore-upgrade)
We've upgraded JavaScriptCore to the latest version, and there are a handful of performance and memory improvements in it.
- Inline caching of function calls has been redesigned, reducing memory usage thanks to [@Constellation](https://github.com/Constellation) - [#65c8acc46999](https://github.com/WebKit/WebKit/commit/65c8acc4699947d9a9b6326b9672a2fca5804a8c) [#d0345d69220e](https://github.com/WebKit/WebKit/commit/d0345d69220e43945f9b9632378eab88cb50e1da)
- Error location tracking has been redesigned to reduce memory usage, thanks to [@MenloDorian](https://github.com/MenloDorian): [#22880](https://github.com/WebKit/WebKit/pull/22880)
- Case-insensitive `RegExp` with backreferences including non-ascii characters are now JIT compiled, thanks to [@msaboff](https://github.com/msaboff): [#26391](https://github.com/WebKit/WebKit/pull/26391)
- String.prototype.includes, String.prototype.replace adapts how it searches based on the input, thanks to [@Constellation](https://github.com/Constellation): [#bacdbdaaf182](https://github.com/WebKit/WebKit/commit/bacdbdaaf1824b08dc7ad35035d5d8358be623c5)
- Multiplying strings by numbers gets 18% faster, thanks to [@Constellation](https://github.com/Constellation) - [#57a7762336ee](https://github.com/WebKit/WebKit/commit/57a7762336eea989764e026e58f1e3a5e845f652)
- RegExp /u flags now respects atomicity of surrogate pairs, thanks to [@msaboff](https://github.com/msaboff) - [#584a9a820ab2](https://github.com/WebKit/WebKit/commit/584a9a820ab2d2408314858daaccc8a9f01f6c56)
- `Float32Array` access gets 9% faster, thanks to [@Constellation](https://github.com/Constellation) - [#eebb374f2bcd](https://github.com/WebKit/WebKit/commit/eebb374f2bcd1ebf9c6b5740f839dcaa3e2af3a4)
- Checking if two strings are equal gets 1% faster when one string is ascii and the other has non-ascii, thanks to [@Constellation](https://github.com/Constellation): [#bacdbdaaf1](https://github.com/oven-sh/WebKit/commit/bacdbdaaf1824b08dc7ad35035d5d8358be623c5)
Bugfixes:
- A bug with the source location of member expressions with multiple `new` keywords has been fixed, thanks to [@alexey](https://github.com/alexey) - [#27567fb2a9f3](https://github.com/WebKit/WebKit/commit/27567fb2a9f316d9bc6a1b75d2b94b02731756c6)
## []()[Fixed: TOML parsing bug with escape sequences and Windows filesystem paths](bun-v1.1.1.html#fixed-toml-parsing-bug-with-escape-sequences-and-windows-filesystem-paths)
A bug where Bun's TOML parser did not properly handle escape sequences and Windows filesystem paths has been fixed and we've added more tests to prevent this from happening again.
## []()[Fixed: Crash when `node:vm` throws an exception across global objects](bun-v1.1.1.html#fixed-crash-when-node-vm-throws-an-exception-across-global-objects)
A crash that could occur when code run in a `node:vm` context threw an exception to be handled by the main global object has been fixed.
This crash was cuased by assuming the global object was the same one as the main global object.
## []()[Fixed: `process.dlopen` now supports `file:` URLs](bun-v1.1.1.html#fixed-process-dlopen-now-supports-file-urls)
`process.dlopen` in Bun now supports loading shared libraries from `file:` URLs. `file:` URLs passed to `process.dlopen` are automatically translated to a filesystem path.
## []()[Fixed: ResolveMessage.message and BuildMessage.message are now writable](bun-v1.1.1.html#fixed-resolvemessage-message-and-buildmessage-message-are-now-writable)
When trying to use ESLint in Bun, sometimes it would throw an error saying "Attempt to write to read-only property 'message'". This was caused by the `message` property being read-only in the `ResolveMessage` and `BuildMessage` classes in Bun. This isn't a great fix, `BuildMessage` and `ResolveMessage` should really extend `Error` instead of being their own classes - but it's a fix nonetheless.
### []()[Bun Shell improvements](bun-v1.1.1.html#bun-shell-improvements)
Bun Shell powers package.json scripts in `bun run` and lifecycle scripts in `bun install` on Windows.
## []()[Subshells](bun-v1.1.1.html#subshells)
Bun Shell now supports subshells.
```
import { $ } from "bun";
await $`echo hey $(echo hi)`;
// > hey hi
```
Subshells are frequently used to compose multiple commands into a single command.
On Windows, this also means `bun run` package.json scripts now support subshells.
Thanks to [@zackradisic](https://github.com/zackradisic) for implementing this.
## []()[Positional arguments with $0 $1 $2 through $9](bun-v1.1.1.html#positional-arguments-with-0-1-2-through-9)
Bun Shell now supports positional arguments with `$0` `$1` `$2` through `$9`.
Running the following script:
```
import { $ } from "bun";
await $`echo $0 $1 $2 $3 $4 $5 $6 $7 $8 $9`;
```
From Bun Shell will print:
```
bun ./script.ts hello world foo bar baz
```
```
bun ./script.ts hello world foo bar baz
```
Previously, this would have printed:
```
bun ./script.ts hello world foo bar baz
```
```
$0 $1 $2 $3 $4 $5 $6 $7 $8 $9
```
Thanks to [@nektro](https://github.com/nektro) for implementing this.
## []()[Thank you to 8 contributors!](bun-v1.1.1.html#thank-you-to-8-contributors)
- [@cirospaciari](https://github.com/cirospaciari)
- [@dylan-conway](https://github.com/dylan-conway)
- [@gvilums](https://github.com/gvilums)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@mangs](https://github.com/mangs)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@zackradisic](https://github.com/zackradisic)
* * *
#### [Bun v1.1.2](bun-v1.1.2.html)
On this page
- [Fixed: `bun install` failed to install sharp on Windows](bun-v1.1.1.html#fixed-bun-install-failed-to-install-sharp-on-windows)
- [Fixed: bun install hanging on Windows](bun-v1.1.1.html#fixed-bun-install-hanging-on-windows)
- [Fixed: spurious "Install failed" errors in `bun install` on Windows](bun-v1.1.1.html#fixed-spurious-install-failed-errors-in-bun-install-on-windows)
- [Fixed: Workspace linking bug on Windows](bun-v1.1.1.html#fixed-workspace-linking-bug-on-windows)
- [Fixed: "unable to find executable" in bunx](bun-v1.1.1.html#fixed-unable-to-find-executable-in-bunx)
- [Fixed: "Failed to install" error with Git dependencies](bun-v1.1.1.html#fixed-failed-to-install-error-with-git-dependencies)
- [Fixed: Spurious error when pressing CTRL+C in `bun init`](bun-v1.1.1.html#fixed-spurious-error-when-pressing-ctrl-c-in-bun-init)
- [Fixed: `npm install -g bun` should work now on Windows](bun-v1.1.1.html#fixed-npm-install-g-bun-should-work-now-on-windows)
- [Runtime improvements](bun-v1.1.1.html#runtime-improvements)
- [Truncated source code previews in error traces](bun-v1.1.1.html#truncated-source-code-previews-in-error-traces)
- [JavaScriptCore upgrade](bun-v1.1.1.html#javascriptcore-upgrade)
- [Fixed: TOML parsing bug with escape sequences and Windows filesystem paths](bun-v1.1.1.html#fixed-toml-parsing-bug-with-escape-sequences-and-windows-filesystem-paths)
- [Fixed: Crash when `node:vm` throws an exception across global objects](bun-v1.1.1.html#fixed-crash-when-node-vm-throws-an-exception-across-global-objects)
- [Fixed: `process.dlopen` now supports `file:` URLs](bun-v1.1.1.html#fixed-process-dlopen-now-supports-file-urls)
- [Fixed: ResolveMessage.message and BuildMessage.message are now writable](bun-v1.1.1.html#fixed-resolvemessage-message-and-buildmessage-message-are-now-writable)
- [Bun Shell improvements](bun-v1.1.1.html#bun-shell-improvements)
- [Subshells](bun-v1.1.1.html#subshells)
- [Positional arguments with $0 $1 $2 through $9](bun-v1.1.1.html#positional-arguments-with-0-1-2-through-9)
- [Thank you to 8 contributors!](bun-v1.1.1.html#thank-you-to-8-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.10.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/blog/bun-v1.1.11.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/blog/bun-v1.1.13.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/blog/bun-v1.1.14.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.14
* * *
[Chloe Caruso](https://github.com/paperclover) · June 19, 2024
[](../rss.xml)
Bun v1.1.14 is here! This release fixes 63 bugs (addressing 519 👍). Patch node\_modules with `bun patch`. ORM-less object mapping in `bun:sqlite`. Log all `fetch()` calls as a `curl` command. Node.js compatibility improvements. bun install bugfixes, `bun:sqlite` bugfixes, Windows bugfixes. And more.
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
#### Previous releases
- [`v1.1.13`](bun-v1.1.13.html) fixes 97 bugs (addressing 211 👍). Reliability improvements to bun install, WebSocket server, fetch, worker\_threads. worker\_threads now supports eval. `URL.createObjectURL`, stack trace error location improvements, several `bun install` fixes
- [`v1.1.10`](bun-v1.1.10.html) fixes 20 bugs. 2x faster uncached bun install on Windows. `fetch()` uses up to 2.8x less memory. Several bugfixes to bun install, sourcemaps, Windows reliability improvements and Node.js compatibility improvements
- [`v1.1.0`](bun-v1.1.html) Bundows. Windows support is here!
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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 patch`](bun-v1.1.14.html#bun-patch)
Bun v1.1.14 introduces a new subcommand for Bun's package manager: `bun patch`
```
bun patch <pkg>
```
Sometimes, dependencies have bugs or missing features. You could fork the package, make your changes, and publish it. But that's a lot of work for a small change. And what if you don't want to maintain a fork? What if you want to continue to receive updates from the original package, but with your changes?
`bun patch` makes it easy to modify dependencies without forking or vendoring. Changes persist into a `.patch` file which can be reviewed, shared, versioned, and reused in other projects. These `.patch` files are automatically applied on `bun install`, with the results cached in Bun's [Global Cache](../docs/install/cache.html).
To get started, run `bun patch <pkg>` to patch a package.
```
bun patch is-even
```
```
bun patch v1.1.14
+ is-even@1.0.0
5 packages installed [3.00ms]
To patch is-even, edit the following folder:
node_modules/is-even
Once you're done with your changes, run:
bun patch --commit 'node_modules/is-even'
```
Internally, this clones the package in node\_modules with a fresh copy of itself independent from the shared cache. This allows you to safely make edits to files in the package's directory without impacting the Global Cache.
Since we clone the package, you can test your patches locally in your project's node\_modules folder. This makes it easy to iterate on your changes and verify they work as expected.
Once you're happy with your changes, run `bun patch --commit <pkg>` to save your changes.
```
bun patch --commit is-even
```
When you run `bun patch --commit is-even`, Bun:
1. Generates a patch file with your changes
2. Adds the dependency to `"patchedDependencies"` in your `package.json`
3. Saves the patch file in the root of your project under `patches/`
Patch files use the standard `diff` format, so you can review, share, and version them like any other code.
./patches/is-even@1.0.0.patch
```
diff --git a/index.js b/index.js
index 832d92223a9ec491364ee10dcbe3ad495446ab80..2a61f0dd2f476a4a30631c570e6c8d2d148d419a 100644
--- a/index.js
+++ b/index.js
@@ -1,14 +1 @@
-/*!
- * is-even <https://github.com/jonschlinkert/is-even>
- *
- * Copyright (c) 2015, 2017, Jon Schlinkert.
- * Released under the MIT License.
- */
-
-'use strict';
-
-var isOdd = require('is-odd');
-
-module.exports = function isEven(i) {
- return !isOdd(i);
-};
+module.exports = (i) => (i % 2 === 0)
```
Thanks to [@zackradisic](https://github.com/zackradisic) for implementing `bun patch`!
## []()[Better `bun:sqlite`](bun-v1.1.14.html#better-bun-sqlite)
This release adds several improvements to Bun's builtin sqlite module `bun:sqlite`.
### []()[ORM-less object mapping with `query.as(Class)`](bun-v1.1.14.html#orm-less-object-mapping-with-query-as-class)
`bun:sqlite` now supports mapping query results to instances of a class. This lets you attach methods, getters, and setters to query results without using an ORM.
```
import { Database } from "bun:sqlite";
const db = new Database("my.db");
class Tweet {
id: number;
text: string;
username: string;
get isMe() {
return this.username === "jarredsumner";
}
}
const tweets = db
.query("SELECT * FROM tweets")
.as(Tweet);
for (const tweet of tweets.all()) {
if (!tweet.isMe) {
console.log(`${tweet.username}: ${tweet.text}`);
}
}
```
The properties don't need to be defined on the class ahead of time (it's there just to make the example easier to read) and the order of the columns in the query doesn't matter.
This is a light way to map query results to objects. Underneath, it works similarly to `Object.create`, which meanas it doesn't call constructors, run default initializers, and cannot access private fields.
The `as` method is defined on the `Statement` class, so you can use it with `get` and `all` methods. It's important to note that this is not an ORM. It doesn' manage relationships, generate SQL, or anything like that. It makes queries return a class instance instead of a plain object.
#### How it works
When you call `query.as(Class)`, Bun creates a new object with the class's prototype and assigns the query result to it.
```
const query = db.query("SELECT * FROM tweets").as(Tweet);
// Get the first row as a Tweet instance
const tweet: Tweet = query.get();
// Each row is a Tweet instance
const allTweets: Tweet[] = query.all();
```
### []()[Simpler query bindings with `strict: true`](bun-v1.1.14.html#simpler-query-bindings-with-strict-true)
This release adds a new `strict?: boolean` option to the `Database` constructor which lets you omit the `$`, `@`, or `:` prefix when binding values to prepared statements.
```
import { Database } from "bun:sqlite";
const db = new Database(":memory:", {
strict: false,
strict: true,
});
const query = db.query(`select $message;`);
query.all({
$message: "Hello world"
message: "Hello world"
});
```
When `strict: true`, queries will throw if they are missing any bindings.
To keep backwards compatibility, `strict` defaults to false. It is recommended to enable for new projects.
### []()[Track changes with `query.run(sql)`](bun-v1.1.14.html#track-changes-with-query-run-sql)
The `run` method on `Database` and `Statement` now returns an object with `changes` and `lastInsertRowid` properties. This makes it easier to track changes and get the last inserted row id.
```
import { Database } from "bun:sqlite";
const db = new Database(":memory:");
db.run(`CREATE TABLE hey ( id INTEGER, data TEXT)`);
const { changes, lastInsertRowid } = db.run(
`insert into hey (id, data) values (1, 'foo')`,
);
console.log({
changes, // => 1
lastInsertRowid, // => 1
});
```
This is important when verifying that a query has made changes to the database. Previously, `run` would return `undefined`.
### []()[BigInts with `safeIntegers: true`](bun-v1.1.14.html#bigints-with-safeintegers-true)
When `safeIntegers` is `true`, `bun:sqlite` will return integers as `bigint` types.
```
import { Database } from "bun:sqlite";
const db = new Database(":memory:", { safeIntegers: true });
const query = db.query(
`SELECT ${BigInt(Number.MAX_SAFE_INTEGER) + 102n} as max_int`,
);
const result = query.get();
console.log(result.max_int); // => 9007199254741093n
```
These integers must fit within 64-bit range. If an input exceeds that, `bun:sqlite` will throw an error.
```
import { Database } from "bun:sqlite";
const db = new Database(":memory:", { safeIntegers: true, strict: true });
db.run("CREATE TABLE test (id INTEGER PRIMARY KEY, value INTEGER)");
const query = db.query("INSERT INTO test (value) VALUES ($value)");
try {
query.run({ value: BigInt(Number.MAX_SAFE_INTEGER) ** 2n });
} catch (e) {
console.log(e.message); // => BigInt value '81129638414606663681390495662081' is out of range
}
```
Sometimes, you only wnat this behavior for specific queries. The `safeIntegers` method is available on `Statement`.
```
import { Database } from "bun:sqlite";
const db = new Database(":memory:", { strict: true });
const query = db.query("SELECT $value as value").safeIntegers(true);
const result = query.get({ value: BigInt(Number.MAX_SAFE_INTEGER) + 102n });
console.log(result.value); // => 9007199254741093n
```
### []()[Fixed: query.values() with duplicate column names](bun-v1.1.14.html#fixed-query-values-with-duplicate-column-names)
A bug caused duplicate column names to be ignored when calling `query.values()`. This has been fixed.
```
import { Database } from "bun:sqlite";
const db = new Database();
const result = db.prepare("select 1 as id, 2 as id").values();
console.log(result);
```
Fixed:
```
[
[ 1, 2 ]
]
```
Previously:
```
[
[ 2 ]
]
```
This bug would most frequently occur when using JOIN.
### []()[Fixed: `bun:sqlite` with table joins crash fixed.](bun-v1.1.14.html#fixed-bun-sqlite-with-table-joins-crash-fixed)
A crash that sometimes occurred when joining tables with duplicate columns has been fixed. This impacts using Drizzle's driver for `bun:sqlite` and `.leftJoin`.
## []()[bun install reliability](bun-v1.1.14.html#bun-install-reliability)
### []()[Fixed: Tarballs failing to download exit with non-zero code](bun-v1.1.14.html#fixed-tarballs-failing-to-download-exit-with-non-zero-code)
When a tarball failed to download, `bun install` would exited with a zero exit code. This has been fixed. When any HTTP request fails, `bun install` will now exit with a non-zero exit code so that CI systems stop the build.
### []()[Fixed: `bun install` handling transitive folder dependencies](bun-v1.1.14.html#fixed-bun-install-handling-transitive-folder-dependencies)
Sometimes packages are published to the npm registry with a `file:` dependency. Sometimes
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this.
### []()[Fixed: `bun install` extracting bug fix](bun-v1.1.14.html#fixed-bun-install-extracting-bug-fix)
It is possible for a `.tar.gz` archive to contain multiple entries for the same directory (one with `./` and one without it). Bun now handles this while extracting, instead of reporting an error that the directory it's extracting to already exists.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this.
### []()[Fixed: `bun install --production` in a workspace included devDependencies](bun-v1.1.14.html#fixed-bun-install-production-in-a-workspace-included-devdependencies)
When `--production` is passed to `bun install` in a workspace, the dev dependencies of the workspace packages would be included in the install. This is no longer the case.
This also fixed an assertion failure when in this situation.
### []()[Fixed: Not passing `npm_config_user_agent` on Windows](bun-v1.1.14.html#fixed-not-passing-npm-config-user-agent-on-windows)
In order for project initialization scripts like `create-next-app` to know which package manager to use, package managers are expected to set the `npm_config_user_agent` environment variable. Bun on Windows was not always passing modified environment variables to child processes, so that has been fixed.
For example, creating a new Next.js project on Windows will properly tell Next.js to use `bun install`.
```
PS> bun create next-app
✔ What is your project named? … my-app
✔ Would you like to use TypeScript? … No / Yes
✔ Would you like to use ESLint? … No / Yes
✔ Would you like to use Tailwind CSS? … No / Yes
✔ Would you like to use `src/` directory? … No / Yes
✔ Would you like to use App Router? (recommended) … No / Yes
✔ Would you like to customize the default import alias (@/*)? … No / Yes
Creating a new Next.js app in D:\Projects\my-app.
-Using npm.
+Using bun.
Initializing project with template: app-tw
```
Thanks to [@SunsetTechuila](https://github.com/SunsetTechuila) for fixing this.
## []()[Debugging fetch()](bun-v1.1.14.html#debugging-fetch)
This release adds a new environment variable to help debug network traffic when using `fetch()` or `node:http`.
When `BUN_CONFIG_VERBOSE_FETCH=1` is passed as an environment variable, Bun will log all network traffic through `fetch` and `node:http` clients.
[](https://github.com/oven-sh/bun/assets/709451/95d9ebb8-4e25-418e-b68a-a21590e55f02)
### []()[Print fetch() as a `curl` command](bun-v1.1.14.html#print-fetch-as-a-curl-command)
When `BUN_CONFIG_VERBOSE_FETCH=curl` is set as an environment variable, Bun will print all network traffic through `fetch` and `node:http` clients as `curl` commands.
```
process.env.BUN_CONFIG_VERBOSE_FETCH = "curl";
await fetch("https://example.com", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ foo: "bar" }),
});
```
This prints the `fetch` request as a `curl` command to let you copy-paste into your terminal to replicate the request.
```
[fetch] $ curl --http1.1 "https://example.com/" -X POST -H "content-type: application/json" -H "Connection: keep-alive" -H "User-Agent: Bun/1.1.14" -H "Accept: */*" -H "Host: example.com" -H "Accept-Encoding: gzip, deflate, br" --compressed -H "Content-Length: 13" --data-raw "{\"foo\":\"bar\"}"
[fetch] > HTTP/1.1 POST https://example.com/
[fetch] > content-type: application/json
[fetch] > Connection: keep-alive
[fetch] > User-Agent: Bun/1.1.14
[fetch] > Accept: */*
[fetch] > Host: example.com
[fetch] > Accept-Encoding: gzip, deflate, br
[fetch] > Content-Length: 13
[fetch] < 200 OK
[fetch] < Accept-Ranges: bytes
[fetch] < Cache-Control: max-age=604800
[fetch] < Content-Type: text/html; charset=UTF-8
[fetch] < Date: Tue, 18 Jun 2024 05:12:07 GMT
[fetch] < Etag: "3147526947"
[fetch] < Expires: Tue, 25 Jun 2024 05:12:07 GMT
[fetch] < Last-Modified: Thu, 17 Oct 2019 07:18:26 GMT
[fetch] < Server: EOS (vny/044F)
[fetch] < Content-Length: 1256
```
You can use this to debug network requests, to replicate network requests, or to inspect what different JavaScript/TypeScript tools are sending over the network without needing to wire up a proxy.
## []()[Node.js compatibility improvements](bun-v1.1.14.html#node-js-compatibility-improvements)
### []()[`node:fs/promises` functions now accept `FileHandle`](bun-v1.1.14.html#node-fs-promises-functions-now-accept-filehandle)
When using `node:fs/promises`, the `readFile`, `writeFile`, and `appendFile` functions accept [`FileHandle`](https://nodejs.org/docs/latest-v22.x/api/fs.html#class-filehandle) objects as input.
```
import { open, readFile } from 'node:fs/promises';
using file = await open("example.txt", "rw");
const contents = await readFile(file);
console.log(contents);
await writeFile(file, `New data: ${Math.random()}\n`);
```
Thanks to [@nektro](https://github.com/nektro) for implementing this.
### []()[`process.env.NODE_TLS_REJECT_UNAUTHORIZED`](bun-v1.1.14.html#process-env-node-tls-reject-unauthorized)
You can now set `process.env.NODE_TLS_REJECT_UNAUTHORIZED` at runtime to disable or enable SSL certificate verification. This is useful for testing or debugging, but should not be enabled in production.
```
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
await fetch("https://self-signed.badssl.com"); // no error
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "1";
await fetch("https://self-signed.badssl.com"); // throws error
```
Previously, this environment variable could only be passed at startup. Now, it can be set at runtime.
### []()[Fixed: Hang in `node:http` / `express`](bun-v1.1.14.html#fixed-hang-in-node-http-express)
A bug impacting node:http server where `req.completed` was never set to true would cause some requests in Express to hang indefinitely. This has been fixed thanks to [@cirospaciari](https://github.com/cirospaciari)
### []()[Fixed: `blob.type`](bun-v1.1.14.html#fixed-blob-type)
A race condition would sometimes make `blob.type` from `fetch` `undefined`. Thanks to [@cirospaciari](https://github.com/cirospaciari), this has now been resolved.
```
const blob = await fetch("https://bun.sh/logo.svg").then((res) => res.blob());
console.log("Blob type is:", blob.type);
```
### []()[Fixed: `blob.name` is writable](bun-v1.1.14.html#fixed-blob-name-is-writable)
You can now set the `name` property on a `Blob` object.
```
const blob = await fetch("https://bun.sh/logo.svg").then((res) => res.blob());
blob.name = "bun!!!!!";
console.log(blob.name); // "bun!!!!!"
```
Previously, setting `blob.name` would throw a TypeError:
```
1 | const blob = await fetch("https://bun.sh/logo.svg").then((res) => res.blob());
2 | blob.name = "bun!!!!!";
^
TypeError: Attempted to assign to readonly property.
```
### []()[Fixed: WebSocket over SSL with large binary payloads](bun-v1.1.14.html#fixed-websocket-over-ssl-with-large-binary-payloads)
Previously, when sending large binary payloads over `wss://` WebSocket connections, the message might not have been sent. This was due to not calling `set_retry_write` from BoringSSL. Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this.
### []()[Fixed: Bun no longer crashes Windows Terminal](bun-v1.1.14.html#fixed-bun-no-longer-crashes-windows-terminal)
On Windows, the flag `ENABLE_VIRTUAL_TERMINAL_INPUT` was always enabled on the console input. Without removing this flag before exit, most shells would break (`cmd.exe` arrow keys break, Powershell would often crash, `nu` would not be able to accept new lines, etc). This flag was removed, as Bun no longer needed it set for it's input handling (`prompt()`, `node:readline`, `bun init`, etc)
Thanks to [@paperclover](https://github.com/paperclover) for fixing this.
### []()[Fixed: WebSocket header casing inconsistent with node](bun-v1.1.14.html#fixed-websocket-header-casing-inconsistent-with-node)
Previously, using `new WebSocket` would convert all headers into lowercased text. This had some issues with some servers that expected headers to have certain casing, even though headers are meant to be case insensitive. Now, well-known headers will be normalized to their canonical form, and custom headers will retain their exact casing.
For example:
```
const ws = new WebSocket("ws://localhost:3000", {
headers: {
"Origin": "http://localhost:3000",
"authorization": "password",
"X-some-Other-header": "bun!",
},
});
```
Will send these headers:
```
> Origin: http://localhost:3000
> Authorization: password
> X-some-Other-header: bun!
```
Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this.
### []()[Fixed: memory leak in Bun Shell](bun-v1.1.14.html#fixed-memory-leak-in-bun-shell)
A memory leak impacting the Bun Shell has been fixed. This would cause the shell objects to never be garbage collected, preventing memory from being reclaimed.
### []()[Fixed: Regression with error.line](bun-v1.1.14.html#fixed-regression-with-error-line)
A bug where `error.line` and `error.column` would return `0` has been fixed. This regression was introduced in `v1.1.13`.
### []()[Thanks to 10 contributors!](bun-v1.1.14.html#thanks-to-10-contributors)
- [@cirospaciari](https://github.com/cirospaciari)
- [@diogomdp](https://github.com/diogomdp)
- [@dylan-conway](https://github.com/dylan-conway)
- [@huseeiin](https://github.com/huseeiin)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@nektro](https://github.com/nektro)
- [@oscarfsbs](https://github.com/oscarfsbs)
- [@paperclover](https://github.com/paperclover)
- [@ShrootBuck](https://github.com/ShrootBuck)
- [@SunsetTechuila](https://github.com/SunsetTechuila)
- [@zackradisic](https://github.com/zackradisic)
* * *
#### [Bun v1.1.13](bun-v1.1.13.html)
#### [Bun v1.1.16](bun-v1.1.16.html)
On this page
- [`bun patch`](bun-v1.1.14.html#bun-patch)
- [Better `bun:sqlite`](bun-v1.1.14.html#better-bun-sqlite)
- [ORM-less object mapping with `query.as(Class)`](bun-v1.1.14.html#orm-less-object-mapping-with-query-as-class)
- [Simpler query bindings with `strict: true`](bun-v1.1.14.html#simpler-query-bindings-with-strict-true)
- [Track changes with `query.run(sql)`](bun-v1.1.14.html#track-changes-with-query-run-sql)
- [BigInts with `safeIntegers: true`](bun-v1.1.14.html#bigints-with-safeintegers-true)
- [Fixed: query.values() with duplicate column names](bun-v1.1.14.html#fixed-query-values-with-duplicate-column-names)
- [Fixed: `bun:sqlite` with table joins crash fixed.](bun-v1.1.14.html#fixed-bun-sqlite-with-table-joins-crash-fixed)
- [bun install reliability](bun-v1.1.14.html#bun-install-reliability)
- [Fixed: Tarballs failing to download exit with non-zero code](bun-v1.1.14.html#fixed-tarballs-failing-to-download-exit-with-non-zero-code)
- [Fixed: `bun install` handling transitive folder dependencies](bun-v1.1.14.html#fixed-bun-install-handling-transitive-folder-dependencies)
- [Fixed: `bun install` extracting bug fix](bun-v1.1.14.html#fixed-bun-install-extracting-bug-fix)
- [Fixed: `bun install --production` in a workspace included devDependencies](bun-v1.1.14.html#fixed-bun-install-production-in-a-workspace-included-devdependencies)
- [Fixed: Not passing `npm_config_user_agent` on Windows](bun-v1.1.14.html#fixed-not-passing-npm-config-user-agent-on-windows)
- [Debugging fetch()](bun-v1.1.14.html#debugging-fetch)
- [Print fetch() as a `curl` command](bun-v1.1.14.html#print-fetch-as-a-curl-command)
- [Node.js compatibility improvements](bun-v1.1.14.html#node-js-compatibility-improvements)
- [`node:fs/promises` functions now accept `FileHandle`](bun-v1.1.14.html#node-fs-promises-functions-now-accept-filehandle)
- [`process.env.NODE_TLS_REJECT_UNAUTHORIZED`](bun-v1.1.14.html#process-env-node-tls-reject-unauthorized)
- [Fixed: Hang in `node:http` / `express`](bun-v1.1.14.html#fixed-hang-in-node-http-express)
- [Fixed: `blob.type`](bun-v1.1.14.html#fixed-blob-type)
- [Fixed: `blob.name` is writable](bun-v1.1.14.html#fixed-blob-name-is-writable)
- [Fixed: WebSocket over SSL with large binary payloads](bun-v1.1.14.html#fixed-websocket-over-ssl-with-large-binary-payloads)
- [Fixed: Bun no longer crashes Windows Terminal](bun-v1.1.14.html#fixed-bun-no-longer-crashes-windows-terminal)
- [Fixed: WebSocket header casing inconsistent with node](bun-v1.1.14.html#fixed-websocket-header-casing-inconsistent-with-node)
- [Fixed: memory leak in Bun Shell](bun-v1.1.14.html#fixed-memory-leak-in-bun-shell)
- [Fixed: Regression with error.line](bun-v1.1.14.html#fixed-regression-with-error-line)
- [Thanks to 10 contributors!](bun-v1.1.14.html#thanks-to-10-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.16.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/blog/bun-v1.1.17.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/blog/bun-v1.1.18.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/blog/bun-v1.1.19.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.19
* * *
[Dylan Conway](https://github.com/dylan-conway) · July 12, 2024
[](../rss.xml)
Bun v1.1.19 is here! This release fixes 54 bugs (addressing 248 👍). JavaScript gets faster on Windows. Raspberry Pi 4 support returns. `_auth` support in `.npmrc`. `bun install` preserves package.json indentation. `aws-cdk-lib` support. Memory leak fixes in `new Response(request)` and `fs.readdir`. Several reliability improvements. Statically linked UCRT on Windows.
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
#### Previous releases
- [`v1.1.18`](bun-v1.1.18.html) Fixes 55 bugs (addressing 493 👍). Support for npmrc. Improved constant folding & enum inlining. Improved console.log output for functions. Fixes patching dependencies in workspaces. Fixes several bugs in `bun install` when linking binaries. Fixes a crash in `dns.lookup`, and normalizes DNS errors to better match Node. Fixes an assertion failure in `Bun.escapeHTML`. Upgrades JavaScriptCore.
- [`v1.1.17`](bun-v1.1.17.html) Fixes 4 bugs. Fixes a crash in bun repl. Makes fs.readdirSync 5% faster on macOS in small directories. Fixes "ws" module not calling the callback in "send" method. Fixes a crash when reading a corrupted lockfile in bun install. Makes macOS event loop a smidge faster.
- [`v1.1.0`](bun-v1.1.html) Bundows. Windows support is here!
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[JavaScript gets faster on Windows](bun-v1.1.19.html#javascript-gets-faster-on-windows)
This release enables WebKit's [FTL JIT (Faster Than Light Just In Time Compiler)](https://www.webkit.org/blog/5852/introducing-the-b3-jit-compiler/) on Windows, which improves hot path performance. Previously, this JIT was only available on macOS and Linux.
> 9 years ago, JavaScriptCore's FTL JIT was disabled on Windows
>
> Today, [@iangrunert](https://twitter.com/iangrunert?ref_src=twsrc%5Etfw) brought it back[https://t.co/xY5078Zlk6](https://t.co/xY5078Zlk6)
>
> — Jarred Sumner (@jarredsumner) [July 9, 2024](https://twitter.com/jarredsumner/status/1810497635624890391?ref_src=twsrc%5Etfw)
`Object.entries` gets about 20% faster:
Runtimebenchmarktime (avg)Bun v1.1.19Object.entries(26 keys)726 ns/iterBun v1.1.18Object.entries(26 keys)1'006 ns/iterNode v22.4.1Object.entries(26 keys)1'014 ns/iterBun v1.1.19Object.entries(2 keys)55.99 ns/iterBun v1.1.18Object.entries(2 keys)114 ns/iterNode v22.4.1Object.entries(2 keys)115 ns/iterNode v22.4.1Object.keys(26 keys)206 ns/iterBun v1.1.19Object.keys(26 keys)509 ns/iterBun v1.1.18Object.keys(26 keys)671 ns/iter
`Array.map` overhead drops by about 50%:
Runtimebenchmarktime (avg)Bun v1.1.19Array.map x 1 args31.23 ns/iterBun v1.1.18Array.map x 1 args58.32 ns/iterNode v22.4.1Array.map x 1 args84.27 ns/iterBun v1.1.19Array.map x 2 args30.42 ns/iterBun v1.1.18Array.map x 2 args56.96 ns/iterNode v22.4.1Array.map x 2 args84.87 ns/iter
And so much more. JavaScriptCore's FTL JIT is 25,000 lines of C++ -- it does a lot.
```
===============================================================================
Language Files Lines Code Comments Blanks
===============================================================================
C Header 46 4436 2407 1264 765
C++ 35 29919 23306 1925 4688
===============================================================================
Total 81 34355 25713 3189 5453
```
Huge thanks to [@iangrunert](https://github.com/iangrunert)!
## []()[Raspberry Pi 4](bun-v1.1.19.html#raspberry-pi-4)
Bun once again supports Raspberry Pi 4. A build issue preventing Bun from running on the Raspberry Pi 4 has been fixed.
[](https://github.com/user-attachments/assets/38763218-bdc0-4474-94d8-c950e8302ca7)
## []()[1 MB smaller on Linux](bun-v1.1.19.html#1-mb-smaller-on-linux)
We've enabled a link-time optimization that makes Bun 1 MB smaller on Linux.
## []()[Statically-linked Windows build](bun-v1.1.19.html#statically-linked-windows-build)
On Windows, Bun will now use a statically linked copy of UCRT. This means you don't need the Visual C++ runtime installed to run Bun.
## []()[bun install improvements](bun-v1.1.19.html#bun-install-improvements)
### []()[`bun install` respects `package.json` indentation](bun-v1.1.19.html#bun-install-respects-package-json-indentation)
Space and tab indentation in `package.json` is now preserved when saving new dependencies with Bun.
> In the next version of Bun
>
> bun install preserves tabs & indentation when saving package.json [pic.twitter.com/9FqcdebuUY](https://t.co/9FqcdebuUY)
>
> — Bun (@bunjavascript) [July 4, 2024](https://twitter.com/bunjavascript/status/1808759441497731276?ref_src=twsrc%5Etfw)
Thanks to [@dylan-conway](https://github.com/dylan-conway)!
### []()[`bun install` supports `_auth` in `.npmrc`](bun-v1.1.19.html#bun-install-supports-auth-in-npmrc)
`bun install` now supports the `_auth` option in `.npmrc` files. This is useful for providing both username and password together.
.npmrc
```
//http://localhost:4873/:_auth=${NPM_AUTH}
```
Thanks to [@zackradisic](https://github.com/zackradisic)!
### []()[Fixed: crash with optional peer dependencies](bun-v1.1.19.html#fixed-crash-with-optional-peer-dependencies)
During an install with optional peer dependencies, sometimes Bun would crash. To reproduce this crash, one would need this `package.json`
package.json
```
{
"dependencies": {
"a": "1.0.0",
"b": "1.0.0",
}
}
```
with these dependencies:
```
{
"name": "a",
"version": "1.0.0"
}
```
```
{
"name": "b",
"version": "1.0.0",
"peerDependencies": {
"a": "1.0.0"
},
"peerDependenciesMeta": {
"a": {
"optional": true
}
}
}
```
The crash would occur after running `bun install`, deleting `node_modules` and cache (`bun pm cache rm`), bumping `b` to a newer version that still has an optional peer dependency on `a`, then running `bun install` again with the existing lockfile.
There are more than a few steps to reproduce this crash, but it was a common issue with packages like `vite` or `vue` due to their use of optional peer dependencies.
This is now fixed, thanks to [@dylan-conway](https://github.com/dylan-conway)!
### []()[Warn when binaries from `bun install -g` are not in path](bun-v1.1.19.html#warn-when-binaries-from-bun-install-g-are-not-in-path)
When the global bin folder isn't in path, Bun will now print a warning and a suggestion to add the folder to path.
```
bun add v1.1.19 (18a0f05c)
installed node-gyp@10.2.0 with binaries:
- node-gyp
warn: To run "node-gyp", add the global bin folder to $PATH:
fish_add_path "/Users/jarred/.bun/bin"
```
### []()[Fixed: cwd for symlinked dependency postinstall scripts on Windows](bun-v1.1.19.html#fixed-cwd-for-symlinked-dependency-postinstall-scripts-on-windows)
Before running a postinstall script, the cwd is set to the package directory in `node_modules`. When the package is a workspace, the directory in `node_modules` is a symlink to the workspace. On posix this is fine - the symlink is resolved and `process.cwd()` prints the absolute path through the project root. On Windows, the symlink is not resolved, resulting in an unexpected cwd of `C:/path/to/proj/node_modules/workspace` instead of `C:/path/to/proj/workspace`.
Now, Bun resolves these paths manually on Windows to ensure the cwd is the expected path.
Thanks to [@dylan-conway](https://github.com/dylan-conway)!
## []()[Transpiler improvements](bun-v1.1.19.html#transpiler-improvements)
### []()[Improved: Comma expression folding](bun-v1.1.19.html#improved-comma-expression-folding)
Bun no longer uses recursion when folding comma separated expressions in JavaScript/TypeScript, reducing the risk of stack overflow. This fixes crashes when using some libraries like `aws-cdk-lib` and `aws-sdk`.
Thanks to [@paperclover](https://github.com/paperclover)!
### []()[Fixed: invalid transpilation of nested TypeScript `namespace` declarations](bun-v1.1.19.html#fixed-invalid-transpilation-of-nested-typescript-namespace-declarations)
A TypeScript transpilation bug has been fixed where nested `namespace`s were incorrectly transpiled, resulting in exports not being available. This could happen if they were non-inlined namespaces.
```
export namespace Foo.Bar {
export function bar() {
return "hello world";
}
}
console.log(Foo.Bar.bar()); // "hello world"
```
This is fixed thanks to [@paperclover](https://github.com/paperclover)!
## []()[Reliability improvements](bun-v1.1.19.html#reliability-improvements)
### []()[Fixed: `afterEach` callback running for `test.todo`](bun-v1.1.19.html#fixed-aftereach-callback-running-for-test-todo)
Previously, `afterEach` was running for each `test.todo`, causing the following code to fail. This is now fixed. `test.todo` will continue to trigger `afterEach` and `beforeEach` if `--todo` is used.
```
import { test, expect, afterEach } from "bun:test";
let count: number = 0;
afterEach(() => {
count++;
});
test.todo("todo");
test("afterEach should not run for test.todo", () => {
expect(count).toBe(0);
});
```
Thanks to [@ThatOneBro](https://github.com/ThatOneBro)!
### []()[Fixed: memory leak in `new Request(request)`](bun-v1.1.19.html#fixed-memory-leak-in-new-request-request)
When passing a `Request` instance to the `Request` constructor, the `Request` constructor would leak memory. This is now fixed.
```
const old = new Request("https://example.com", { body: "hello!" });
// This would leak memory:
const req = new Request(old);
```
This was only a problem when passing a `Request` instance to the `Request` constructor. Passing a `Request` instance to `fetch` was not affected, nor was passing an object shaped like a `Request` instance.
### []()[Fixed: crash when sending large files with `Bun.serve`](bun-v1.1.19.html#fixed-crash-when-sending-large-files-with-bun-serve)
When sending a large file with `Bun.serve` and the process is killed with `process.kill` or the request is aborted, Bun would sometimes crash. This has been fixed, thanks to [@cirospaciari](https://github.com/cirospaciari)!
### []()[Fixed: crash in remapping stack frames with `bun build`](bun-v1.1.19.html#fixed-crash-in-remapping-stack-frames-with-bun-build)
There was a double free on a string when using `bun build --sourcemap=external --target=bun`, causing a segfault.
This is now fixed, thanks to [@paperclover](https://github.com/paperclover)!
### []()[Fixed: `AbortSignal` reliability improvement with `fetch()`](bun-v1.1.19.html#fixed-abortsignal-reliability-improvement-with-fetch)
When cancelling a request with `AbortSignal` in `fetch()`, sometimes it wouldn't cancel for HTTPS requests until after the response had completed. This bug is now fixed. An incorrect option in our BoringSSL integration caused it to ignore TCP shutdown calls.
Thanks to [@cirospaciari](https://github.com/cirospaciari)!
### []()[Improved: `profile` from `bun:jsc` now supports promises](bun-v1.1.19.html#improved-profile-from-bun-jsc-now-supports-promises)
In Bun v1.1.19 you will now be able to pass promises to `profile`.
```
import { profile } from "bun:jsc";
const { promise, resolve } = Promise.withResolvers();
const result = await profile(
async function test(input: string) {
await Bun.sleep(10).then(() => resolve(input));
},
1,
"input",
);
const input = await promise;
console.log(input); // { "0": "input" }
```
### []()[Fixed: `FormData.set` settings file name incorrectly](bun-v1.1.19.html#fixed-formdata-set-settings-file-name-incorrectly)
A bug has been fixed where `FormData` would incorrectly set file names with `.set`. This code will now work as expected, thanks to [@billywhizz](https://github.com/billywhizz)!
```
using server = Bun.serve({
port: 0,
fetch: async req => {
const data = await req.formData();
const file = data.get("file");
console.log(file.name); // foo.txt
return new Response();
}
})
const form = new FormData();
form.set("file", new File(["hello"], "foo.txt"));
await fetch(server.url, { method: "POST", body: form });
```
## []()[Node.js compatibility improvements](bun-v1.1.19.html#node-js-compatibility-improvements)
### []()[fs errors](bun-v1.1.19.html#fs-errors)
This release fixes argument validation issues in `node:fs`.
Previously, the following code would throw a confusing error:
```
import { fs } from "fs";
fs.open("path");
```
Previous error:
bun-1.1.18.ts
```
1 | fs.open("path")
^
TypeError: path must be a string or TypedArray
code: "ERR_INVALID_ARG_TYPE"
at node:fs:36:26
at open2 (node:fs:276:25)
at path-to-file.ts:1:4
```
Now, the error correctly mentions the missing callback:
bun-1.1.19.ts
```
1 | fs.open("path")
^
TypeError: The "cb" argument must be of type function. Received undefined
code: "ERR_INVALID_ARG_TYPE"
at node:fs:2:30
at open (node:fs:288:25)
at path-to-file.ts:1:4
```
### []()[fs.write argument fix](bun-v1.1.19.html#fs-write-argument-fix)
Previously, the following input would incorrectly throw an error:
```
import fs from "fs";
fs.write(1, Buffer.from("hi"), 0, console.log, undefined);
```
Now it works as expected, consistent with Node.js.
Previously, this threw an error about a missing callback:
```
1 | fs.write(1, Buffer.from("hi"), 0, console.log, undefined)
^
TypeError: Callback must be a function
code: "ERR_INVALID_ARG_TYPE"
at node:fs:2:30
at write2 (node:fs:297:27)
```
### []()[Fixed: memory leak in `fs.readdir` `withFileTypes: true`](bun-v1.1.19.html#fixed-memory-leak-in-fs-readdir-withfiletypes-true)
When calling `fs.readdir` with `withFileTypes: true`, the `path` property was leaking memory while directory entries were being read. This is now fixed, thanks to [@billywhizz](https://github.com/billywhizz)!
### []()[Thanks to 25 contributors!](bun-v1.1.19.html#thanks-to-25-contributors)
- [@0livare](https://github.com/0livare)
- [@billywhizz](https://github.com/billywhizz)
- [@bjon](https://github.com/bjon)
- [@cirospaciari](https://github.com/cirospaciari)
- [@dylan-conway](https://github.com/dylan-conway)
- [@farcaller](https://github.com/farcaller)
- [@ghoshArnab](https://github.com/ghoshArnab)
- [@Imgodmaoyouknow](https://github.com/Imgodmaoyouknow)
- [@jakeboone02](https://github.com/jakeboone02)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@kdrag0n](https://github.com/kdrag0n)
- [@lmmfranco](https://github.com/lmmfranco)
- [@otecd](https://github.com/otecd)
- [@paperclover](https://github.com/paperclover)
- [@Ptitet](https://github.com/Ptitet)
- [@rista404](https://github.com/rista404)
- [@ryuujo1573](https://github.com/ryuujo1573)
- [@silverwind](https://github.com/silverwind)
- [@speelbarrow](https://github.com/speelbarrow)
- [@ThatOneBro](https://github.com/ThatOneBro)
- [@trcio](https://github.com/trcio)
- [@vadzim](https://github.com/vadzim)
- [@victor-homyakov](https://github.com/victor-homyakov)
- [@zackradisic](https://github.com/zackradisic)
- [@zpix1](https://github.com/zpix1)
* * *
#### [Bun v1.1.18](bun-v1.1.18.html)
#### [Bun v1.1.21](bun-v1.1.21.html)
On this page
- [JavaScript gets faster on Windows](bun-v1.1.19.html#javascript-gets-faster-on-windows)
- [Raspberry Pi 4](bun-v1.1.19.html#raspberry-pi-4)
- [1 MB smaller on Linux](bun-v1.1.19.html#1-mb-smaller-on-linux)
- [Statically-linked Windows build](bun-v1.1.19.html#statically-linked-windows-build)
- [bun install improvements](bun-v1.1.19.html#bun-install-improvements)
- [`bun install` respects `package.json` indentation](bun-v1.1.19.html#bun-install-respects-package-json-indentation)
- [`bun install` supports `_auth` in `.npmrc`](bun-v1.1.19.html#bun-install-supports-auth-in-npmrc)
- [Fixed: crash with optional peer dependencies](bun-v1.1.19.html#fixed-crash-with-optional-peer-dependencies)
- [Warn when binaries from `bun install -g` are not in path](bun-v1.1.19.html#warn-when-binaries-from-bun-install-g-are-not-in-path)
- [Fixed: cwd for symlinked dependency postinstall scripts on Windows](bun-v1.1.19.html#fixed-cwd-for-symlinked-dependency-postinstall-scripts-on-windows)
- [Transpiler improvements](bun-v1.1.19.html#transpiler-improvements)
- [Improved: Comma expression folding](bun-v1.1.19.html#improved-comma-expression-folding)
- [Fixed: invalid transpilation of nested TypeScript `namespace` declarations](bun-v1.1.19.html#fixed-invalid-transpilation-of-nested-typescript-namespace-declarations)
- [Reliability improvements](bun-v1.1.19.html#reliability-improvements)
- [Fixed: `afterEach` callback running for `test.todo`](bun-v1.1.19.html#fixed-aftereach-callback-running-for-test-todo)
- [Fixed: memory leak in `new Request(request)`](bun-v1.1.19.html#fixed-memory-leak-in-new-request-request)
- [Fixed: crash when sending large files with `Bun.serve`](bun-v1.1.19.html#fixed-crash-when-sending-large-files-with-bun-serve)
- [Fixed: crash in remapping stack frames with `bun build`](bun-v1.1.19.html#fixed-crash-in-remapping-stack-frames-with-bun-build)
- [Fixed: `AbortSignal` reliability improvement with `fetch()`](bun-v1.1.19.html#fixed-abortsignal-reliability-improvement-with-fetch)
- [Improved: `profile` from `bun:jsc` now supports promises](bun-v1.1.19.html#improved-profile-from-bun-jsc-now-supports-promises)
- [Fixed: `FormData.set` settings file name incorrectly](bun-v1.1.19.html#fixed-formdata-set-settings-file-name-incorrectly)
- [Node.js compatibility improvements](bun-v1.1.19.html#node-js-compatibility-improvements)
- [fs errors](bun-v1.1.19.html#fs-errors)
- [fs.write argument fix](bun-v1.1.19.html#fs-write-argument-fix)
- [Fixed: memory leak in `fs.readdir` `withFileTypes: true`](bun-v1.1.19.html#fixed-memory-leak-in-fs-readdir-withfiletypes-true)
- [Thanks to 25 contributors!](bun-v1.1.19.html#thanks-to-25-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.2.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.2
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · April 6, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one.
Bun v1.1.2 fixes 4 bugs (addressing 44 👍 reactions). EBUSY on Windows in vite dev, next dev, and saving bun.lockb has been fixed. Bun Shell gets support for seq, yes, basename and dirname. A TypeScript parsing edgecase has been fixed. A bug causing 'unreachable code' errors has been fixed. fs.watch on Windows has been rewritten to improve performance and reliability.
#### Previous releases
- [`v1.1.1`](bun-v1.1.1.html) Bun v1.1.1 fixes 20 bugs (addressing 60 👍 reactions). Add subshell and positional argument support. Printed source code in errors no longer fill up your terminal. Upgrades JavaScriptCore, which includes performance improvements to RegExp, typed arrays, String indexOf and String replace. Error objects and JIT'd function calls use less memory. Fixes several bugs with bun install on Windows. Fixes a bug with Bun.serve() on Windows. Fixes a TOML parser bug impacting escape sequences and windows paths in .toml files.
- [`v1.1.0`](bun-v1.1.html) Bundows. Windows support is here! Plus, JSON IPC Node <-> Bun.
#### To install Bun:
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
### []()[Windows support improvements](bun-v1.1.2.html#windows-support-improvements)
## []()[Fixed: `EBUSY` when saving bun.lockb](bun-v1.1.2.html#fixed-ebusy-when-saving-bun-lockb)
When adding dependencies to `bun.lockb`, sometimes `bun install` on Windows would throw an `EBUSY` error. This was caused by keeping file handles open for too long and not requesting the correct permissions.
Windows permissions continues to be complicated.
## []()[Fixed: `ENOENT` and `EEXIST` error when extracting tarballs to cache on Windows](bun-v1.1.2.html#fixed-enoent-and-eexist-error-when-extracting-tarballs-to-cache-on-windows)
Sometimes packages failed to install on Windows due to a race condition where extracting the tarball for an npm package would fail with `ENOENT` or `EEXIST` errors. This error was mostly caused by requesting the wrong permissions when opening the directory to the new tarball. We've made the code more error-tolerant and now it will request the correct permissions.
## []()[Fixed: `EBUSY` when using `next dev` or `vite dev` on Windows](bun-v1.1.2.html#fixed-ebusy-when-using-next-dev-or-vite-dev-on-windows)
A regression in v1.1.0 caused `next dev` and `vite dev` to throw an `EBUSY` error when running on Windows. The main cause was a permissions issue. We were keeping a file handle open for the watched directory when we didn't need to.
We've updated our integration tests to catch this bug in the future.
Along the way, we've rewritten how `fs.watch` works on Windows. `fs.watch` will auto-deduplicate fileystem paths so if multiple watchers watch the same path, it will only use the resources of one of them. This should make `fs.watch` faster, more reilable, and use less memory.
## []()[Fixed: `bun install` unable to install tarballs with invalid file paths](bun-v1.1.2.html#fixed-bun-install-unable-to-install-tarballs-with-invalid-file-paths)
Windows doesn't support charaacters like `?`, `<`, `>`, and more in file paths. Sometimes, npm packages have these characters in their file paths of the tarballs they publish. Bun was not handling that correctly. Now, `bun install` behaves the same as `npm install` on Windows and successfully installs the package but inserts a replacement character.
## []()[Fixed: `CouldntReadCurrentDirectory` error](bun-v1.1.2.html#fixed-couldntreadcurrentdirectory-error)
Bun was asking for too many permissions in directories, which could cause `CouldntReadCurrentDirectory` errors to throw for non-Administrator accounts on Windows.
## []()[Rewrote `fs.watch` on Windows](bun-v1.1.2.html#rewrote-fs-watch-on-windows)
We rewrote the implementation of `fs.watch` on Windows to be more reliable and faster.
It now de-duplicates file paths being watched internally, which reduces resource usage when using things like fs.watch in a glob.
### []()[Shell & bun run improvements](bun-v1.1.2.html#shell-bun-run-improvements)
## []()[Support for `seq`, `yes`, `basename`, and `dirname` in Bun Shell](bun-v1.1.2.html#support-for-seq-yes-basename-and-dirname-in-bun-shell)
The GNU Coreutils commands `seq`, `yes`, `basename`, and `dirname` are now supported in Bun Shell, thanks to [@nektro](https://github.com/nektro).
foo/hello.js
```
import { $ } from "bun";
await $`seq 0 3`;
// 0
// 1
// 2
// 3
await $`basename $1`; // hello.js
await $`dirname $1`; // foo
```
## []()[Fixed: Parsing bugs with `*` in environment variables](bun-v1.1.2.html#fixed-parsing-bugs-with-in-environment-variables)
A few parsing bugs have been fixed with `*` in environment variables, thanks to [@zackradisic](https://github.com/zackradisic).
A bug that could cause `bun install` to hang for awhile has been fixed.
### []()[Bun install improvements](bun-v1.1.2.html#bun-install-improvements)
## []()[install `--production` without a lockfile](bun-v1.1.2.html#install-production-without-a-lockfile)
You can now use `bun install --production` and `bun install --frozen-lockfile` without a lockfile. This is helpful for CI environments where you might not have checked in your `bun.lockb` to `git`. There was no real reason why this was banned previously, so we just removed the ban.
## []()[Fixed: Potential crash when downloading tarballs](bun-v1.1.2.html#fixed-potential-crash-when-downloading-tarballs)
A bug that could cause `bun install` to crash when downloading tarballs has been fixed. This sometimes caused an "Unreachable code reached" error in Bun for Windows.
### []()[WebKit upgrade](bun-v1.1.2.html#webkit-upgrade)
We've upgraded WebKit yet again! And the incredible @Constellation & JSC team brings us new performance improvements and bug fixes.
## []()[5x faster `{ ...obj }` clone](bun-v1.1.2.html#5x-faster-obj-clone)
In microbenchmarks, code like the following now runs 5x faster:
```
{ ...obj }
```
This optimization is specific to an empty object literal with a single `...` spread operator on another object.
bench
splat.mjs
bench
```
❯ bun splat.mjs
cpu: Apple M1 Max
runtime: bun 1.1.2 (arm64-darwin)
benchmark time (avg) (min … max) p75 p99 p995
-------------------------------------------------- -----------------------------
{ ...obj } 20.33 ns/iter (18.38 ns … 92.75 ns) 20.08 ns 49.05 ns 53.68 ns
❯ bun-1.1.0 splat.mjs
cpu: Apple M1 Max
runtime: bun 1.1.0 (arm64-darwin)
benchmark time (avg) (min … max) p75 p99 p995
-------------------------------------------------- -----------------------------
{ ...obj } 105.38 ns/iter (100.83 ns … 188.37 ns) 103.29 ns 146.97 ns 149.57 ns
```
splat.mjs
```
import { bench, run } from "mitata";
const obj = {
a: 1,
b: 2,
c: 3,
d: 4,
e: 5,
f: 6,
g: 7,
h: 8,
i: 9,
};
bench("{ ...obj }", () => {
return { ...obj };
});
await run();
```
### []()[Parser improvements](bun-v1.1.2.html#parser-improvements)
## []()[Fixed: TypeScript parsing edgecase](bun-v1.1.2.html#fixed-typescript-parsing-edgecase)
A bug caused Bun's parser to fail to parse the following TypeScript code:
```
var bar: Bar extends string | infer Bar extends string ? Bar : never;
var bar: Bar extends string & infer Bar extends string ? Bar : never;
```
This bug has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
## []()[Thanks to 7 contributors!](bun-v1.1.2.html#thanks-to-7-contributors)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@mangs](https://github.com/mangs)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@sitiom](https://github.com/sitiom)
- [@zackradisic](https://github.com/zackradisic)
* * *
#### [Bun v1.1.1](bun-v1.1.1.html)
#### [Bun v1.1.3](bun-v1.1.3.html)
On this page
- [Fixed: `EBUSY` when saving bun.lockb](bun-v1.1.2.html#fixed-ebusy-when-saving-bun-lockb)
- [Fixed: `ENOENT` and `EEXIST` error when extracting tarballs to cache on Windows](bun-v1.1.2.html#fixed-enoent-and-eexist-error-when-extracting-tarballs-to-cache-on-windows)
- [Fixed: `EBUSY` when using `next dev` or `vite dev` on Windows](bun-v1.1.2.html#fixed-ebusy-when-using-next-dev-or-vite-dev-on-windows)
- [Fixed: `bun install` unable to install tarballs with invalid file paths](bun-v1.1.2.html#fixed-bun-install-unable-to-install-tarballs-with-invalid-file-paths)
- [Fixed: `CouldntReadCurrentDirectory` error](bun-v1.1.2.html#fixed-couldntreadcurrentdirectory-error)
- [Rewrote `fs.watch` on Windows](bun-v1.1.2.html#rewrote-fs-watch-on-windows)
- [Shell & bun run improvements](bun-v1.1.2.html#shell-bun-run-improvements)
- [Support for `seq`, `yes`, `basename`, and `dirname` in Bun Shell](bun-v1.1.2.html#support-for-seq-yes-basename-and-dirname-in-bun-shell)
- [Fixed: Parsing bugs with `*` in environment variables](bun-v1.1.2.html#fixed-parsing-bugs-with-in-environment-variables)
- [Bun install improvements](bun-v1.1.2.html#bun-install-improvements)
- [install `--production` without a lockfile](bun-v1.1.2.html#install-production-without-a-lockfile)
- [Fixed: Potential crash when downloading tarballs](bun-v1.1.2.html#fixed-potential-crash-when-downloading-tarballs)
- [WebKit upgrade](bun-v1.1.2.html#webkit-upgrade)
- [5x faster `{ ...obj }` clone](bun-v1.1.2.html#5x-faster-obj-clone)
- [Parser improvements](bun-v1.1.2.html#parser-improvements)
- [Fixed: TypeScript parsing edgecase](bun-v1.1.2.html#fixed-typescript-parsing-edgecase)
- [Thanks to 7 contributors!](bun-v1.1.2.html#thanks-to-7-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.21.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.21
* * *
[Ashcon Partovi](https://twitter.com/ashconpartovi) · July 27, 2024
[](../rss.xml)
Bun v1.1.21 is here! This release fixes 72 bugs (addressing 63 👍). 30% faster fetch() decompression, New --fetch-preconnect flag, improved Remix support, Bun gets 4 MB smaller on Linux, bundle packages excluding dependencies, many bundler fixes and node compatibility improvements.
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
#### Previous releases
- [`v1.1.20`](bun-v1.1.19.html) & [`v1.1.19`](bun-v1.1.19.html) Fixes 54 bugs (addressing 248 👍). JavaScript gets faster on Windows. Raspberry Pi 4 support. `_auth` support in `.npmrc`. `bun install` preserves package.json indentation. `aws-cdk-lib` support. Memory leak fixes in `new Response(request)` and `fs.readdir`. Several reliability improvements.
- [`v1.1.18`](bun-v1.1.18.html) Fixes 55 bugs (addressing 493 👍). Support for npmrc. Improved constant folding & enum inlining. Improved console.log output for functions. Fixes patching dependencies in workspaces. Fixes several bugs in `bun install` when linking binaries. Fixes a crash in `dns.lookup`, and normalizes DNS errors to better match Node. Fixes an assertion failure in `Bun.escapeHTML`. Upgrades JavaScriptCore.
- [`v1.1.0`](bun-v1.1.html) Bundows. Windows support is here!
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
### []()[fetch() decompresses 30% faster](bun-v1.1.21.html#fetch-decompresses-30-faster)
Decompressing `fetch()` response bodies compressed with gzip or deflate get 30% faster on Linux x64, thanks to [libdeflate](https://github.com/ebiggers/libdeflate).
> In the next version of Bun
>
> fetch() decompresses gzip'd data 30% faster, thanks to libdeflate. [pic.twitter.com/obCjWo2fHv](https://t.co/obCjWo2fHv)
>
> — Jarred Sumner (@jarredsumner) [July 27, 2024](https://twitter.com/jarredsumner/status/1817067294591451208?ref_src=twsrc%5Etfw)
We've also enabled libdeflate with the websocket server, to make decompressing small messages faster.
### []()[New: `--fetch-preconnect` warms up a connection ahead of time](bun-v1.1.21.html#new-fetch-preconnect-warms-up-a-connection-ahead-of-time)
We've added a new flag `--fetch-preconnect=<url> <file>` that starts up an HTTP request to the given URL before any code is executed.
```
bun --fetch-preconnect='https://example.com' ./index.ts
```
For many production services, the first thing a script in Bun does is send HTTP requests to a server using `fetch` or `node:http`. The slowest part of many network requests is the initial connection setup, which can involve DNS lookups, TCP connection establishment, and TLS negotiation. Sometimes this takes 100ms before sending the HTTP request.
This work is network-bound. What if you could start up that connection before any code is executed, so that by the time the rest of your code runs, the connection is already established? This is what `--fetch-preconnect` does. It's a lot like `<link rel="preconnect">` in HTML, but for server-side JavaScript.
Along the way, we've also added a JavaScript API to do the same thing:
```
fetch.preconnect(url: string): void;
```
This is useful for serverless environments and databases that run on top of `fetch` or `node:http`.
```
bun --fetch-preconnect=https://example.com ./hey.mjs
[8.37ms] fetch(https://example.com)
❯ bun hey.mjs # Without preconnect
[51.92ms] fetch(https://example.com)
❯ node hey.mjs
fetch(https://example.com): 68.417ms
❯ cat hey.mjs
│ File: hey.mjs
1 │ if (globalThis.Bun) {
2 │ await Bun.sleep(1000);
3 │ } else {
4 │ await new Promise(resolve => setTimeout(resolve, 1000));
5 │ }
6 │
7 │ console.time("fetch(https://example.com)");
8 │ await fetch("https://example.com");
9 │ console.timeEnd("fetch(https://example.com)");
```
### []()[Improved Remix support](bun-v1.1.21.html#improved-remix-support)
We fixed a bug where overriding globals like `Request` or `Response` could cause issues with `node:http`. Internally, Bun's implementation of `node:http` uses `Bun.serve()` which expects the user to return the native `Response` object.
Remix and other frameworks globally polyfill `Request` and `Response`, and Bun's `node:http` was previously using the global `Request` and `Response` objects. We fixed this by always using the native `Request` and `Response` objects in `node:http`.
We also fixed similar issues in Bun's polyfill of `node-fetch` and `undici`.
If you experienced the following error, it has now been fixed:
```
// error: Expected a Response object, but received 'Response {
// [Symbol(Body internals)]: {
// body: ReadableStream {
// ...
```
We also added an integration test for Remix, so we can continue to ensure compatibility in the future.
### []()[bun install retries on HTTP 500 errors](bun-v1.1.21.html#bun-install-retries-on-http-500-errors)
In this release, `bun install` will now retry on network errors with an HTTP status code > 499.
We've seen reports from users and from our own CI where the official npm registry returned HTTP 500 errors, which would cause `bun install` to fail. Now, `bun install` will retry on these errors, which should help compensate for temporary issues with the npm registry (reducing spurious CI failures).
### []()[4 MB smaller on Linux](bun-v1.1.21.html#4-mb-smaller-on-linux)
In this release, we've shrunk Bun's Linux x64 binary size by 4 MB, which makes it 23% smaller than the official Node.js v22.5.1 executable.
Binary SizeVersion92 MBBun v1.1.2196 MBBun v1.1.2097 MBBun v1.1.1997 MBBun v1.1.18114 MBNode.js v22.5.1
### []()[1ms faster on Linux](bun-v1.1.21.html#1ms-faster-on-linux)
We've also improved Bun's startup time on Linux by 1ms.
```
hyperfine "bun --reivison" "bun-1.1.20 --revision"
```
```
Benchmark 1: bun --revision
Time (mean ± σ): 1.4 ms ± 0.2 ms [User: 0.9 ms, System: 0.4 ms]
Range (min … max): 1.2 ms … 2.6 ms 1143 runs
Benchmark 2: bun-1.1.20 --revision
Time (mean ± σ): 2.3 ms ± 0.2 ms [User: 1.1 ms, System: 1.1 ms]
Range (min … max): 2.2 ms … 5.0 ms 1099 runs
```
These size & start time improvements came from a combination of linker flags, compiler flags, link-time optimization and a few small code changes.
### []()[Bundle packages excluding dependencies with `bun build --packages=external`](bun-v1.1.21.html#bundle-packages-excluding-dependencies-with-bun-build-packages-external)
You can now control if package dependencies are included in your bundle or not. If the import does not start with `.`, `..` or `/`, then it is considered a package.
CLI
```
bun build ./index.ts --packages external
```
You can also use this in the JavaScript API:
JavaScript
```
await Bun.build({
entrypoints: ["./index.ts"],
packages: "external",
});
```
This is useful when bundling libraries. It lets you reduce the number of files your users have to download, while continuing to support peer or external dependencies.
Thanks to [@zpix1](https://github.com/zpix1) for implementing this feature!
### []()[Improved hashes for code-splitting in `bun build`](bun-v1.1.21.html#improved-hashes-for-code-splitting-in-bun-build)
Previously, Bun would generated "isolated" hashes for files during code-splitting, so it can be done in parallel. However, this would mean that if an imported file was changed, the hash of the file that owns the import would not change.
entry.ts
```
const other = await import('./second');
```
second.ts
```
export const second = 1;
```
This has been fixed, and hashes are also shorter by switching to a base32 encoding, similar to how `esbuild` does it.
Thanks to [@paperclover](https://github.com/paperclover) for working on this!
### []()[Fixed: Import resolves as `.mjs` when file is `.mts`](bun-v1.1.21.html#fixed-import-resolves-as-mjs-when-file-is-mts)
We fixed a bug where a `.mjs` import would not resolve to a `.mts` file.
bar.mts
```
import "./foo.mjs";
```
foo.mts
```
export const foo = 1;
```
This has now been fixed thanks to [@190n](https://github.com/190n)!
### []()[Fixed: Crash with `Bun.write` on Windows](bun-v1.1.21.html#fixed-crash-with-bun-write-on-windows)
We fixed a bug in `Bun.write()` on Windows, where Bun could crash after creating the directory for a file that didn't exist.
```
import { write, file } from "bun";
const txt = file("/does/not/exist/example.txt");
await write(txt, "hello world");
```
### []()[Fixed: `setSystemTime` would not work with a number](bun-v1.1.21.html#fixed-setsystemtime-would-not-work-with-a-number)
There was a bug where using `setSystemTime` from the `bun:test` module would not work with a number, instead of a `Date` object.
```
import { test, expect, setSystemTime } from "bun:test";
test("setSystemTime", () => {
const future = Date.now() + 1000;
setSystemTime(future);
expect(Date.now()).toBe(future);
// Before: <test failed>
// After: <test passed>
});
```
Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this bug!
### []()[Fixed: Crash when merging nested TypeScript namespaces](bun-v1.1.21.html#fixed-crash-when-merging-nested-typescript-namespaces)
There was a bug in Bun where a TypeScript namespaces could crash Bun. This was an edge-case in Bun's transpiler where it was not properly handling when a function would merge with a class or namespace.
```
namespace X {
export function Y(): void {}
export namespace Y {
export const Z = 1;
}
}
```
Thanks to [@paperclover](https://github.com/paperclover) for fixing this bug!
This has now been fixed thanks to [@190n](https://github.com/190n)!
### []()[Fixed: Crash with aborted request after server closed](bun-v1.1.21.html#fixed-crash-with-aborted-request-after-server-closed)
We fixed a rare crash in `Bun.serve()` that could occur if a `Request` was manually aborted after the the server was closed before the request finished sending the body.
Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this bug!
### []()[Fixed: Crash with empty value in `CryptoHasher.update()`](bun-v1.1.21.html#fixed-crash-with-empty-value-in-cryptohasher-update)
We fixed a bug in `CryptoHasher.update()` where an empty value would cause a crash.
```
import { CryptoHasher } from "bun";
const hasher = new CryptoHasher("sha1");
hasher.update(); // <crash>
```
Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this bug!
### []()[Fixed: Crash while printing error stacks](bun-v1.1.21.html#fixed-crash-while-printing-error-stacks)
A crash could occur when printing stack traces in Bun. This was caused by not correctly checking if the stackframe came from a JavaScript function or from a native function.
Thanks to [@nektro](https://github.com/nektro) for fixing this bug!
### []()[Fixed: using `expect.any()` with `expect.toThrow()`](bun-v1.1.21.html#fixed-using-expect-any-with-expect-tothrow)
The expected value for `expect.toThrow()` can now use asymmetric matcher `expect.any()`. The following code will work as expected:
```
test("toThrow asymmetric matcher", () => {
expect(() => {
throw new Error("error!");
}).toThrow(expect.any(Error)); // passes
});
```
Thanks to [@ippsav](https://github.com/ippsav)!
### []()[Fixed a crash with the return value of `test.each` in `bun test`](bun-v1.1.21.html#fixed-a-crash-with-the-return-value-of-test-each-in-bun-test)
There was a bug in `bun test` where a null pointer could be used for the return value of `test.each`, resulting in a crash if the value was used in JavaScript. Now, `test.each` will return `undefined`.
```
console.log(test.each([1, 2])("test.each %d", () => {})); // Before: <crash>, After: undefined
```
Thanks to [@dylan-conway](https://github.com/dylan-conway)!
### []()[Fixed: Code coverage on Windows now excludes node\_modules](bun-v1.1.21.html#fixed-code-coverage-on-windows-now-excludes-node-modules)
We fixed a bug in `bun test --coverage` where the code coverage report would include files from `node_modules` on Windows. This was caused by only checking `/` as the path separator, when on Windows it may either be `\` or `/`.
Thanks to [@dariushalipour](https://github.com/dariushalipour) for fixing this bug!
## []()[Node.js compatibility improvements](bun-v1.1.21.html#node-js-compatibility-improvements)
### []()[Fixed: Silent errors in node:http request 'data' callback](bun-v1.1.21.html#fixed-silent-errors-in-node-http-request-data-callback)
A bug causing errors to be silent in the `data` callback of a `node:http` client request has been fixed.
Previously, the following code would not error:
```
const { request } = require("node:http");
const req = request("http://www.google.com", (res) => {
res.on("data", (chunk) => {
throw new Error("oopsie");
});
}).end();
```
Now, it correctly throws an error:
```
1 | const { request } = require("node:http");
2 | const req = request("http://www.google.com", (res) => {
3 | res.on("data", (chunk) => {
4 | throw new Error("oopsie");
^
error: oopsie
at silent.js:4:15
at emit (node:events:180:48)
at addChunk (node:stream:2029:22)
at readableAddChunk (node:stream:1983:30)
at node:http:136:44
Bun v1.1.21 (macOS arm64)
```
### []()[Fixed: `Readable.fromWeb` stopped early with `fetch()` streams](bun-v1.1.21.html#fixed-readable-fromweb-stopped-early-with-fetch-streams)
We fixed a bug where `Readable.fromWeb` when passed a `ReadableStream` from `fetch()` would stop reading early in some cases if the stream was not finished being downloaded yet.
```
import { Readable } from "node:stream";
const res = await fetch("https://bun.sh");
const stream = Readable.fromWeb(res.body);
stream.on("data", (chunk) => {
console.log("Received", chunk.length);
});
```
New:
```
❯ bun chunk.js
Received 16384
[... more chunks ...]
Received 3883
```
Previously:
```
❯ bun-1.1.20 chunk.js # Before
```
This bug specifically impacted `fetch()`'s ReadableStream.
### []()[Fixed: Allow `undefined` extension in `path.basename()`](bun-v1.1.21.html#fixed-allow-undefined-extension-in-path-basename)
We fixed a compatibility bug in `path.basename()` where it would not allow `undefined` as the extension.
```
import path from "path";
path.basename("foo", undefined);
path.posix.basename("bar", undefined);
path.win32.basename("baz", undefined);
```
If you encountered the following error, it has now been fixed:
```
> 2 | path.posix.basename("bar", undefined);
^
TypeError: "ext" property must be of type string, got undefined
code: "ERR_INVALID_ARG_TYPE"
```
Thanks to [@190n](https://github.com/190n)!
### []()[Fixed: Unref in `node:dgram` before socket is connected](bun-v1.1.21.html#fixed-unref-in-node-dgram-before-socket-is-connected)
We fixed a bug in `node:dgram` where would not properly unref the UDP socket, if it was done before the socket was connected.
```
import dgram from "node:dgram";
const socket = dgram.createSocket("udp4");
socket.unref(); // <would not unref>
```
Thanks to [@190n](https://github.com/190n) for fixing this bug!
### []()[Fixed: `napi_threadsafe_function` would keep the process alive after finalizing](bun-v1.1.21.html#fixed-napi-threadsafe-function-would-keep-the-process-alive-after-finalizing)
We fixed a regression in Node-API where after a `napi_threadsafe_function` was finalized, it would continue to keep the process alive. Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this!
```
...
napi_threadsafe_function tsfn;
...
napi_release_threadsafe_function(tsfn, napi_tsfn_release);
// `tsfn` will allow the process to exit if all threads have released it.
...
```
### []()[Fixed: process.exitCode should be undefined until process.exit() is called](bun-v1.1.21.html#fixed-process-exitcode-should-be-undefined-until-process-exit-is-called)
In Node.js, `process.exitCode` is undefined until either:
- `process.exitCode` is set manually
- `process.exit()` is called
We fixed a bug in Bun where `process.exitCode` would be set to `0` before `process.exit()` was called.
```
console.log(process.exitCode); // Before: 0, After: undefined
```
Thanks to [@nektro](https://github.com/nektro) for fixing this bug!
### []()[Fixed: Crash in node:zlib brotli decompression](bun-v1.1.21.html#fixed-crash-in-node-zlib-brotli-decompression)
A crash could occur when synchronously decompressing a brotli stream composed of many chunks over a long period of time. This has been fixed. The crash was caused by not properly keeping the value from JavaScript alive while the decompression was happening.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this bug!
## []()[Bundler fixes](bun-v1.1.21.html#bundler-fixes)
### []()[Slightly smaller bundles](bun-v1.1.21.html#slightly-smaller-bundles)
> In the next version of Bun
>
> Bun's bundler gets slightly smarter at dead-code elimination [pic.twitter.com/nUoNbVgM8J](https://t.co/nUoNbVgM8J)
>
> — clo (@paperclover\_dev) [July 24, 2024](https://twitter.com/paperclover_dev/status/1816033742231855600?ref_src=twsrc%5Etfw)
### []()[Fixed: Crash in `bun build` when bundling with external property access](bun-v1.1.21.html#fixed-crash-in-bun-build-when-bundling-with-external-property-access)
We fixed a bug in `bun build` where there could be a crash when a module used property access on an imported external module.
This has been fixed thanks to [@paperclover](https://github.com/paperclover)!
### []()[Fixed: Trailing slash in `require()` using `bun build`](bun-v1.1.21.html#fixed-trailing-slash-in-require-using-bun-build)
We fixed a bug where a `require()` call with a trailing slash would not work when using `bun build`.
To match Node.js, if you try to require `process/`, it should resolve to `node_modules/process/...`. Previously, Bun was confused and resolved to the built-in `node:process` module.
```
var process2 = require("process/");
// Error: Cannot find module 'process/'
```
This has now been fixed thanks to [@paperclover](https://github.com/paperclover)!
### []()[Fixed: import with rope strings crash](bun-v1.1.21.html#fixed-import-with-rope-strings-crash)
There was a bug in Bun where a non-literal value in `with` option on `import()` would crash Bun. This was because Bun's transpiler was not properly visiting the `with` option.
```
import("./foo", { with: "text" }); // would work
import("./foo", { with: "te" + "xt" }); // would crash
```
This has now been fixed, thanks to [@paperclover](https://github.com/paperclover)!
### []()[Fixed: Class hoisting bug](bun-v1.1.21.html#fixed-class-hoisting-bug)
A bug causing the following error has been fixed:
TypeError: The superclass is not a constructor.
When a class declaration has side effects, it cannot be hoisted. We fixed a bug where Bun's bundler would hoist a class declaration with side effects.
entry.js
other.js
entry.js
```
async function hi() {
const { default: MyInherited } = await import('./other.js');
const myInstance = new MyInherited();
console.log(myInstance.greet())
}
hi();
```
other.js
```
const MyReassignedSuper = class MySuper {
greet() {
return 'Hello, world!';
}
};
class MyInherited extends MyReassignedSuper {};
export default MyInherited;
```
This produces the correct output now:
diff.js
new.js
old.js
diff.js
```
- class MyInherited extends MyReassignedSuper {
- }
- var MyReassignedSuper, other_default;
- MyReassignedSuper = class MySuper {
- greet() {
- return "Hello, world!";
- }
+ var MyReassignedSuper = class MySuper {
+ greet() {
+ return "Hello, world!";
+ }
+ }, MyInherited, other_default;
+ MyInherited = class MyInherited extends MyReassignedSuper {
+ };
+ other_default = MyInherited;
// ...
```
new.js
```
var __defProp = Object.defineProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, {
get: all[name],
enumerable: true,
configurable: true,
set: (newValue) => all[name] = () => newValue
});
};
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
// other.js
var exports_other = {};
__export(exports_other, {
default: () => other_default
});
var MyReassignedSuper = class MySuper {
greet() {
return "Hello, world!";
}
}, MyInherited, other_default;
var init_other = __esm(() => {
MyInherited = class MyInherited extends MyReassignedSuper {
};
other_default = MyInherited;
});
// entry.js
async function hi() {
const { default: MyInherited2 } = await Promise.resolve().then(() => (init_other(), exports_other));
const myInstance = new MyInherited2;
console.log(myInstance.greet());
}
hi();
```
old.js
```
var __defProp = Object.defineProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, {
get: all[name],
enumerable: true,
configurable: true,
set: (newValue) => all[name] = () => newValue
});
};
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
// other.js
var exports_other = {};
__export(exports_other, {
default: () => other_default
});
class MyInherited extends MyReassignedSuper {
}
var MyReassignedSuper, other_default;
var init_other = __esm(() => {
MyReassignedSuper = class MySuper {
greet() {
return "Hello, world!";
}
};
other_default = MyInherited;
});
// entry.js
async function hi() {
const { default: MyInherited2 } = await Promise.resolve().then(() => (init_other(), exports_other));
const myInstance = new MyInherited2;
console.log(myInstance.greet());
}
hi();
```
### []()[Internal: LLVM 18 on macOS & Windows](bun-v1.1.21.html#internal-llvm-18-on-macos-windows)
We've upgraded from LLVM 16 to LLVM 18 on macOS and Windows. This let us add more debug assertions on macOS which help catch some bugs earlier.
## []()[Thanks to 14 contributors!](bun-v1.1.21.html#thanks-to-14-contributors)
- [@190n](https://github.com/190n)
- [@cirospaciari](https://github.com/cirospaciari)
- [@dariushalipour](https://github.com/dariushalipour)
- [@davidstevens37](https://github.com/davidstevens37)
- [@dylan-conway](https://github.com/dylan-conway)
- [@eval](https://github.com/eval)
- [@HibanaSama](https://github.com/HibanaSama)
- [@huseeiin](https://github.com/huseeiin)
- [@ippsav](https://github.com/ippsav)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@mangs](https://github.com/mangs)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@zpix1](https://github.com/zpix1)
* * *
#### [Bun v1.1.19](bun-v1.1.19.html)
#### [Bun v1.1.22](bun-v1.1.22.html)
On this page
- [Node.js compatibility improvements](bun-v1.1.21.html#node-js-compatibility-improvements)
- [Fixed: Silent errors in node:http request 'data' callback](bun-v1.1.21.html#fixed-silent-errors-in-node-http-request-data-callback)
- [Fixed: `Readable.fromWeb` stopped early with `fetch()` streams](bun-v1.1.21.html#fixed-readable-fromweb-stopped-early-with-fetch-streams)
- [Fixed: Allow `undefined` extension in `path.basename()`](bun-v1.1.21.html#fixed-allow-undefined-extension-in-path-basename)
- [Fixed: Unref in `node:dgram` before socket is connected](bun-v1.1.21.html#fixed-unref-in-node-dgram-before-socket-is-connected)
- [Fixed: `napi_threadsafe_function` would keep the process alive after finalizing](bun-v1.1.21.html#fixed-napi-threadsafe-function-would-keep-the-process-alive-after-finalizing)
- [Fixed: process.exitCode should be undefined until process.exit() is called](bun-v1.1.21.html#fixed-process-exitcode-should-be-undefined-until-process-exit-is-called)
- [Fixed: Crash in node:zlib brotli decompression](bun-v1.1.21.html#fixed-crash-in-node-zlib-brotli-decompression)
- [Bundler fixes](bun-v1.1.21.html#bundler-fixes)
- [Slightly smaller bundles](bun-v1.1.21.html#slightly-smaller-bundles)
- [Fixed: Crash in `bun build` when bundling with external property access](bun-v1.1.21.html#fixed-crash-in-bun-build-when-bundling-with-external-property-access)
- [Fixed: Trailing slash in `require()` using `bun build`](bun-v1.1.21.html#fixed-trailing-slash-in-require-using-bun-build)
- [Fixed: import with rope strings crash](bun-v1.1.21.html#fixed-import-with-rope-strings-crash)
- [Fixed: Class hoisting bug](bun-v1.1.21.html#fixed-class-hoisting-bug)
- [Internal: LLVM 18 on macOS & Windows](bun-v1.1.21.html#internal-llvm-18-on-macos-windows)
- [Thanks to 14 contributors!](bun-v1.1.21.html#thanks-to-14-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.22.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.22
* * *
[Ashcon Partovi](https://twitter.com/ashconpartovi) · August 7, 2024
[](../rss.xml)
Bun v1.1.22 is here! This release fixes 79 bugs (addressing 93 👍). Express is now 3x faster in Bun, ES modules load faster on Windows, 10% faster Bun.serve() at POST requests, source maps in `bun build --compile`. Memory usage reductions to `--hot`, Bun.serve(), and imports. `Uint8Array.toBase64()`, `Uint8Array.toHex()`, and lots of Node.js compatibiltiy improvements and bugfixes.
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[Express is now 3x faster in Bun](bun-v1.1.22.html#express-is-now-3x-faster-in-bun)
In this release, we made performance and compatibility improvements to Bun's `node:http` implementation. This increased `express` request throughput by 50% compared to Bun v1.1.21, which means its 3x faster in Bun than Node.js running the same code.
[](https://github.com/user-attachments/assets/f96ad9dc-7957-4073-8057-60e130824d28)
## []()[ES Modules load up to 4x faster on Windows](bun-v1.1.22.html#es-modules-load-up-to-4x-faster-on-windows)
To make running TypeScript, JSX, ES modules, and CommonJS all just work in Bun, we transpile every file on the fly. This inherently has a performance cost.
This release brings concurrent transpilation support to Bundows, which makes loading ES modules faster.
```
async function benchmark(name) {
console.time(name);
await import(name);
console.timeEnd(name);
}
await benchmark("lodash-es");
```
In this benchmark, we're running the above code and measuring the time it to import a popular package, like `lodash-es`.
RuntimeTime (ms)Bun v1.1.2239Bun v1.1.2182Node.js v22.4.1186
This optimization previously was only supported on Bun for Linux & macOS, but now it is also supported on Windows.
## []()[10% higher throughput POST requests in `Bun.serve()`](bun-v1.1.22.html#10-higher-throughput-post-requests-in-bun-serve)
If you code does not read the body of an incoming `Request`, there is a 10% performance improvement from the last release of Bun.
> In the next version of Bun
>
> Bun.serve() gets 10% higher req/s on POST requests that ignore the body. [pic.twitter.com/OxkIGwYaWn](https://t.co/OxkIGwYaWn)
>
> — Bun (@bunjavascript) [July 31, 2024](https://twitter.com/bunjavascript/status/1818590757118525457?ref_src=twsrc%5Etfw)
## []()[Less memory usage](bun-v1.1.22.html#less-memory-usage)
### []()[`bun --hot` uses less memory](bun-v1.1.22.html#bun-hot-uses-less-memory)
In this release, Bun uses 2x less memory when you use `bun --hot` to reload code.
> In the next version of Bun
>
> bun --hot uses less memory after many runs
>
> left: Bun v1.1.22 (new)
> right: Bun v1.1.21 (old) [pic.twitter.com/eDl5iqZsme](https://t.co/eDl5iqZsme)
>
> — Jarred Sumner (@jarredsumner) [August 1, 2024](https://twitter.com/jarredsumner/status/1818918642022858847?ref_src=twsrc%5Etfw)
Previously, we were not always releasing the source code for old versions of modules. This also applies if your code or dependencies modifies [`require.cache`](https://nodejs.org/api/modules.html#requirecache), which is a common pattern for reloading code.
### []()[Importing modules that are garbage collected uses less memory](bun-v1.1.22.html#importing-modules-that-are-garbage-collected-uses-less-memory)
We fixed a bug where importing or requiring a module that is garbage collected would keep a reference to that module's source code.
This was also caused when a module would throw an error, which would keep a reference to the module's source code.
> In the next version of Bun
>
> require()'ing or import'ing large modules that throw an error uses less memory [pic.twitter.com/ruMqFNDzqM](https://t.co/ruMqFNDzqM)
>
> — Jarred Sumner (@jarredsumner) [August 1, 2024](https://twitter.com/jarredsumner/status/1818932723664535928?ref_src=twsrc%5Etfw)
### []()[Memory reductions](bun-v1.1.22.html#memory-reductions)
We also patched various memory leaks, including when:
- requiring a CommonJS module
- computing line offsets in source maps
- transpiling more than 64 files, concurrently
- creating a large number of `setTimeout()` or `setInterval()` timers
## []()[Better stack traces](bun-v1.1.22.html#better-stack-traces)
We fixed a bug in how `error.stack` traces are rendered in Bun. Sometimes the source URL of a call site would be empty, which would cause the stack trace to be slightly different than what most tools expect to receive. Now, Next.js renders stack traces properly.
 
Before: Stack traces do not render in Next.js.
After: Stack traces show the correct source in Next.js.
## []()[Sourcemaps in single-file executables](bun-v1.1.22.html#sourcemaps-in-single-file-executables)
`bun build --compile` lets you generate a [single-file executable](../docs/bundler/executables.html) that bundles your source code, dependencies, and Bun into a single file you can deploy to production without needing other dependencies.
In this release of Bun, `--sourcemap` is now properly supported in single-file executables. This gives you better stack traces for debugging.
```
bun build cli.ts --compile --sourcemap
```
Before:
```
/tmp
❯ bun-1.1.21 build --compile --sourcemap errory.ts
[3ms] bundle 1 modules
[110ms] compile errory
/tmp
❯ ./errory
2 | // @bun
3 | // errory.ts
4 | throw new Error("hey " + n);
^
error: hey 42
at hey (/$bunfs/root/errory:4:9)
at /$bunfs/root/errory:6:4
Bun v1.1.21 (macOS arm64)
```
After:
```
❯ bun build --compile --sourcemap errory.ts
[1ms] bundle 1 modules
[101ms] compile errory
/tmp
❯ ./errory
1 | function hey(n: number) {
2 | throw new Error("hey " + n);
^
error: hey 42
at hey (errory.ts:2:9)
at errory.ts:4:1
Bun v1.1.22-canary.104+c527058f1 (macOS arm64)
```
To reduce the memory and file-size cost of sourcemaps, we compress the input source code with `zstd` and serialize into a custom binary format.
## []()[Node.js compatibility](bun-v1.1.22.html#node-js-compatibility)
### []()[`util.getSystemErrorName()`](bun-v1.1.22.html#util-getsystemerrorname)
Bun now supports the [`util.getSystemErrorName()`](https://nodejs.org/api/util.html#utilgetsystemerrornameerr) function from the `node:util` module. This allows you to return the name of the error code for an error object.
```
import { readFileSync } from "node:fs";
import { getSystemErrorName } from "node:util";
try {
readFileSync("/does/not/exist");
} catch (error) {
console.log(getSystemErrorName(error)); // "ENOENT"
}
```
Thanks to [@nektro](https://github.com/nektro) for implementing this feature!
### []()[`util.aborted()`](bun-v1.1.22.html#util-aborted)
Bun now supports the [`util.aborted()`](https://nodejs.org/api/util.html#utilabortedsignal-resource) function from the `node:util` module. This allows you to listen to an `AbortSignal` and receive a promise that resolves when the signal is aborted.
```
import { aborted } from "node:util";
const controller = new AbortController();
const promise = aborted(controller.signal);
promise.then(() => {
console.log("Aborted!");
});
```
### []()[`events.getEventListeners()`](bun-v1.1.22.html#events-geteventlisteners)
Bun also now supports the [`events.getEventListeners()`](https://nodejs.org/api/events.html#eventsgeteventlistenersemitterortarget-eventname) function for `EventTarget` objects from the `node:events` module. This allows you to get all listeners for a given event name on a given emitter.
```
import { getEventListeners } from "node:events";
const emitter = new EventTarget();
emitter.addEventListener("foo", function foo() {});
console.log(getEventListeners(emitter, "foo"));
// [ [Function: foo] ]
```
Previously, this was only supported for `EventEmitter` objects from the `node:events` module.
### []()[`NODE_EXTRA_CA_CERTS`](bun-v1.1.22.html#node-extra-ca-certs)
Bun now supports the [`NODE_EXTRA_CA_CERTS`](https://nodejs.org/api/cli.html#node_extra_ca_certsfile) environment variable, which allows you to specify a file containing one or more CA certificates to use when verifying TLS certificates. This works for the runtime, `bun install`, and everything else in Bun that makes HTTPS requests.
```
NODE_EXTRA_CA_CERTS=ca.pem bun install
```
```
NODE_EXTRA_CA_CERTS=another.pem bun run script.ts
```
### []()[Fixed: Support async interators in `fs.promises.writeFile()`](bun-v1.1.22.html#fixed-support-async-interators-in-fs-promises-writefile)
Node.js has [undocumented](https://github.com/nodejs/node/blob/2eff28fb7a93d3f672f80b582f664a7c701569fb/lib/internal/fs/promises.js#L481-L493) support for async iterators in `fs.promises.writeFile()`. This was relied upon by various packages, and we decided to support it in Bun.
```
import { writeFile } from "node:fs/promises";
const iterator = async function* () {
yield "Hello";
yield "World";
};
await writeFile("hello.txt", iterator);
```
### []()[Fixed: Bun now exits with `1` if `process.on("exit")` throws](bun-v1.1.22.html#fixed-bun-now-exits-with-1-if-process-on-exit-throws)
We fixed a bug where Bun would not propagate the right exit code if the `exit` or `beforeExit` event listeners threw an error.
```
process.on("exit", () => {
throw new Error("Oh no!");
});
```
This has been fixed thanks to [@nektro](https://github.com/nektro)!
### []()[Fixed: `Worker` constructor would misinterpret `eval` property](bun-v1.1.22.html#fixed-worker-constructor-would-misinterpret-eval-property)
There was a bug where the `Worker` constructor would misinterpret the `eval` property, when being explicitly defined. This was a regression that was introduced in Bun v1.1.13, and has now been fixed.
```
const worker = new Worker("console.log('hello!')", { eval: false });
// Before: hello!
// After: BuildMessage: ModuleNotFound
```
Thanks to [@dcrousso](https://x.com/dcrousso) and [@constellation](https://x.com/constellation) for implementing these features in WebKit!
## []()[`bun build`](bun-v1.1.22.html#bun-build)
### []()[Converting `require.main === module` to `import.meta.main`](bun-v1.1.22.html#converting-require-main-module-to-import-meta-main)
Previously, using `require.main === module` would mark the module as CommonJS (since it uses `module`). Now, Bun rewrites this into `import.meta.main`, meaning you can use this pattern alongside import statements.
```
import * as fs from "fs";
if (typeof require !== "undefined" && require.main === module) {
console.log("main!", fs);
}
```
```
1 | import "fs";
^
error: Cannot use import statement with CommonJS-only features
at /index.js:1:8
note: Try require("fs") instead
note: This file is CommonJS because 'module' was used
```
This also fixes support for `require.main === module` in single-file executables using CommonJS modules and `bun build --compile`.
Thanks to [@paperclover](https://github.com/paperclover) for implementing these features!
### []()[`--ignore-dce-annotations`](bun-v1.1.22.html#ignore-dce-annotations)
Some JavaScript tools support special annotations that can influence during dead-code elimination. For example, the `@__PURE__` annotation tells bundlers that a function call is pure (regardless of if it actually is), and that the call can be removed if it is not used.
```
let button = /* @__PURE__ */ React.createElement(Button, null);
```
Bundling or running the above code will result in an empty file, since the `button` variable is not used.
Sometimes, a library may include incorrect annotations, which can cause Bun to remove side effects which were needed. To workaround these issue, you can use the `--ignore-dce-annotations` flag when running `bun build` to ignore all annotations. This should only be used if dead-code elimination breaks bundles, and fixing the annotations should be preferred to leaving this flag on.
Thanks to [@paperclover](https://github.com/paperclover) for implementing this feature!
### []()[Fixed: Assignment to `module.exports` in bundles](bun-v1.1.22.html#fixed-assignment-to-module-exports-in-bundles)
When bundling CommonJS modules, Bun tries to convert `module.exports` into `exports` if possible. This helps minification, but assigning to either `module.exports` or `exports` must undo optimization. This did not happen for instances of `module.exports` textually before the assignment, which is important for functions.
input.ts
```
function main() {
console.log(module.exports);
}
module.exports = 123;
main();
```
out.js
```
var __commonJS = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
// input.ts
var require_input = __commonJS((exports, module) => {
function main() {
- console.log(exports);
+ console.log(module.exports);
}
module.exports = 123;
main();
});
export default require_input();
```
Thanks to [@paperclover](https://github.com/paperclover) for fixing this!
### []()[Fixed: Minifying `await import("react-dom/server")`](bun-v1.1.22.html#fixed-minifying-await-import-react-dom-server)
A bug causing the following error when using `--minify-identifier` on a package that dynamically imports `react-dom` has been fixed:
```
SyntaxError: Cannot declare an imported binding name twice
```
For some packages like React, Bun applies extra optimizations to convert CommonJS into ESM. In this conversion, the generated import statements had the wrong scope assigned, causing the minifier to two import statements the same minified variable name.
## []()[Fixed bugs](bun-v1.1.22.html#fixed-bugs)
We spend a lot of time fixing bugs in Bun. That's because our top priority is to support Bun in production.
> We fixed 180 bugs in July [pic.twitter.com/KwXyZy9sTG](https://t.co/KwXyZy9sTG)
>
> — Bun (@bunjavascript) [August 2, 2024](https://twitter.com/bunjavascript/status/1819466793779638782?ref_src=twsrc%5Etfw)
If you experience a bug that we haven't fixed, please file an issue or upvote an existing issue on GitHub so we can prioritize it. It helps if you are able to provide a minimal reproducible example.
### []()[Missing preview with uncaught error in `Bun.serve()`](bun-v1.1.22.html#missing-preview-with-uncaught-error-in-bun-serve)
When you pass `development: true` to `Bun.serve()`, we enable a builtin error handler that shows a preview of the error when an uncaught exception is thrown in the handler.
We fixed a bug where the error preview would not be shown if an uncaught exception was thrown in `Bun.serve()`. This was a regression that was introduced in Bun v1.1.9, and has now been fixed.
 
Before: Error is missing
After: Error and stack trace is shown
### []()[`TextDecoder` not properly decoding 192 or 193 correctly](bun-v1.1.22.html#textdecoder-not-properly-decoding-192-or-193-correctly)
We fixed a bug where `TextDecoder` would not properly decode UTF-8 sequences that started with `192` or `193`.
```
const decoder = new TextDecoder();
const bytes = new Uint8Array([192, 191]);
console.log(decoder.decode(bytes));
// Before: "?"
// After: "\uFFFD\uFFFD"
```
### []()[Non-ASCII template literals with addition operator](bun-v1.1.22.html#non-ascii-template-literals-with-addition-operator)
We fixed a transpiler bug where template literals with an addition operator and non-ASCII input would not be transpiled correctly in certain cases. This was a regression that was introduced in Bun v1.1.17.
```
console.log(`${123}➖` + "123456 456");
// Before: 123➖
// After: 123➖123456 456
```
Thanks to [@paperclover](https://github.com/paperclover) for fixing this bug!
### []()[`Bun.serve()` reliability improvements](bun-v1.1.22.html#bun-serve-reliability-improvements)
We have made several reliability improvements to `Bun.serve()`. This includes:
- No longer creating unnecessary `DOMException` objects when HTTP requests fail or are aborted
- Fixed a bug where throwing an error when consuming a `ReadableStream` via async iterators could cause an uncatchable global error to be thrown
- Unnecessarily abrupt TLS shutdown caused clients to not receive a WebSocket close frame in some cases
- Serving a `Bun.file()` in certain cases would omit the trailing newline from the response body
- A crash that could occur when abruptly stopping a Bun.serve() server while there are still open HTTP requests has been fixed
### []()[WebSocket server publish after close](bun-v1.1.22.html#websocket-server-publish-after-close)
A bug where calling `.publish()` on a closed `ServerWebSocket` would incorrectly attempt to publish a message instead of returning `0` has been fixed. In rare cases this could cause a crash.
### []()[WebSocket client receives spurious 1006 close code](bun-v1.1.22.html#websocket-client-receives-spurious-1006-close-code)
We fixed a bug in the `WebSocket` client, where it would receive a spurious `1006` close code, even after sending the server a close frame with a different code. This was because Bun was doing a fast-shutdown, which meant that the close frame was sometimes not sent properly.
Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this bug!
### []()[Missing `Date` header when sending `Bun.file()` as response](bun-v1.1.22.html#missing-date-header-when-sending-bun-file-as-response)
We fixed a bug where the `Date` header was not being sent when sending a `File` as a response in `Bun.serve()`. This was because Bun uses the `sendfile()` syscall for sending files, and that code path was not setting the `Date` header.
```
const server = Bun.serve({
async fetch(req) {
const file = Bun.file("hello.txt");
return new Response(file);
},
});
const response = await fetch(server.url);
console.log(response.headers.get("Date"));
// Before: undefined
// After: "Wed, 06 Aug 2024 19:46:05 GMT"
```
Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this bug!
### []()[Cloned `File` would use the wrong filename](bun-v1.1.22.html#cloned-file-would-use-the-wrong-filename)
There was a bug where cloning a `File` from another file, while defining a new name, would use the wrong name. This has now been fixed.
```
const original = Bun.file("original.txt");
const clone = new File([original], "clone.txt");
console.log(clone.name);
// Before: "original.txt"
// After: "clone.txt"
```
### []()[`bun upgrade` on Windows with space in home directory](bun-v1.1.22.html#bun-upgrade-on-windows-with-space-in-home-directory)
We fixed a bug where `bun upgrade` would fail on Windows if your home directory contained a space.
```
bun upgrade
```
```
Bun v1.1.22 is out! You're on v1.1.21
Expand-Archive : A positional parameter cannot be found that accepts argument 'PC\AppData\Local\Temp\1.1.22'.
At line:1 char:47
+ ... lyContinue';Expand-Archive -Path bun.zip C:\Users\My PC\AppDat ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Expand-Archive], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Expand-Archive
error: Failed to verify Bun (code: FileNotFound))
```
If you experienced the following error, it has now been fixed, but you will have to run the PowerShell installer once more to receive the fixed build:
```
powershell -c "irm bun.sh/install.ps1 | iex"
(function() {
let currentActive = null;
let userClicked = false;
function updateActiveItem(tocItem, isUserClick = false) {
if (!tocItem || tocItem === currentActive) return;
userClicked = isUserClick;
// Remove active class from all items
document.querySelectorAll('[data-heading-id]').forEach((item) => item.classList.remove('active'));
// Add active class to current item
tocItem.classList.add('active');
currentActive = tocItem;
if (isUserClick) {
setTimeout(() => {
userClicked = false;
}, 100);
}
}
// Handle clicks on ToC items
document.querySelectorAll('[data-heading-id]').forEach(item => {
item.addEventListener('click', () => {
updateActiveItem(item, true);
});
});
const observer = new IntersectionObserver((entries) => {
if (userClicked) return;
// Sort entries by their position in the document
const sortedEntries = entries.sort((a, b) => {
const aRect = a.target.getBoundingClientRect();
const bRect = b.target.getBoundingClientRect();
return aRect.top - bRect.top;
});
// Find the first visible heading
const visibleEntry = sortedEntries.find(entry => entry.isIntersecting);
if (visibleEntry) {
const id = visibleEntry.target.getAttribute('id');
const tocItem = document.querySelector(`[data-heading-id="${id}"]`);
updateActiveItem(tocItem);
} else if (currentActive) {
// If no heading is visible, find the nearest one above the viewport
const headings = Array.from(document.querySelectorAll('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]'));
const aboveHeadings = headings.filter(h => {
const rect = h.getBoundingClientRect();
return rect.bottom <= 0;
});
if (aboveHeadings.length > 0) {
const nearestHeading = aboveHeadings[aboveHeadings.length - 1];
const nearestId = nearestHeading.getAttribute('id');
const nearestTocItem = document.querySelector(`[data-heading-id="${nearestId}"]`);
updateActiveItem(nearestTocItem);
}
}
}, {
rootMargin: '-80px 0px -66%',
threshold: [0, 1]
});
document.querySelectorAll('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').forEach((heading) => {
observer.observe(heading);
});
})();
```
`Resources`
`DocsGuidesDiscordGitHub Blog`
`Toolkit`
`RuntimePackage managerTest runnerBundlerPackage runner`
`Project`
`Bun 1.0Bun 1.1Bun 1.2RoadmapContributingLicense`
`Baked with ❤️ in San Francisco`
`We're hiring →`
`
`
=== bun.sh/blog/bun-v1.1.23.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.23
* * *
[Ashcon Partovi](https://twitter.com/ashconpartovi) · August 14, 2024
[](../rss.xml)
Bun v1.1.23 is here! This release fixes 27 bugs (addressing 128 👍). Support for `TextEncoderStream` and `TextDecoderStream`, 50% faster `console.log(string)`, support for `Float16Array`, better out of memory handling, Node.js<>Bun IPC on Windows, truncate large arrays in `console.log()`, and many more bug fixes and Node.js compatibility improvements.
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
#### Previous releases
- [`v1.1.22`](bun-v1.1.22.html) fixes 72 bugs (addressing 63 👍). 30% faster fetch() decompression, New --fetch-preconnect flag, improved Remix support, Bun gets 4 MB smaller on Linux, bundle packages excluding dependencies, many bundler fixes and node compatibility improvements.
- [`v1.1.0`](bun-v1.1.html) Bundows. Windows support is here!
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[New features](bun-v1.1.23.html#new-features)
### []()[`TextEncoderStream` & `TextDecoderStream`](bun-v1.1.23.html#textencoderstream-textdecoderstream)
We've implemented the [`TextEncoderStream`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoderStream) and [`TextDecoderStream`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoderStream) Web APIs. These APIs are the streaming equivalents of [`TextEncoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder) and [`TextDecoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder).
You can use `TextDecoderStream` to decode a stream of bytes into a stream of UTF-8 strings.
```
const response = await fetch("https://example.com");
const body = response.body.pipeThrough(new TextDecoderStream());
for await (const chunk of body) {
console.log(chunk); // typeof chunk === "string"
}
```
You can use `TextEncoderStream` to encode a stream of UTF-8 strings into a stream of bytes.
```
const stream = new ReadableStream({
start(controller) {
controller.enqueue("Hello, world!");
controller.close();
},
});
const body = stream.pipeThrough(new TextEncoderStream());
for await (const chunk of body) {
console.log(chunk); // chunk instanceof Uint8Array
}
```
`TextEncoderStream` in Bun is relatively fast.
> TextEncoderStream in Bun v1.1.23 encodes the same input 3x - 30x faster than in Node v22.5.1 [pic.twitter.com/GCEfgfK0GU](https://t.co/GCEfgfK0GU)
>
> — Jarred Sumner (@jarredsumner) [August 10, 2024](https://twitter.com/jarredsumner/status/1822221334056935771?ref_src=twsrc%5Etfw)
#### Why TextEncoderStream?
The `TextEncoderStream` API is used in popular packages like Next.js' App Router for middleware.
Since most natively-implemented streams in Bun support both text and binary data, you rarely ever need to use `TextEncoderStream` in Bun. In fact, using `TextEncoderStream` in Bun is slower than not using it because it adds significant overhead to the stream. So, don't use this API unless a library you depend on is already using it.
#### `stream` option in `TextDecoder`
This release also adds support for the `stream` option in `TextDecoder`. This tells the decoder that chunks are part of a larger stream, and it should not throw an error if chunk is not a complete UTF-8 code point.
```
const decoder = new TextDecoder("utf-8");
const first = decoder.decode(new Uint8Array([226, 153]), { stream: true });
const second = decoder.decode(new Uint8Array([165]), { stream: true });
console.log(first); // ""
console.log(second); // "♥"
```
### []()[50% faster `console.log(string)`](bun-v1.1.23.html#50-faster-console-log-string)
In this release of bun, we made `console.log(string)` 50% faster.
> In the next version of Bun
>
> console.log(string) gets 50% faster, thanks to [@justjs14](https://twitter.com/justjs14?ref_src=twsrc%5Etfw) [pic.twitter.com/DBKd1fKODe](https://t.co/DBKd1fKODe)
>
> — Bun (@bunjavascript) [August 13, 2024](https://twitter.com/bunjavascript/status/1823263542067536197?ref_src=twsrc%5Etfw)
Previously, Bun had a fast-path for printing a single string with `console.log()`. In theory, this would mean that only 1 syscall would be needed to print the string. However, this was not the case because `console.log()` needs to print a newline character and reset ANSI escape codes. We made it faster by removing this no-so-fast-path and buffering the write like in other cases.
Thanks to [@billywhizz](https://github.com/billywhizz) and [@nektro](https://github.com/nektro) for making this faster!
### []()[Truncate large arrays in `console.log()`](bun-v1.1.23.html#truncate-large-arrays-in-console-log)
When you `console.log(largeArray)` a large array in Bun, instead of printing out the entire array element by element, Bun will now stop after printing 100 total elements, and print an ellipsis with a count (`... 1,234 more items`) to indicate that there are more elements.
> In the next version of Bun,
>
> console.log truncates arrays after 100 elements [pic.twitter.com/qPZtkb6sup](https://t.co/qPZtkb6sup)
>
> — meghan 🌻 (@nektro) [August 10, 2024](https://twitter.com/nektro/status/1822418503191892426?ref_src=twsrc%5Etfw)
Thanks to [@nektro](https://github.com/nektro) for working on this feature!
### []()[`Float16Array`](bun-v1.1.23.html#float16array)
In this release of Bun, there is support for the newly added [`Float16Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float16Array) API. This is a [stage 3](https://github.com/tc39/proposal-float16array) TC39 proposal that was implemented in WebKit.
```
const float16 = new Float16Array(3);
const float32 = new Float32Array(3);
for (let i = 0; i < 3; i++) {
float16[i] = i + 0.123;
float32[i] = i + 0.123;
}
console.log(float16); // Float16Array(3) [ 0, 1.123046875, 2.123046875 ]
console.log(float32); // Float32Array(3) [ 0, 1.1230000257492065, 2.122999906539917 ]
```
Thanks to the WebKit team for implementing this feature!
### []()[Better handling of out-of-memory errors](bun-v1.1.23.html#better-handling-of-out-of-memory-errors)
We improved how out-of-memory errors are handled in `Response`, `Request,` `Blob`, and `node:fs`. Previously, Bun would crash or potentially truncate if an operation exceeded an engine limit, now Bun will check if the operation will definitely exceed a limit and properly throw an error if it does.
```
import { expect } from "bun:test";
const buf = Buffer.alloc(4294967295, "abc");
try {
const blob = new Blob([buf, buf]);
await blob.text();
} catch (e) {
expect(e.message).toBe(
"Cannot create a string longer than 2^32-1 characters",
);
expect(e.code).toBe("ERR_STRING_TOO_LONG");
}
// Before: `catch` block would not be called
// After: `catch` block is called
```
The improved out-of-memory error handling affects the following APIs:
- `text()`, `json()`, `bytes()`, `formData()`,`arrayBuffer()` methods on `Blob`, `Request`, and `Response`
- `fs.writeFile()` & `fs.readFile()`
## []()[Node.js compatibility improvements](bun-v1.1.23.html#node-js-compatibility-improvements)
### []()[Fixed: `fs.F_OK`, `fs.R_OK`, `fs.W_OK`, and similar constants](bun-v1.1.23.html#fixed-fs-f-ok-fs-r-ok-fs-w-ok-and-similar-constants)
We fixed a bug where `node:fs` constants, such as `F_OK`, were not defined in Bun. These were deprecated in favor of `fs.constants` in Node.js 20, but are still defined for compatibility reasons.
```
import fs from "node:fs";
console.log(fs.F_OK); // old way
console.log(fs.constants.F_OK); // new way
```
### []()[Fixed: `fs.readFile` memory & size limits](bun-v1.1.23.html#fixed-fs-readfile-memory-size-limits)
Strings and typed arrays in Bun are limited to 2^32 characters of length by the engine (JavaScriptCore). Node.js/V8 has a lower limit for strings and a higher limit for typed arrays.
When reading files larger than this limit with `fs.readFile`, previously Bun would behave incorrectly. In certain cases, Bun would crash due to incorrect JavaScript exception handling and in other cases, Bun would potentially return a truncated string or typed array.
Now, Bun will throw an error if the file as soon as it is known that the file will not be able to be read from JavaScript. This saves you memory and CPU time because it avoids reading the complete file into memory before throwing an error.
## []()[Fixed: Backpressure in 'ws' module](bun-v1.1.23.html#fixed-backpressure-in-ws-module)
We fixed a bug where calling `WebSocket.send()` under high-load would cause a message to be sent multiple times. This was due to incorrect handling of backpressure when a message was rejected by the socket.
```
import { WebSocket } from "ws";
const ws = new WebSocket("ws://example.com");
ws.on("open", () => {
for (let i = 0; i < 1_000; i++) {
ws.send(`Hello, world! ${i}`);
}
});
// Before: | After:
// ... | ...
// Hello, world! 999 | Hello, world! 997
// Hello, world! 999 | Hello, world! 998
// Hello, world! 999 | Hello, world! 999
// ... | ...
```
This only affected `WebSocket` clients that were created by importing the `ws` package, which Bun changes to use our own implementation of `WebSocket`.
Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this bug!
### []()[Cross-runtime IPC on Windows with Node.js](bun-v1.1.23.html#cross-runtime-ipc-on-windows-with-node-js)
We fixed a bug where inter-process-communication (IPC) in `node:child_process` would not work on Windows when sending messages between Bun and Node.js processes. In certain cases, this could cause some build tools to hang on Windows.
Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this bug!
### []()[JIT crashes in `node:vm`](bun-v1.1.23.html#jit-crashes-in-node-vm)
We fixed several crashes that could occur when code is JIT'd and being evaluated in a `node:vm` context. This would occur when the `globalThis` object in the `node:vm` context was not the same as the real `globalThis` object.
```
import { Script } from "node:vm";
const script = new Script(`
for (let i = 0; i < 1_000_000; i++) {
performance.now();
}
`);
script.runInContext(globalThis); // ok
script.runInContext({ performance }); // would crash
```
This affected only certain code paths after about a million times invocations:
- `performance.now()`
- `TextEncoder.encode()` & `TextDecoder.decode()`
- `crypto.randomUUID()` & `crypto.getRandomValues()`
- `crypto.timingSafeEqual()`
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this bug!
## []()[Bugfixes](bun-v1.1.23.html#bugfixes)
### []()[Fixed: Buffering gigabytes of data over `Bun.serve()`](bun-v1.1.23.html#fixed-buffering-gigabytes-of-data-over-bun-serve)
We fixed a bug where receving then streaming a large response from `Bun.serve()` would cause the response to be truncated. This was because if the data was larger than `2^32-1` bytes, the flush would be truncated.
Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this bug!
### []()[Fixed: moving tagged template literals when bundling](bun-v1.1.23.html#fixed-moving-tagged-template-literals-when-bundling)
We fixed a bundler bug where tagged template literals would be incorrectly moved during bundling. This would cause the template literal to be evaluated in the wrong scope, which would cause it to throw an error.
foo.ts
```
globalThis.foo = () => console.log("foo");
const bar = await import("./bar.ts");
```
bar.ts
```
console.log("bar");
export const bar = foo`bar`;
```
```
// Before: TypeError: undefined is not a function (near '...foo`)
// After: bar\nfoo
```
This was a regression introduced in Bun v1.1.18, and has now been fixed.
Thanks to [@paperclover](https://github.com/paperclover) for fixing this bug!
### []()[Fixed: AbortSignal with `fetch()` when using custom TLS certificates](bun-v1.1.23.html#fixed-abortsignal-with-fetch-when-using-custom-tls-certificates)
We fixed a bug where calling `fetch()` with a custom TLS certificate would not abort the request due to a timeout. Bun supports [`tls`](../docs/api/fetch.html#tls) options when making a `fetch()` request, which if often needed in non-browser environments where you need to use a custom TLS certificate.
```
const response = await fetch("https://example.com", {
signal: AbortSignal.timeout(1000),
tls: {
ca: "...",
},
});
```
Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this bug!
### []()[Fixed: memory leak when `new Response` threw an error](bun-v1.1.23.html#fixed-memory-leak-when-new-response-threw-an-error)
We fixed a memory leak where setting a custom `statusText` on a `new Response` would not be cleaned up. We've also added more tests to ensure that leaks to `Request` and `Response` are caught.
### []()[Fixed: crash when importing an empty `.toml` file](bun-v1.1.23.html#fixed-crash-when-importing-an-empty-toml-file)
We fixed a bug when importing an empty `.toml` file would cause Bun to crash. This would also affect certain `.json` files, like `package.json` and `tsconfig.json`.
```
import config from "./config.toml";
console.log(config);
// Before: <crash>
// After: { enabled: true }
```
### []()[Fixed: Regression with TLS sockets in 1.1.22](bun-v1.1.23.html#fixed-regression-with-tls-sockets-in-1-1-22)
A regression introduced in 1.1.22 could cause a crash when a TLS socket failed to connect due to a DNS issue has been fixed, thanks to [@cirospaciari](https://github.com/cirospaciari).
## []()[Thank you to 6 contributors!](bun-v1.1.23.html#thank-you-to-6-contributors)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@cirospaciari](https://github.com/cirospaciari)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@dylan-conway](https://github.com/dylan-conway)
- [@huseeiin](https://github.com/huseeiin)
- [@billywhizz](https://github.com/billywhizz)
* * *
#### [Bun v1.1.22](bun-v1.1.22.html)
#### [Bun v1.1.25](bun-v1.1.25.html)
On this page
- [New features](bun-v1.1.23.html#new-features)
- [`TextEncoderStream` & `TextDecoderStream`](bun-v1.1.23.html#textencoderstream-textdecoderstream)
- [50% faster `console.log(string)`](bun-v1.1.23.html#50-faster-console-log-string)
- [Truncate large arrays in `console.log()`](bun-v1.1.23.html#truncate-large-arrays-in-console-log)
- [`Float16Array`](bun-v1.1.23.html#float16array)
- [Better handling of out-of-memory errors](bun-v1.1.23.html#better-handling-of-out-of-memory-errors)
- [Node.js compatibility improvements](bun-v1.1.23.html#node-js-compatibility-improvements)
- [Fixed: `fs.F_OK`, `fs.R_OK`, `fs.W_OK`, and similar constants](bun-v1.1.23.html#fixed-fs-f-ok-fs-r-ok-fs-w-ok-and-similar-constants)
- [Fixed: `fs.readFile` memory & size limits](bun-v1.1.23.html#fixed-fs-readfile-memory-size-limits)
- [Fixed: Backpressure in 'ws' module](bun-v1.1.23.html#fixed-backpressure-in-ws-module)
- [Cross-runtime IPC on Windows with Node.js](bun-v1.1.23.html#cross-runtime-ipc-on-windows-with-node-js)
- [JIT crashes in `node:vm`](bun-v1.1.23.html#jit-crashes-in-node-vm)
- [Bugfixes](bun-v1.1.23.html#bugfixes)
- [Fixed: Buffering gigabytes of data over `Bun.serve()`](bun-v1.1.23.html#fixed-buffering-gigabytes-of-data-over-bun-serve)
- [Fixed: moving tagged template literals when bundling](bun-v1.1.23.html#fixed-moving-tagged-template-literals-when-bundling)
- [Fixed: AbortSignal with `fetch()` when using custom TLS certificates](bun-v1.1.23.html#fixed-abortsignal-with-fetch-when-using-custom-tls-certificates)
- [Fixed: memory leak when `new Response` threw an error](bun-v1.1.23.html#fixed-memory-leak-when-new-response-threw-an-error)
- [Fixed: crash when importing an empty `.toml` file](bun-v1.1.23.html#fixed-crash-when-importing-an-empty-toml-file)
- [Fixed: Regression with TLS sockets in 1.1.22](bun-v1.1.23.html#fixed-regression-with-tls-sockets-in-1-1-22)
- [Thank you to 6 contributors!](bun-v1.1.23.html#thank-you-to-6-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.25.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.25
* * *
[Ashcon Partovi](https://twitter.com/ashconpartovi) · August 21, 2024
[](../rss.xml)
Bun v1.1.25 is here! This release fixes 42 bugs (addressing 470 👍). Support for `node:cluster` and V8's C++ API. Faster WebAssembly on Windows with OMGJIT. 5x faster S3 uploads with @aws-sdk/client-s3, Worker in standalone executables, and more Node.js compatibility improvements and bug fixes.
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[`node:cluster` support](bun-v1.1.25.html#node-cluster-support)
Bun now supports the [`node:cluster`](https://nodejs.org/api/cluster.html) API.
This allows you to run a pool of Bun workers that share the same port, enabling higher throughput and utilization on machines with many CPU cores. This is great for load balancing in production environments.
> In the next version of Bun
>
> Initial node:cluster support has landed. Here's 1.29 million HTTP requests per second in TypeScript. [pic.twitter.com/YzU1cZxk3S](https://t.co/YzU1cZxk3S)
>
> — Bun (@bunjavascript) [August 18, 2024](https://twitter.com/bunjavascript/status/1825075013877457002?ref_src=twsrc%5Etfw)
Here's an example of how it works:
- The primary worker spawns `n` child workers (usually equal to the number of CPU cores)
- Each child worker listens on the same port (using [`reusePort`](https://lwn.net/Articles/542629/))
- Incoming HTTP requests are load balanced across the child workers
```
import cluster from "node:cluster";
import http from "node:http";
import { cpus } from "node:os";
import process from "node:process";
if (cluster.isPrimary) {
console.log(`Primary ${process.pid} is running`);
// Start N workers for the number of CPUs
for (let i = 0; i < cpus().length; i++) {
cluster.fork();
}
cluster.on("exit", (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} exited`);
});
} else {
// Incoming requests are handled by the pool of workers
// instead of the primary worker.
http
.createServer((req, res) => {
res.writeHead(200);
res.end("hello world\n");
})
.listen(3000);
console.log(`Worker ${process.pid} started`);
}
```
This works with the [`node:http`](https://nodejs.org/api/http.html) APIs, as well as the `Bun.serve()` API.
```
import cluster from "node:cluster";
import { cpus } from "node:os";
if (cluster.isPrimary) {
for (let i = 0; i < cpus().length; i++) {
cluster.fork();
}
} else {
Bun.serve({
port: 3000,
fetch(request) {
return new Response(`Hello from Worker ${process.pid}`);
},
});
}
```
Note that currently, `reusePort` is only effective on Linux. On Windows and macOS, the operating system does not load balance HTTP connections as one would expect.
Thanks to [@nektro](https://github.com/nektro) for implementing this feature!
## []()[Initial V8 C++ API support](bun-v1.1.25.html#initial-v8-c-api-support)
Bun now supports V8's public C++ API, which unblocks packages like `cpu-features` to work in Bun.
This is notable change because Bun is not built on top of [V8](https://v8.dev/) like Node.js. Instead, Bun is built on top of [JavaScriptCore](https://docs.webkit.org/Deep%20Dive/JSC/JavaScriptCore.html), the JavaScript engine that powers Safari.
That means we had to implement our own C++ translation layer between V8's APIs and JavaScriptCore.
src/bun.js/bindings/v8/V8String.cpp
```
#include "v8.h"
#include "V8Primitive.h"
#include "V8MaybeLocal.h"
#include "V8Isolate.h"
namespace v8 {
enum class NewStringType { /* ... */ };
class String : Primitive {
public:
enum WriteOptions { /* ... */ };
BUN_EXPORT static MaybeLocal<String> NewFromUtf8(Isolate* isolate, char const* data, NewStringType type, int length = -1);
BUN_EXPORT int WriteUtf8(Isolate* isolate, char* buffer, int length = -1, int* nchars_ref = nullptr, int options = NO_OPTIONS) const;
BUN_EXPORT int Length() const;
JSC::JSString* localToJSString()
{
return localToObjectPointer<JSC::JSString>();
}
};
}
```
This is difficult engineering work. JavaScriptCore and V8 represent JavaScript values differently. V8 uses a moving, concurrent garbage collector with explicit handle scopes whereas JavaScriptCore uses a non-moving concurrent garbage collector that scans stack memory (sort of like an implicit handle scope).
Before, if you tried to import a package that used these APIs, you would get an error like this:
```
console.log(require("cpu-features")());
```
```
dyld[94465]: missing symbol called
fish: Job 1, 'bun index.ts' terminated by signal SIGABRT (Abort)
```
Now, packages like `cpu-features` can be imported and just work in Bun.
```
$ bun index.ts
{
arch: "aarch64",
flags: {
fp: true,
asimd: true,
// ...
},
}
```
This is just the start of support for V8's internal APIs. If your package runs into an area of the V8 API that we have not yet implemented, you'll receive an error that directs you to upvote an issue on GitHub.
#### Why support V8's internal APIs?
We did not originally intend to support these APIs, but decided to after we found that many [popular](https://github.com/oven-sh/bun/issues/4290) packages depend on these APIs, such as:
- [`cpu-features`](https://www.npmjs.com/package/cpu-features)
- [`node-canvas@v2`](https://www.npmjs.com/package/canvas)
- [`node-sqlite3`](https://www.npmjs.com/package/sqlite3)
- [`libxmljs`](https://www.npmjs.com/package/libxmljs)
- and many packages using [`nan`](https://www.npmjs.com/package/nan)
In this release, only `cpu-features` is supported from the list above, but we're working on improving support so all of these packages and more just work in Bun.
Thanks to [@190n](https://github.com/190n) for implementing this feature!
## []()[5x faster S3 uploads with @aws-sdk/client-s3](bun-v1.1.25.html#5x-faster-s3-uploads-with-aws-sdk-client-s3)
We fixed a bug in our node:http client implementation and that made uploading to S3 5x faster.
> In the next version of Bun
>
> Uploading files via [@aws](https://twitter.com/AWS?ref_src=twsrc%5Etfw)-sdk/client-s3 gets 5x faster [pic.twitter.com/tptxegT7vh](https://t.co/tptxegT7vh)
>
> — Ciro Spaciari (@cirospaciari) [August 21, 2024](https://twitter.com/cirospaciari/status/1826086715393716457?ref_src=twsrc%5Etfw)
## []()[Worker in standalone executables](bun-v1.1.25.html#worker-in-standalone-executables)
Bun's single-file standalone executables now support bundling `Worker` and `node:worker_threads`.
main.ts
my-worker.ts
main.ts
```
console.log("Hello from main thread!");
new Worker("./my-worker.ts");
```
my-worker.ts
```
console.log("Hello from another thread!");
```
To compile a standalone executable with a worker, pass the entry points to `bun build --compile`:
```
bun build --compile ./main.ts ./my-worker.ts
```
This will bundle `my-worker.ts` and `main.ts` as separate entry points in the resulting executable.
### []()[Embedding files in standalone executables without importing](bun-v1.1.25.html#embedding-files-in-standalone-executables-without-importing)
You can now embed files in standalone executables without an explicit `import` statement, if you want.
```
bun build --compile ./main.ts ./public/**/*.png
```
Usually, you'd have to import the file to use it:
```
import logo from "./public/icons/logo.png" with {type: "file"};
```
But, sometimes you want to import a large number of files that may need to programmatically be referenced.
#### Bun.embeddedFiles
The new `Bun.embeddedFiles` API lets you see a list of all embedded files in a standalone executable.
```
import { embeddedFiles } from "bun";
for (const file of embeddedFiles) {
console.log(file.name); // "logo.png"
console.log(file.size); // 1234
console.log(await file.bytes()); // Uint8Array(1234) [...]
}
```
This combines all non-javascript entry points and assets into a single array of `Blob` objects sorted by name.
#### Relative imports for embedded files in standalone executables
You can now reference runtime-known imports of embedded files using relative paths in standalone executables.
```
function getWasmFilePath(file: string) {
return require.resolve(`./${file}.wasm`);
}
const wasmFile = getWasmFilePath("my-wasm-file");
console.log(wasmFile); // "./my-wasm-file.wasm"
```
Previously, this was only supported with statically-analyzable imports that are knonwn at build time. Now, you can do this with any embedded file.
### []()[Faster WebAssembly on Windows with OMGJIT](bun-v1.1.25.html#faster-webassembly-on-windows-with-omgjit)
WebAssembly on Windows now supports JavaScriptCore's optimized Just-In-Time compiler (JIT) called OMGJIT.
> In the next version of Bun
>
> JavaScriptCore's optimizing WebAssembly JIT "OMGJIT" is enabled on Windows, making this wasm hashing benchmark 20% faster [pic.twitter.com/8qhKVS4E6z](https://t.co/8qhKVS4E6z)
>
> — Bun (@bunjavascript) [August 17, 2024](https://twitter.com/bunjavascript/status/1824750540062068815?ref_src=twsrc%5Etfw)
Thanks to Ian Grunert for shipping this feature in WebKit!
## []()[Node.js compatiblity improvements](bun-v1.1.25.html#node-js-compatiblity-improvements)
### []()[`execa` now works](bun-v1.1.25.html#execa-now-works)
We fixed a bug where Bun was not properly supporting `setMaxListeners()` for `EventTarget`. This affected packages like `execa`, which would error out with `undefined is not a function`.
```
import { execa } from "execa";
const { stdout } = await execa`echo "test"`;
```
If you experienced an error that looks like this, it has now been fixed:
```
91 | const controller = new AbortController();
92 | setMaxListeners(Number.POSITIVE_INFINITY, controller.signal);
^
TypeError: undefined is not a function
at node:events:101:30
at spawnSubprocessAsync (/node_modules/execa/lib/methods/main-async.js:92:2)
at execaCoreAsync (/node_modules/execa/lib/methods/main-async.js:26:32)
at index.mjs:3:26
```
### []()[Fixed: Connection hangs with `node:net` after `destroy()`](bun-v1.1.25.html#fixed-connection-hangs-with-node-net-after-destroy)
We fixed a bug where calling `destroy()` on a TCP connection, didn't always properly exit the process, since the event loop was still active. This would sometimes cause packages like `postgres` to hang indefinitely.
```
import net from "node:net";
const server = net.createServer((socket) => {
socket.on("connect", (data) => {
socket.destroy();
// This would destroy the connection,
// but the event loop would still be active
});
});
server.listen(3000);
```
### []()[Fixed: node:net.Socket's ref and unref this](bun-v1.1.25.html#fixed-node-net-socket-s-ref-and-unref-this)
The `ref` and `unref` methods on `node:net.Socket` were not returning the `this` value.
Now, they return `this`.
Thanks to [@nektro](https://github.com/nektro) for fixing this bug!
## []()[Bugfixes](bun-v1.1.25.html#bugfixes)
### []()[Fixed: `TextEncoderStream` yielded the wrong type](bun-v1.1.25.html#fixed-textencoderstream-yielded-the-wrong-type)
In Bun v1.1.23, we introduced support the the `TextEncoderStream` API. We fixed a bug where the chunks from the stream were `Buffer` objects instead of `Uint8Array` objects.
```
const response = await fetch("https://example.com");
const body = response.body.pipeThrough(new TextEncoderStream());
for await (const chunk of body) {
console.log(chunk);
// Before: Buffer
// Now: Uint8Array
}
```
### []()[Fixed: crash with escaped backticks in Bun's shell](bun-v1.1.25.html#fixed-crash-with-escaped-backticks-in-bun-s-shell)
We fixed a crash in Bun's shell that would not properly handle escaped backticks.
```
import { $ } from "bun";
console.log(await $`cd \`find -name dir\``.text());
```
Thanks to [@zackradisic](https://github.com/zackradisic) for fixing this bug!
### []()[Fixed: JIT crash with `TextEncoder`](bun-v1.1.25.html#fixed-jit-crash-with-textencoder)
We fixed a bug where if `TextEncoder` was JIT'd after being run millions of times, it would crash. This was due to a bug in Bun's generated code for enabling the JIT on a function.
### []()[Fixed: Crash in jest.fn and mock()](bun-v1.1.25.html#fixed-crash-in-jest-fn-and-mock)
A crash that could occur when calling functions on a `jest.fn` or `mock()` object with an unexpected `this` value has been fixed.
### []()[Fixed: Crash in IPC](bun-v1.1.25.html#fixed-crash-in-ipc)
When a child process exited before the parent process received a message, a crash could occur in some cases.
This has been fixed, thanks to [@cirospaciari](https://github.com/cirospaciari).
### []()[Fixed: console.log a File's name](bun-v1.1.25.html#fixed-console-log-a-file-s-name)
When you use the web `File` constructor to create a Blob, the name of the file was not being included in the output of `console.log`.
Input:
```
console.log(new File(["hello world"], "hello.txt"));
```
New:
```
File (11 bytes) {
name: "hello.txt",
lastModified: 1724218333315
}
```
Previously:
```
Blob (11 bytes)
```
### []()[Fixed: rare crash in websocket server](bun-v1.1.25.html#fixed-rare-crash-in-websocket-server)
A rare crash that could potentially occur when a long amount of time has passed since the server has called a callback and the `ServerWebSocket` object has been garbage collected has been fixed.
## []()[Thank you to 11 contributors!](bun-v1.1.25.html#thank-you-to-11-contributors)
- [@190n](https://github.com/190n)
- [@cirospaciari](https://github.com/cirospaciari)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Electroid](https://github.com/Electroid)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@MARCROCK22](https://github.com/MARCROCK22)
- [@mroyme](https://github.com/mroyme)
- [@nektro](https://github.com/nektro)
- [@oddyamill](https://github.com/oddyamill)
- [@paperclover](https://github.com/paperclover)
- [@vktrl](https://github.com/vktrl)
- [@zackradisic](https://github.com/zackradisic)
* * *
#### [Bun v1.1.23](bun-v1.1.23.html)
#### [Bun v1.1.26](bun-v1.1.26.html)
On this page
- [`node:cluster` support](bun-v1.1.25.html#node-cluster-support)
- [Initial V8 C++ API support](bun-v1.1.25.html#initial-v8-c-api-support)
- [5x faster S3 uploads with @aws-sdk/client-s3](bun-v1.1.25.html#5x-faster-s3-uploads-with-aws-sdk-client-s3)
- [Worker in standalone executables](bun-v1.1.25.html#worker-in-standalone-executables)
- [Embedding files in standalone executables without importing](bun-v1.1.25.html#embedding-files-in-standalone-executables-without-importing)
- [Faster WebAssembly on Windows with OMGJIT](bun-v1.1.25.html#faster-webassembly-on-windows-with-omgjit)
- [Node.js compatiblity improvements](bun-v1.1.25.html#node-js-compatiblity-improvements)
- [`execa` now works](bun-v1.1.25.html#execa-now-works)
- [Fixed: Connection hangs with `node:net` after `destroy()`](bun-v1.1.25.html#fixed-connection-hangs-with-node-net-after-destroy)
- [Fixed: node:net.Socket's ref and unref this](bun-v1.1.25.html#fixed-node-net-socket-s-ref-and-unref-this)
- [Bugfixes](bun-v1.1.25.html#bugfixes)
- [Fixed: `TextEncoderStream` yielded the wrong type](bun-v1.1.25.html#fixed-textencoderstream-yielded-the-wrong-type)
- [Fixed: crash with escaped backticks in Bun's shell](bun-v1.1.25.html#fixed-crash-with-escaped-backticks-in-bun-s-shell)
- [Fixed: JIT crash with `TextEncoder`](bun-v1.1.25.html#fixed-jit-crash-with-textencoder)
- [Fixed: Crash in jest.fn and mock()](bun-v1.1.25.html#fixed-crash-in-jest-fn-and-mock)
- [Fixed: Crash in IPC](bun-v1.1.25.html#fixed-crash-in-ipc)
- [Fixed: console.log a File's name](bun-v1.1.25.html#fixed-console-log-a-file-s-name)
- [Fixed: rare crash in websocket server](bun-v1.1.25.html#fixed-rare-crash-in-websocket-server)
- [Thank you to 11 contributors!](bun-v1.1.25.html#thank-you-to-11-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.26.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.26
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · August 24, 2024
[](../rss.xml)
Bun v1.1.26 is here! This release fixes 9 bugs (addressing 652 👍). `bun outdated` shows outdated dependencies. `Bun.serve()` gets a new `idleTimeout` option for socket timeouts, and `subscriberCount(topic: string)` for a count of websocket clients subscribed to a topic. bun test.only skips all other tests. expect.assertions(n) in async functionn is fixed. "use strict" in CommonJS modules is now preserved. Plus, more node.js compatibility improvements and bug fixes.
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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 outdated` shows outdated dependencies](bun-v1.1.26.html#bun-outdated-shows-outdated-dependencies)
`bun outdated` is a new subcommand that shows you which dependencies are outdated.
```
bun outdated
```
> In the next version of Bun
>
> bun outdated lists outdated dependencies, their semver-matching versions, and the latest version [pic.twitter.com/7pKSSdQfGK](https://t.co/7pKSSdQfGK)
>
> — Bun (@bunjavascript) [August 23, 2024](https://twitter.com/bunjavascript/status/1826800196837409209?ref_src=twsrc%5Etfw)
The `Update` column displays what the next semver-matching version is. The `Latest` column displays the `latest` tagged version from the npm registry.
This was one of the top most upvoted issues on Bun's GitHub repository. Huge thanks to [@dylan-conway](https://github.com/dylan-conway) for implementing this feature!
## []()[`test.only` skips all other tests](bun-v1.1.26.html#test-only-skips-all-other-tests)
Previously, the following would run the first two tests, and skip the third test. This was very confusing! Why did we do it this way!?
```
import { test, describe } from "bun:test";
test("i should not run!", () => {
// previously: runs
// now: does not run
console.log("why am i running?");
});
// ... more tests in a much longer file ...
test.only("i should run!", () => {
// runs
console.log("yes only i should run");
});
test("I definitely should not run!", () => {
// does not run
console.log("i don't run");
});
```
This was really frustrating because the only way around it was the `--only` CLI flag.
```
bun test --only
```
Now, you don't have to do that. `bun test` will detect there was a `.only` test in the file and skip all the tests that don't have `.only` in them.
The existence of a `.only` test in a file is also reset when the next module starts loading tests. This means that a `.only` will only impact the current file instead of all files.
### []()[subscriberCount(topic: string) in Bun.serve()](bun-v1.1.26.html#subscribercount-topic-string-in-bun-serve)
`Bun.serve()`'s builtin-in WebSocket server now supports `subscriberCount(topic: string)` to get the number of websocket clients subscribed to a topic.
```
import { serve } from "bun";
const server = serve({
port: 3002,
websocket: {
open(ws) {
const count = server.subscriberCount("chat");
ws.subscribe("chat");
ws.publish(`chat`, `🐰 #${count} joined the chat`);
},
},
fetch(req, server) {
return server.upgrade(req);
},
});
```
### []()[`idleTimeout` in `Bun.serve()`](bun-v1.1.26.html#idletimeout-in-bun-serve)
You can now set a custom idle timeout (in seconds) for Bun.serve()'s builtin-in HTTP(s) server.
```
import { serve } from "bun";
const server = serve({
async fetch(req) {
await Bun.sleep(1000 * 60 * 2); // 2 minutes
return new Response("Hello, it's been 2 minutes!");
},
// minutes:
idleTimeout: 60 * 4, // 4 minutes
});
```
Previously, this was always set to 10 seconds. The default continues to be 10 seconds, but in cases where you need that to be a longer or shorter amount of time, you can now set it to a different value.
This option was previously only available for connected WebSocket clients, and now it's available for regular HTTP(s) requests as well.
Thanks to [@cirospaciari](https://github.com/cirospaciari) for implementing this feature!
### []()[Fixed: `expect.assertions(n)` in async functions](bun-v1.1.26.html#fixed-expect-assertions-n-in-async-functions)
`expect.assertions(n: number)` now works as expected in async functions.
The following test that should've failed previously would not have failed.
```
import { test, expect } from "bun:test";
test("this test should NOT pass", async () => {
expect.assertions(1);
await Bun.sleep(2);
// the assertion is commented out.
// so this test should always fail.
// expect(1).toBe(1);
});
```
Now, the test will fail:
```
bun test
```
```
bun test v1.1.26
passy.test.ts:
AssertionError: expected 1 assertions, but test ended with 0 assertions
✗ this test should NOT pass [3.57ms]
0 pass
1 fail
Ran 1 tests across 1 files. [8.00ms]
```
### []()[`expect().toThrow()` supports asymmetric matchers](bun-v1.1.26.html#expect-tothrow-supports-asymmetric-matchers)
You can now use `expect().toThrow()` with asymmetric matchers like `expect.objectContaining()`:
```
import { test, expect } from "bun:test";
test("this test should NOT pass", () => {
expect(() => {
const error = new Error("oh no!");
error.code = "ERR_OH_NO";
throw error;
}).toThrow(expect.objectContaining({ message: "oh no!", code: "ERR_OH_NO" }));
});
```
### []()[Fixed: `done` callback in tests causing a hang](bun-v1.1.26.html#fixed-done-callback-in-tests-causing-a-hang)
Previously, there were a number of cases where using a `done` callback in `test` would cause the test to hang indefinitely when not called.
For example, this test would fail and then hang forever:
```
import { test, expect } from "bun:test";
test("this test should NOT hang", (done) => {
process.nextTick(() => {
throw new Error("oh no!");
done();
});
});
```
One could argue, "The `done` callback was never called! It's only logical that it would hang forever!" but that's not the case. The test already failed. It had an uncaught exception. Therefore, the test does not need to hang forever (or timeout). It can fail immediately once all microtasks have been drained and the task queue is empty.
In other words, tests will continue running once all other known work is complete instead of waiting for the `done` callback to be called after an exception is thrown.
### []()[Fixed: mock().mockName() not returning `this`](bun-v1.1.26.html#fixed-mock-mockname-not-returning-this)
The `mock()` function in Bun's test runner now returns `this`. This is to align the behavior with jest so that existing tests written for jest can be ported to Bun.
## []()[Node.js compatibility improvements](bun-v1.1.26.html#node-js-compatibility-improvements)
### []()[Fixed: Top-level `"use strict"` in CommonJS modules preserved at runtime](bun-v1.1.26.html#fixed-top-level-use-strict-in-commonjs-modules-preserved-at-runtime)
Previously, Bun would strip a top-level `"use strict"` directive from CommonJS modules at runtime. This was intended for ES modules as it is unnecessary in those cases, but it IS necessary for CommonJS modules and is now fixed.
Preivously, the following code would print "I am globalThis" in Node.js, and "I am undefined" in Bun.
```
// Before:
"use strict";
function whoami() {
return this;
}
const me = whoami();
if (me === globalThis) {
console.log("I am globalThis!");
} else {
console.log("I am undefined!");
}
exports.whoami = whoami;
```
Now, it prints "I am globalThis" in both Node.js and Bun.
### []()[Fixed: util.inherits bug](bun-v1.1.26.html#fixed-util-inherits-bug)
A bug where `util.inherits` was using `Object.create` instead of `Object.setPrototypeOf` has been fixed. This caused the snowflake sdk to fail to load.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this bug!
### []()[Fixed: crypto.randomValues() crash in certain cases](bun-v1.1.26.html#fixed-crypto-randomvalues-crash-in-certain-cases)
A rare JIT-related crash in `crypto.randomValues()` has been fixed.
### []()[Fixed: crash in Buffer in certain cases](bun-v1.1.26.html#fixed-crash-in-buffer-in-certain-cases)
A rare crash in `Buffer` found while running the Node.js test suite has been fixed.
### []()[Fixed: `ERR_INVALID_THIS` code returned in certain web APIs](bun-v1.1.26.html#fixed-err-invalid-this-code-returned-in-certain-web-apis)
Node.js' test suite expects certain web APIs to return an error with the `ERR_INVALID_THIS` `code` property.
For compatibility, Bun now returns these errors with the `ERR_INVALID_THIS` code.
### []()[Fixed: dns.resolveSrv confusing `weight` and `priority`](bun-v1.1.26.html#fixed-dns-resolvesrv-confusing-weight-and-priority)
A bug where the `priority` field was being set to the `weight` field in `dns.resolveSrv` has been fixed, thanks to [@cirospaciari](https://github.com/cirospaciari).
### []()[Fixed: rare crash in fetch()](bun-v1.1.26.html#fixed-rare-crash-in-fetch)
A rare crash in `fetch()` involving AbortSignal has been fixed, thanks to [@cirospaciari](https://github.com/cirospaciari).
### []()[Thanks to 3 contributors!](bun-v1.1.26.html#thanks-to-3-contributors)
- [@cirospaciari](https://github.com/cirospaciari)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
* * *
#### [Bun v1.1.25](bun-v1.1.25.html)
#### [Bun v1.1.27](bun-v1.1.27.html)
On this page
- [`bun outdated` shows outdated dependencies](bun-v1.1.26.html#bun-outdated-shows-outdated-dependencies)
- [`test.only` skips all other tests](bun-v1.1.26.html#test-only-skips-all-other-tests)
- [subscriberCount(topic: string) in Bun.serve()](bun-v1.1.26.html#subscribercount-topic-string-in-bun-serve)
- [`idleTimeout` in `Bun.serve()`](bun-v1.1.26.html#idletimeout-in-bun-serve)
- [Fixed: `expect.assertions(n)` in async functions](bun-v1.1.26.html#fixed-expect-assertions-n-in-async-functions)
- [`expect().toThrow()` supports asymmetric matchers](bun-v1.1.26.html#expect-tothrow-supports-asymmetric-matchers)
- [Fixed: `done` callback in tests causing a hang](bun-v1.1.26.html#fixed-done-callback-in-tests-causing-a-hang)
- [Fixed: mock().mockName() not returning `this`](bun-v1.1.26.html#fixed-mock-mockname-not-returning-this)
- [Node.js compatibility improvements](bun-v1.1.26.html#node-js-compatibility-improvements)
- [Fixed: Top-level `"use strict"` in CommonJS modules preserved at runtime](bun-v1.1.26.html#fixed-top-level-use-strict-in-commonjs-modules-preserved-at-runtime)
- [Fixed: util.inherits bug](bun-v1.1.26.html#fixed-util-inherits-bug)
- [Fixed: crypto.randomValues() crash in certain cases](bun-v1.1.26.html#fixed-crypto-randomvalues-crash-in-certain-cases)
- [Fixed: crash in Buffer in certain cases](bun-v1.1.26.html#fixed-crash-in-buffer-in-certain-cases)
- [Fixed: `ERR_INVALID_THIS` code returned in certain web APIs](bun-v1.1.26.html#fixed-err-invalid-this-code-returned-in-certain-web-apis)
- [Fixed: dns.resolveSrv confusing `weight` and `priority`](bun-v1.1.26.html#fixed-dns-resolvesrv-confusing-weight-and-priority)
- [Fixed: rare crash in fetch()](bun-v1.1.26.html#fixed-rare-crash-in-fetch)
- [Thanks to 3 contributors!](bun-v1.1.26.html#thanks-to-3-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.27.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.27
* * *
[Chloe Caruso](https://github.com/paperclover) · September 7, 2024
[](../rss.xml)
Bun v1.1.27 is here! This release fixes 130 bugs (addressing 250 👍). `bun pm pack`, faster `node:zlib`. Static routes in Bun.serve(). ReadableStream support in response.clone() & request.clone(). Per-request timeouts. Cancel method in ReadableStream is called. `bun run` handles CTRL + C better. Faster buffered streams. `bun outdated` package filtering. Watch arbtirary file types in --hot and --watch. Fixes to proxies on Windows. Several Node.js compatibility improvements.
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[Native `node:zlib`](bun-v1.1.27.html#native-node-zlib)
We rewrote `node:zlib` to use native code.
Runtimenode:zlibStream (MB/s)Sync (MB/s)Bun v1.1.27`deflate`32.79 MB/s14.82 MB/sNode v22.5.1`deflate`15.50 MB/s31.39 MB/sBun v1.1.26`deflate`15.59 MB/s10.29 MB/sBun v1.1.27`deflateRaw`32.68 MB/s14.60 MB/sNode v22.5.1`deflateRaw`19.77 MB/s31.41 MB/sBun v1.1.26`deflateRaw`15.67 MB/s10.38 MB/sBun v1.1.27`gunzip`87.72 MB/s107.60 MB/sBun v1.1.26`gunzip`46.49 MB/s42.74 MB/sNode v22.5.1`gunzip`31.01 MB/s75.86 MB/sBun v1.1.27`gzip`32.69 MB/s14.91 MB/sNode v22.5.1`gzip`18.46 MB/s31.10 MB/sBun v1.1.26`gzip`15.29 MB/s10.11 MB/sBun v1.1.27`inflate`87.79 MB/s102.86 MB/sBun v1.1.26`inflate`50.72 MB/s43.83 MB/sNode v22.5.1`inflate`26.07 MB/s74.64 MB/sBun v1.1.27`inflateRaw`87.68 MB/s101.78 MB/sBun v1.1.26`inflateRaw`53.89 MB/s43.13 MB/sNode v22.5.1`inflateRaw`33.35 MB/s75.02 MB/s
Via a [third-party zlib benchmark](https://github.com/timotejroiko/zlib-benchmark) on a Linux x64 Hetzner server.
There's still more to do to optimize `node:zlib` in Bun, but this is a good start.
Big thanks to [@nektro](https://github.com/nektro) for implementing this.
## []()[New command: `bun pm pack`](bun-v1.1.27.html#new-command-bun-pm-pack)
> In the next version of Bun
>
> bun pm pack creates an npm package tarball for publishing or installing locally [pic.twitter.com/RdXdyzI3He](https://t.co/RdXdyzI3He)
>
> — Bun (@bunjavascript) [September 7, 2024](https://twitter.com/bunjavascript/status/1832386689182122092?ref_src=twsrc%5Etfw)
`bun pm pack` is designed to be a drop-in replacement for `npm pack`.
## []()[New in `Bun.serve()` (HTTP server)](bun-v1.1.27.html#new-in-bun-serve-http-server)
This release introduces reliability and quality of life improvements to `Bun.serve()`, our fast HTTP server.
### []()[Static routes](bun-v1.1.27.html#static-routes)
You can now pass a `static` option to serve static `Response` objects for a path.
```
Bun.serve({
static: {
"/api/health-check": new Response("🟢"),
"/old-link": Response.redirect("/new-link", 301),
"/api/version": Response.json(
{
app: require("./package.json").version,
bun: Bun.version,
},
{
headers: {
"X-Powered-By": "bun",
},
},
),
},
async fetch(req) {
return new Response("Dynamic!");
},
});
```
### []()[ReadableStream support in `request.clone()` and `response.clone()`](bun-v1.1.27.html#readablestream-support-in-request-clone-and-response-clone)
Cloning a streaming `Request` or `Response` is now supported via [`request.clone()`](https://developer.mozilla.org/en-US/docs/Web/API/Request/clone) and [`response.clone()`](https://developer.mozilla.org/en-US/docs/Web/API/Response/clone).
To clone a request from `Bun.serve`:
```
Bun.serve({
async fetch(req, server) {
const cloned = req.clone();
await req.json();
// Previously, this would be empty.
await cloned.json();
// ... rest of the code
},
});
```
To clone a Response from `fetch`:
```
const response = await fetch("https://example.com");
const cloned = response.clone();
console.log(await response.text());
console.log(await cloned.text());
```
Previously, this was only supported for static responses like when passing a string, an ArrayBuffer, or a Blob to the `Response` constructor.
### []()[The "cancel" method in ReadableStream](bun-v1.1.27.html#the-cancel-method-in-readablestream)
When a request is aborted, Bun now calls the `cancel` method in `ReadableStream` .
```
import { serve } from "bun";
serve({
async fetch(req, server) {
req.signal.addEventListener("abort", () => {
// Previously, AbortSignal was the only way to detect if a request was aborted.
console.log("Request aborted");
});
return new Response(
new ReadableStream({
async pull(controller) {
controller.enqueue("Hello World");
await Bun.sleep(1000);
},
cancel() {
// New! Called when the request is aborted.
console.log("Stream cancelled");
},
}),
);
},
});
```
### []()[Per-request timeouts](bun-v1.1.27.html#per-request-timeouts)
The new `server.timeout(request: Request, seconds: number)` method allows you to set a timeout per specific HTTP request.
To set a 60 second timeout for a request:
```
Bun.serve({
async fetch(req, server) {
server.timeout(req, 60); // 60 seconds
await req.formData();
return new Response("Slow response");
},
});
```
Thanks to [@cirospaciari](https://github.com/cirospaciari) for implementing this.
### []()[Faster buffered streams](bun-v1.1.27.html#faster-buffered-streams)
We didn't just add new features to `Bun.serve()` this release. We also made it faster.
> In the next version of Bun
>
> The fast path in request.json() & similar methods now works after accessing “.body”
>
> New: 65,000 req/s
> Prev: 29,000 req/s [pic.twitter.com/2EqYyCoq4G](https://t.co/2EqYyCoq4G)
>
> — Jarred Sumner (@jarredsumner) [September 3, 2024](https://twitter.com/jarredsumner/status/1830900845778743450?ref_src=twsrc%5Etfw)
### []()[New CLI flag: `--max-http-header-size`](bun-v1.1.27.html#new-cli-flag-max-http-header-size)
Passing `--max-http-header-size` sets the size of the HTTP request header buffer.
https://github.com/oven-sh/bun/pull/13577
### []()[Fixed: `server.requestIP` after `await`](bun-v1.1.27.html#fixed-server-requestip-after-await)
Previously, using `server.requestIP` after a callback or call to `await` would lose the request metadata. This has been fixed.
```
Bun.serve({
port: 3000,
async fetch(req, server) {
console.log(server.requestIP(req));
// { address: '127.0.0.1', family: 'IPv4', ... }
await req.formData();
console.log(server.requestIP(req));
// now: { address: '127.0.0.1', family: 'IPv4', ... }
// before: undefined
},
});
```
### []()[Fixed: `ws.publish` on a closed WebSocket](bun-v1.1.27.html#fixed-ws-publish-on-a-closed-websocket)
In `Bun.serve`, calling `.publish` on a websocket will send a message to all clients except the websocket itself. When using this in the `close` handler, the WebSocket was already closed and no message could be sent. This has now been fixed.
Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this.
### []()[Fixed: memory leak when accessing request body and buffered methods](bun-v1.1.27.html#fixed-memory-leak-when-accessing-request-body-and-buffered-methods)
A memory leak has been fixed in code like the below:
```
Bun.serve({
async fetch(req) {
if (req.body) {
await req.json();
}
// ... rest of the code
},
});
```
When the `Request` body's `ReadableStream` was accessed, in certain cases a buffering method like `req.json` may use a different implementation and the `Request` object was incorrectly holding a strong reference to the `Promise` returned by `req.json` in those cases, leaking memory.
While adding clone() support for streams, we revised the implementation of `Request` and `Response` to fix this and similar issues.
## []()[`bun outdated` filtering](bun-v1.1.27.html#bun-outdated-filtering)
`bun outdated` now has `--filter`, which allows you to choose which workspaces you want to audit for outdated packages.
```
# Path patterns:
# Matches all workspaces in `./packages`
```
```
bun outdated --filter="./packages/*"
```
```
# Name patterns:
# All workspaces with names starting with `pkg`
```
```
bun outdated --filter="pkg*"
```
```
# All workspaces excluding `pkg1`
```
```
bun outdated --filter="*" --filter="!pkg1"
```
Additionally, positional arguments filter the list of dependencies, which can be helpful if you only want to check certain packages for updates.
```
# All dependencies starting with `is-` (could display `is-even`, `is-odd`, ...)
```
```
bun outdated "is-*"
```
```
# All dependencies from a particular scope
```
```
bun outdated "@discordjs/*"
```
```
# With `--filter`. Matches all outdated `jquery` dependencies in all workspaces.
```
```
bun outdated jquery --filter="*"
```
## []()[`bun run` Ctrl + C behavior is fixed](bun-v1.1.27.html#bun-run-ctrl-c-behavior-is-fixed)
`bun run` wasn't propagating POSIX signals from the `bun` process to the child process (only from child -> parent). This led to strange bugs in certain cases, like CTRL + C not exiting the child process until later when an I/O error occurs from reading stdin on a disconnected terminal. This visually manifested as the `^[[A` character appearing when you press ↑ Up instead of the previous command.
This has been fixed.
> In the next version of Bun
>
> A bug where the following would sometimes print ^[[A is fixed
> 1. bun run <package.json script>
> 2. Ctrl + C
> 3. ↑ Up [pic.twitter.com/7YlR2knMLh](https://t.co/7YlR2knMLh)
>
> — Jarred Sumner (@jarredsumner) [September 6, 2024](https://twitter.com/jarredsumner/status/1831935501252882675?ref_src=twsrc%5Etfw)
Thanks to [@xales](https://github.com/xales) for debugging this.
## []()[Watch arbitrary file types in `--watch` and `--hot`](bun-v1.1.27.html#watch-arbitrary-file-types-in-watch-and-hot)
Bun's builtin watch & hot reloading now supports watching arbitrary file types.
To watch a file, import it.
```
import "./tailwind.css";
// ... rest of my app
```
Bun's watcher relies on the module graph to determine which files trigger a reload. This reduces unnecessary reloads, improving your iteration cycle time.
Previously, only JavaScript, TypeScript, JSON, TOML and .txt files were watched. Now, Bun will watch any file that is imported regardless of file extension.
### []()[Fixed: Default `idleTimeout` no longer set in node:http](bun-v1.1.27.html#fixed-default-idletimeout-no-longer-set-in-node-http)
In Bun 1.1.26, the default `idleTimeout` was 10 seconds, which was a breaking change as versions before had unlimited timeout. The default value of `idleTimeout` is now `0`, which disables the timeout.
## []()[Node.js compatibility improvements](bun-v1.1.27.html#node-js-compatibility-improvements)
This release also includes a number of Node.js compatibility improvements.
### []()[Fixed: Crash while throwing an exception from N-API](bun-v1.1.27.html#fixed-crash-while-throwing-an-exception-from-n-api)
A bug causing a crash in N-API when an exception was thrown has been fixed.
### []()[Fixed: Crash in N-API when accessing heap-allocated JSValue](bun-v1.1.27.html#fixed-crash-in-n-api-when-accessing-heap-allocated-jsvalue)
JavaScriptCore & V8 are different engines with different approaches to garbage collection. JavaScriptCore scans the stack. V8 relies on handle scopes.
Previously, Bun didn't implement handle scopes. This led to crashes in N-API packages like DuckDB that heap-allocate napi values without referencing them in stack memory. The garbage collector wouldn't see them, and clean up the memory prematurely.
Thanks to [@190n](https://github.com/190n) for implementing handle scopes.
### []()[Fixed: Crash impacting Next.js middleware](bun-v1.1.27.html#fixed-crash-impacting-next-js-middleware)
A crash in `node:vm` when using a class extending a built-in class like `URL` or `Response` inside of `node:vm` has been fixed. This crash was reproducible in Next.js middleware.
### []()[Fixed: Missing `ERR_INVALID_ARG_TYPE` in some `Buffer` methods](bun-v1.1.27.html#fixed-missing-err-invalid-arg-type-in-some-buffer-methods)
In `Buffer.isAscii` and `Buffer.isUtf8`, the error thrown when given invalid arguments now properly includes `code: "ERR_INVALID_ARG_TYPE"`.
### []()[Fixed: Missing `ERR_INVALID_URL` in `new URL`](bun-v1.1.27.html#fixed-missing-err-invalid-url-in-new-url)
To match Node.js, the error thrown by `new URL` when giving an invalid URL now includes `code: "ERR_INVALID_URL"`
### []()[Fixed: `AES-GCM` encryption of empty messages](bun-v1.1.27.html#fixed-aes-gcm-encryption-of-empty-messages)
Thanks to [@wpaulino](https://github.com/wpaulino), an empty message now properly round-trips in `AES-GCM` encryption.
### []()[Fixed: `util.promisify` with `crypto.generateKeyPair`](bun-v1.1.27.html#fixed-util-promisify-with-crypto-generatekeypair)
Thanks to [@wpaulino](https://github.com/wpaulino), calling `util.promisify` on `crypto.generateKeyPair` will now return the proper promisified function.
### []()[Fixed: Handling out-of-memory errors in `Buffer`](bun-v1.1.27.html#fixed-handling-out-of-memory-errors-in-buffer)
When converting a large string to a `Buffer`, Bun now handles out-of-memory errors by throwing an `OutOfMemoryError` instead of crashing.
### []()[Fixed: `node:tls` accepting an arbitrary stream for a TLS socket. Fixed `mssql` package](bun-v1.1.27.html#fixed-node-tls-accepting-an-arbitrary-stream-for-a-tls-socket-fixed-mssql-package)
The `tls.connect` function from `node:tls` accepts a `socket` option. This lets you upgrade any `net.Socket` to TLS. However, this parameter can actually be any arbitrary `stream.Duplex`, which Bun previously did not support, as it relies the underlying network connection to engage in TLS more efficiently.
This resolves the `mssql` package throwing `Error: socket must be an instance of net.Socket` when used.
Thanks to [@cirospaciari](https://github.com/cirospaciari)
### []()[Fixed: `node:http` agent ignored](bun-v1.1.27.html#fixed-node-http-agent-ignored)
In certain cases, the `node:http` agent was not being used. This has been fixed.
Thanks to [@nektro](https://github.com/nektro)
### []()[Fixed: `node:http` setTimeout & server.setTimeout ignored](bun-v1.1.27.html#fixed-node-http-settimeout-server-settimeout-ignored)
With `server.timeout` now implemented, we've also added support for `server.setTimeout` and `request.setTimeout` in `node:http`.
Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this.
### []()[Fixed: `node:vm` inconsistencies](bun-v1.1.27.html#fixed-node-vm-inconsistencies)
Various subtle mistakes in `node:vm` have been fixed:
- `vm.runInThisContext` now operates in global context
- `script.runInNewContext` now operates in it's own context
- `script.runInThisContext` and `vm.runInThisContext` don't take context as an argument
- `vm.runInThisContext`, `vm.runInContext`, and `vm.runInContext` take a string as the options argument.
Thanks to [@SunsetTechuila](https://github.com/SunsetTechuila) for fixing these!
### []()[Fixed: Missing `net.Socket.destroySoon`](bun-v1.1.27.html#fixed-missing-net-socket-destroysoon)
Previously, this method in `node:net` was undefined. This is now fixed.
## []()[fetch reliability improvements](bun-v1.1.27.html#fetch-reliability-improvements)
### []()[Proxies in fetch() on Windows work better now](bun-v1.1.27.html#proxies-in-fetch-on-windows-work-better-now)
On Windows, using a proxy with `fetch` often led to `error: Syscall` being thrown.
This has been resolved thanks to [@cirospaciari](https://github.com/cirospaciari).
### []()[Fixed: a memory leak with `FormData` or `URLSearchParams` body](bun-v1.1.27.html#fixed-a-memory-leak-with-formdata-or-urlsearchparams-body)
In Bun v1.1.25, a regression was introduced where sending `FormData` and `URLSearchParams` in the body of a `fetch()` request would leak memory. This regression is now fixed.
## []()[Lots more fixes](bun-v1.1.27.html#lots-more-fixes)
### []()[Fixed: Reading large files `Bun.file` was truncated](bun-v1.1.27.html#fixed-reading-large-files-bun-file-was-truncated)
When reading a file over 4gb into a single `ArrayBuffer`, the buffer would be truncated to 4gb. This has now been fixed.
### []()[Fixed: Clearing screen in some terminals](bun-v1.1.27.html#fixed-clearing-screen-in-some-terminals)
The ANSI escape code used to clear the terminal screen has been changed from `\x1b[H\x1b[2J` to `\x1B[2J\x1B[3J\x1B[H`, which is compatible with more terminals. Most notably, this fixes Visual Studio Code's terminal, which did not fully clear before this change.
Thanks to [@jakebailey](https://github.com/jakebailey) for fixing this.
### []()[Fixed: Handling out-of-memory errors in `Bun.escapeHTML`](bun-v1.1.27.html#fixed-handling-out-of-memory-errors-in-bun-escapehtml)
When giving large enough strings to `Bun.escapeHTML`, it will now throw an `OutOfMemoryError` instead of crashing.
### []()[`Bun.deepEquals` performance improvements for `Map` and `Set`](bun-v1.1.27.html#bun-deepequals-performance-improvements-for-map-and-set)
After a the WebKit upgrade for Bun v1.1.19, the implementation of `Map` and `Set` changed to the point we had to remove their fast paths in `Bun.deepEquals`. Thanks to [@wpaulino](https://github.com/wpaulino), a new fast path has been added, which is better than what was previously in place.
Additionally, the fast path covers custom classes that extend `Map` or `Set`, giving them nearly indistinguishable performance in `Bun.deepEquals` from the base class itself.
### []()[Fixed: `Failed to link package: EBUSY` on Windows](bun-v1.1.27.html#fixed-failed-to-link-package-ebusy-on-windows)
In bun install, an issue updating package binaries while they are currently open has been fixed
Thanks to [@dylan-conway](https://github.com/dylan-conway)
### []()[Fixed: LCOV reporter properly reports non-hit lines](bun-v1.1.27.html#fixed-lcov-reporter-properly-reports-non-hit-lines)
Bun's LCOV reporter previously would sometimes report `100%` line coverage when that wasnt always the case. This has now been fixed thanks to [@fmorency](https://github.com/fmorency).
### []()[Fixed: `bun add -g` postinstall message](bun-v1.1.27.html#fixed-bun-add-g-postinstall-message)
When installing a global package with a blocked postinstall script, the message will now include the correct command:
```
$ bun install -g @delance/runtime
bun add v1.1.27
installed @delance/runtime@2024.8.103 with binaries:
- delance-langserver
68 packages installed [1.98s]
-Blocked 1 postinstall. Run `bun pm untrusted` for details.
+Blocked 1 postinstall. Run `bun pm -g untrusted` for details.
```
Thanks to [@RiskyMH](https://github.com/RiskyMH) for fixing this
### []()[Fixed: Race condition in `Bun.build`](bun-v1.1.27.html#fixed-race-condition-in-bun-build)
A race condition causing a `Bun.build` promise to hang has been fixed. This could be caused if you queued many `Bun.build` calls in a short period of time.
### []()[Fixed: bun shell not keeping parent process alive](bun-v1.1.27.html#fixed-bun-shell-not-keeping-parent-process-alive)
A bug where the following code would exit prematurely, wtihout printing "never reached!!! why!!" has been fixed.
```
import { $ } from "bun";
console.log("before shell");
(async function () {
await `echo hi`;
console.log("never reached!!! why!!");
})();
```
## []()[Thanks to 17 contributors!](bun-v1.1.27.html#thanks-to-17-contributors)
- [@17hz](https://github.com/17hz)
- [@190n](https://github.com/190n)
- [@xales](https://github.com/xales)
- [@nektro](https://github.com/nektro)
- [@RiskyMH](https://github.com/RiskyMH)
- [@fmorency](https://github.com/fmorency)
- [@wpaulino](https://github.com/wpaulino)
- [@mohit-s96](https://github.com/mohit-s96)
- [@Nanome203](https://github.com/Nanome203)
- [@jakebailey](https://github.com/jakebailey)
- [@sacsbrainz](https://github.com/sacsbrainz)
- [@jakeboone02](https://github.com/jakeboone02)
- [@cirospaciari](https://github.com/cirospaciari)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Marukome0743](https://github.com/Marukome0743)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@SunsetTechuila](https://github.com/SunsetTechuila)
* * *
#### [Bun v1.1.26](bun-v1.1.26.html)
#### [Bun v1.1.28](bun-v1.1.28.html)
On this page
- [Native `node:zlib`](bun-v1.1.27.html#native-node-zlib)
- [New command: `bun pm pack`](bun-v1.1.27.html#new-command-bun-pm-pack)
- [New in `Bun.serve()` (HTTP server)](bun-v1.1.27.html#new-in-bun-serve-http-server)
- [Static routes](bun-v1.1.27.html#static-routes)
- [ReadableStream support in `request.clone()` and `response.clone()`](bun-v1.1.27.html#readablestream-support-in-request-clone-and-response-clone)
- [The "cancel" method in ReadableStream](bun-v1.1.27.html#the-cancel-method-in-readablestream)
- [Per-request timeouts](bun-v1.1.27.html#per-request-timeouts)
- [Faster buffered streams](bun-v1.1.27.html#faster-buffered-streams)
- [New CLI flag: `--max-http-header-size`](bun-v1.1.27.html#new-cli-flag-max-http-header-size)
- [Fixed: `server.requestIP` after `await`](bun-v1.1.27.html#fixed-server-requestip-after-await)
- [Fixed: `ws.publish` on a closed WebSocket](bun-v1.1.27.html#fixed-ws-publish-on-a-closed-websocket)
- [Fixed: memory leak when accessing request body and buffered methods](bun-v1.1.27.html#fixed-memory-leak-when-accessing-request-body-and-buffered-methods)
- [`bun outdated` filtering](bun-v1.1.27.html#bun-outdated-filtering)
- [`bun run` Ctrl + C behavior is fixed](bun-v1.1.27.html#bun-run-ctrl-c-behavior-is-fixed)
- [Watch arbitrary file types in `--watch` and `--hot`](bun-v1.1.27.html#watch-arbitrary-file-types-in-watch-and-hot)
- [Fixed: Default `idleTimeout` no longer set in node:http](bun-v1.1.27.html#fixed-default-idletimeout-no-longer-set-in-node-http)
- [Node.js compatibility improvements](bun-v1.1.27.html#node-js-compatibility-improvements)
- [Fixed: Crash while throwing an exception from N-API](bun-v1.1.27.html#fixed-crash-while-throwing-an-exception-from-n-api)
- [Fixed: Crash in N-API when accessing heap-allocated JSValue](bun-v1.1.27.html#fixed-crash-in-n-api-when-accessing-heap-allocated-jsvalue)
- [Fixed: Crash impacting Next.js middleware](bun-v1.1.27.html#fixed-crash-impacting-next-js-middleware)
- [Fixed: Missing `ERR_INVALID_ARG_TYPE` in some `Buffer` methods](bun-v1.1.27.html#fixed-missing-err-invalid-arg-type-in-some-buffer-methods)
- [Fixed: Missing `ERR_INVALID_URL` in `new URL`](bun-v1.1.27.html#fixed-missing-err-invalid-url-in-new-url)
- [Fixed: `AES-GCM` encryption of empty messages](bun-v1.1.27.html#fixed-aes-gcm-encryption-of-empty-messages)
- [Fixed: `util.promisify` with `crypto.generateKeyPair`](bun-v1.1.27.html#fixed-util-promisify-with-crypto-generatekeypair)
- [Fixed: Handling out-of-memory errors in `Buffer`](bun-v1.1.27.html#fixed-handling-out-of-memory-errors-in-buffer)
- [Fixed: `node:tls` accepting an arbitrary stream for a TLS socket. Fixed `mssql` package](bun-v1.1.27.html#fixed-node-tls-accepting-an-arbitrary-stream-for-a-tls-socket-fixed-mssql-package)
- [Fixed: `node:http` agent ignored](bun-v1.1.27.html#fixed-node-http-agent-ignored)
- [Fixed: `node:http` setTimeout & server.setTimeout ignored](bun-v1.1.27.html#fixed-node-http-settimeout-server-settimeout-ignored)
- [Fixed: `node:vm` inconsistencies](bun-v1.1.27.html#fixed-node-vm-inconsistencies)
- [Fixed: Missing `net.Socket.destroySoon`](bun-v1.1.27.html#fixed-missing-net-socket-destroysoon)
- [fetch reliability improvements](bun-v1.1.27.html#fetch-reliability-improvements)
- [Proxies in fetch() on Windows work better now](bun-v1.1.27.html#proxies-in-fetch-on-windows-work-better-now)
- [Fixed: a memory leak with `FormData` or `URLSearchParams` body](bun-v1.1.27.html#fixed-a-memory-leak-with-formdata-or-urlsearchparams-body)
- [Lots more fixes](bun-v1.1.27.html#lots-more-fixes)
- [Fixed: Reading large files `Bun.file` was truncated](bun-v1.1.27.html#fixed-reading-large-files-bun-file-was-truncated)
- [Fixed: Clearing screen in some terminals](bun-v1.1.27.html#fixed-clearing-screen-in-some-terminals)
- [Fixed: Handling out-of-memory errors in `Bun.escapeHTML`](bun-v1.1.27.html#fixed-handling-out-of-memory-errors-in-bun-escapehtml)
- [`Bun.deepEquals` performance improvements for `Map` and `Set`](bun-v1.1.27.html#bun-deepequals-performance-improvements-for-map-and-set)
- [Fixed: `Failed to link package: EBUSY` on Windows](bun-v1.1.27.html#fixed-failed-to-link-package-ebusy-on-windows)
- [Fixed: LCOV reporter properly reports non-hit lines](bun-v1.1.27.html#fixed-lcov-reporter-properly-reports-non-hit-lines)
- [Fixed: `bun add -g` postinstall message](bun-v1.1.27.html#fixed-bun-add-g-postinstall-message)
- [Fixed: Race condition in `Bun.build`](bun-v1.1.27.html#fixed-race-condition-in-bun-build)
- [Fixed: bun shell not keeping parent process alive](bun-v1.1.27.html#fixed-bun-shell-not-keeping-parent-process-alive)
- [Thanks to 17 contributors!](bun-v1.1.27.html#thanks-to-17-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.28.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.28
* * *
[Dylan Conway](https://github.com/dylan-conway) · September 18, 2024
[](../rss.xml)
Bun v1.1.28 is here! This release fixes 40 bugs (addressing 51 👍). Compile & run C from JavaScript. 30x faster `path.resolve`. Named pipes on Windows. Several Node.js compatibility improvements and bugfixes.
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[Compile & run C from JavaScript](bun-v1.1.28.html#compile-run-c-from-javascript)
Bun now supports compiling and running C from JavaScript. This is a simple way to use native system libraries from JavaScript without adding an extra build step.
Learn more about this feature [here](compile-and-run-c-in-js.html).
## []()[30x faster `path.resolve`](bun-v1.1.28.html#30x-faster-path-resolve)
This release makes `path.resolve` 30x faster.
> In the next version of Bun
>
> path.resolve() gets 30x faster [pic.twitter.com/ukdAHtK6lT](https://t.co/ukdAHtK6lT)
>
> — Jarred Sumner (@jarredsumner) [September 12, 2024](https://twitter.com/jarredsumner/status/1834353346318401915?ref_src=twsrc%5Etfw)
## []()[Named pipes on Windows](bun-v1.1.28.html#named-pipes-on-windows)
Bun now supports named pipes on Windows in many Node.js & Bun APIs, thanks to [@cirospaciari](https://github.com/cirospaciari)! Named pipes are interesting because they're not exactly files on disk. They're this other thing, sort of like Unix domain sockets but also not.
## []()[Node.js compatibility improvements](bun-v1.1.28.html#node-js-compatibility-improvements)
### []()[`process._exiting` is set to `false`](bun-v1.1.28.html#process-exiting-is-set-to-false)
Previously, `process._exiting` would be set to `undefined` before the `exit` event was emitted. Now, it will be `false`
```
console.log(process._exiting); // Previously: `undefined`, now: `false`
process.on("exit", () => {
console.log(process._exiting); // true
});
```
### []()[`workerData` from `worker_threads` defaults to `null`](bun-v1.1.28.html#workerdata-from-worker-threads-defaults-to-null)
The default value of `workerData` has been changed from `undefined` to `null`.
```
import { workerData } from "worker_threads";
console.log(workerData); // Previously: `undefined`, now: `null`
```
### []()[Missing constants from `perf_hooks` have been added](bun-v1.1.28.html#missing-constants-from-perf-hooks-have-been-added)
The following constants were previously missing from the `perf_hooks` module:
```
import { constants } from "perf_hooks";
console.log(constants.NODE_PERFORMANCE_MILESTONE_BOOTSTRAP_COMPLETE); // 7
console.log(constants.NODE_PERFORMANCE_MILESTONE_ENVIRONMENT); // 2
console.log(constants.NODE_PERFORMANCE_MILESTONE_LOOP_EXIT); // 6
console.log(constants.NODE_PERFORMANCE_MILESTONE_LOOP_START); // 5
console.log(constants.NODE_PERFORMANCE_MILESTONE_NODE_START); // 3
console.log(constants.NODE_PERFORMANCE_MILESTONE_TIME_ORIGIN_TIMESTAMP); // 0
console.log(constants.NODE_PERFORMANCE_MILESTONE_TIME_ORIGIN); // 1
console.log(constants.NODE_PERFORMANCE_MILESTONE_V8_START); // 4
console.log(constants.NODE_PERFORMANCE_ENTRY_TYPE_DNS); // 4
console.log(constants.NODE_PERFORMANCE_ENTRY_TYPE_GC); // 0
console.log(constants.NODE_PERFORMANCE_ENTRY_TYPE_HTTP); // 1
console.log(constants.NODE_PERFORMANCE_ENTRY_TYPE_HTTP2); // 2
console.log(constants.NODE_PERFORMANCE_ENTRY_TYPE_NET); // 3
```
### []()[Fixed logic for undefined options provided `node:zlib`](bun-v1.1.28.html#fixed-logic-for-undefined-options-provided-node-zlib)
Option handling in `node:zlib` has been fixed, allowing options to be `undefined` without causing an error.
```
import { createGzip } from "zlib";
createGzip({ level: undefined });
```
### []()[`OutgoingMessage.headersSent` from `node:http` is now set to `true`](bun-v1.1.28.html#outgoingmessage-headerssent-from-node-http-is-now-set-to-true)
After headers have been sent, `req.headersSent` will be set to `true`
### []()[Added `timers.promises`](bun-v1.1.28.html#added-timers-promises)
Exports from `node:timers/promises` are now also available in `timers.promises` to better match Node.js.
```
import { promises } from "timers";
console.time("timeout");
await promises.setTimeout(1000);
console.timeEnd("timeout"); // [1002.48ms] test
```
### []()[Fixed: `cwd` is updated before searching for executables in `node:child_process` before spawning processes](bun-v1.1.28.html#fixed-cwd-is-updated-before-searching-for-executables-in-node-child-process-before-spawning-processes)
Previously, Bun would search for executables to spawn in the calling process's `cwd`. If a different `cwd` was provided and a relative path was given for the executable path, the expected executable would fail to be found. Now, Bun will search from the target `cwd`.
```
import { spawnSync } from "child_process";
import { join } from "path";
// This will search for `foo` in `./node_modules/package/bin/`
spawnSync("./bin/foo", { cwd: join(import.meta.dir, "node_modules/package") });
```
### []()[Fixed: crash in napi escapable handle scopes](bun-v1.1.28.html#fixed-crash-in-napi-escapable-handle-scopes)
A bug where `napi` escapable handle scopes could crash Bun has been fixed, thanks to [@190n](https://github.com/190n)!
### []()[Fixed: crash in napi handle scope finalization](bun-v1.1.28.html#fixed-crash-in-napi-handle-scope-finalization)
A bug where a napi finalizer is called and then we attempt to allocate a handle scope has been fixed. This would cause a crash in certain cases in the `sqlite3` package. This was a regression from v1.1.27. Thanks to [@190n](https://github.com/190n) for the fix!
## []()[More fixes and improvements](bun-v1.1.28.html#more-fixes-and-improvements)
### []()[Fixed an edgecase with `os` and `cpu` fields in `bun install`](bun-v1.1.28.html#fixed-an-edgecase-with-os-and-cpu-fields-in-bun-install)
In certain cases, the `os` and `cpu` fields in `bun install` would not handle exclusions properly, leading to always-skipped installs. This has been fixed.
We've also added an extra log message in `bun install --verbose` to make it easier to debug why a package is being skipped.
### []()[Fixed: IPC through `bun run`](bun-v1.1.28.html#fixed-ipc-through-bun-run)
Previously, if you spawned a process that opened `bun run` with IPC enabled, the IPC socket would be closed before the child process could use it. This has been fixed, thanks to [@snoglobe](https://github.com/snoglobe)!
### []()[Fixed: case-insensitive watch mode on Windows](bun-v1.1.28.html#fixed-case-insensitive-watch-mode-on-windows)
On Windows, watch mode would not pick up on changes to case-sensitive files in certain cases. This has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway)!
### []()[Fixed: `bun ./bun.lockb` would print env loaded message](bun-v1.1.28.html#fixed-bun-bun-lockb-would-print-env-loaded-message)
If you ran `bun ./bun.lockb`, with a `.env` file in the same directory Bun would print a mesasge telling you it loaded the .env file. It shouldn't be loading the .env file, but regardless it also shouldn't be printing a message when it did load the .env file since that's noise when you're just trying to see a yarn.lock printed from the bun.lockb. This has been fixed, thanks to [@snoglobe](https://github.com/snoglobe)!
### []()[Fixed: Bun.file(path).text() on Windows not reading to end of file sometimes](bun-v1.1.28.html#fixed-bun-file-path-text-on-windows-not-reading-to-end-of-file-sometimes)
On Windows, in certain cases, `Bun.file(path).text()` would not read to the end of the file. This has been fixed, thanks to [@190n](https://github.com/190n)!
### []()[Fixed: React 19 production mode SSR](bun-v1.1.28.html#fixed-react-19-production-mode-ssr)
React 19 changed the symbol used for identifying JSX elements. This broke Bun's JSX inlining optimization. To continue to support React 19, we've disabled the optimization for now.
Thanks to [@paperclover](https://github.com/paperclover) for the fix!
### []()[Fixed: DOMJIT crash with TextDecoder](bun-v1.1.28.html#fixed-domjit-crash-with-textdecoder)
A crash that could occur when throwing an exception from a `TextDecoder` has been fixed. DOMJIT is a neat feature in JavaScriptCore that allows us to leverage type information at build-time to call natively-implemented JS functions around 30% faster. We added typed array support to this some time ago, but it has proven to cause crashes in certain cases - so we're disabling it for now and will re-enable it once we make this API more robust.
## []()[Thanks to 12 contributors!](bun-v1.1.28.html#thanks-to-12-contributors)
- [@190n](https://github.com/190n)
- [@cirospaciari](https://github.com/cirospaciari)
- [@DannyJJK](https://github.com/DannyJJK)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Electroid](https://github.com/Electroid)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@levabala](https://github.com/levabala)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@snoglobe](https://github.com/snoglobe)
- [@stilt0n](https://github.com/stilt0n)
- [@wpaulino](https://github.com/wpaulino)
* * *
#### [Bun v1.1.27](bun-v1.1.27.html)
#### [Bun v1.1.29](bun-v1.1.29.html)
On this page
- [Compile & run C from JavaScript](bun-v1.1.28.html#compile-run-c-from-javascript)
- [30x faster `path.resolve`](bun-v1.1.28.html#30x-faster-path-resolve)
- [Named pipes on Windows](bun-v1.1.28.html#named-pipes-on-windows)
- [Node.js compatibility improvements](bun-v1.1.28.html#node-js-compatibility-improvements)
- [`process._exiting` is set to `false`](bun-v1.1.28.html#process-exiting-is-set-to-false)
- [`workerData` from `worker_threads` defaults to `null`](bun-v1.1.28.html#workerdata-from-worker-threads-defaults-to-null)
- [Missing constants from `perf_hooks` have been added](bun-v1.1.28.html#missing-constants-from-perf-hooks-have-been-added)
- [Fixed logic for undefined options provided `node:zlib`](bun-v1.1.28.html#fixed-logic-for-undefined-options-provided-node-zlib)
- [`OutgoingMessage.headersSent` from `node:http` is now set to `true`](bun-v1.1.28.html#outgoingmessage-headerssent-from-node-http-is-now-set-to-true)
- [Added `timers.promises`](bun-v1.1.28.html#added-timers-promises)
- [Fixed: `cwd` is updated before searching for executables in `node:child_process` before spawning processes](bun-v1.1.28.html#fixed-cwd-is-updated-before-searching-for-executables-in-node-child-process-before-spawning-processes)
- [Fixed: crash in napi escapable handle scopes](bun-v1.1.28.html#fixed-crash-in-napi-escapable-handle-scopes)
- [Fixed: crash in napi handle scope finalization](bun-v1.1.28.html#fixed-crash-in-napi-handle-scope-finalization)
- [More fixes and improvements](bun-v1.1.28.html#more-fixes-and-improvements)
- [Fixed an edgecase with `os` and `cpu` fields in `bun install`](bun-v1.1.28.html#fixed-an-edgecase-with-os-and-cpu-fields-in-bun-install)
- [Fixed: IPC through `bun run`](bun-v1.1.28.html#fixed-ipc-through-bun-run)
- [Fixed: case-insensitive watch mode on Windows](bun-v1.1.28.html#fixed-case-insensitive-watch-mode-on-windows)
- [Fixed: `bun ./bun.lockb` would print env loaded message](bun-v1.1.28.html#fixed-bun-bun-lockb-would-print-env-loaded-message)
- [Fixed: Bun.file(path).text() on Windows not reading to end of file sometimes](bun-v1.1.28.html#fixed-bun-file-path-text-on-windows-not-reading-to-end-of-file-sometimes)
- [Fixed: React 19 production mode SSR](bun-v1.1.28.html#fixed-react-19-production-mode-ssr)
- [Fixed: DOMJIT crash with TextDecoder](bun-v1.1.28.html#fixed-domjit-crash-with-textdecoder)
- [Thanks to 12 contributors!](bun-v1.1.28.html#thanks-to-12-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.29.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.29
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · September 20, 2024
[](../rss.xml)
Bun v1.1.29 is here! This release fixes 21 bugs (addressing 22 👍). Fixes issue with proxying requests with axios. N-API (napi) support in compiled C. Faster typed arrays in `bun:ffi` with 'buffer' type. Fixes issue with bundling imported .wasm files in `bun build`. Fixes regression with `bun build` from v1.1.28. Fixes snapshot regression in `bun test`. Fixes bug with argument validation in `Bun.build` plugins.
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
### []()[N-API (napi) support in compiled C](bun-v1.1.29.html#n-api-napi-support-in-compiled-c)
In Bun v1.1.28 (previous version), we introduced support for [compiling and running C code from JavaScript](compile-and-run-c-in-js.html).
In this release, we've added N-API (napi) support to `cc`. This makes it easier to return JavaScript strings, objects, arrays and other non-primitive values from C code.
For example, this returns a JavaScript string `"Hello, Napi!"`:
hello-napi.c
hello-napi.js
hello-napi.c
```
#include <node/node_api.h>
napi_value hello_napi(napi_env env) {
napi_value result;
napi_create_string_utf8(env, "Hello, Napi!", NAPI_AUTO_LENGTH, &result);
return result;
}
```
hello-napi.js
```
import { cc } from "bun:ffi";
import source from "./hello-napi.c" with {type: "file"};
const hello_napi = cc({
source,
symbols: {
hello_napi: {
args: ["napi_env"],
returns: "napi_value",
},
},
});
console.log(hello_napi());
// => "Hello, Napi!"
```
You can continue to use types like `int`, `float`, `double` to send & receive primitive values from C code, but now you can also use N-API types! Also, this works when using `dlopen` to load shared libraries with `bun:ffi` (such as Rust or C++ libraries with C ABI exports).
### []()[`"buffer"` type in bun:ffi](bun-v1.1.29.html#buffer-type-in-bun-ffi)
You can now use the `"buffer"` type in `bun:ffi` to send and receive JavaScript typed arrays (`Uint8Array`, `Buffer`, etc) in C code slightly faster and simpler.
The following example returns the last byte of a Uint8Array:
last-byte.c
last-byte.js
last-byte.c
```
uint8_t lastByte(uint8_t *arr, size_t len) {
return arr[len - 1];
}
```
last-byte.js
```
import { cc } from "bun:ffi";
import source from "./last-byte.c" with {type: "file"};
const lastByte = cc({
source,
symbols: {
lastByte: {
args: ["buffer", "usize"],
returns: "u8",
},
},
});
const arr = new Uint8Array([1, 2, 3, 4, 5]);
console.log(lastByte(arr, arr.length));
// => 5
```
In this microbenchmark, the hash function gets **30% faster by using the `"buffer"` type** in `bun:ffi` instead of wrapping the Uint8Array in the `ptr()` function.
```
bun ./bench.js
```
```
cpu: Apple M3 Max
runtime: bun 1.1.29 (arm64-darwin)
benchmark time (avg) (min … max) p75 p99 p995
----------------------------------------------------- -----------------------------
hash (ptr) 82.63 ns/iter (79.6 ns … 172.82 ns) 81.65 ns 111.22 ns 118.77 ns
hash (buffer) 48.59 ns/iter (45.04 ns … 94.9 ns) 50.09 ns 79.17 ns 81.93 ns
```
Benchmark code
bench.js
```
import { dlopen, ptr } from "bun:ffi";
import { bench, run } from "mitata";
const {
symbols: { ffi_hash: hash },
} = dlopen(import.meta.dir + "/src/ffi_napi_bench.node", {
ffi_hash: { args: ["ptr", "u32"], returns: "u32" },
});
const bytes = new Uint8Array(64);
const {
symbols: { ffi_hash: hashBuffer },
} = dlopen(import.meta.dir + "/src/ffi_napi_bench.node", {
ffi_hash: { args: ["buffer", "u32"], returns: "u32" },
});
bench("hash (ptr)", () => hash(ptr(bytes), bytes.byteLength));
bench("hash (buffer)", () => hashBuffer(bytes, bytes.byteLength));
await run();
```
Under the hood, we've made the conversion between JavaScript typed arrays and C `uint8_t*` happen inline without external function calls, which makes it faster than using the `ptr` function from `bun:ffi`.
### []()[Fixed: proxy with axios](bun-v1.1.29.html#fixed-proxy-with-axios)
A bug causing proxying requests with axios to not work properly is fixed.
Thanks to [@cirospaciari](https://github.com/cirospaciari) for the fix!
### []()[Fixed: Bundling imported .wasm files in `bun build`](bun-v1.1.29.html#fixed-bundling-imported-wasm-files-in-bun-build)
A bug that could cause a crash when bundling imported .wasm files in `bun build` is fixed.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for the fix!
### []()[Fixed: regression with `bun build` from v1.1.28](bun-v1.1.29.html#fixed-regression-with-bun-build-from-v1-1-28)
A regression where certain symbols were being re-ordered incorrectly in `bun build` is fixed.
Thanks to [@paperclover](https://github.com/paperclover) for the fix!
### []()[Fixed: snapshot regression in bun test](bun-v1.1.29.html#fixed-snapshot-regression-in-bun-test)
A regression that caused `bun test` to always update snapshots is fixed.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for the fix!
### []()[Fixed: Argument validation issue in Bun.build plugins](bun-v1.1.29.html#fixed-argument-validation-issue-in-bun-build-plugins)
A crash that could happen when passing an incorrect argument to the `plugins` option in `Bun.build` is fixed.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for the fix!
### []()[Fixed: `cc` missing include directories on Linux and macOS](bun-v1.1.29.html#fixed-cc-missing-include-directories-on-linux-and-macos)
A bug that caused `cc` to not find the default system include directories on Linux and macOS is fixed.
### []()[Thanks to 3 contributors!](bun-v1.1.29.html#thanks-to-3-contributors)
- [@cirospaciari](https://github.com/cirospaciari)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
* * *
#### [Bun v1.1.28](bun-v1.1.28.html)
#### [Bun v1.1.30](bun-v1.1.30.html)
On this page
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.3.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.3
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · April 8, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one.
Bun v1.1.3 fixes 5 bugs. bun install gets 50% faster on Windows. A bug that could cause bun install to hang in rare cases has been fixed. A bug where some errors in bun install would not produce a non-zero exit code has been fixed. A bug that could cause specific certain combinations of dependencies to fail to install has been fixed. A bug on Windows where CTRL + C on cmd.exe after exiting bun would not behave as expected has been fixed. A bug where missing permissions on Windows for reading a directory could lead to a crash has been fixed.
#### Previous releases
- [`v1.1.2`](bun-v1.1.2.html) Bun v1.1.2 fixes 4 bugs (addressing 44 👍 reactions). EBUSY on Windows in vite dev, next dev, and saving bun.lockb has been fixed. Bun Shell gets support for seq, yes, basename and dirname. A TypeScript parsing edgecase has been fixed. A bug causing 'unreachable code' errors has been fixed. fs.watch on Windows has been rewritten to improve performance and reliability.
- [`v1.1.1`](bun-v1.1.1.html) Bun v1.1.1 fixes 20 bugs (addressing 60 👍 reactions). Add subshell and positional argument support. Printed source code in errors no longer fill up your terminal. Upgrades JavaScriptCore, which includes performance improvements to RegExp, typed arrays, String indexOf and String replace. Error objects and JIT'd function calls use less memory. Fixes several bugs with bun install on Windows. Fixes a bug with Bun.serve() on Windows. Fixes a TOML parser bug impacting escape sequences and windows paths in .toml files.
- [`v1.1.0`](bun-v1.1.html) Bundows. Windows support is here! Plus, JSON IPC Node <-> Bun.
#### To install Bun:
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
### []()[Windows support improvements](bun-v1.1.3.html#windows-support-improvements)
## []()[Up to 50% faster `bun install` on Windows](bun-v1.1.3.html#up-to-50-faster-bun-install-on-windows)
In this release, `bun install` gets up to 50% faster at installing packages on Windows compared to Bun v1.1.2 and earlier.
For an application which has `next`, SvelteKit, and a handful more in package.json:
```
PS > hyperfine "bun install --ignore-scripts" "bun-1.1.2.exe install --ignore-scripts" --prepare="rm -r node_modules || true" --warmup=2
Benchmark 1: bun install --ignore-scripts # New
Time (mean ± σ): 720.7 ms ± 39.8 ms [User: 20.3 ms, System: 423.4 ms]
Range (min … max): 676.4 ms … 801.9 ms 10 runs
Benchmark 2: bun-1.1.2.exe install --ignore-scripts # Old
Time (mean ± σ): 1.158 s ± 0.017 s [User: 0.011 s, System: 0.419 s]
Range (min … max): 1.135 s … 1.180 s 10 runs
Summary
bun install --ignore-scripts ran
1.61 ± 0.09 times faster than bun-1.1.2.exe install --ignore-scripts
```
We've paralellized some of where `bun install` copies/hardlinks files on Windows, but not all of them.
Bun for Windows is still compiled using `ReleaseSafe` mode which adds runtime safety checks that can cause some performance issues. Once there are fewer bug reports in bundows, we'll switch to `ReleaseFast` mode.
## []()[Fixed: CTRL + C on cmd.exe after exiting bun](bun-v1.1.3.html#fixed-ctrl-c-on-cmd-exe-after-exiting-bun)
One difference between `cmd.exe` and PowerShell is the console mode. On exit, PowerShell always resets the console mode. Command Prompt (cmd.exe) does not.
Previously, bun wasn't resetting the console mode on exit. This would cause issues with pressing Up or Down arrows in Command Prompt after exiting bun.
This has been fixed.
[](https://github.com/oven-sh/bun/assets/709451/c34bd241-7884-4927-b601-d0c8b2091b4b)
## []()[Fixed: Potential crash when loading modules without permissions](bun-v1.1.3.html#fixed-potential-crash-when-loading-modules-without-permissions)
A bug that could cause loading a JavaScript or TypeScript file to crash if the file was not readable has been fixed.
This bug was caused by assuming the permission was accessible when it wasn't.
### []()[bun install improvements](bun-v1.1.3.html#bun-install-improvements)
## []()[Fixed: Spurious "Install failed" error](bun-v1.1.3.html#fixed-spurious-install-failed-error)
When installing packages with a nested node\_modules folder where the parent package needs to be downloaded along with a number of more subtle conditions, bun install would sometimes fail with an "Install failed" error.
This has been fixed.
## []()[Fixed: Non-zero exit code after errors](bun-v1.1.3.html#fixed-non-zero-exit-code-after-errors)
Some errors in `bun install` didn't cause bun to exit with a non-zero exit code. This has been fixed.
Most of the errors where this would happen had to do with filesystem permissions.
## []()[Fixed: Potential deadlock in `bun install`](bun-v1.1.3.html#fixed-potential-deadlock-in-bun-install)
A rare deadlock in `bun install` has been fixed. This would happen potentially if many packages finished extracting at the exact same time and for some reason the main thread did not wake up when notified.
## []()[Thanks to 5 contributors!](bun-v1.1.3.html#thanks-to-5-contributors)
- [@Bellisario](https://github.com/Bellisario)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@jprinaldi](https://github.com/jprinaldi)
- [@tomerh2001](https://github.com/tomerh2001)
- [@yoavbls](https://github.com/yoavbls)
* * *
#### [Bun v1.1.2](bun-v1.1.2.html)
#### [Bun v1.1.4](bun-v1.1.4.html)
On this page
- [Up to 50% faster `bun install` on Windows](bun-v1.1.3.html#up-to-50-faster-bun-install-on-windows)
- [Fixed: CTRL + C on cmd.exe after exiting bun](bun-v1.1.3.html#fixed-ctrl-c-on-cmd-exe-after-exiting-bun)
- [Fixed: Potential crash when loading modules without permissions](bun-v1.1.3.html#fixed-potential-crash-when-loading-modules-without-permissions)
- [bun install improvements](bun-v1.1.3.html#bun-install-improvements)
- [Fixed: Spurious "Install failed" error](bun-v1.1.3.html#fixed-spurious-install-failed-error)
- [Fixed: Non-zero exit code after errors](bun-v1.1.3.html#fixed-non-zero-exit-code-after-errors)
- [Fixed: Potential deadlock in `bun install`](bun-v1.1.3.html#fixed-potential-deadlock-in-bun-install)
- [Thanks to 5 contributors!](bun-v1.1.3.html#thanks-to-5-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.30.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.30
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · October 8, 2024
[](../rss.xml)
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
This release fixes 57 bugs (addressing 150 👍). Bun's CSS bundler is here (and very experimental). `bun publish` is a drop-in replacement for `npm publish`. `bun build --bytecode` compiles to bytecode leading to 2x faster start time. Bun.color() formats and normalizes colors. `bun pm whoami` prints your npm username. `bun install` reads `$HOME/.npmrc`. `bun build --format=cjs` outputs CommonJS modules. `bun build --target=node` now supports Node.js native addons. 30x faster `crypto.privateEncrypt()` & `crypto.publicDecrypt()`. Zombie process killer in bun test. `--banner` and `--footer` options in `bun build`. `Bun.serve().stop()` returns a promise. `Bun.CryptoHasher` now supports HMAC. Bugfixes for node:zlib, node:module, and node:buffer. Lots more bugfixes and Node.js compatibility improvements
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[Experimental: CSS Parsing & bundling](bun-v1.1.30.html#experimental-css-parsing-bundling)
Over the last two months, [@zackradisic](https://x.com/zack_overflow) built a CSS parser and bundler for Bun.
It's based on [@devongovett](https://x.com/devongovett)'s excellent [LightningCSS](https://github.com/parcel-bundler/lightningcss) parser, rewritten from Rust to Zig to vertically integrate into Bun's JavaScript & TypeScript parser, bundler, and runtime.
You can try it out today via `bun build` (CLI) or `Bun.build` (API) with the `--experimental-css` flag.
### []()[CSS bundling](bun-v1.1.30.html#css-bundling)
Bun's CSS bundler concatenates multiple CSS files and any assets referenced via `url`, `@import`, `@font-face`, etc into a single CSS file you can send to browsers, avoiding a waterfall of network requests.
index.css
```
@import "foo.css";
@import "bar.css";
```
To try it out with `bun build` via CLI:
shell
```
bun build --experimental-css ./index.css
```
Those two CSS files become a single bundled CSS file:
dist.css
```
/** foo.css */
.foo {
background: red;
}
/** bar.css */
.bar {
background: blue;
}
```
### []()[Import .css files in JavaScript & TypeScript](bun-v1.1.30.html#import-css-files-in-javascript-typescript)
Bun's CSS parser integrates with our JavaScript & TypeScript parser & bundler.
You can import .css files in JavaScript & TypeScript and an additional css entrypoint will be created that combines all the css files imported from a JavaScript/TypeScript module graph, along with any `@import` rules.
index.ts
```
import "./style.css";
import Component from "./MyComponent.tsx";
// ... rest of your app
```
Then, if `MyComponent.tsx` imports a CSS file, instead of adding extra .css files to the bundle, all the CSS imported per entrypoint is flattened into a single CSS file.
shell
```
bun build --experimental-css ./index.ts --outdir=dist
```
```
index.js 0.10 KB
index.css 0.10 KB
[5ms] bundle 4 modules
```
This outputs the following css file, which came from TypeScript imports:
style.css
```
/* style.css */
.hello {
background: red;
}
/* MyComponent.css */
.MyComponent {
color: green;
}
```
### []()[Bundle CSS with `Bun.build`:](bun-v1.1.30.html#bundle-css-with-bun-build)
We've also added support for programmatically bundling CSS with the `Bun.build` API. You can bundle both CSS and JavaScript in the same build with the same API.
api.ts
```
import { build } from "bun";
const results = await build({
entrypoints: ["./index.css"],
outdir: "./dist",
experimentalCss: true,
});
console.log(results);
```
### []()[How fast can it parse & bundle CSS?](bun-v1.1.30.html#how-fast-can-it-parse-bundle-css)
We will release benchmarks once it's more stable, but I think you will be satisfied with the performance.
Huge thanks to [@zackradisic](https://github.com/zackradisic) for building this, and for @devongovett for his excellent LightningCSS library.
## []()[`bun publish`: drop-in replacement for `npm publish`](bun-v1.1.30.html#bun-publish-drop-in-replacement-for-npm-publish)
You can use bun to publish npm packages via `bun publish`
```
bun publish
```
```
bun publish v1.1.30 (ecad797a)
packed 108B package.json
packed 3B README.md
packed 19B index.js
Total files: 3
Shasum: abd73b91b21057f0b07a58472077f5a3bbfb3e89
Integrity: sha512-aWkWikXiSXyR[...]Ubll4PQcEEoNw==
Unpacked size: 130B
Packed size: 254B
Tag: latest
Access: default
Registry: http://localhost:4873
+ lodash-2@1.0.0
```
`bun publish` is intended as a drop-in replacement for `npm publish`, and supports many of the same features like:
- Reading .npmrc files for authentication
- Packing tarballs, accounting for `.gitignore` and `.npmignore` files in multiple directories
- OTP / Two-factor authentication
- Handling various edgecases with package.json fields like `"bin"`, `"files"`, etc
- Handling missing README files carefully
Additionally, when using workspaces, `bun publish` will automatically rewrite dependency versions of workspace packages to point to the published version so that you can publish packages correctly that internally use `workspace:` dependencies.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for implementing this!
## []()[`bun pm whoami`](bun-v1.1.30.html#bun-pm-whoami)
The new `bun pm whoami` command will print the current user's npm username.
```
bun pm whoami
```
```
bun
```
Thanks to [@dylan-conway](https://github.com/dylan-conway) for implementing this!
## []()[Compile to bytecode for 2x faster startup time](bun-v1.1.30.html#compile-to-bytecode-for-2x-faster-startup-time)
`bun build` now supports bundling JavaScript & TypeScript to bytecode for a 2x faster startup time.
```
bun build --bytecode --compile ./index.ts
```
### []()[Single-file bytecode executables](bun-v1.1.30.html#single-file-bytecode-executables)
> bun build --bytecode --compile makes eslint start 2x faster [pic.twitter.com/kFQ1KUJj2Z](https://t.co/kFQ1KUJj2Z)
>
> — Jarred Sumner (@jarredsumner) [September 30, 2024](https://twitter.com/jarredsumner/status/1840729983528137043?ref_src=twsrc%5Etfw)
### []()[Bytecode bundles](bun-v1.1.30.html#bytecode-bundles)
You can also use this without `--compile` if you would prefer individual files without the [standalone executable](../docs/bundler/executables.html).
```
bun build --bytecode --outdir=./dist ./index.ts
```
This will output `.jsc` files alongside `.js` files. These `.jsc` contain the bytecode version of the file. Both are necessary to run in Bun, as the bytecode compilation doesn't currently compile async functions, generators, eval, and a handful of other edge cases.
The bytecode can be 8x larger than the source code, so this makes startup faster at a cost of increased disk space.
## []()[CommonJS bundle output format](bun-v1.1.30.html#commonjs-bundle-output-format)
`bun build` now supports `--format=cjs` to output CommonJS bundles. Preivously, only `--format=esm` was supported.
This makes it easier to use `bun build` to build libraries & applications meant for Node.js in situations where CommonJS modules are easier to work with.
shell.sh
index.js
output.js
shell.sh
```
bun build --format=cjs index.js
```
index.js
```
// index.js
export default "Hello, world!";
```
output.js
```
var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __moduleCache = /* @__PURE__ */ new WeakMap;
var __toCommonJS = (from) => {
var entry = __moduleCache.get(from), desc;
if (entry)
return entry;
entry = __defProp({}, "__esModule", { value: true });
if (from && typeof from === "object" || typeof from === "function")
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
get: () => from[key],
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
}));
__moduleCache.set(from, entry);
return entry;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, {
get: all[name],
enumerable: true,
configurable: true,
set: (newValue) => all[name] = () => newValue
});
};
// index.js
var exports_site = {};
__export(exports_site, {
default: () => site_default
});
module.exports = __toCommonJS(exports_site);
var site_default = "Hello, world!";
```
## []()[Zombie process killer in `bun test`](bun-v1.1.30.html#zombie-process-killer-in-bun-test)
On Linux and macOS, when a spawned process is not waited on, it's called a "zombie process".
Bun now automatically kills zombie processes from test timeouts in `bun test`.
When a test that spawns process(es) times out in `bun test`, if the process is not accessible outside of the test, then you would end up with a process that potentially never gets cleaned up if `bun test` were to exit soon after. This was especially noticable with tools like Puppeteer that spawn a browser instance. Lingering Chromium processes can cost you 100s of MBs of RAM and cause all sorts of issues.
Bun now internally tracks all processes spawned inside tests and if a test times out, Bun will automatically kill the process.
## []()[Bundle `.node` files with `--target=node`](bun-v1.1.30.html#bundle-node-files-with-target-node)
You can now bundle Node.js native modules using Bun and run those Node.js native modules in Node.js.
We fixed a bug that prevented `--target=node` from correctly bundling `.node` files, which are Node.js native modules. Previously, this was only supported with `--target=bun`, and now it's supported with `--target=node` as well.
## []()[--banner and --footer options in `bun build`](bun-v1.1.30.html#banner-and-footer-options-in-bun-build)
You can now add a banner and footer above and below bundled output with `--banner` and `--footer` options in `bun build` and `Bun.build`.
Input:
shell
api.js
shell
```
bun build --banner "/* Hello, world! */" --footer "/* Goodbye! */" index.ts
```
api.js
```
await Bun.build({
entrypoints: ["./index.ts"],
outdir: "./dist",
banner: "/* Hello, world! */",
footer: "/* Goodbye! */",
});
```
Output:
```
/**
* Hello, world!
*/
export default "Hello, world!";
/**
* Goodbye!
*/
```
Huge thanks to [@versecafe](https://github.com/versecafe) for implementing this!
### []()[`--registry` flag in `bun install`](bun-v1.1.30.html#registry-flag-in-bun-install)
You can now specify a custom registry from the command line when installing packages with `bun install`. You can use this flag by itself or with packages you want to add to your project.
```
# Install packages from a custom local registry instead of the default npm registry.
```
```
bun install --registry=http://localhost:4873/
```
```
# With packages
```
```
bun install zod --registry=http://localhost:4873/
```
You can continue to set the registry in `.npmrc` files, `bunfig.toml`, or via `NPM_CONFIG_REGISTRY` environment variable. This extra CLI flag is useful if you want to globally install a package from a private registry without having to set the registry in your `.npmrc` file or use a scoped package name.
## []()[Bun.color() formats and normalizes colors](bun-v1.1.30.html#bun-color-formats-and-normalizes-colors)
> In the next version of Bun
>
> Bun.color(input, outputFormat) leverages Bun's new CSS parser to parse, normalize, and convert colors into a variety of formats [pic.twitter.com/ffULyAVxHb](https://t.co/ffULyAVxHb)
>
> — zack (in SF) (@zack\_overflow) [September 26, 2024](https://twitter.com/zack_overflow/status/1839407314329321561?ref_src=twsrc%5Etfw)
## []()[`stop()` in Bun.serve() returns a Promise](bun-v1.1.30.html#stop-in-bun-serve-returns-a-promise)
Bun's HTTP server API `Bun.serve()` now returns a Promise from `server.stop()` which resolves when all connections are closed.
This lets you use `await server.stop()` to wait for all the connections to close without abruptly closing them.
```
const server = Bun.serve({
port: 3000,
async fetch(req) {
return new Response("Hello, world!");
},
});
await server.stop();
```
## []()[HMAC in `Bun.CryptoHasher`](bun-v1.1.30.html#hmac-in-bun-cryptohasher)
`Bun.CryptoHasher` can now be used to compute HMAC digests. To do so, pass the key to the constructor.
```
import { CryptoHasher } from "bun";
const hasher = new CryptoHasher("sha1", "secret-key");
const hash = hasher
.update("message")
// This creates the HMAC signature
.digest("hex");
console.log(hash); // 48de2656eac2c9c21b04faeec4f1be9672ef53c1
```
## []()[bun install reads $HOME/.npmrc now](bun-v1.1.30.html#bun-install-reads-home-npmrc-now)
`bun install` now reads `$HOME/.npmrc` files for authentication if no other registry is specified.
Previously, only `.npmrc` in the current directory was read. Now, `$HOME/.npmrc` is also read if no `.npmrc` is found in the current package.json directory.
Thanks to [@robertshuford](https://github.com/robertshuford) for implementing this!
## []()[Bundler fixes](bun-v1.1.30.html#bundler-fixes)
### []()[Fixed: top-level `await` bug in `bun build`](bun-v1.1.30.html#fixed-top-level-await-bug-in-bun-build)
A bug that could cause spurious top-level `await` errors in `bun build` has been fixed, thanks to [@snoglobe](https://github.com/snoglobe)!
### []()[Fixed: importing JSON with unicode characters in `bun build`](bun-v1.1.30.html#fixed-importing-json-with-unicode-characters-in-bun-build)
Importing JSON with unicode characters now works correctly with `bun build`. Bun was previously incorrectly converting the encoding of strings from JSON, causing unicode characters to be interpreted in the wrong encoding.
```
// test.json
{
"测试a": "b"
}
```
```
// test.js
import data from "./test.json";
console.log(data["测试" + "a"]); // b
```
Thanks to [@snoglobe](https://github.com/snoglobe)!
## []()[Node.js compatibility improvements](bun-v1.1.30.html#node-js-compatibility-improvements)
### []()[30x faster crypto.privateEncrypt() & crypto.publicDecrypt()](bun-v1.1.30.html#30x-faster-crypto-privateencrypt-crypto-publicdecrypt)
`crypto.privateEncrypt()` and `crypto.publicDecrypt()` in Bun are now powered by BoringSSL, which leads to a 30x performance improvement to these functions over the previous JavaScript polyfill implementation.
After:
```
benchmark time (avg) (min … max) p75 p99 p999
----------------------------------------------------------------------------- -----------------------------
RSA sign RSA_PKCS1_PADDING round-trip 832 µs/iter (816 µs … 915 µs) 834 µs 893 µs 915 µs
```
Before:
```
benchmark time (avg) (min … max) p75 p99 p999
----------------------------------------------------------------------------- -----------------------------
RSA sign RSA_PKCS1_PADDING round-trip 26'997 µs/iter (26'657 µs … 27'551 µs) 27'119 µs 27'551 µs 27'551 µs
```
Thanks to [@wpaulino](https://github.com/wpaulino) for the fix!
### []()[`require("cluster")` gets 6ms faster](bun-v1.1.30.html#require-cluster-gets-6ms-faster)
The time it takes to `require("cluster")` has been reduced by 6ms, thanks to [@nektro](https://github.com/nektro)
Previously:
```
bun-1.1.29 --print 'console.time("require(`cluster`)");require(`cluster`);console.timeEnd("require(`cluster`)");' # Old
```
```
[7.62ms] require(`cluster`)
```
Now:
```
bun --print 'console.time("require(`cluster`)");require(`cluster`);console.timeEnd("require(`cluster`)");' # New
```
```
[1.39ms] require(`cluster`)
```
### []()[Fixed: Buffer.alloc bug with 2nd argument bug](bun-v1.1.30.html#fixed-buffer-alloc-bug-with-2nd-argument-bug)
A bug when Buffer.alloc was passed an empty string as the second argument has been fixed.
Thanks to [@nektro](https://github.com/nektro) for the fix!
### []()[Fixed: Several node:zlib issues](bun-v1.1.30.html#fixed-several-node-zlib-issues)
Bun's node:zlib implementation now passes many more Node.js tests, thanks to [@nektro](https://github.com/nektro)! This addresses issues with Sharp/Jimp, Zip.js, some GPRC libraries, pubnub, and more.
Thanks to [@nektro](https://github.com/nektro) for the fix!
### []()[Fixed: Prisma not waiting for promises before exiting](bun-v1.1.30.html#fixed-prisma-not-waiting-for-promises-before-exiting)
A bug in our NAPI implementation could cause Prisma to not wait for promises in queries before the Bun process exits.
Thanks to [@190n](https://github.com/190n) for the fix!
### []()[Fixed: Missing exports in `node:module`](bun-v1.1.30.html#fixed-missing-exports-in-node-module)
A handful of missing exports in `node:module` have been added:
- `_preloadModules` was previously undefined. Now it does nothing
- `_debug` & `_pathCache` was previously `undefined`
- `enableCompileCache` and `getCompileCache` were previously undefined
- `__resolveFilename` and `_resolveFilename` were previously both defined, now only `_resolveFilename` is defined
### []()[Fixed: console.log on `require.cache`](bun-v1.1.30.html#fixed-console-log-on-require-cache)
Previously, `console.log(require.cache)` would print an empty object. Now it prints the cache.
```
// Old
{}
// New
{
"/path/to/module": Module {
id: "/path/to/module",
exports: {},
parent: null,
filename: "/path/to/module.js",
loaded: false,
children: [],
paths: []
}
}
```
### []()[Fixed: `process.cwd()` returning the wrong path on Windows for the root of a drive](bun-v1.1.30.html#fixed-process-cwd-returning-the-wrong-path-on-windows-for-the-root-of-a-drive)
A regression has been fixed where `process.cwd()` would return an incorrect path on Windows if the current working directory was at the root of a drive. For example, if the current working directory was `C:\`, `process.cwd()` would return `C:` instead of `C:\`.
### []()[Fixed: 2 rare crashes in Bun.spawn()](bun-v1.1.30.html#fixed-2-rare-crashes-in-bun-spawn)
Two rare crashes in `Bun.spawn()` have been fixed. One was a regression from Bun v1.1.25. It sometimes happened when the subprocess was garbage collected before referencing stdin in certain cases.
### []()[Prototype pollution mitigation](bun-v1.1.30.html#prototype-pollution-mitigation)
To make [prototype pollution](https://en.wikipedia.org/wiki/Prototype_pollution) more difficult to exploit in Bun's APIs, Bun APIs now ignore the `Object` prototype when reading values from objects and functions in natively implemented Bun APIs (such as `fetch`, `Request`, `Response`, etc).
Previously, the following code would cause `glob.scanSync` to follow symlinks:
```
import { Glob } from "bun";
const glob = new Glob("*.ts");
Object.defineProperty(Object.prototype, "followSymlinks", {
value: true,
writable: true,
configurable: true,
enumerable: true,
});
const second = glob.scanSync({
cwd: path.join(dir, "abc"),
onlyFiles: true,
});
```
Now, since the `Object.prototype` is ignored, this attack is mitigated. We've done this for nearly all Bun APIs implemented in Zig.
This doesn't fully prevent prototype pollution attacks, but it does make them more difficult to exploit in Bun APIs. Thanks to [@lirantal](https://github.com/lirantal) for the report!
### []()[Fixed: `bun add` incorrectly adding relative paths to tarballs in workspaces](bun-v1.1.30.html#fixed-bun-add-incorrectly-adding-relative-paths-to-tarballs-in-workspaces)
A bug was fixed causing `bun add` to fail to add local tarball packages to workspaces. This would happen because bun was using the workspace root as the base path rather than the current workspace package the tarball would be added to.
## []()[Thanks to 17 contributors!](bun-v1.1.30.html#thanks-to-17-contributors)
- [@190n](https://github.com/190n)
- [@cirospaciari](https://github.com/cirospaciari)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Electroid](https://github.com/Electroid)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@lewismiddleton](https://github.com/lewismiddleton)
- [@matubu](https://github.com/matubu)
- [@metonym](https://github.com/metonym)
- [@mjomble](https://github.com/mjomble)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@robertshuford](https://github.com/robertshuford)
- [@snoglobe](https://github.com/snoglobe)
- [@versecafe](https://github.com/versecafe)
- [@wpaulino](https://github.com/wpaulino)
- [@Xmarmalade](https://github.com/Xmarmalade)
- [@zackradisic](https://github.com/zackradisic)
* * *
#### [Bun v1.1.29](bun-v1.1.29.html)
#### [Bun v1.1.31](bun-v1.1.31.html)
On this page
- [Experimental: CSS Parsing & bundling](bun-v1.1.30.html#experimental-css-parsing-bundling)
- [CSS bundling](bun-v1.1.30.html#css-bundling)
- [Import .css files in JavaScript & TypeScript](bun-v1.1.30.html#import-css-files-in-javascript-typescript)
- [Bundle CSS with `Bun.build`:](bun-v1.1.30.html#bundle-css-with-bun-build)
- [How fast can it parse & bundle CSS?](bun-v1.1.30.html#how-fast-can-it-parse-bundle-css)
- [`bun publish`: drop-in replacement for `npm publish`](bun-v1.1.30.html#bun-publish-drop-in-replacement-for-npm-publish)
- [`bun pm whoami`](bun-v1.1.30.html#bun-pm-whoami)
- [Compile to bytecode for 2x faster startup time](bun-v1.1.30.html#compile-to-bytecode-for-2x-faster-startup-time)
- [Single-file bytecode executables](bun-v1.1.30.html#single-file-bytecode-executables)
- [Bytecode bundles](bun-v1.1.30.html#bytecode-bundles)
- [CommonJS bundle output format](bun-v1.1.30.html#commonjs-bundle-output-format)
- [Zombie process killer in `bun test`](bun-v1.1.30.html#zombie-process-killer-in-bun-test)
- [Bundle `.node` files with `--target=node`](bun-v1.1.30.html#bundle-node-files-with-target-node)
- [--banner and --footer options in `bun build`](bun-v1.1.30.html#banner-and-footer-options-in-bun-build)
- [`--registry` flag in `bun install`](bun-v1.1.30.html#registry-flag-in-bun-install)
- [Bun.color() formats and normalizes colors](bun-v1.1.30.html#bun-color-formats-and-normalizes-colors)
- [`stop()` in Bun.serve() returns a Promise](bun-v1.1.30.html#stop-in-bun-serve-returns-a-promise)
- [HMAC in `Bun.CryptoHasher`](bun-v1.1.30.html#hmac-in-bun-cryptohasher)
- [bun install reads $HOME/.npmrc now](bun-v1.1.30.html#bun-install-reads-home-npmrc-now)
- [Bundler fixes](bun-v1.1.30.html#bundler-fixes)
- [Fixed: top-level `await` bug in `bun build`](bun-v1.1.30.html#fixed-top-level-await-bug-in-bun-build)
- [Fixed: importing JSON with unicode characters in `bun build`](bun-v1.1.30.html#fixed-importing-json-with-unicode-characters-in-bun-build)
- [Node.js compatibility improvements](bun-v1.1.30.html#node-js-compatibility-improvements)
- [30x faster crypto.privateEncrypt() & crypto.publicDecrypt()](bun-v1.1.30.html#30x-faster-crypto-privateencrypt-crypto-publicdecrypt)
- [`require("cluster")` gets 6ms faster](bun-v1.1.30.html#require-cluster-gets-6ms-faster)
- [Fixed: Buffer.alloc bug with 2nd argument bug](bun-v1.1.30.html#fixed-buffer-alloc-bug-with-2nd-argument-bug)
- [Fixed: Several node:zlib issues](bun-v1.1.30.html#fixed-several-node-zlib-issues)
- [Fixed: Prisma not waiting for promises before exiting](bun-v1.1.30.html#fixed-prisma-not-waiting-for-promises-before-exiting)
- [Fixed: Missing exports in `node:module`](bun-v1.1.30.html#fixed-missing-exports-in-node-module)
- [Fixed: console.log on `require.cache`](bun-v1.1.30.html#fixed-console-log-on-require-cache)
- [Fixed: `process.cwd()` returning the wrong path on Windows for the root of a drive](bun-v1.1.30.html#fixed-process-cwd-returning-the-wrong-path-on-windows-for-the-root-of-a-drive)
- [Fixed: 2 rare crashes in Bun.spawn()](bun-v1.1.30.html#fixed-2-rare-crashes-in-bun-spawn)
- [Prototype pollution mitigation](bun-v1.1.30.html#prototype-pollution-mitigation)
- [Fixed: `bun add` incorrectly adding relative paths to tarballs in workspaces](bun-v1.1.30.html#fixed-bun-add-incorrectly-adding-relative-paths-to-tarballs-in-workspaces)
- [Thanks to 17 contributors!](bun-v1.1.30.html#thanks-to-17-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.31.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.31
* * *
[Ashcon Partovi](https://twitter.com/ashconpartovi) · October 18, 2024
[](../rss.xml)
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
This release fixes 41 bugs (addressing 595 👍). It includes node:http2 server and gRPC server support, ca and cafile support in bun install, Bun.inspect.table, bun build --drop, Promise.try, Buffer.copyBytesFrom, iterable SQLite queries, iterator helpers, and several Node.js compatibility improvements and bugfixes.
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[Support for `node:http2` server and gRPC](bun-v1.1.31.html#support-for-node-http2-server-and-grpc)
In this release of Bun, we added support for our [most upvoted](https://github.com/oven-sh/bun/issues/8823) feature request: HTTP2 server and gRPC support. Bun has supported the node:http2 client since [v1.0.13](bun-v1.0.13.html#http2-client-support), but we didn't support the server, until now.
In Bun, `node:http2` runs 2.4x faster than in Node v23.
> In the next version of Bun
>
> node:http2 server support is implemented. For the same code:
>
> Bun v1.1.31: 128,879 req/s (2.4x faster)
> Node v23.0.0: 52,785 req/s [pic.twitter.com/SIM0I0Td4T](https://t.co/SIM0I0Td4T)
>
> — Bun (@bunjavascript) [October 17, 2024](https://twitter.com/bunjavascript/status/1847014951661326396?ref_src=twsrc%5Etfw)
You can use the [`node:http2`](https://nodejs.org/api/http2.html#core-api) API to create an HTTP2 server.
```
import { createSecureServer } from "node:http2";
import { readFileSync } from "node:fs";
const server = createSecureServer({
key: readFileSync("privkey.pem"),
cert: readFileSync("cert.pem"),
});
server.on("error", (error) => console.error(error));
server.on("stream", (stream, headers) => {
stream.respond({
":status": 200,
"content-type": "text/html; charset=utf-8",
});
stream.end("<h1>Hello from Bun!</h1>");
});
server.listen(3000);
```
With HTTP2 support, you can also use gRPC with packages like [`@grpc/grpc-js`](https://www.npmjs.com/package/@grpc/grpc-js).
```
const grpc = require("@grpc/grpc-js");
const protoLoader = require("@grpc/proto-loader");
const packageDefinition = protoLoader.loadSync("benchmark.proto", {});
const proto = grpc.loadPackageDefinition(packageDefinition).benchmark;
const fs = require("fs");
function ping(call, callback) {
callback(null, { message: "Hello, World" });
}
function main() {
const server = new grpc.Server();
server.addService(proto.BenchmarkService.service, { ping: ping });
const tls =
!!process.env.TLS &&
(process.env.TLS === "1" || process.env.TLS === "true");
const port = process.env.PORT || 50051;
const host = process.env.HOST || "localhost";
let credentials;
if (tls) {
const ca = fs.readFileSync("./cert.pem");
const key = fs.readFileSync("./key.pem");
const cert = fs.readFileSync("./cert.pem");
credentials = grpc.ServerCredentials.createSsl(ca, [
{ private_key: key, cert_chain: cert },
]);
} else {
credentials = grpc.ServerCredentials.createInsecure();
}
server.bindAsync(`${host}:${port}`, credentials, () => {
console.log(
`Server running at ${tls ? "https" : "http"}://${host}:${port}`,
);
});
}
main();
```
## []()[CA support in `bun install`](bun-v1.1.31.html#ca-support-in-bun-install)
You can now configure CA certificates for `bun install`. This is useful when you need to install packages from your company's private registry, or if you want to use self-signed certificate.
bunfig.toml
```
[install]
# The CA certificate as a string
ca = "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
# A path to a CA certificate file. The file can contain multiple certificates.
cafile = "path/to/cafile"
```
If you don't want to change your `bunfig.toml` file, you can also use the `--ca` and `--cafile` flags.
```
bun install --cafile=/path/to/cafile
```
```
bun install --ca="..."
```
If you are using an existing `.npmrc` file, you can also configure CA certificates there.
.npmrc
```
cafile=/path/to/cafile
ca="..."
```
## []()[`bun build --drop`](bun-v1.1.31.html#bun-build-drop)
You can use `--drop` to remove function calls from your JavaScript bundle. This is useful if you want to remove debug code from your production bundle. For example, if you pass `--drop=console`, all calls to `console.log` will be removed from your code.
JavaScript
CLI
JavaScript
```
await Bun.build({
entrypoints: ["./index.tsx"],
outdir: "./out",
drop: ["console", "anyIdentifier.or.propertyAccess"],
})
```
CLI
```
bun build ./index.tsx --outdir ./out --drop=console --drop=anyIdentifier.or.propertyAccess
```
### []()[`bun --drop`](bun-v1.1.31.html#bun-drop)
`--drop` also works at runtime.
index.ts
```
for (let i = 0; i < 3; i++) {
console.log("hello called!");
}
```
Before `--drop`, you'd see `hello called!` 3 times.
```
bun ./index.ts
```
```
hello called!
hello called!
hello called!
```
With `--drop=console`, `console.log` calls get dropped and you don't see `hello called!` anymore.
```
bun --drop=console ./index.ts
```
```
# no output
```
## []()[`Bun.inspect.table()`](bun-v1.1.31.html#bun-inspect-table)
You can now use `Bun.inspect.table` to format tabular data into a string. It is similar to [`console.table`](https://developer.mozilla.org/en-US/docs/Web/API/console/table_static), except it returns a string rather than printing to the console.
```
console.log(
Bun.inspect.table([
{ a: 1, b: 2, c: 3 },
{ a: 4, b: 5, c: 6 },
{ a: 7, b: 8, c: 9 },
]),
);
// ┌───┬───┬───┬───┐
// │ │ a │ b │ c │
// ├───┼───┼───┼───┤
// │ 0 │ 1 │ 2 │ 3 │
// │ 1 │ 4 │ 5 │ 6 │
// │ 2 │ 7 │ 8 │ 9 │
// └───┴───┴───┴───┘
```
You can also pass an array of property names to display only a subset of properties.
```
console.log(
Bun.inspect.table(
[
{ a: 1, b: 2, c: 3 },
{ a: 4, b: 5, c: 6 },
],
["a", "c"],
),
);
// ┌───┬───┬───┐
// │ │ a │ c │
// ├───┼───┼───┤
// │ 0 │ 1 │ 3 │
// │ 1 │ 4 │ 6 │
// └───┴───┴───┘
```
If you want to enable ANSI colors, you can set the `colors` property on the options object.
```
console.log(
Bun.inspect.table(
[
{ a: 1, b: 2, c: 3 },
{ a: 4, b: 5, c: 6 },
],
{
colors: true,
},
),
);
```
## []()[Iterable SQLite queries](bun-v1.1.31.html#iterable-sqlite-queries)
Bun has a built-in [SQLite](../docs/api/sqlite.html) API, that makes it easy to query SQLite databases. Instead of returning an array of rows, you can now return an iterator that yields rows as they are returned from the database.
```
import { Database } from "bun:sqlite";
const sst = new Database(":memory:");
sst.run("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)");
class User {
id: number;
name: string;
email: string;
get nameAndEmail() {
return `${this.name} <${this.email}>`;
}
}
const rows = sst
.query("SELECT * FROM users")
.as(User)
.iterate() // <--- here
// call the .nameAndEmail property on each row
.map((row) => row.nameAndEmail);
for (const row of rows) {
console.log(row);
}
// prints nothing because sst has no users
```
You can also call the `.iterate()` method on a query to get an iterator that yields rows as they are returned from the database.
```
for (const row of db.query("SELECT * FROM users").iterate()) {
console.log(row); // { id: 1, name: "Bun" }
}
```
Thanks to [@Skywalker13](https://github.com/Skywalker13) for implementing this!
## []()[Iterator helpers](bun-v1.1.31.html#iterator-helpers)
In this release of Bun, there are new APIs that make it easier to work with JavaScript iterators and generators. These APIs were introduced in a [TC39 proposal](https://github.com/tc39/proposal-iterator-helpers), and are now available in Safari and Chrome. Thanks to the WebKit team for implementing these APIs, especially [@sosukesuzuki](https://github.com/sosukesuzuki) and [@shvaikalesh](https://github.com/shvaikalesh)!
### []()[`iterator.map(fn)`](bun-v1.1.31.html#iterator-map-fn)
Returns an iterator that yields the results of the `fn` function applied to each value of the original iterator, similar to `Array.prototype.map`.
```
function* range(start: number, end: number): Generator<number> {
for (let i = start; i < end; i++) {
yield i;
}
}
const result = range(3, 5).map((x) => x * 2);
result.next(); // { value: 6, done: false }
```
### []()[`iterator.flatMap(fn)`](bun-v1.1.31.html#iterator-flatmap-fn)
Returns an iterator that yields the values of the original iterator, but flattens the results of the `fn` function, similar to `Array.prototype.flatMap`.
```
function* randomThoughts(): Generator<string> {
yield "Bun is written in Zig";
yield "Bun runs JavaScript and TypeScript";
}
const result = randomThoughts().flatMap((x) => x.split(" "));
result.next(); // { value: "Bun", done: false }
result.next(); // { value: "is", done: false }
// ...
result.next(); // { value: "TypeScript", done: false }
```
### []()[`iterator.filter(fn)`](bun-v1.1.31.html#iterator-filter-fn)
Returns an iterator that only yields values that pass the `fn` predicate, similar to `Array.prototype.filter`.
```
function* range(start: number, end: number): Generator<number> {
for (let i = start; i < end; i++) {
yield i;
}
}
const result = range(3, 5).filter((x) => x % 2 === 0);
result.next(); // { value: 4, done: false }
```
### []()[`iterator.take(n)`](bun-v1.1.31.html#iterator-take-n)
Returns an iterator that yields the first `n` values of the original iterator.
```
function* odds(): Generator<number> {
let i = 1;
while (true) {
yield i;
i += 2;
}
}
const result = odds().take(1);
result.next(); // { value: 1, done: false }
result.next(); // { done: true }
```
### []()[`iterator.drop(n)`](bun-v1.1.31.html#iterator-drop-n)
Returns an iterator that yields all values of the original iterator, except the first `n` values.
```
function* evens(): Generator<number> {
let i = 0;
while (true) {
yield i;
i += 2;
}
}
const result = evens().drop(2);
result.next(); // { value: 4, done: false }
result.next(); // { value: 6, done: false }
```
### []()[`iterator.reduce(fn, initialValue)`](bun-v1.1.31.html#iterator-reduce-fn-initialvalue)
Reduces the values of an iterator with a function, similar to `Array.prototype.reduce`.
```
function* powersOfTwo(): Generator<number> {
let i = 1;
while (true) {
yield i;
i *= 2;
}
}
const result = powersOfTwo()
.take(5)
.reduce((acc, x) => acc + x, 0);
console.log(result); // 15
```
### []()[`iterator.toArray()`](bun-v1.1.31.html#iterator-toarray)
Returns an array that contains all the values of the original iterator. Make sure that the iterator is finite, otherwise this will cause an infinite loop.
```
function* range(start: number, end: number): Generator<number> {
for (let i = start; i < end; i++) {
yield i;
}
}
const result = range(1, 5).toArray();
console.log(result); // [1, 2, 3, 4]
```
### []()[`iterator.forEach(fn)`](bun-v1.1.31.html#iterator-foreach-fn)
Calls the `fn` function on each value of the original iterator, similar to `Array.prototype.forEach`.
```
function* randomThoughts(): Generator<string> {
yield "Bun is written in Zig";
yield "Bun runs JavaScript and TypeScript";
}
const result = randomThoughts().forEach((x) => console.log(x));
// Bun is written in Zig
// Bun runs JavaScript and TypeScript
```
### []()[`iterator.find(fn)`](bun-v1.1.31.html#iterator-find-fn)
Returns the first value of the original iterator that passes the `fn` predicate, similar to `Array.prototype.find`. If no such value exists, it returns `undefined`.
```
function* range(start: number, end: number): Generator<number> {
for (let i = start; i < end; i++) {
yield i;
}
}
const result = range(0, 99).find((x) => x % 100 === 0);
console.log(result); // undefined
```
## []()[Promise.try](bun-v1.1.31.html#promise-try)
The `Promise.try` method is similar to `Promise.resolve`, but it also works with synchronous functions.
```
Promise.try(() => {
return 1 + 1;
}).then((result) => {
console.log(result); // 2
});
```
This is a stage4 TC39 proposal (i.e. it has graduated from proposal to standardized ECMAScript). Thanks to [@rkirsling](https://github.com/rkirsling) for implementing this!
## []()[9x faster `Error.captureStackTrace`](bun-v1.1.31.html#9x-faster-error-capturestacktrace)
> In the next version of Bun
>
> Error.captureStackTrace(err) gets 9x faster [pic.twitter.com/Ej7XW8KPNk](https://t.co/Ej7XW8KPNk)
>
> — Jarred Sumner (@jarredsumner) [October 14, 2024](https://twitter.com/jarredsumner/status/1845736532298383391?ref_src=twsrc%5Etfw)
## []()[`expect(fn).toThrow()` prints the return value if it does not throw](bun-v1.1.31.html#expect-fn-tothrow-prints-the-return-value-if-it-does-not-throw)
Before:
[](https://github.com/user-attachments/assets/7a380fc4-71ef-4c34-b91d-d5aa724cba20)
And now:
[](https://github.com/user-attachments/assets/dca4f20d-175f-4a4e-9f05-9787b536f371)
Thanks to [@nektro](https://github.com/nektro) for implementing this!
## []()[Warn on first idle request timeout](bun-v1.1.31.html#warn-on-first-idle-request-timeout)
> In the next version of Bun
>
> Added a warning when a request times out automatically in Bun.serve() without explicitly passing idleTimeout and without using AbortSignal [pic.twitter.com/krMmUNi14x](https://t.co/krMmUNi14x)
>
> — Jarred Sumner (@jarredsumner) [October 11, 2024](https://twitter.com/jarredsumner/status/1844560929897529417?ref_src=twsrc%5Etfw)
## []()[New error: Mismatched JSX closing tag](bun-v1.1.31.html#new-error-mismatched-jsx-closing-tag)
Previously, the following code would not throw an error, even though it's invalid JSX:
```
const Oopsie = () => {
return (
<h1>
That should be an h1! Not a div.
</div>
);
};
```
We should have always thrown an error here, but we were not. Now we do:
```
❯ bun build Oopsie.tsx
5 | </div>
^
error: Expected closing JSX tag to match opening tag "<h1>"
at Oopsie.tsx:5:7
3 | <h1>
^
note: Opening tag here:
at Oopsie.tsx:3:6
```
Thanks to [@DonIsaac](https://github.com/DonIsaac) for fixing this!
## []()[Node.js compatibility](bun-v1.1.31.html#node-js-compatibility)
### []()[New: `Buffer.copyBytesFrom(view[, offset[, length]])`](bun-v1.1.31.html#new-buffer-copybytesfrom-view-offset-length)
You can now use the `Buffer.copyBytesFrom` method to create a new `Buffer` by copying bytes from a typed array or DataView.
```
const u16 = new Uint16Array([0, 0xffff]);
const buf = Buffer.copyBytesFrom(u16, 1, 1);
u16[1] = 0;
console.log(buf.length); // 2
console.log(buf[0]); // 255
console.log(buf[1]); // 255
```
Thanks to [@nektro](https://github.com/nektro) for implementing this!
### []()[Fixed: `fs.open()`](bun-v1.1.31.html#fixed-fs-open)
We fixed various issues in `fs.open()`, so it more closely matches Node.js's behavior. Thanks to [@nektro](https://github.com/nektro) for fixing this!
### []()[Fixed: Node-API bugs](bun-v1.1.31.html#fixed-node-api-bugs)
We've been working on fixing bugs in Bun's implementation of Node-API. Thanks to [@190n](https://github.com/190n) for fixing these bugs!
- `napi_create_empty_array` does not crash when the array is too large
- `napi_create_empty_array` uses empty slots, instead of `undefined` values
- `napi_get_value_int32` uses the same bitwise conversions as in JavaScript
- `napi_get_value_int64` now matches Node.js's behavior
- `napi_throw_error` and `napi_create_error` are now tested and don't sometimes crash
### []()[Fixed: Setting `UV_THREADPOOL_SIZE`](bun-v1.1.31.html#fixed-setting-uv-threadpool-size)
There are some Node.js packages that set the `UV_THREADPOOL_SIZE` environment variable to control the number of threads used by libuv. While Bun only uses libuv on Windows, and only for some APIs, it will now respect this environment variable.
### []()[Fixed: `Buffer.from` JSON serialization](bun-v1.1.31.html#fixed-buffer-from-json-serialization)
When you call `JSON.stringify` on a Buffer, it adds `{type: "Buffer", value: [...buffer contents]}` to the JSON. This already worked, but Buffer.from would not accept this JSON. Now it does.
```
const buf = Buffer.from([1, 2, 3]);
JSON.stringify(buf); // "{"type":"Buffer","data":[1,2,3]}"
Buffer.from(JSON.parse('{"type":"Buffer","data":[1,2,3]}'))[0] === 1; // works
```
Previously, this would throw:
```
TypeError: The first argument must be of type string or an instance of Buffer, ArrayBuffer, or Array or an Array-like Object.
at [file]:3:20
```
Thanks to [@nektro](https://github.com/nektro) for fixing this!
### []()[Fixed: `node:child_process.SpawnResult` `.stderr` should be null if `.stdio` is not `"pipe"`](bun-v1.1.31.html#fixed-node-child-process-spawnresult-stderr-should-be-null-if-stdio-is-not-pipe)
```
import child_process from "node:child_process";
const res = child_process.spawn("ls", {
stdio: "inherit",
});
console.log(res.stderr); // now 'null'
```
This unblocked use of the [`tinyexec`](https://www.npmjs.com/package/tinyexec) package.
Thanks to [@nektro](https://github.com/nektro) for fixing this!
## []()[Bugs squashed](bun-v1.1.31.html#bugs-squashed)
### []()[Fixed: Format of `console.table` with numeric keys](bun-v1.1.31.html#fixed-format-of-console-table-with-numeric-keys)
We fixed a bug where `console.table` would format with incorrect spacing when the keys were numeric. Thanks to [@pfgithub](https://github.com/pfgithub) for fixing this!
```
console.table({test: {"10": 123, "100": 154}});
// Before
┌──────┬─────┬─────┐
│ │ 10 │ 100 │
├──────┼─────┼─────┤
│ test │ │ │
└──────┴─────┴─────┘
// After
┌─────────┬─────┬─────┐
│ (index) │ 10 │ 100 │
├─────────┼─────┼─────┤
│ test │ 123 │ 154 │
└─────────┴─────┴─────┘
```
### []()[Fixed: Crash using `Bun.color`](bun-v1.1.31.html#fixed-crash-using-bun-color)
In a recent release, we introduced [`Bun.color`](../docs/api/color.html), an API that allows you to parse and transform colors in different formats, including css, ansi, hex, rgb, hsl, and more.
We fixed a bug where `Bun.color` would crash if you did not pass it a format string.
### []()[Fixed: Regression with `instanceof`](bun-v1.1.31.html#fixed-regression-with-instanceof)
An `instanceof` regression introduced in Bun v1.1.30 through a WebKit upgrade has been fixed. The bug could be caused by JavaScript code storing the output value of `instanceof` in the same variable as the input. The error message would look like:
```
error: [BUG] Unreachable
at ... (input.js:2247:47)
```
This bug was most often seen when using [`sass`](https://www.npmjs.com/package/sass) with source maps enabled.
Fixed thanks to [@hyjorc1](https://github.com/hyjorc1)!
### []()[Fixed: Transpiler bug with `using` and generators](bun-v1.1.31.html#fixed-transpiler-bug-with-using-and-generators)
We fixed a bug where a variable declaration before a `using` statement would cause the transpiler to hoist a generator outside the scope of the `using` declaration. This would cause a `ReferenceError`, but has now been fixed thanks to [@snoglobe](https://github.com/snoglobe).
### []()[Fixed: File permissions with `bun install`](bun-v1.1.31.html#fixed-file-permissions-with-bun-install)
Some npm packages are published with incorrect file permissions, we added a check in Bun to ensure that files extracted from an npm package are at-least readable. This matches the behavior of `npm install`.
### []()[Fixed: Missing metadata publishing with `bun publish`](bun-v1.1.31.html#fixed-missing-metadata-publishing-with-bun-publish)
A bug was fixed where `bun publish` was sending publish requests without important package metadata, including dependencies and binaries from `bin` or `directories.bin`. This would cause published packages to install incorrectly due to missing transitive dependencies and binaries in `node_modules/.bin`.
### []()[Fixed: empty string argument for `fs.mkdir`](bun-v1.1.31.html#fixed-empty-string-argument-for-fs-mkdir)
An integer overflow caused by passing an empty string to `fs.mkdir` has been fixed. This would only happen when the `recursive` option was set to `true`.
```
const fs = require("fs");
fs.mkdirSync("", { recursive: true }); // throws ENOENT
```
### []()[Fixed: fetch `keepalive` option](bun-v1.1.31.html#fixed-fetch-keepalive-option)
The `keepalive` option for `fetch` was previously ignored. Now it disables the "Connection: keep-alive" header from being sent by default.
```
const res = await fetch("https://example.com", { keepalive: false });
console.log(res.headers.get("connection")); // "close"
```
## []()[Thanks to 19 contributors!](bun-v1.1.31.html#thanks-to-19-contributors)
- [@190n](https://github.com/190n)
- [@cirospaciari](https://github.com/cirospaciari)
- [@deiga](https://github.com/deiga)
- [@DonIsaac](https://github.com/DonIsaac)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Electroid](https://github.com/Electroid)
- [@FaSe22](https://github.com/FaSe22)
- [@fel1x-developer](https://github.com/fel1x-developer)
- [@huseeiin](https://github.com/huseeiin)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@pfgithub](https://github.com/pfgithub)
- [@refi64](https://github.com/refi64)
- [@RiskyMH](https://github.com/RiskyMH)
- [@Skywalker13](https://github.com/Skywalker13)
- [@snoglobe](https://github.com/snoglobe)
- [@SunsetTechuila](https://github.com/SunsetTechuila)
- [@zackradisic](https://github.com/zackradisic)
* * *
#### [Bun v1.1.30](bun-v1.1.30.html)
#### [Bun v1.1.32](bun-v1.1.32.html)
On this page
- [Support for `node:http2` server and gRPC](bun-v1.1.31.html#support-for-node-http2-server-and-grpc)
- [CA support in `bun install`](bun-v1.1.31.html#ca-support-in-bun-install)
- [`bun build --drop`](bun-v1.1.31.html#bun-build-drop)
- [`bun --drop`](bun-v1.1.31.html#bun-drop)
- [`Bun.inspect.table()`](bun-v1.1.31.html#bun-inspect-table)
- [Iterable SQLite queries](bun-v1.1.31.html#iterable-sqlite-queries)
- [Iterator helpers](bun-v1.1.31.html#iterator-helpers)
- [`iterator.map(fn)`](bun-v1.1.31.html#iterator-map-fn)
- [`iterator.flatMap(fn)`](bun-v1.1.31.html#iterator-flatmap-fn)
- [`iterator.filter(fn)`](bun-v1.1.31.html#iterator-filter-fn)
- [`iterator.take(n)`](bun-v1.1.31.html#iterator-take-n)
- [`iterator.drop(n)`](bun-v1.1.31.html#iterator-drop-n)
- [`iterator.reduce(fn, initialValue)`](bun-v1.1.31.html#iterator-reduce-fn-initialvalue)
- [`iterator.toArray()`](bun-v1.1.31.html#iterator-toarray)
- [`iterator.forEach(fn)`](bun-v1.1.31.html#iterator-foreach-fn)
- [`iterator.find(fn)`](bun-v1.1.31.html#iterator-find-fn)
- [Promise.try](bun-v1.1.31.html#promise-try)
- [9x faster `Error.captureStackTrace`](bun-v1.1.31.html#9x-faster-error-capturestacktrace)
- [`expect(fn).toThrow()` prints the return value if it does not throw](bun-v1.1.31.html#expect-fn-tothrow-prints-the-return-value-if-it-does-not-throw)
- [Warn on first idle request timeout](bun-v1.1.31.html#warn-on-first-idle-request-timeout)
- [New error: Mismatched JSX closing tag](bun-v1.1.31.html#new-error-mismatched-jsx-closing-tag)
- [Node.js compatibility](bun-v1.1.31.html#node-js-compatibility)
- [New: `Buffer.copyBytesFrom(view[, offset[, length]])`](bun-v1.1.31.html#new-buffer-copybytesfrom-view-offset-length)
- [Fixed: `fs.open()`](bun-v1.1.31.html#fixed-fs-open)
- [Fixed: Node-API bugs](bun-v1.1.31.html#fixed-node-api-bugs)
- [Fixed: Setting `UV_THREADPOOL_SIZE`](bun-v1.1.31.html#fixed-setting-uv-threadpool-size)
- [Fixed: `Buffer.from` JSON serialization](bun-v1.1.31.html#fixed-buffer-from-json-serialization)
- [Fixed: `node:child_process.SpawnResult` `.stderr` should be null if `.stdio` is not `"pipe"`](bun-v1.1.31.html#fixed-node-child-process-spawnresult-stderr-should-be-null-if-stdio-is-not-pipe)
- [Bugs squashed](bun-v1.1.31.html#bugs-squashed)
- [Fixed: Format of `console.table` with numeric keys](bun-v1.1.31.html#fixed-format-of-console-table-with-numeric-keys)
- [Fixed: Crash using `Bun.color`](bun-v1.1.31.html#fixed-crash-using-bun-color)
- [Fixed: Regression with `instanceof`](bun-v1.1.31.html#fixed-regression-with-instanceof)
- [Fixed: Transpiler bug with `using` and generators](bun-v1.1.31.html#fixed-transpiler-bug-with-using-and-generators)
- [Fixed: File permissions with `bun install`](bun-v1.1.31.html#fixed-file-permissions-with-bun-install)
- [Fixed: Missing metadata publishing with `bun publish`](bun-v1.1.31.html#fixed-missing-metadata-publishing-with-bun-publish)
- [Fixed: empty string argument for `fs.mkdir`](bun-v1.1.31.html#fixed-empty-string-argument-for-fs-mkdir)
- [Fixed: fetch `keepalive` option](bun-v1.1.31.html#fixed-fetch-keepalive-option)
- [Thanks to 19 contributors!](bun-v1.1.31.html#thanks-to-19-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.32.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/blog/bun-v1.1.33.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.33
* * *
[Dylan Conway](https://github.com/dylan-conway) · October 24, 2024
[](../rss.xml)
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
This release fixes 8 bugs including: JSX symbol collisions with imports, `bun install` slowdowns, skipping optional dependencies, optional dependency postinstall failures, and an assertion failure in the CSS parser.
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[Fixed: `NPM_CONFIG_TOKEN` environment variable](bun-v1.1.33.html#fixed-npm-config-token-environment-variable)
A bug reading the `NPM_CONFIG_TOKEN` environment variable due to lowercase letters was fixed. The diff was:
```
- "NPM_CONFIG_token",
+ "NPM_CONFIG_TOKEN",
```
## []()[Reduced `bun install` max simultaneous connections](bun-v1.1.33.html#reduced-bun-install-max-simultaneous-connections)
`bun install` was using 256 as the default maximum number of simultaneous network connections. Allowing this many connections at once could cause install slowdowns while fetching dependency tarballs and manifests. We've reduced the default to 64 with and without a proxy.
## []()[Fixed: `optional = false` in `bunfig.toml`](bun-v1.1.33.html#fixed-optional-false-in-bunfig-toml)
Our docs mention setting `optional = false` in `bunfig.toml` will skip optional dependencies during installs, but the implementation was missing. This is now working as expected thanks to [@Eckhardt-D](https://github.com/Eckhardt-D)!
bunfig.toml
```
[install]
optional = false
```
## []()[Deleting optional dependencies on postinstall failure](bun-v1.1.33.html#deleting-optional-dependencies-on-postinstall-failure)
When an optional dependency lifecycle script fails, bun will now ignore the error and continue with the installation. Additionally, the directory will be deleted from `node_modules` to prevent unexpected errors from using a half-installed package.
Fixed thanks to [@dylan-conway](https://github.com/dylan-conway)!
## []()[Fixed: JSX symbol collisions](bun-v1.1.33.html#fixed-jsx-symbol-collisions)
A bug was fixed where imports sharing the same name as a JSX symbol would cause bun to fail to include the JSX import source in the transpiled output, resulting in a reference error. For example, running tests in the [`hono`](https://github.com/honojs/hono) repository:
```
bun test runtime-tests/bun/index.test.tsx
```
```
✗ JSX Middleware > Should return rendered HTML with Layout [0.12ms]
254 | app.post('/about/some/thing', (c) => c.text('About Page 3tier'))
255 | app.get('/bravo', (c) => c.html('Bravo Page'))
256 | app.get('/Charlie', async (c, next) => {
257 | c.setRenderer((content, head) => {
258 | return c.html(
259 | <html>
^
ReferenceError: Can't find variable: jsx
at /Users/dylan/code/hono/runtime-tests/bun/index.test.tsx:259:11
at /Users/dylan/code/hono/src/compose.ts:74:23
```
Fixed thanks to [@snoglobe](https://github.com/snoglobe)!
## []()[Fixed: assertion failure in the CSS parser](bun-v1.1.33.html#fixed-assertion-failure-in-the-css-parser)
A hashing function in the CSS parser was casting a `u64` to a `u32` without telling zig safety checks to ignore truncating non-zero bits. This was fixed by using the `@truncate` zig builtin function.
## []()[Single quotes in module resolution error messages](bun-v1.1.33.html#single-quotes-in-module-resolution-error-messages)
When bun fails to resolve a module or package, the error message has been changed to use single quotes instead of double quotes. This fixes the [`optional-require`](https://www.npmjs.com/package/optional-require) package, which checks for the package name surrounded by single quotes.
index.js
```
require('does-not-exist');
// before: Cannot find package "does-not-exist" from "/path/to/index.js"
// after: Cannot find package 'does-not-exist' from '/path/to/index.js'
```
Fixed thanks to [@nektro](https://github.com/nektro)!
## []()[Thanks to 10 contributors!](bun-v1.1.33.html#thanks-to-10-contributors)
- [@CanadaHonk](https://github.com/CanadaHonk)
- [@cirospaciari](https://github.com/cirospaciari)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Eckhardt-D](https://github.com/Eckhardt-D)
- [@Electroid](https://github.com/Electroid)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@lirantal](https://github.com/lirantal)
- [@Nanome203](https://github.com/Nanome203)
- [@nektro](https://github.com/nektro)
- [@snoglobe](https://github.com/snoglobe)
* * *
#### [Bun v1.1.32](bun-v1.1.32.html)
#### [Bun v1.1.34](bun-v1.1.34.html)
On this page
- [Fixed: `NPM_CONFIG_TOKEN` environment variable](bun-v1.1.33.html#fixed-npm-config-token-environment-variable)
- [Reduced `bun install` max simultaneous connections](bun-v1.1.33.html#reduced-bun-install-max-simultaneous-connections)
- [Fixed: `optional = false` in `bunfig.toml`](bun-v1.1.33.html#fixed-optional-false-in-bunfig-toml)
- [Deleting optional dependencies on postinstall failure](bun-v1.1.33.html#deleting-optional-dependencies-on-postinstall-failure)
- [Fixed: JSX symbol collisions](bun-v1.1.33.html#fixed-jsx-symbol-collisions)
- [Fixed: assertion failure in the CSS parser](bun-v1.1.33.html#fixed-assertion-failure-in-the-css-parser)
- [Single quotes in module resolution error messages](bun-v1.1.33.html#single-quotes-in-module-resolution-error-messages)
- [Thanks to 10 contributors!](bun-v1.1.33.html#thanks-to-10-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.34.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.34
* * *
[Dylan Conway](https://github.com/dylan-conway) · November 2, 2024
[](../rss.xml)
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
This release fixes 64 bugs (addressing 62 👍). It introduces `Bun.randomUUIDv7`, reduced memory usage for long-running processes, `napi_type_tag_object` and `napi_check_object_type_tag`, redacted secrets from config logs, `ReadableStream` and HTTP/1.1 spec fixes, and several `bun install` and Node.js compatibility improvements.
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
### []()[New: `Bun.randomUUIDv7()`](bun-v1.1.34.html#new-bun-randomuuidv7)
`Bun.randomUUIDv7()` returns a [UUID v7](https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-01.html#name-uuidv7-layout-and-bit-order), a monotonic UUID suitable for sorting and databases.
index.ts
```
import { randomUUIDv7 } from "bun";
const id = randomUUIDv7();
// => "0192ce11-26d5-7dc3-9305-1426de888c5a"
```
### []()[Long-running processes use less memory](bun-v1.1.34.html#long-running-processes-use-less-memory)
While your application sleeps in the event loop, the garbage collector runs and frees more memory. This reduces memory usage for long-running processes.
> In the next version of Bun
>
> Long-lived processes use a little less memory [pic.twitter.com/Q71tY0kU5r](https://t.co/Q71tY0kU5r)
>
> — Jarred Sumner (@jarredsumner) [October 29, 2024](https://twitter.com/jarredsumner/status/1851178003486949719?ref_src=twsrc%5Etfw)
Sample code
index.js
```
console.clear();
console.log("Starting...");
const iterationCount = 100000;
globalThis.signals = new Array(iterationCount);
globalThis.requests = new Array(iterationCount);
var total = 0;
setInterval(() => {
const rss = (process.memoryUsage.rss() / 1024 / 1024) | 0;
const objectTypeCounts = require("bun:jsc").heapStats().objectTypeCounts;
console.table({
"Memory usage MB (RSS)": rss,
"AbortSignal alive count": objectTypeCounts.AbortSignal || 0,
"new AbortSignal() calls": total,
"Uptime (seconds)": Math.floor(process.uptime()),
});
}, 10000);
while (true) {
for (let i = 0; i < iterationCount; i++) {
const req = new Request("https://example.com/");
requests[i] = req;
signals[i] = AbortSignal.any([req.signal, new AbortController().signal]);
}
total += iterationCount;
await Bun.sleep(1000);
}
```
### []()[`napi_type_tag_object` and `napi_check_object_type_tag`](bun-v1.1.34.html#napi-type-tag-object-and-napi-check-object-type-tag)
Bun v1.1.34 adds Node-API support for `napi_type_tag_object` and `napi_check_object_type_tag`. These functions allow associating a [type tag](https://nodejs.org/api/n-api.html#napi_type_tag) with objects, and unblocks the [tree-sitter](https://www.npmjs.com/package/tree-sitter) package.
Implemented thanks to [@190n](https://github.com/190n)!
### []()[Redacted secrets in `bunfig.toml` and `.npmrc` logs](bun-v1.1.34.html#redacted-secrets-in-bunfig-toml-and-npmrc-logs)
Bun will now redact secrets that appear in `bunfig.toml` and `.npmrc` logs for syntax errors or invalid configurations. UUIDs, npm secret tokens, url passwords, and values following `_auth`, `_authToken`, `email`, `_password`, and `token` will be replaced with `*`.
bunfig.toml
```
[registry]
a = { b = "http://user:pass@site.org", ; token = "ooops" }
```
```
$ bun install
- 2 | a = { b = "http://user:pass@site.org", ; token = "ooops" }
+ 2 | a = { b = "http://user:****@site.org", ; token = "*****" }
^
error: Unexpected semicolon
at /path/to/bunfig.toml:2:40
SyntaxError: failed to load bunfig
```
Thanks to [@dylan-conway](https://github.com/dylan-conway)!
### []()[Inline `process.versions.bun` in `bun build --compile`](bun-v1.1.34.html#inline-process-versions-bun-in-bun-build-compile)
When you use `bun build --compile`, Bun will now inline usages of `process.versions.bun`.
This means that the following code can be used to statically load node native addons when using `bun build --compile`:
```
const bindings =
typeof process.versions.bun === "string"
? // `bun build --compile` will bundle the prebuilt .node file into the standalone build
require(`./preload/${process.platform}-${process.arch}/my-addon.node`) // -> ./preload/linux-x64/my-addon.node
: // Otherwise, use node-gyp-build to resolve the .node file at runtime
require("node-gyp-build")(
path.join(
__dirname,
`${process.platform}-${process.arch}`,
`my-addon.node`,
),
);
```
Thanks to [@youennf](https://github.com/youennf)!
## []()[Bugfixes](bun-v1.1.34.html#bugfixes)
### []()[Fixed: ReadableStream spec updates](bun-v1.1.34.html#fixed-readablestream-spec-updates)
We've updated our ReadableStream implementation based on WebKit's upstream changes, fixing several spec issues including:
- An error on piped ReadableStream could lead to an unhandled promise rejection
- `pipeThrough` and `pipeTo` promises were not marked as handled
- An error in a `ReadableStream` was rejecting closed promises before erroring read promises
- `ReadableStreamDefaultReader.releaseLock` was rejecting pending read promises
Thanks to [@pfgithub](https://github.com/pfgithub) and @youennf (via WebKit) for the important fixes!
### []()[Fixed: `bun install` failing with `patchedDependencies` and `bin` fields](bun-v1.1.34.html#fixed-bun-install-failing-with-patcheddependencies-and-bin-fields)
A bug causing patched dependencies to fail to install when `package.json` also contained a `bin` field has been fixed. Now, both can exist in `package.json` and patches will be applied correctly.
package.json
```
{
"name": "pkg",
"version": "1.0.0",
"bin": "pkg.js",
"dependencies": {
"zod": "3.23.8"
},
"patchedDependencies": {
"zod@3.23.8": "patches/zod@3.23.8.patch"
}
}
```
Fixed thanks to [@dylan-conway](https://github.com/dylan-conway)!
### []()[Fixed: Migrating `package-lock.json` with dependency on the root package](bun-v1.1.34.html#fixed-migrating-package-lock-json-with-dependency-on-the-root-package)
Given the following `package.json`:
package.json
```
{
"name": "root-dep",
"dependencies": {
// becomes `./node_modules/root-dep`, a symlink to the root package
"root-dep": "."
}
}
```
`npm` will generate a `package-lock.json` with two packages: one for the root package and one for the dependency on the root package. The root package dependency will have a `resolved` value of an empty string. When migrating `package.json`s with this structure, Bun would panic because a root dependency of this kind was not expected.
Fixed thanks to [@dylan-conway](https://github.com/dylan-conway)!
### []()[Fixed: Multiple output files without an `outdir` in `Bun.build`](bun-v1.1.34.html#fixed-multiple-output-files-without-an-outdir-in-bun-build)
A bug was fixed where calling `Bun.build` with multiple output files and no `outdir` would fail with a message saying an output directory was required. `Bun.build` defaults to an in-memory build when `outdir` is undefined, so this error was incorrect. Now, `Bun.build` will create a build with multiple output files in-memory without error.
build.ts
```
const result = await Bun.build({
entrypoints: ["main.ts", "index.html"],
})
for (const output of result.outputs) {
console.log(output.path);
}
// "./main.js"
// "./index.js"
// "./index-7qpw8w4s.html"
```
Fixed thanks to [@BjornTheProgrammer](https://github.com/BjornTheProgrammer)!
### []()[Fixed: Amazon Linux 2 regression](bun-v1.1.34.html#fixed-amazon-linux-2-regression)
A regression in Bun v1.1.33 where Amazon Linux 2 was no longer supported has been fixed.
The bug was caused by depending on the libc `powf` function, which used a later version of glibc than Amazon Linux 2 supported. We have added a regression test that ensures we don't add dependencies on symbols that are not available in glibc versions 2.27. This bug also impacted Vercel builds when using their Node.js v18 image.
### []()[Fixed: `bun:sqlite` regression on arm64 Linux with glibc-compat](bun-v1.1.34.html#fixed-bun-sqlite-regression-on-arm64-linux-with-glibc-compat)
A regression where using `bun:sqlite` via glibc inside of alpine linux on Linux would lead to a crash has been fixed.
### []()[Added: `node:net` Socket's `bytesWritten` property](bun-v1.1.34.html#added-node-net-socket-s-byteswritten-property)
The `bytesWritten` property on `node:net` `Socket` objects is now correctly implemented, thanks to [@cirospaciari](https://github.com/cirospaciari).
This also makes the `encoding` option in `net.Socket` consistent with Node.js' behavior.
### []()[Fixed: `node:fs`' options parsing with `"encoding"` option](bun-v1.1.34.html#fixed-node-fs-options-parsing-with-encoding-option)
The `encoding` option in `node:fs` was not being parsed correctly in certain node:fs functions. This led to throwing errors when Node does not throw them. This has been fixed.
### []()[Fixed: Potential crash when appending a FormData from a `File` object created from another `File`](bun-v1.1.34.html#fixed-potential-crash-when-appending-a-formdata-from-a-file-object-created-from-another-file)
A bug where appending a `FormData` from a Web `File` object created from another `File` could cause a crash in certain cases has been fixed. This impacted the OpenAI package.
### []()[Fixed: napi property methods on non-objects](bun-v1.1.34.html#fixed-napi-property-methods-on-non-objects)
Node-API functions support calling methods on primitive values like string literals and numbers. This is consistent with JavaScript (like `"foo".slice()`), but in native code, to improve performance, the underlying implementation treats these values differently than in JavaScript.
A bug where we were throwing an error when calling Node-API functions like `String.prototype.slice` or `Number.prototype.toFixed` on non-objects has been fixed, thanks to [@190n](https://github.com/190n).
### []()[Fixed: `TextEncoder.encode(undefined)` incorrect result](bun-v1.1.34.html#fixed-textencoder-encode-undefined-incorrect-result)
`TextEncoder.encode()` stringifies input, unless the input is `undefined`. Bun was incorrectly including `undefined` in the string conversion, where it should have returned an empty `Uint8Array`.
index.js
```
const encoder = new TextEncoder();
console.log(encoder.encode());
// Before: Uint8Array(9) [ 117, 110, 100, 101, 102, 105, 110, 101, 100 ]
// Bun v1.1.34: Uint8Array(0) []
```
Fixed thanks to [@dylan-conway](https://github.com/dylan-conway)!
### []()[Fixed: Crash in `Error.prepareStackTrace` argument conversion](bun-v1.1.34.html#fixed-crash-in-error-preparestacktrace-argument-conversion)
A bug was fixed where calling `Error.prepareStackTrace()` with an array of non-CallSite values would crash. Now, values are stringified for the error stack trace as expected.
index.js
```
const result = Error.prepareStackTrace(new Error("oops"), [{ a: 1 }]);
console.log(result);
// Error: oops
// at [object Object]
```
### []()[Fixed: Several HTTP spec issues](bun-v1.1.34.html#fixed-several-http-spec-issues)
Our [uWebSockets](https://github.com/uNetworking/uWebSockets) dependency was updated and added additional HTTP/1.1 spec compliance tests, addressing several HTTP spec issues involving invalid headers.
Thanks to Alex Hultman for the important fix!
### []()[Fixed: `EventEmitter.name`](bun-v1.1.34.html#fixed-eventemitter-name)
A bug was fixed where `EventEmitter.name` was set to `EventEmitter2` instead of `EventEmitter`.
index.js
```
import { EventEmitter } from "events";
console.log(EventEmitter.name);
// Before: EventEmitter2
// Bun v1.1.34: EventEmitter
```
### []()[Fixed: additional arguments escaping with `package.json` scripts](bun-v1.1.34.html#fixed-additional-arguments-escaping-with-package-json-scripts)
Arguments were not being escaped correctly when passed to a script in `package.json`. This has been fixed thanks to [@pfgithub](https://github.com/pfgithub)!
Given the following `package.json`:
package.json
```
{
"scripts": {
"args": "echo"
}
}
```
`bun run args \$HOME` would previously print `/path/to/home` instead of `$HOME`.
### []()[Improved: Removed warning for unused registry options in `.npmrc`](bun-v1.1.34.html#improved-removed-warning-for-unused-registry-options-in-npmrc)
Previously, Bun would print a warning if an option from `npmrc` was set for a registry other than the default registry (set with `registry=<...>`). We've removed this warning, as it was unnecessary.
Thanks to [@dylan-conway](https://github.com/dylan-conway)!
### []()[Improved: `package.json` formatting with first dependency from `bun add`](bun-v1.1.34.html#improved-package-json-formatting-with-first-dependency-from-bun-add)
When adding the first dependency to `dependencies` with `bun add/install/update`, the resulting `package.json` will now have nicer formatting.
```
bun add jquery@4.0.0-beta.2
```
package.json
```
{
"name": "dependency-formatting",
"dependencies": {
"jquery": "4.0.0-beta.2"
},
"dependencies": { "jquery": "4.0.0-beta.2" }
}
```
Thanks to [@nektro](https://github.com/nektro)!
### []()[Improved: `bun install -g <package>` will not link transitive binaries](bun-v1.1.34.html#improved-bun-install-g-package-will-not-link-transitive-binaries)
Installing a package globally will no longer link binaries from transitive dependencies to the global `bin` directory. This will prevent placing unexpected binaries in PATH.
Thanks to [@dylan-conway](https://github.com/dylan-conwawy)!
## []()[Thanks to 14 contributors!](bun-v1.1.34.html#thanks-to-14-contributors)
- [@190n](https://github.com/190n)
- [@arthurvanl](https://github.com/arthurvanl)
- [@BjornTheProgrammer](https://github.com/BjornTheProgrammer)
- [@cirospaciari](https://github.com/cirospaciari)
- [@DonIsaac](https://github.com/DonIsaac)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Electroid](https://github.com/Electroid)
- [@fel1x-developer](https://github.com/fel1x-developer)
- [@gjungb](https://github.com/gjungb)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@pfgithub](https://github.com/pfgithub)
- [@zackradisic](https://github.com/zackradisic)
* * *
#### [Bun v1.1.33](bun-v1.1.33.html)
#### [Bun v1.1.35](bun-v1.1.35.html)
On this page
- [Bugfixes](bun-v1.1.34.html#bugfixes)
- [Fixed: ReadableStream spec updates](bun-v1.1.34.html#fixed-readablestream-spec-updates)
- [Fixed: `bun install` failing with `patchedDependencies` and `bin` fields](bun-v1.1.34.html#fixed-bun-install-failing-with-patcheddependencies-and-bin-fields)
- [Fixed: Migrating `package-lock.json` with dependency on the root package](bun-v1.1.34.html#fixed-migrating-package-lock-json-with-dependency-on-the-root-package)
- [Fixed: Multiple output files without an `outdir` in `Bun.build`](bun-v1.1.34.html#fixed-multiple-output-files-without-an-outdir-in-bun-build)
- [Fixed: Amazon Linux 2 regression](bun-v1.1.34.html#fixed-amazon-linux-2-regression)
- [Fixed: `bun:sqlite` regression on arm64 Linux with glibc-compat](bun-v1.1.34.html#fixed-bun-sqlite-regression-on-arm64-linux-with-glibc-compat)
- [Added: `node:net` Socket's `bytesWritten` property](bun-v1.1.34.html#added-node-net-socket-s-byteswritten-property)
- [Fixed: `node:fs`' options parsing with `"encoding"` option](bun-v1.1.34.html#fixed-node-fs-options-parsing-with-encoding-option)
- [Fixed: Potential crash when appending a FormData from a `File` object created from another `File`](bun-v1.1.34.html#fixed-potential-crash-when-appending-a-formdata-from-a-file-object-created-from-another-file)
- [Fixed: napi property methods on non-objects](bun-v1.1.34.html#fixed-napi-property-methods-on-non-objects)
- [Fixed: `TextEncoder.encode(undefined)` incorrect result](bun-v1.1.34.html#fixed-textencoder-encode-undefined-incorrect-result)
- [Fixed: Crash in `Error.prepareStackTrace` argument conversion](bun-v1.1.34.html#fixed-crash-in-error-preparestacktrace-argument-conversion)
- [Fixed: Several HTTP spec issues](bun-v1.1.34.html#fixed-several-http-spec-issues)
- [Fixed: `EventEmitter.name`](bun-v1.1.34.html#fixed-eventemitter-name)
- [Fixed: additional arguments escaping with `package.json` scripts](bun-v1.1.34.html#fixed-additional-arguments-escaping-with-package-json-scripts)
- [Improved: Removed warning for unused registry options in `.npmrc`](bun-v1.1.34.html#improved-removed-warning-for-unused-registry-options-in-npmrc)
- [Improved: `package.json` formatting with first dependency from `bun add`](bun-v1.1.34.html#improved-package-json-formatting-with-first-dependency-from-bun-add)
- [Improved: `bun install -g <package>` will not link transitive binaries](bun-v1.1.34.html#improved-bun-install-g-package-will-not-link-transitive-binaries)
- [Thanks to 14 contributors!](bun-v1.1.34.html#thanks-to-14-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.35.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.35
* * *
[Dylan Conway](https://github.com/dylan-conway) · November 19, 2024
[](../rss.xml)
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
This release fixes 46 bugs (addressing 570 👍). It introduces Musl LibC support, JUnit XML test output, 6 MB binary size reduction, `Worker` `preload` option, faster `fs.readFile` for small files, deep equality support for `Headers` and `URLSearchParams`, `node:net` compatibility improvements, unicode import bugfixes, and several `bun install` fixes.
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
### []()[Native support for Musl & Alpine Linux](bun-v1.1.35.html#native-support-for-musl-alpine-linux)
Bun v1.1.35 ships binaries with native support for [Musl LibC](https://musl.libc.org) and is now tested on every commit. This was our #1 rated outstanding feature request with over 281 :+1:. If you are running on Alpine Linux the Bun install script will now download these binaries.
This change additionally affects any use of the Docker image `oven/bun:alpine`. Previously, we relied on a glibc compatibility hack to run Bun on Alpine Linux - and now it's native.
Thanks to [@nektro](https://github.com/nektro) and [@Electroid](https://github.com/Electroid)!
### []()[Bun gets 6 MB smaller](bun-v1.1.35.html#bun-gets-6-mb-smaller)
We've reduced the size of the Bun binary by 3.5 MB on Windows, and by 6 MB on Linux and macOS. This was achieved by allocating large structs on the heap instead of the stack, and by removing unwind tables created by our dependencies.
### []()[JUnit XML output support for `bun test`](bun-v1.1.35.html#junit-xml-output-support-for-bun-test)
Bun v1.1.35 adds support for JUnit output in `bun test`. It can be enabled through the command line with `--reporter` or through `bunfig.toml`.
To enable the JUnit reporter and write the output to `junit.xml`:
```
bun test --reporter junit --reporter-outfile junit.xml
```
Or in `bunfig.toml`:
bunfig.toml
```
[test.reporter]
junit = "junit.xml"
```
JUnit is a commonly used XML format for CI/CD test integration with Jenkins, CircleCI, GitLab CI, and more.
> In the next version of Bun
>
> bun test supports reporting test results in the junit xml format, which is used in CI/Cd like GitLab [pic.twitter.com/MbP8Q5HQxk](https://t.co/MbP8Q5HQxk)
>
> — Bun (@bunjavascript) [November 19, 2024](https://twitter.com/bunjavascript/status/1858816473751580912?ref_src=twsrc%5Etfw)
### []()[`preload` option for `Worker`](bun-v1.1.35.html#preload-option-for-worker)
Bun v1.1.35 introduces a `preload` option for `Worker`, which allows you to evaluate a script before the worker script is executed.
preload.js
```
globalThis.preloaded = true;
```
index.js
```
const worker = new Worker(new URL("worker.js", import.meta.url).href, {
preload: new URL("preload.js", import.meta.url).href
});
```
worker.js
```
console.log(globalThis.preloaded); // true
```
### []()[data URI `import` support](bun-v1.1.35.html#data-uri-import-support)
Bun v1.1.35 adds support for importing data URIs as modules.
index.ts
```
import data from "data:text/javascript,export default 'bun!';"
console.log(data) // bun!
```
Thanks to [@yamalight](https://github.com/yamalight)!
### []()[`console.group` and `console.groupEnd`](bun-v1.1.35.html#console-group-and-console-groupend)
Bun v1.1.35 also adds support for `console.group` and `console.groupEnd`.
index.js
```
console.group("begin");
console.log("indent!");
console.groupEnd();
// begin
// indent!
```
### []()[`${configDir}` support in `tsconfig.json`](bun-v1.1.35.html#configdir-support-in-tsconfig-json)
Bun v1.1.35 adds support for `${configDir}` in `tsconfig.json` files. This makes relative paths from extended `tsconfig.json` files more useful, as they can be relative to the directory containing the derived `tsconfig.json`.
tsconfig.json
```
{
"extends": "../tsconfig.base.json"
}
```
tsconfig.base.json
```
{
"compilerOptions": {
"outDir": "${configDir}/dist"
}
}
```
### []()[`fs.readFile` gets up to 10% faster for small files](bun-v1.1.35.html#fs-readfile-gets-up-to-10-faster-for-small-files)
We've micro-optimized `fs.readFile` for small files, making it up to 10% faster.
> In the next version of Bun
>
> fs.readFile gets up to 10% faster at reading small files (reminder: 1 µs == 1000ns) [pic.twitter.com/3vgg8FRfMs](https://t.co/3vgg8FRfMs)
>
> — Jarred Sumner (@jarredsumner) [November 10, 2024](https://twitter.com/jarredsumner/status/1855427363133333870?ref_src=twsrc%5Etfw)
### []()[`[eval with bun]` VSCode codelens action](bun-v1.1.35.html#eval-with-bun-vscode-codelens-action)
> In the next version of Bun's VSCode extension
>
> Untitled JavaScript & TypeScript files have an "eval with bun" codelens action (only on scratch files) [pic.twitter.com/iv9L6444wv](https://t.co/iv9L6444wv)
>
> — Jarred Sumner (@jarredsumner) [November 4, 2024](https://twitter.com/jarredsumner/status/1853394062629540275?ref_src=twsrc%5Etfw)
### []()[`Headers` and `URLSearchParams` support in `expect().toEqual()`](bun-v1.1.35.html#headers-and-urlsearchparams-support-in-expect-toequal)
Deep equals support for `Headers` and `URLSearchParams` has been added in Bun v1.1.35. This allows you to compare entries in `Headers` and `URLSearchParams` objects in `expect().toEqual()`, `Bun.deepEquals()`, and other deep equality checks.
Each of the following tests would previously fail.
index.test.js
```
test("Headers", () => {
const headers1 = new Headers([["a", "b"]]);
const headers2 = new Headers([["a", "c"]]);
expect(headers1).not.toEqual(headers2);
});
test("URLSearchParams", () => {
const params1 = new URLSearchParams("a=b");
const params2 = new URLSearchParams("a=c");
expect(params1).not.toEqual(params2);
});
```
## []()[Node compatibility improvements](bun-v1.1.35.html#node-compatibility-improvements)
### []()[`node:net` compatibility improvements for `net.Server`, `net.Socket`, and event emitting bugs](bun-v1.1.35.html#node-net-compatibility-improvements-for-net-server-net-socket-and-event-emitting-bugs)
We've fixed many compatibility issues with `node:net` in this release. Most notably, the `net.Server` class is now fully implemented, and `Socket.setKeepAlive` and `Socket.setNoDelay` are implemented.
Thanks to [@cirospaciari](https://github.com/cirospaciari)!
### []()[Fixed: `node:zlib` class prototypes and function names](bun-v1.1.35.html#fixed-node-zlib-class-prototypes-and-function-names)
The classes in `node:zlib` were missing `Object.setPrototypeOf`, which would cause subtle issues when the classes are subclassed. This was been fixed, along with more tests for `name` properties from `node:zlib`.
### []()[Fixed: Resulting signal codes from `child_process.spawnSync`](bun-v1.1.35.html#fixed-resulting-signal-codes-from-child-process-spawnsync)
The `signal` property of the result from `child_process.spawnSync` was not being set correctly. The following code would print `null` instead of `SIGTRAP`.
index.js
```
import { spawnSync } from 'child_process';
console.log(spawnSync(process.argv0, ['-e', 'process.kill(process.pid, "SIGTRAP")']).signal);
// Before: null
// Bun v1.1.35: SIGTRAP
```
Fixed thanks to [@ippsav](https://github.com/ippsav)!
### []()[Fixed: `node:https` `Agent` prototype chain regression](bun-v1.1.35.html#fixed-node-https-agent-prototype-chain-regression)
A regression causing the prototype chain for `node:https` `Agent` instances to be incorrectly set was fixed, thanks to [@nektro](https://github.com/nektro)!
index.js
```
import { request } from 'node:https';
console.log(request('https://bun.sh/', { agent: false }).end().host);
// Before: ConnectionRefused: Unable to connect. Is this computer able to access the url?
// path: "https://bun.sh:80/"
// Bun v1.1.35: bun.sh
```
### []()[Fixed: `node:net` `listen` with a unix socket path](bun-v1.1.35.html#fixed-node-net-listen-with-a-unix-socket-path)
Mishandling of the `path` option in `listen` from a server from `node:net` was fixed. The following code would throw an error before Bun v1.1.35 saying `TypeError: undefined is not an object`.
index.js
```
import { createServer } from 'node:net';
const server = createServer();
server.listen({ path: 'socket-path' });
```
Fixed thanks to [@ippsav](https://github.com/ippsav)!
## []()[Bugfixes](bun-v1.1.35.html#bugfixes)
### []()[Fixed: Unicode imports and unicode-escaped variable names](bun-v1.1.35.html#fixed-unicode-imports-and-unicode-escaped-variable-names)
Several bugs have been fixed with importing and exporting variables with unicode characters, thanks to [@pfgithub](https://github.com/pfgithub)!
index.js
```
import { mile𐃘nautical } from "./lib"
console.log(mile𐃘nautical(10)); // 12
```
lib.js
```
export const mile𐃘nautical = int => Math.round(int * 1.150779448)
```
### []()[Fixed: Windows named pipes with forward slashes](bun-v1.1.35.html#fixed-windows-named-pipes-with-forward-slashes)
Bun was mishandling named pipes with forward slashes on Windows. This has been fixed thanks to [@cirospaciari](https://github.com/cirospaciari)!
Examples from our updated tests:
```
test(`\\\\.\\pipe\\test\\${randomUUID()}`);
test(`\\\\?\\pipe\\test\\${randomUUID()}`);
test(`//?/pipe/test/${randomUUID()}`);
test(`//./pipe/test/${randomUUID()}`);
test(`/\\./pipe/test/${randomUUID()}`);
test(`/\\./pipe\\test/${randomUUID()}`);
test(`\\/.\\pipe/test\\${randomUUID()}`);
```
### []()[Fixed: vscode debugger bugfix](bun-v1.1.35.html#fixed-vscode-debugger-bugfix)
The vscode debugger wasn't being enabled correctly unless the `--inspect` flag was used. This caused scoped variables to not be displayed in the debugger.
Fixed thanks to [@RiskyMH](https://github.com/RiskyMH)!
### []()[Fixed: `node-fetch` `Request.url` bugfix](bun-v1.1.35.html#fixed-node-fetch-request-url-bugfix)
A bug was causing the `url` property of a `Request` object from `node-fetch` to be undefined. This was fixed by [@pfgithub](https://github.com/pfgithub)!
index.js
```
import { Request } from 'node-fetch';
console.log(new Request('https://bun.sh/').url);
// Before: undefined
// After: 'https://bun.sh/'
```
### []()[Fixed: Panic when parsing self closing JSX tags](bun-v1.1.35.html#fixed-panic-when-parsing-self-closing-jsx-tags)
A crash was fixed where a combination of JSX and function definitions would panic. The fix involved deleting the code used to check for self closing JSX tags, as it was unnecessary.
index.jsx
```
function Input() {
return <input>{(() => { if (true) { } })}</input>
}
function fn1() { return 1; }
function fn2() { return 2; }
```
Fixed thanks to [@ceymard](https://github.com/ceymard)!
### []()[Fixed: Regression in `Bun.CryptoHasher`](bun-v1.1.35.html#fixed-regression-in-bun-cryptohasher)
In Bun v1.1.34 a regression was introduced where `Bun.CryptoHasher.update()` would throw an error when given a `Blob`.
index.js
```
const hasher = new Bun.CryptoHasher("sha512")
hasher.update(new Blob(["hello blob!"]));
hasher.digest();
```
Fixed thanks to [@dylan-conway](https://github.com/dylan-conway)!
### []()[Fixed: Migrating `package-lock.json` with a root dependency with scripts](bun-v1.1.35.html#fixed-migrating-package-lock-json-with-a-root-dependency-with-scripts)
An assertion failure was triggered by migrating a `package-lock.json` with a root dependency that had lifecycle scripts. Fixed by [@dylan-conway](https://github.com/dylan-conway)!
### []()[Fixed: Assertion failure with non-existent `cafile` in `bun install`](bun-v1.1.35.html#fixed-assertion-failure-with-non-existent-cafile-in-bun-install)
An assertion failure was fixed when an absolute path to a non-existent `cafile` was provided to `bun install` on Windows.
bunfig.toml
```
[install]
cafile = "/does/not/exist/cafile.pem"
```
Fixed thanks to [@dylan-conway](https://github.com)!
### []()[Fixed: Auto-install not working on Windows when symlinks are disabled](bun-v1.1.35.html#fixed-auto-install-not-working-on-windows-when-symlinks-are-disabled)
Bun [auto-install](../docs/runtime/autoimport.html) uses symlinks to resolve dependencies from the global cache. On Windows, if symlinks weren't available, Bun would fail to import the dependency because the symlink wouldn't exist. This has been fixed by using [junctions](https://learn.microsoft.com/en-us/windows/win32/fileio/hard-links-and-junctions#junctions) for auto-install links.
Thanks to [@dylan-conway](https://github.com/dylan-conway)!
### []()[Fixed: Crash with non-existent preload script](bun-v1.1.35.html#fixed-crash-with-non-existent-preload-script)
A crash was fixed when a non-existent preload script was provided to Bun in combination with `--hot` or `--watch`.
### []()[Fixed: `fetch` with method `OPTIONS` always returning `""`](bun-v1.1.35.html#fixed-fetch-with-method-options-always-returning)
A bug causing `fetch` to always return an empty string with method `OPTIONS` was fixed, thanks to [@Kapsonfire-DE](https://github.com/Kapsonfire-DE)!
index.js
```
const res = await fetch('https://google.com', { method: 'OPTIONS' });
console.log(await res.text());
```
### []()[Fixed: Bundler crash with `onLoad` plugins on copy-file loaders used on entrypoints](bun-v1.1.35.html#fixed-bundler-crash-with-onload-plugins-on-copy-file-loaders-used-on-entrypoints)
A crash was fixed in `Bun.build` when an `onLoad` plugin matched the entrypoint, and the entrypoint had a copy-file loader type (css with `experimentalCss: false`, wasm, ...). This was fixed by [@zackradisic](https://githhub.com/zackradisic)!
### []()[Fixed: `setTimeout` with `node:util.promisify`](bun-v1.1.35.html#fixed-settimeout-with-node-util-promisify)
A regression from Bun v1.1.27 was fixed where `setTimeout` wouldn't have a promisify implementation if `node:timers` wasn't imported in the same file. The bug could be reproduced with the following code:
```
bun --print "require('util').promisify(setTimeout)(1000).then(() => 'done')"
```
This will now correctly wait one second and print `done`.
Fixed thanks to [@pfgithub](https://github.com/pfgithub)!
### []()[Fixed: Hang on Linux](bun-v1.1.35.html#fixed-hang-on-linux)
In Bun v1.1.34, [we allowed the garbage collector to do work while the event loop was asleep](bun-v1.1.34.html#long-running-processes-use-less-memory). This reduced Bun's memory usage in long-running processes. However, in some circumstances this change also [caused a deadlock that would hang the Bun process](https://github.com/oven-sh/bun/issues/14982). We're investigating how to keep the memory usage reduction without causing hangs, but in the meantime we've reverted the change from v1.1.34 so that Bun does not hang anymore.
## []()[Thanks to 16 contributors!](bun-v1.1.35.html#thanks-to-16-contributors)
- [@adhamu](https://github.com/adhamu)
- [@ceymard](https://github.com/ceymard)
- [@cirospaciari](https://github.com/cirospaciari)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Electroid](https://github.com/Electroid)
- [@ippsav](https://github.com/ippsav)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@Kapsonfire-DE](https://github.com/Kapsonfire-DE)
- [@Nanome203](https://github.com/Nanome203)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@pfgithub](https://github.com/pfgithub)
- [@RiskyMH](https://github.com/RiskyMH)
- [@SunsetTechuila](https://github.com/SunsetTechuila)
- [@yamalight](https://github.com/yamalight)
- [@zackradisic](https://github.com/zackradisic)
* * *
#### [Bun v1.1.34](bun-v1.1.34.html)
#### [Bun v1.1.37](bun-v1.1.37.html)
On this page
- [Node compatibility improvements](bun-v1.1.35.html#node-compatibility-improvements)
- [`node:net` compatibility improvements for `net.Server`, `net.Socket`, and event emitting bugs](bun-v1.1.35.html#node-net-compatibility-improvements-for-net-server-net-socket-and-event-emitting-bugs)
- [Fixed: `node:zlib` class prototypes and function names](bun-v1.1.35.html#fixed-node-zlib-class-prototypes-and-function-names)
- [Fixed: Resulting signal codes from `child_process.spawnSync`](bun-v1.1.35.html#fixed-resulting-signal-codes-from-child-process-spawnsync)
- [Fixed: `node:https` `Agent` prototype chain regression](bun-v1.1.35.html#fixed-node-https-agent-prototype-chain-regression)
- [Fixed: `node:net` `listen` with a unix socket path](bun-v1.1.35.html#fixed-node-net-listen-with-a-unix-socket-path)
- [Bugfixes](bun-v1.1.35.html#bugfixes)
- [Fixed: Unicode imports and unicode-escaped variable names](bun-v1.1.35.html#fixed-unicode-imports-and-unicode-escaped-variable-names)
- [Fixed: Windows named pipes with forward slashes](bun-v1.1.35.html#fixed-windows-named-pipes-with-forward-slashes)
- [Fixed: vscode debugger bugfix](bun-v1.1.35.html#fixed-vscode-debugger-bugfix)
- [Fixed: `node-fetch` `Request.url` bugfix](bun-v1.1.35.html#fixed-node-fetch-request-url-bugfix)
- [Fixed: Panic when parsing self closing JSX tags](bun-v1.1.35.html#fixed-panic-when-parsing-self-closing-jsx-tags)
- [Fixed: Regression in `Bun.CryptoHasher`](bun-v1.1.35.html#fixed-regression-in-bun-cryptohasher)
- [Fixed: Migrating `package-lock.json` with a root dependency with scripts](bun-v1.1.35.html#fixed-migrating-package-lock-json-with-a-root-dependency-with-scripts)
- [Fixed: Assertion failure with non-existent `cafile` in `bun install`](bun-v1.1.35.html#fixed-assertion-failure-with-non-existent-cafile-in-bun-install)
- [Fixed: Auto-install not working on Windows when symlinks are disabled](bun-v1.1.35.html#fixed-auto-install-not-working-on-windows-when-symlinks-are-disabled)
- [Fixed: Crash with non-existent preload script](bun-v1.1.35.html#fixed-crash-with-non-existent-preload-script)
- [Fixed: `fetch` with method `OPTIONS` always returning `""`](bun-v1.1.35.html#fixed-fetch-with-method-options-always-returning)
- [Fixed: Bundler crash with `onLoad` plugins on copy-file loaders used on entrypoints](bun-v1.1.35.html#fixed-bundler-crash-with-onload-plugins-on-copy-file-loaders-used-on-entrypoints)
- [Fixed: `setTimeout` with `node:util.promisify`](bun-v1.1.35.html#fixed-settimeout-with-node-util-promisify)
- [Fixed: Hang on Linux](bun-v1.1.35.html#fixed-hang-on-linux)
- [Thanks to 16 contributors!](bun-v1.1.35.html#thanks-to-16-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.37.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.37
* * *
[Dylan Conway](https://github.com/dylan-conway) · November 26, 2024
[](../rss.xml)
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
This release fixes 62 bugs (addressing 109 👍). It introduces realtime error reporting & test runner in VSCode, self-referencing `import` & `require`, package.json `config` environment variables, improved CSS parser errors, fixes for a Prisma memory leak, a `bun install` regression, `expect.toMatchSnapshot` quote escaping, `node:net` regression impacting `http2-wrapper`, and several other bugfixes and improvements.
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[Realtime debuggerless error reporting in VSCode](bun-v1.1.37.html#realtime-debuggerless-error-reporting-in-vscode)
[Bun for VSCode](https://marketplace.visualstudio.com/items?itemName=oven-sh.bun) now reports runtime errors with their stack trace in the "Problems" tab when you run bun in the VSCode terminal. This works without the debugger attached, with no configuration, and no need to pause execution. There's nothing extra to configure, it just works.
To get started:
1. Install [Bun for VSCode](https://marketplace.visualstudio.com/items?itemName=oven-sh.bun)
2. Open a terminal in VSCode
3. Run `bun test --watch`, `bun run foo.ts`, or any other script
4. Watch errors reported in the "Problems" tab
[](https://raw.githubusercontent.com/oven-sh/bun/d7a050dd4bdea443c979f0bd1061024e1cc669ba/packages/bun-vscode/error-messages.gif)
### []()[How is this different from tools like TypeScript, ESLint, and Biome?](bun-v1.1.37.html#how-is-this-different-from-tools-like-typescript-eslint-and-biome)
Runtime errors have no false positives, but they only appear when you run the code.
Runtime errors only appear when the error prevents further execution, such as an uncaught exception, a rejected promise, or a test failure that halted execution. You'll usually only get 1 error in total, unlike static analysis tools that report many errors without running any code.
#### Can I still use TypeScript, ESLint, or Biome?
**Yes!** This works perfectly alongside static analysis tools like TypeScript, ESLint, or Biome. It doesn't compete or replace them.
This reports errors that static analysis tools can't catch:
- Filesystem errors like `ENOENT`
- Syntax errors from parsing invalid JSON
- Exceptions like `TypeError` and `RangeError`
On the other hand, this will only report one error at a time. It doesn't come from reading your code, it comes from running your code.
Big thanks to [@alii](https://github.com/alii) for implementing this.
### []()[Self-referencing `import` & `require`](bun-v1.1.37.html#self-referencing-import-require)
Bun v1.1.37 adds support for self-referencing imports within a module. This allows modules to import themselves by name through the `exports` field in their package.json.
Given the package.json and foo.js for module `foo`:
./package.json
./foo.js
./package.json
```
{
"name": "foo",
"exports": {
".": "./foo.js"
}
}
```
./foo.js
```
import * as foo from 'foo';
export const bar = foo;
```
The following code in `index.js` will print `true`:
./index.js
```
import * as foo from 'foo';
console.log(foo.bar === foo); // true
```
Implemented thanks to [@SunsetTechuila](https://github.com/SunsetTechuila)!
### []()[Memory leak impacting Prisma fixed](bun-v1.1.37.html#memory-leak-impacting-prisma-fixed)
`napi_threadsafe_function` is a structure that can be used by other threads to enqueue requests to call a function on the main JavaScript thread. This is necessary since JavaScript is single-threaded, and you can't access the JavaScript engine from any other thread. Previous versions of Bun never freed the queue used to keep track of pending calls to the threadsafe function, which manifested as an 8-byte memory leak for each Prisma query since every query creates a threadsafe function with a queue size of 1. We expect this change may fix memory leaks in other Node-API packages too, but Prisma was the most widely-reported leak.
> In the next version of Bun
>
> A slow memory leak impacting napi & Prisma has been fixed [pic.twitter.com/Dl1ZeXEFmj](https://t.co/Dl1ZeXEFmj)
>
> — Bun (@bunjavascript) [November 20, 2024](https://twitter.com/bunjavascript/status/1859323013700911223?ref_src=twsrc%5Etfw)
### []()[Crash in `shadcn` & `sv` on Windows fixed](bun-v1.1.37.html#crash-in-shadcn-sv-on-windows-fixed)
A crash on Windows, commonly seen in cli packages like `shadcn`, `sv`, `prompts`, `solidui-cli`, and `create-astro`, has been fixed. The bug existed in `node:readline` `setRawMode` in C++ where a type was incorrectly casted to another.
Fixed thanks to [@heimskr](https://github.com/heimskr)!
### []()[`npm_package_config_` environment variables using `bun run`](bun-v1.1.37.html#npm-package-config-environment-variables-using-bun-run)
We've added support for populating `npm_package_config_` environment variables from the `config` field in package.json.
Given the package.json:
package.json
```
{
"name": "env",
"config": {
"foo": "bar",
},
"scripts": {
"echo": "echo $npm_package_config_foo"
}
}
```
Running `bun run echo` will print `bar`.
We've also added `npm_lifecycle_event` for script names, `npm_lifecycle_script` for script values, and `npm_command` variables for `bun run`, `bun publish`, and `bun pm pack`.
```
bun run: npm_command=run-script
bun publish: npm_command=publish
bun pm pack: npm_command=pack
```
Thanks to [@nektro](https://github.com/nektro)!
### []()[Improved CSS parser error messages](bun-v1.1.37.html#improved-css-parser-error-messages)
We've changed the error messages in our CSS parser to be more descriptive and helpful. For example, declaring a rule before `@import` produces:
sh
red.css
```
bun build --experimental-css red.css
```
```
error: @import rules must come before any other rules except @charset and @layer
at /path/to/red.css:5:8
```
red.css
```
div {
color: red;
}
@import url('blue.css');
```
This and many other errors have been improved in this release. A snippet of the changes:
src/css/error.zig
```
return switch (this) {
- .at_rule_invalid => |name| writer.print("at_rule_invalid: {s}", .{name}),
- .unexpected_token => |token| writer.print("unexpected_token: {}", .{token}),
- .selector_error => |err| writer.print("selector_error: {}", .{err}),
- else => writer.print("{s}", .{@tagName(this)}),
+ .at_rule_body_invalid => writer.writeAll("Invalid at-rule body"),
+ .at_rule_prelude_invalid => writer.writeAll("Invalid at-rule prelude"),
+ .at_rule_invalid => |name| writer.print("Unknown at-rule @{s}", .{name}),
+ .end_of_input => writer.writeAll("Unexpected end of input"),
+ .invalid_declaration => writer.writeAll("Invalid declaration"),
+ .invalid_media_query => writer.writeAll("Invalid media query"),
+ .invalid_nesting => writer.writeAll("Invalid CSS nesting"),
+ .deprecated_nest_rule => writer.writeAll("The @nest rule is deprecated, use standard CSS nesting instead"),
+ .invalid_page_selector => writer.writeAll("Invalid @page selector"),
+ .invalid_value => writer.writeAll("Invalid value"),
+ .qualified_rule_invalid => writer.writeAll("Invalid qualified rule"),
+ .selector_error => |err| writer.print("Invalid selector. {s}", .{err}),
+ .unexpected_import_rule => writer.writeAll("@import rules must come before any other rules except @charset and @layer"),
+ .unexpected_namespace_rule => writer.writeAll("@namespace rules must come before any other rules except @charset, @import, and @layer"),
+ .unexpected_token => |token| writer.print("Unexpected token. {}", .{token}),
+ .maximum_nesting_depth => writer.writeAll("Maximum CSS nesting depth exceeded"),
};
```
Thanks to [@zackradisic](https://github.com/zackradisic)!
### []()[Improved `Bun.write` error messages](bun-v1.1.37.html#improved-bun-write-error-messages)
`Bun.write` now prints the received value when passed an unexpected argument. For example, passing a BigInt as the first argument will print:
```
bun --print "Bun.write(1n, 'hello stdout')"
```
```
TypeError: The "destination" argument must be of type path, file descriptor, or Blob. Received 1n
code: "ERR_INVALID_ARG_TYPE"
at /home/[eval]:1:5
Bun v1.1.37 (macOS arm64)
```
Thanks to [@nektro](https://github.com/nektro)!
### []()[`performance.markResourceTiming` stub](bun-v1.1.37.html#performance-markresourcetiming-stub)
We've stubbed `performance.markResourceTiming` to unblock packages that rely on it. While the function will only return `undefined`, it will no longer throw runtime errors in packages like `@sveltejs/adapter-cloudflare`.
### []()[`Bun.file` throws OOM errors if the file is too large on Windows](bun-v1.1.37.html#bun-file-throws-oom-errors-if-the-file-is-too-large-on-windows)
Given a file larger than 4GB, `Bun.file` will now throw an OOM error on Windows. Previously, it would crash with an assertion failure. Fixed thanks to [@cirospaciari](https://github.com/cirospaciari)!
index.js
```
const hugeFile = Bun.file('huge-file.txt'); // throws ENOMEM
console.log(hugeFile.size);
```
### []()[Fixed regression in `bun install`](bun-v1.1.37.html#fixed-regression-in-bun-install)
Part of the work towards reducing the binary size of Bun in v1.1.35 was moving Bun's package manager state out of the BSS section of the binary, and heap allocating it when needed. This change caused crashes when parsing aliased dependencies (e.g. `npm:zod@1.11.17`) due to accessing undefined memory.
This has been fixed in this release, thanks to [@dylan-conway](https://github.com/dylan-conway)!
### []()[Fixed quote and template escaping in `expect.toMatchSnapshot`](bun-v1.1.37.html#fixed-quote-and-template-escaping-in-expect-tomatchsnapshot)
`expect.toMatchSnapshot` writes the stringified test name plus a counter and the received value to disk, both within a template literal. The release fixing escaping issues where backticks and ${} were not escaped correcly, causing snapshot to fail to match upon re-running the test.
index.test.ts
```
import { expect, test } from "bun:test";
test("snapshot `foo`", () => {
const foo: string = "hello ${}!";
expect(bar).toMatchSnapshot();
});
```
Fixed thanks to [@pfgithub](https://github.com/pfgithub)!
### []()[Fixed `bun --hot` with single quote in the entrypoint](bun-v1.1.37.html#fixed-bun-hot-with-single-quote-in-the-entrypoint)
Previously `bun --hot` would report a syntax error when the entrypoint contained a single quote.
```
bun --hot "src/single'quote.ts"
```
Now, Bun will run the entrypoint as expected, thanks to [@pfgithub](https://github.com/pfgithub)!
### []()[Fixed `WebSocket.ping` called without arguments](bun-v1.1.37.html#fixed-websocket-ping-called-without-arguments)
A bug was fixed where calling `WebSocket.ping` without arguments would fail to send a message without a payload.
```
import { WebSocketServer } from "ws";
const server = new WebSocketServer({ noServer: true });
server.on("connection", (ws) => {
ws.ping(); // fixed
});
```
Fixed thanks to [@cirospaciari](https://github.com/cirospaciari)!
### []()[Regression in printing `\uFFFF`](bun-v1.1.37.html#regression-in-printing-uffff)
A regression in our JavaScript printer caused `\uFFFF` to print incorrectly. This has been fixed and now works as expected.
```
bun --print "'\uFFFF'.charCodeAt(1)"
```
```
# Previously: 57343
# Bun v1.1.37: NaN
```
Thanks to [@pfgithub](https://github.com/pfgithub)!
### []()[Non-zero for non-existent absolute file path in `bun test`](bun-v1.1.37.html#non-zero-for-non-existent-absolute-file-path-in-bun-test)
Given an aboslute file path to a file that does not exist, `bun test` will now exit with a non-zero exit code along with a module resolution error. Previously, the error would be reported but the exit code would be 0.
```
bun test /path/to/non-existent-file.test.ts
```
```
error: ModuleNotFound resolving "/path/to/non-existent-file.test.ts" (entry point)
```
### []()[`node:net` regression fixed](bun-v1.1.37.html#node-net-regression-fixed)
A regression impacting the `http2-wrapper` package has been fixed. The cause was a change in the `node:net` builtin module, where `TLSSocket._handle._parentWrap` was not set to `JSStreamSocket` correctly.
### []()[Fixed errors printing twice in watch or hot mode](bun-v1.1.37.html#fixed-errors-printing-twice-in-watch-or-hot-mode)
Running a script with `--watch` or `--hot` would print unhandled exceptions to the console twice. A simple example of this would be:
```
$ bun --watch --print "throw new Error('oops!')"
1 | throw new Error('oops')
^
error: oops!
at /home/user/[eval]:1:7
1 | throw new Error('oops')
^
error: oops!
at /home/user/[eval]:1:7
```
This has been fixed and now only prints once, thanks to [@alii](https://github.com/alii)!
### []()[Targeting browser with `node:buffer` in `bun build`](bun-v1.1.37.html#targeting-browser-with-node-buffer-in-bun-build)
A bug preventing `Buffer` imports from `node:buffer` when targeting the browser with `bun build` has been fixed. Existing code could access `Buffer` through the default export, but importing `Buffer` directly would fail.
```
import { Buffer } from "node:buffer";
const buf = Buffer.from("bun!");
console.log(buf.toString());
```
```
bun build --target browser --outfile out.js
```
```
# Previously: error: No matching export in "../../../../../bun-vfs$$/node_modules/buffer/index.js" for import "Buffer"
# Bun v1.1.37: out.js 41.66 KB
```
## []()[Thanks to 14 contributors!](bun-v1.1.37.html#thanks-to-14-contributors)
- [@advaith1](https://github.com/advaith1)
- [@alii](https://github.com/alii)
- [@cirospaciari](https://github.com/cirospaciari)
- [@Electroid](https://github.com/Electroid)
- [@heimskr](https://github.com/heimskr)
- [@imide](https://github.com/imide)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@luavixen](https://github.com/luavixen)
- [@Nanome203](https://github.com/Nanome203)
- [@nektro](https://github.com/nektro)
- [@pfgithub](https://github.com/pfgithub)
- [@RiskyMH](https://github.com/RiskyMH)
- [@rtzll](https://github.com/rtzll)
- [@SunsetTechuila](https://github.com/SunsetTechuila)
* * *
#### [Bun v1.1.35](bun-v1.1.35.html)
#### [Bun v1.1.38](bun-v1.1.38.html)
On this page
- [Realtime debuggerless error reporting in VSCode](bun-v1.1.37.html#realtime-debuggerless-error-reporting-in-vscode)
- [How is this different from tools like TypeScript, ESLint, and Biome?](bun-v1.1.37.html#how-is-this-different-from-tools-like-typescript-eslint-and-biome)
- [Self-referencing `import` & `require`](bun-v1.1.37.html#self-referencing-import-require)
- [Memory leak impacting Prisma fixed](bun-v1.1.37.html#memory-leak-impacting-prisma-fixed)
- [Crash in `shadcn` & `sv` on Windows fixed](bun-v1.1.37.html#crash-in-shadcn-sv-on-windows-fixed)
- [`npm_package_config_` environment variables using `bun run`](bun-v1.1.37.html#npm-package-config-environment-variables-using-bun-run)
- [Improved CSS parser error messages](bun-v1.1.37.html#improved-css-parser-error-messages)
- [Improved `Bun.write` error messages](bun-v1.1.37.html#improved-bun-write-error-messages)
- [`performance.markResourceTiming` stub](bun-v1.1.37.html#performance-markresourcetiming-stub)
- [`Bun.file` throws OOM errors if the file is too large on Windows](bun-v1.1.37.html#bun-file-throws-oom-errors-if-the-file-is-too-large-on-windows)
- [Fixed regression in `bun install`](bun-v1.1.37.html#fixed-regression-in-bun-install)
- [Fixed quote and template escaping in `expect.toMatchSnapshot`](bun-v1.1.37.html#fixed-quote-and-template-escaping-in-expect-tomatchsnapshot)
- [Fixed `bun --hot` with single quote in the entrypoint](bun-v1.1.37.html#fixed-bun-hot-with-single-quote-in-the-entrypoint)
- [Fixed `WebSocket.ping` called without arguments](bun-v1.1.37.html#fixed-websocket-ping-called-without-arguments)
- [Regression in printing `\uFFFF`](bun-v1.1.37.html#regression-in-printing-uffff)
- [Non-zero for non-existent absolute file path in `bun test`](bun-v1.1.37.html#non-zero-for-non-existent-absolute-file-path-in-bun-test)
- [`node:net` regression fixed](bun-v1.1.37.html#node-net-regression-fixed)
- [Fixed errors printing twice in watch or hot mode](bun-v1.1.37.html#fixed-errors-printing-twice-in-watch-or-hot-mode)
- [Targeting browser with `node:buffer` in `bun build`](bun-v1.1.37.html#targeting-browser-with-node-buffer-in-bun-build)
- [Thanks to 14 contributors!](bun-v1.1.37.html#thanks-to-14-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.38.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.38
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · November 29, 2024
[](../rss.xml)
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
This release fixes 7 bugs (addressing 14 👍), a debugger bug causing Bun to hang in VSCode terminal, a crash in `postgres` npm package, a TypeScript minification bug, console.log improvements, updated SQLite and c-ares, adds `reusePort` option to `Bun.listen` and `node:net`, fixes a bug in `Bun.FileSystemRouter.reload()`, fixes rare crash in `fetch()`, and fixes an assertion failure when re-assigning global modules in `--print` or `--eval`.
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
### []()[Fixed: Debugger causing Bun to hang in VSCode terminal](bun-v1.1.38.html#fixed-debugger-causing-bun-to-hang-in-vscode-terminal)
A regression introduced in Bun v1.1.37 caused older versions of Bun to hang when run from the VSCode terminal in certain cases. This has been fixed.
### []()[Fixed: Crash impacting `postgres` npm package](bun-v1.1.38.html#fixed-crash-impacting-postgres-npm-package)
When using the `postgres` npm package, a crash could occur after upgrading from a TCP to a TLS socket when an application error occurred.
This has been fixed, thanks to [@cirospaciari](https://github.com/cirospaciari).
### []()[Fixed: `allowHalfOpen` & `exclusive` being set to `true` incorrectly](bun-v1.1.38.html#fixed-allowhalfopen-exclusive-being-set-to-true-incorrectly)
An arguments validation regression introduced in Bun v1.1.34 caused `allowHalfOpen` to be set to `true` when `false` was passed. This has been fixed, thanks to [@cirospaciari](https://github.com/cirospaciari).
This impacted `node:net` and `Bun.listen`.
### []()[console.log improvements](bun-v1.1.38.html#console-log-improvements)
> In the next version of Bun
>
> console.log includes extended classes, null prototype, and prints arguments like an array, thanks to RiskyMH [pic.twitter.com/DIsYRb8mdj](https://t.co/DIsYRb8mdj)
>
> — Bun (@bunjavascript) [November 29, 2024](https://twitter.com/bunjavascript/status/1862439893886279753?ref_src=twsrc%5Etfw)
### []()[`reusePort` option in Bun.listen](bun-v1.1.38.html#reuseport-option-in-bun-listen)
The `reusePort` option has been added to `Bun.listen` and `node:net`. This is consistent with the behavior in `Bun.serve`.
### []()[Fixed: Bun.FileSystemRouter.reload() missing new directory contents](bun-v1.1.38.html#fixed-bun-filesystemrouter-reload-missing-new-directory-contents)
A cache invalidation issue caused `reload()` in `Bun.FileSystemRouter` to miss new directory contents. This has been fixed, thanks to [@Kapsonfire-DE](https://github.com/Kapsonfire-DE).
### []()[Fixed: Module resolution cache invalidation bug on Windows](bun-v1.1.38.html#fixed-module-resolution-cache-invalidation-bug-on-windows)
A module resolution cache invalidation bug was causing incorrect behavior on Windows. This has been fixed, thanks to [@Kapsonfire-DE](https://github.com/Kapsonfire-DE).
### []()[Fixed: File descriptor limit exceeded on musl](bun-v1.1.38.html#fixed-file-descriptor-limit-exceeded-on-musl)
When Bun used the `prlimit` libc function on musl to ask how many file descriptors Bun can open, musl often lied and said Bun could only open 1024 file descriptors or so.
Now, we don't trust the result of `prlimit` function to tell us when the number is relatively low, and attempt to ask for a number greater than the reported limit.
### []()[Updated SQLite from 3.45 -> 3.47](bun-v1.1.38.html#updated-sqlite-from-3-45-3-47)
The version of SQLite `bun:sqlite` embeds on Linux and Windows has been updated from 3.45 to 3.47.
Release notes from the SQLite team can be found [here](https://www.sqlite.org/changes.html):
- [SQLite3 v3.46.0](https://www.sqlite.org/releaselog/3_46_0.html)
- [SQLite3 v3.47.0](https://www.sqlite.org/releaselog/3_47_0.html)
In Bun's repo, we've also setup auto-updating of native dependencies like sqlite, libarchive, etc to minimize delays for future updates.
### []()[Fixed: Rare crash in fetch()](bun-v1.1.38.html#fixed-rare-crash-in-fetch)
A difficult to trigger crash in `fetch()` has been fixed, thanks to [@cirospaciari](https://github.com/cirospaciari)
### []()[Fixed: Re-assigning global modules in `--print` or `--eval`](bun-v1.1.38.html#fixed-re-assigning-global-modules-in-print-or-eval)
When using `--print` or `--eval`, an assertion failure could occur when re-assigning global modules.
For example, the following code would trigger an assertion failure:
```
// like in node, --print and --eval make a number of modules available globally.
const fs = require("node:fs");
```
### []()[Fixed: TypeScript minification bug](bun-v1.1.38.html#fixed-typescript-minification-bug)
The following code was minified incorrectly:
```
export class Foo {
constructor(public name: string) {}
}
```
Before:
```
class o{c;constructor(c){this.name=c}}export{o as Foo};
```
After:
```
class o{name;constructor(c){this.name=c}}export{o as Foo};
```
We were incorrectly minifying the property name on the class instance, causing issues with `Object.keys` and other similar functions.
This has been fixed, thanks to [@heimskr](https://github.com/heimskr).
### []()[Thanks to 11 contributors!](bun-v1.1.38.html#thanks-to-11-contributors)
- [@alii](https://github.com/alii)
- [@cdfzo](https://github.com/cdfzo)
- [@cirospaciari](https://github.com/cirospaciari)
- [@heimskr](https://github.com/heimskr)
- [@jarred-sumner](https://github.com/jarred-sumner)
- [@kapsonfire-de](https://github.com/kapsonfire-de)
- [@nektro](https://github.com/nektro)
- [@nreilingh](https://github.com/nreilingh)
- [@paperclover](https://github.com/paperclover)
- [@riskymh](https://github.com/riskymh)
- [@snoglobe](https://github.com/snoglobe)
* * *
#### [Bun v1.1.37](bun-v1.1.37.html)
#### [Bun v1.1.39](bun-v1.1.39.html)
On this page
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.39.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.39
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · December 17, 2024
[](../rss.xml)
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
This release fixes 61 bugs (addressing 99 👍). It introduces `bun.lock`, a new text-based lockfile format. It makes cached `bun install` 30% faster. It adds support for `fetch()` request body streams. It brings Node.js' `string_decoder`, `punycode` and `querystring` to 100% Node.js compatibility. It adds a native plugin API for `Bun.build()`, along with a Rust crate integrating with napi.rs. It implements `expect().toMatchInlineSnapshot()`. It adds more accurate heap snapshots. It reduces WebSocket server memory usage. It upgrades WebKit bringing `Error.isError`, faster `String.prototype.at`, and more.
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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.lock` is bun's new text-based lockfile](bun-v1.1.39.html#bun-lock-is-bun-s-new-text-based-lockfile)
In this release, we've added a new human-readable lockfile format: `bun.lock`. This makes git diffs and merge conflicts work better, and unblocks tooling like Dependabot, Renovate, Turbo prune, and more.
To try it out, run:
```
bun install --save-text-lockfile
```
[**We wrote a blog post about `bun.lock`**](bun-lock-text-lockfile.html)
Along the way, we also **made cached `bun install` 30% faster**. Specifically, when the packages were previously installed and it needs to verify the versions of every installed package to ensure they haven't changed (a common scenario when running `bun install` locally).
Big thanks to [@dylan-conway](https://github.com/dylan-conway) for implementing this!
## []()[fetch() request body streams](bun-v1.1.39.html#fetch-request-body-streams)
You can now send `fetch()` `Request` bodies as streams. Previously, only `Response` bodies could be streamed in the client (Bun.serve() always supported both).
This uses HTTP/1.1 `Transfer-Encoding: chunked` on the client. When the content length is known ahead of time, it uses `Content-Length` instead.
> In the next version of Bun
>
> fetch()'s body supports streaming ReadableStream, Node.js streams and async generator* functions [pic.twitter.com/s6V2ugfEkK](https://t.co/s6V2ugfEkK)
>
> — Bun (@bunjavascript) [December 5, 2024](https://twitter.com/bunjavascript/status/1864497708658249749?ref_src=twsrc%5Etfw)
Thanks to [@cirospaciari](https://github.com/cirospaciari) for implementing this!
## []()[Node.js Compatibility](bun-v1.1.39.html#node-js-compatibility)
### []()[Fixed: Hang in connection error on `postgres` package](bun-v1.1.39.html#fixed-hang-in-connection-error-on-postgres-package)
Two different bugs could lead to a hang in the `postgres` package:
- When an `AbortSignal` passed to `net.connect` signals, Bun was calling `destroy` on the `net.Socket` instead of emitting an `abort` event. This has been fixed, thanks to [@cirospaciari](https://github.com/cirospaciari)!
- Calling `pause` on a `net.Socket` that came from an upgraded TLS connection could cause the underlying socket to be paused instead of just the node:stream.
Thanks to [@cirospaciari](https://github.com/cirospaciari) for the fix!
### []()[100% of Node's `string_decoder` tests pass](bun-v1.1.39.html#100-of-node-s-string-decoder-tests-pass)
We fixed an edgecase in the `"string_decoder"` module's handling of incomplete multi-byte characters to align with Node.js, and now all Node.js' string\_decoder tests pass.
Thanks to [@paperclover](https://github.com/paperclover)!
### []()[100% of Node's `punycode` tests pass](bun-v1.1.39.html#100-of-node-s-punycode-tests-pass)
Bun is now fully compatible with Node.js punycode implementation.
Thanks to [@snoglobe](https://github.com/snoglobe)!
### []()[100% of Node's `querystring` tests pass](bun-v1.1.39.html#100-of-node-s-querystring-tests-pass)
We fixed some edgecases in the `"querystring"` module to align with Node.js.
Thanks to [@pfgithub](https://github.com/pfgithub)!
### []()[Improved node:path test coverage](bun-v1.1.39.html#improved-node-path-test-coverage)
All but one of Node's `path` tests now pass (the one for the newly-added method, `path.matchesGlob` is not implemented yet).
Thanks to [@DonIsaac](https://github.com/DonIsaac)!
### []()[Improved node:os test coverage](bun-v1.1.39.html#improved-node-os-test-coverage)
Only one test failure remains in the `os` module.
### []()[Fixed: `crypto.createHash(alg, options)` missing option](bun-v1.1.39.html#fixed-crypto-createhash-alg-options-missing-option)
Thanks to [@heimskr](https://github.com/heimskr)!
### []()[Fixed: `napi_wrap`](bun-v1.1.39.html#fixed-napi-wrap)
The `napi_wrap` function now behaves the same as in Node.js.
Thanks to [@190n](https://github.com/190n)!
### []()[Fixed: error code in node:zlib](bun-v1.1.39.html#fixed-error-code-in-node-zlib)
Bun was not throwing precisely the same `error.code` properties for zlib errors as Node.js. This has been fixed, thanks to [@nektro](https://github.com/nektro)!
### []()[Fixed: `fs.readFileSync` with `flag` parameter in object](bun-v1.1.39.html#fixed-fs-readfilesync-with-flag-parameter-in-object)
The following would incorrectly ignore the `flag` parameter:
```
import fs from "fs";
fs.readFileSync("data.txt", { encoding: "utf8", flag: "w+" });
```
This has been fixed, thanks to [@pfgithub](https://github.com/pfgithub)!
## []()[Bundler improvements](bun-v1.1.39.html#bundler-improvements)
### []()[`onBeforeParse` - Rust/C/Zig plugin API](bun-v1.1.39.html#onbeforeparse-rust-c-zig-plugin-api)
This release introduces a new zero-copy native plugin API for `Bun.build()`. Unlike our JavaScript plugin API, this runs inside Bun's threadpool immediately before parsing, without cloning the source code, without undergoing string conversion, and with practically zero overhead.
```
bun add -g @napi-rs/cli
napi new
cargo add bun-native-plugin
```
From there, you can implement the `onBeforeParse` hook:
lib.rs
```
use bun_native_plugin::{define_bun_plugin, OnBeforeParse, bun, Result, anyhow, BunLoader};
use napi_derive::napi;
/// Define the plugin and its name
define_bun_plugin!("replace-foo-with-bar");
/// Here we'll implement `onBeforeParse` with code that replaces all occurrences of
/// `foo` with `bar`.
///
/// We use the #[bun] macro to generate some of the boilerplate code.
///
/// The argument of the function (`handle: &mut OnBeforeParse`) tells
/// the macro that this function implements the `onBeforeParse` hook.
#[bun]
pub fn replace_foo_with_bar(handle: &mut OnBeforeParse) -> Result<()> {
// Fetch the input source code.
let input_source_code = handle.input_source_code()?;
// Get the Loader for the file
let loader = handle.output_loader();
let output_source_code = input_source_code.replace("foo", "bar");
handle.set_output_source_code(output_source_code, BunLoader::BUN_LOADER_JSX);
Ok(())
}
```
To use in `Bun.build()`:
```
import myNativeAddon from "./my-native-addon";
Bun.build({
entrypoints: ["./app.tsx"],
plugins: [
{
name: "my-plugin",
setup(build) {
build.onBeforeParse(
{
namespace: "file",
filter: "**/*.tsx",
},
{
napiModule: myNativeAddon,
symbol: "replace_foo_with_bar",
// external: myNativeAddon.getSharedState()
},
);
},
},
],
});
```
This plugin API is designed for use with NAPI addons so that existing libraries can add these without thinking much about how to initialize them.
Thanks to [@zackradisic](https://github.com/zackradisic) for implementing this!
### []()[CSS parser improvements](bun-v1.1.39.html#css-parser-improvements)
Several CSS parser and printer edge cases have been fixed, thanks to [@zackradisic](https://github.com/zackradisic)!
### []()[Inject environment variables in `Bun.build()`](bun-v1.1.39.html#inject-environment-variables-in-bun-build)
This release adds support for injecting environment variables in `Bun.build()` and `bun build`:
API
CLI
API
```
// In Bun.build()
await Bun.build({
entrypoints: ['./app.tsx'],
outdir: './out',
// All environment variables starting with "PUBLIC_"
// will be injected in the build as process.env.PUBLIC_*
env: "PUBLIC_*",
// eg
// console.log(process.env.PUBLIC_FOO); => "bar"
});
await Bun.build({
entrypoints: ['./app.tsx'],
outdir: './out',
// Inject all environment variables in the build when used.
env: "inline",
});
```
CLI
```
bun build ./app.tsx --env='PUBLIC_*'
bun build ./app.tsx --env=inline
```
## []()[Inline snapshot tests](bun-v1.1.39.html#inline-snapshot-tests)
This release implements `expect().toMatchInlineSnapshot()` in `bun:test`. Inline snapshots are stored directly in the test file, and are updated with `bun test -u`.
```
import { expect, test } from "bun:test";
test("format user profile", () => {
const result = formatProfile({
name: "Jarred",
role: "admin",
});
// Snapshot stored directly in test file
expect(result).toMatchInlineSnapshot(`{
"displayName": "Jarred",
"permissions": ["admin"],
"createdAt": "2024-12-13T00:00:00.000Z"
}`);
});
test("validate input", () => {
// Match error messages
expect(() => validateInput({})).toThrowErrorMatchingInlineSnapshot(`
"Invalid input:
- Missing required field: name"
`);
});
```
Update snapshots with:
```
bun test -u
```
We've also added:
- `expect().toThrowErrorMatchingSnapshot()`
- `expect().toThrowErrorMatchingInlineSnapshot()`
Thanks to [@pfgithub](https://github.com/pfgithub) for implementing this!
## []()[Memory Profiler improvements](bun-v1.1.39.html#memory-profiler-improvements)
We've implemented support for reporting memory usage from native code in our JavaScriptCore <> Zig class bindings generator. This makes heap snapshots reporting more accurate:
- `Blob`, `Request`, and `Response` now report the size including their body, URL, and underlying structs instead of only the JavaScript wrapper object sizes.
- `URLSearchParams` and `Headers` now report the size of size of the C++ classes along with the size of each string.
- `ServerWebSocket` and `WebSocket` now reports the size of the underlying structs and buffered data
- `FormData`'s size now includes the size of each string, the underlying C++ classes, and the size of any files contained in it.
- `Subprocess` (`Bun.spawn`) reports the size of the underlying structs and buffered data
- `Bun.file().writer()` reports the size of buffered data
- All other classes implemented in Zig report their internal struct's size
This does not impact memory usage from the garbage collector's perspective or from the runtime's perspective, but this does make it easier for you to debug what's taking up memory in applications using Bun.
### []()[New: `estimateShallowMemoryUsageOf` in `"bun:jsc"`](bun-v1.1.39.html#new-estimateshallowmemoryusageof-in-bun-jsc)
The `estimateShallowMemoryUsageOf` function in `"bun:jsc"` estimates the memory usage of a JavaScript value without including the memory usage of its children, properties, or internal slots.
```
import { estimateShallowMemoryUsageOf } from "bun:jsc";
const obj = { foo: "bar" };
const usage = estimateShallowMemoryUsageOf(obj);
console.log(usage); // => 16
const buffer = Buffer.alloc(1024 * 1024);
estimateShallowMemoryUsageOf(buffer);
// => 1048624
```
### []()[WebSocket server memory reduction](bun-v1.1.39.html#websocket-server-memory-reduction)
This release reduces the memory usage of Bun's builtin WebSocket server `Bun.serve()`, particularly for long-running processes that open and close many WebSocket server connections.
In this microbenchmark that opens and closes 200,000 WebSocket connections in loops, the peak RSS drops by 15%.
Microbenchmark
```
const batchSize = 500;
let onClosePromise = Promise.withResolvers();
let onCloseCount = 0;
using server = Bun.serve({
port: 0,
fetch(req, server) {
return server.upgrade(req);
},
websocket: {
open(socket) {},
drain(ws) {},
close(ws) {
onCloseCount++;
if (onCloseCount === batchSize) {
onClosePromise.resolve();
}
},
},
});
async function batch() {
const clients = new Array(batchSize);
const promises = new Array(batchSize + 1);
onCloseCount = 0;
onClosePromise = Promise.withResolvers();
console.time(`Batch of ${batchSize}`);
for (let i = 0; i < batchSize; i++) {
const client = new WebSocket(server.url);
const { promise, resolve, reject } = Promise.withResolvers();
clients[i] = client;
promises[i] = promise;
client.onclose = () => {
resolve();
};
client.onopen = () => {
client.close();
};
}
promises[batchSize] = onClosePromise;
await Promise.all(promises);
Bun.gc(true);
console.timeEnd(`Batch of ${batchSize}`);
console.log(`RSS:`, (process.memoryUsage.rss() / 1024 / 1024) | 0, "MB");
}
for (let i = 0; i < 400; i++) {
Bun.gc(true);
const heapStats = require("bun:jsc").heapStats();
for (const key in heapStats.zones) {
if (heapStats.zones[key] < 2048 * 1024) delete heapStats.zones[key];
}
for (const key in heapStats.objectTypeCounts) {
if (heapStats.objectTypeCounts[key] < 100) delete heapStats.objectTypeCounts[key];
}
console.log(heapStats);
await batch();
}
Bun.gc(true);
const rss = process.memoryUsage.rss();
console.log(`Initial RSS: ${(rss / 1024 / 1024) | 0} MB`);
for (let i = 0; i < 200; i++) {
Bun.gc(true);
const heapStats = require("bun:jsc").heapStats();
for (const key in heapStats.zones) {
if (heapStats.zones[key] < 2048 * 1024) delete heapStats.zones[key];
}
for (const key in heapStats.objectTypeCounts) {
if (heapStats.objectTypeCounts[key] < 100) delete heapStats.objectTypeCounts[key];
}
console.log(heapStats);
await batch();
}
Bun.gc(true);
const finalRss = process.memoryUsage.rss();
console.log(`Final RSS: ${(finalRss / 1024 / 1024) | 0}MB`);
```
## []()[Dependency upgrades](bun-v1.1.39.html#dependency-upgrades)
We've updated several dependencies:
- c-ares to v1.34.3
- lshpack to v2.3.3
- libdeflate to v1.22
- SQLite to 3.470.200
- BoringSSL
## []()[WebKit Upgrade](bun-v1.1.39.html#webkit-upgrade)
This release upgrades the internal version of JavaScriptCore from upstream WebKit, which includes improvements to loop unrolling, `Intl.PluralRules`, and `Intl.NumberFormat`, and more.
### []()[Error.isError](bun-v1.1.39.html#error-iserror)
The `Error.isError(object)` method returns `true` if the `object` is really an `Error` instance.
```
Error.isError(new Error()); // => true
Error.isError({}); // => false
Error.isError(new Error("foo")); // => true
Error.isError(new Error("foo").message); // => false
Error.isError({ [Symbol.toStringTag]: "Error" }); // => false
Error.isError(new (class Error {})()); // => false
Error.isError({ constructor: function Error() {} }); // => false
```
[`Error.isError` is a stage3 TC39 proposal](https://github.com/tc39/proposal-is-error).
### []()[Faster String.prototype.at](bun-v1.1.39.html#faster-string-prototype-at)
> In the next version of Bun & Safari
>
> "foo".at(i) gets 44% faster, thanks to [@\_\_sosukesuzuki](https://twitter.com/__sosukesuzuki?ref_src=twsrc%5Etfw) [pic.twitter.com/UtkkJSp6Vb](https://t.co/UtkkJSp6Vb)
>
> — Bun (@bunjavascript) [December 12, 2024](https://twitter.com/bunjavascript/status/1867203604777676961?ref_src=twsrc%5Etfw)
## []()[Bug Fixes](bun-v1.1.39.html#bug-fixes)
### []()[Fixed: Debugger flakiness in VSCode](bun-v1.1.39.html#fixed-debugger-flakiness-in-vscode)
The process would sometimes exit before the debugger could attach. Please let us know if you're still experiencing this!
This has been fixed, thanks to [@RiskyMH](https://github.com/RiskyMH)
### []()[Fixed: Crash in POSIX signal handling](bun-v1.1.39.html#fixed-crash-in-posix-signal-handling)
A crash or deadlock that could occur occur after registering a signal handler like `process.on('SIGINT')` or `process.on('SIGTERM')` and repeatedly receiving signals has been fixed.
### []()[Fixed: Rare file descriptor leak in Bun Shell and `Bun.spawn`](bun-v1.1.39.html#fixed-rare-file-descriptor-leak-in-bun-shell-and-bun-spawn)
A theoretical file descriptor leak in Bun Shell and `Bun.spawn` has been fixed. This could potentially happen when spawning processes on other threads in older versions of Linux.
It turns out we were also not always correctly marking file descriptors as non-blocking, which also has been fixed.
### []()[Fixed: fetch redirect handling with `"Connection: close"`](bun-v1.1.39.html#fixed-fetch-redirect-handling-with-connection-close)
When `fetch()` redirects with `"Connection": "close"`, Bun could potentially report a connection error instead of handling the redirect as expected. Thanks to [@cirospaciari](https://github.com/cirospaciari) for the fix!
### []()[Fixed: Crash in bun install with invalid package.json in workspace](bun-v1.1.39.html#fixed-crash-in-bun-install-with-invalid-package-json-in-workspace)
A crash that could occur when running `bun install` on a workspace with invalid `package.json` files has been fixed.
### []()[Fixed: rare crash in Bun.build() plugins](bun-v1.1.39.html#fixed-rare-crash-in-bun-build-plugins)
A rare crash that could occur in Bun.build() plugins has been fixed. This would potentially happen if using the `"file"` loader in a plugin.
### []()[Fixed: crash in Bun.build() with a lot of comments in TypeScript files](bun-v1.1.39.html#fixed-crash-in-bun-build-with-a-lot-of-comments-in-typescript-files)
A crash that could occur in certain cases when many comments were present in TypeScript files has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway)!
### []()[Fixed: global .npmrc not using auth](bun-v1.1.39.html#fixed-global-npmrc-not-using-auth)
Auth configuration was only applied per .npmrc file and then discarded. Therefore, auth defined in the global .npmrc wouldn't apply to registries in the project .npmrc.
This has been fixed, thanks to [@robertshuford](https://github.com/robertshuford)!
## []()[Thanks to 20 contributors!](bun-v1.1.39.html#thanks-to-20-contributors)
- [@01101sam](https://github.com/01101sam)
- [@190n](https://github.com/190n)
- [@cirospaciari](https://github.com/cirospaciari)
- [@DonIsaac](https://github.com/DonIsaac)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Electroid](https://github.com/Electroid)
- [@eventualbuddha](https://github.com/eventualbuddha)
- [@heimskr](https://github.com/heimskr)
- [@hex2f](https://github.com/hex2f)
- [@imide](https://github.com/imide)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@nattui](https://github.com/nattui)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@pfgithub](https://github.com/pfgithub)
- [@RiskyMH](https://github.com/RiskyMH)
- [@robertshuford](https://github.com/robertshuford)
- [@snoglobe](https://github.com/snoglobe)
- [@swen128](https://github.com/swen128)
- [@zackradisic](https://github.com/zackradisic)
* * *
#### [Bun v1.1.38](bun-v1.1.38.html)
#### [Bun v1.1.40](bun-v1.1.40.html)
On this page
- [`bun.lock` is bun's new text-based lockfile](bun-v1.1.39.html#bun-lock-is-bun-s-new-text-based-lockfile)
- [fetch() request body streams](bun-v1.1.39.html#fetch-request-body-streams)
- [Node.js Compatibility](bun-v1.1.39.html#node-js-compatibility)
- [Fixed: Hang in connection error on `postgres` package](bun-v1.1.39.html#fixed-hang-in-connection-error-on-postgres-package)
- [100% of Node's `string_decoder` tests pass](bun-v1.1.39.html#100-of-node-s-string-decoder-tests-pass)
- [100% of Node's `punycode` tests pass](bun-v1.1.39.html#100-of-node-s-punycode-tests-pass)
- [100% of Node's `querystring` tests pass](bun-v1.1.39.html#100-of-node-s-querystring-tests-pass)
- [Improved node:path test coverage](bun-v1.1.39.html#improved-node-path-test-coverage)
- [Improved node:os test coverage](bun-v1.1.39.html#improved-node-os-test-coverage)
- [Fixed: `crypto.createHash(alg, options)` missing option](bun-v1.1.39.html#fixed-crypto-createhash-alg-options-missing-option)
- [Fixed: `napi_wrap`](bun-v1.1.39.html#fixed-napi-wrap)
- [Fixed: error code in node:zlib](bun-v1.1.39.html#fixed-error-code-in-node-zlib)
- [Fixed: `fs.readFileSync` with `flag` parameter in object](bun-v1.1.39.html#fixed-fs-readfilesync-with-flag-parameter-in-object)
- [Bundler improvements](bun-v1.1.39.html#bundler-improvements)
- [`onBeforeParse` - Rust/C/Zig plugin API](bun-v1.1.39.html#onbeforeparse-rust-c-zig-plugin-api)
- [CSS parser improvements](bun-v1.1.39.html#css-parser-improvements)
- [Inject environment variables in `Bun.build()`](bun-v1.1.39.html#inject-environment-variables-in-bun-build)
- [Inline snapshot tests](bun-v1.1.39.html#inline-snapshot-tests)
- [Memory Profiler improvements](bun-v1.1.39.html#memory-profiler-improvements)
- [New: `estimateShallowMemoryUsageOf` in `"bun:jsc"`](bun-v1.1.39.html#new-estimateshallowmemoryusageof-in-bun-jsc)
- [WebSocket server memory reduction](bun-v1.1.39.html#websocket-server-memory-reduction)
- [Dependency upgrades](bun-v1.1.39.html#dependency-upgrades)
- [WebKit Upgrade](bun-v1.1.39.html#webkit-upgrade)
- [Error.isError](bun-v1.1.39.html#error-iserror)
- [Faster String.prototype.at](bun-v1.1.39.html#faster-string-prototype-at)
- [Bug Fixes](bun-v1.1.39.html#bug-fixes)
- [Fixed: Debugger flakiness in VSCode](bun-v1.1.39.html#fixed-debugger-flakiness-in-vscode)
- [Fixed: Crash in POSIX signal handling](bun-v1.1.39.html#fixed-crash-in-posix-signal-handling)
- [Fixed: Rare file descriptor leak in Bun Shell and `Bun.spawn`](bun-v1.1.39.html#fixed-rare-file-descriptor-leak-in-bun-shell-and-bun-spawn)
- [Fixed: fetch redirect handling with `"Connection: close"`](bun-v1.1.39.html#fixed-fetch-redirect-handling-with-connection-close)
- [Fixed: Crash in bun install with invalid package.json in workspace](bun-v1.1.39.html#fixed-crash-in-bun-install-with-invalid-package-json-in-workspace)
- [Fixed: rare crash in Bun.build() plugins](bun-v1.1.39.html#fixed-rare-crash-in-bun-build-plugins)
- [Fixed: crash in Bun.build() with a lot of comments in TypeScript files](bun-v1.1.39.html#fixed-crash-in-bun-build-with-a-lot-of-comments-in-typescript-files)
- [Fixed: global .npmrc not using auth](bun-v1.1.39.html#fixed-global-npmrc-not-using-auth)
- [Thanks to 20 contributors!](bun-v1.1.39.html#thanks-to-20-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.4.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.4
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · April 16, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one.
Bun v1.1.4 fixes 40 bugs (addressing 84 👍 reactions). `bun run --filter <workspace> <script>` lets you run multiple workspace scripts in parallel. Reinstalls get up to 50% faster in bun install. Important reliability fixes to bun install. bun:sqlite supports `using` for resource cleanup and has a few bugfixes. Memory leak impacting Next.js Standalone & Web Streams is fixed. Node.js compatibility improvements `fs` and `child_process`. Fix for "Connection closed" in fetch(). A few bugfixes for Bundows.
#### Previous releases
- [`v1.1.3`](bun-v1.1.3.html) Bun v1.1.3 fixes 5 bugs. bun install gets 50% faster on Windows. A bug that could cause bun install to hang in rare cases has been fixed. A bug where some errors in bun install would not produce a non-zero exit code has been fixed. A bug that could cause specific certain combinations of dependencies to fail to install has been fixed. A bug on Windows where CTRL + C on cmd.exe after exiting bun would not behave as expected has been fixed. A bug where missing permissions on Windows for reading a directory could lead to a crash has been fixed.
- [`v1.1.2`](bun-v1.1.2.html) Bun v1.1.2 fixes 4 bugs (addressing 44 👍 reactions). EBUSY on Windows in vite dev, next dev, and saving bun.lockb has been fixed. Bun Shell gets support for seq, yes, basename and dirname. A TypeScript parsing edgecase has been fixed. A bug causing 'unreachable code' errors has been fixed. fs.watch on Windows has been rewritten to improve performance and reliability.
- [`v1.1.1`](bun-v1.1.1.html) Bun v1.1.1 fixes 20 bugs (addressing 60 👍 reactions).
- [`v1.1.0`](bun-v1.1.html) Bundows. Windows support is here! Plus, JSON IPC Node <-> Bun.
#### To install Bun:
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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 install fixes](bun-v1.1.4.html#bun-install-fixes)
## []()[`bun --filter` runs workspace scripts in parallel](bun-v1.1.4.html#bun-filter-runs-workspace-scripts-in-parallel)
Say you have a monorepo with two packages: `packages/api` and `packages/frontend`, both with a `dev` script that will start a local development server.
Normally, you would have to open two separate terminal tabs, cd into each package directory, and run `bun dev`:
Using `--filter`, you can run the `dev` script in both packages at once, using glob patterns to filter which projects to run the script in:
```
bun --filter='*' dev
```
Both commands will be run in parallel, and you will see a nice terminal UI showing their respective outputs:
[](https://github.com/oven-sh/bun/assets/48869301/2a103e42-9921-4c33-948f-a1ad6e6bac71)
You can pass multiple filters to `--filter`:
```
bun --filter 'packages/api' --filter 'packages/frontend' dev
```
You can think of this as a more powerful replacement for `npm run --workspace <workspace> <script>`.
Thanks to pnpm for the inspiration, and to [@gvilums](https://github.com/gvilums) for implementing this feature.
## []()[Up to 50% faster reinstalls in `bun install`](bun-v1.1.4.html#up-to-50-faster-reinstalls-in-bun-install)
When dependencies in `node_modules` have to be reinstalled (for example, because the version on-disk is different), bun install is now up to 50% faster.
In a repository with 450 MB of `node_modules` on a Macbook Pro M3:
```
❯ hyperfine "bun install --ignore-scripts" "bun-1.1.3 install --ignore-scripts" --prepare="rm -rf node_modules/**/package.json" --warmup=2
Benchmark 1: bun install --ignore-scripts
Time (mean ± σ): 501.6 ms ± 15.6 ms [User: 18.0 ms, System: 1174.0 ms]
Range (min … max): 491.1 ms … 543.8 ms 10 runs
Benchmark 2: bun-1.1.3 install --ignore-scripts
Time (mean ± σ): 771.4 ms ± 13.4 ms [User: 13.9 ms, System: 616.6 ms]
Range (min … max): 756.0 ms … 800.4 ms 10 runs
Summary
bun install --ignore-scripts ran
1.54 ± 0.05 times faster than bun-1.1.3 install --ignore-scripts
```
We moved deleting the old package's files to a separate thread to speed up the wall-clock time and reduce blocking I/O on the main thread.
## []()[Fixed: Hoisting aliased packages](bun-v1.1.4.html#fixed-hoisting-aliased-packages)
Bun was not hoisting aliased npm packages before. This meant we would install the same aliased packages multiple times in `node_modules` unnecessarily.
This has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
## []()[Fixed: Sometimes flaky `bun install` in CI environments](bun-v1.1.4.html#fixed-sometimes-flaky-bun-install-in-ci-environments)
A bug that could cause `bun install` to fail in CI environments sporadically has been fixed.
The code that waited for dependencies in `node_modules` of dependencies within a child `node_modules` folder was not correctly always waiting for the parent to finish installing before installing the children. This led to potentially creating the parent dependencies folder in node\_modules, installing the package, and then deleting it.
This bug manifested most frequently when installing many different versions of the same package simultaneously when there was no cached version available on disk. For example, this bug could cause `string-width` to potentially throw an `ERR_REQUIRE_ESM` when used in Node.js.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this.
### []()[Node.js compatibility improvements](bun-v1.1.4.html#node-js-compatibility-improvements)
## []()[fs.close() callback is optional](bun-v1.1.4.html#fs-close-callback-is-optional)
Previously, the following code would work in Node.js but not in Bun:
```
import fs from "fs";
fs.open("file.txt", "r", (err, fd) => {
// missing the callback in the 2nd argument!
fs.close(fd);
});
```
Now, the callback is optional in Bun as well.
Thanks to [@gvilums](https://github.com/gvilums) for fixing this.
## []()[fs.writeFile(fd, data) should not truncate](bun-v1.1.4.html#fs-writefile-fd-data-should-not-truncate)
In Node.js, when `fs.writeFile` is called with a file descriptor, it does not truncate the file. When called with a path, it does.
Previously in Bun, `fs.writeFile` would truncate the file when called with a file descriptor or a path. This has been fixed to now match Node.js behavior and only truncate when called with a path.
```
import { writeFile } from "fs/promises";
import { openSync } from "fs";
const fd = openSync("file.txt", "w");
await writeFile(fd, "hello"); // does not truncate
await writeFile("file.txt", "hello"); // truncates
```
Thanks to [@gvilums](https://github.com/gvilums) for fixing this.
## []()[FileHandle#appendFile appends](bun-v1.1.4.html#filehandle-appendfile-appends)
In Node.js, `FileHandle#appendFile` appends to the file. Previously in Bun, it would truncate the file before appending. This has been fixed.
```
import { open } from "fs/promises";
const file = await open("file.txt", "a");
await file.appendFile("hello"); // appends
```
### []()[bun:sqlite improvmeents](bun-v1.1.4.html#bun-sqlite-improvmeents)
## []()[New: `using` Database & Statement](bun-v1.1.4.html#new-using-database-statement)
The `using` syntax is now supported for `Database` and `Statement` objects in bun:sqlite. This syntax will automatically call `Database#close` and `Statement#finalize` when the scope ends.
```
import { Database } from "bun:sqlite";
{
// Automatically close the Database at the end of this scope
using db = new Database("file.db");
// Automatically finalize the statement at the end of this scope.
using query = db.query("SELECT * FROM users");
for (const row of query.all()) {
console.log(row);
}
}
```
`using` is part of the stage3 TC39 proposal [Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management).
## []()[New: `Database#fileControl` method](bun-v1.1.4.html#new-database-filecontrol-method)
The low-level [`sqlite3_file_control`](https://www.sqlite.org/c3ref/file_control.html) method is now exposed in bun:sqlite as `Database#fileControl`.
```
import { Database, constants } from "bun:sqlite";
const db = new Database();
// Ensure WAL mode is NOT persistent
// this prevents wal files from lingering after the database is closed
db.fileControl(constants.SQLITE_FCNTL_PERSIST_WAL, 0);
```
## []()[New: `Database#close(throwOnError: boolean = false)` argument](bun-v1.1.4.html#new-database-close-throwonerror-boolean-false-argument)
You can now pass a `throwOnError` argument to `Database#close` to throw an error if the database cannot be closed for any reason.
```
import { Database, constants } from "bun:sqlite";
const db = new Database();
const query = db.query("SELECT * FROM users");
db.close(true); // "Database is locked"
db.close(false); // no error, stop new queries from being created
```
Internally, when `throwOnError` is true, `sqlite3_close` is called instead of `sqlite3_close_v2`.
This is not a breaking change because previously `close` did not accept any arguments, and the behavior remains the same if no arguments are passed. The argument defaults to false.
## []()[Fixed: Close database when garbage collected](bun-v1.1.4.html#fixed-close-database-when-garbage-collected)
When the `Database` object gets garbage collecte due to no longer being in use, the `Database` will now be closed in sqlite automatically.
Previously, bun:sqlite would only close databases automatically on process exit. This was not good enough.
## []()[Fixed: Bug with binding to duplicate column names in JOIN](bun-v1.1.4.html#fixed-bug-with-binding-to-duplicate-column-names-in-join)
A longstanding bug related to duplicate column names in JOIN queries when using bun:sqlite has been fixed.
```
import { Database } from "bun:sqlite";
const db = new Database();
db.query(
"CREATE TABLE Users (Id INTEGER PRIMARY KEY, Name VARCHAR(255));",
).run();
db.query(
"CREATE TABLE Cars (Id INTEGER PRIMARY KEY, Driver INTEGER, FOREIGN KEY (Driver) REFERENCES Users(Id))",
).run();
db.query('INSERT INTO Users (Id, Name) VALUES (1, "Alice");').run();
db.query("INSERT INTO Cars (Id, Driver) VALUES (1, 1);").run();
const car = db.query("SELECT * FROM Cars JOIN Users ON Driver=Users.Id").get();
console.log(car);
db.close();
```
Previously, the above code would incorrectly log:
```
{
Id: 1,
Driver: 1,
Name: 1,
}
```
Now, it correctly logs:
```
{
Driver: 1,
Id: 1,
Name: "Alice",
}
```
This matches the behavior of the popular `better-sqlite3` package.
Thanks to [@gvilums](https://github.com/gvilums) for fixing this, and to [@Hanaasagi](https://github.com/Hanaasagi) for the initial investigation.
### []()[Bundows improvements](bun-v1.1.4.html#bundows-improvements)
## []()[`windowsHide` & `windowsVerbatimArguments`](bun-v1.1.4.html#windowshide-windowsverbatimarguments)
The Node.js `child_process` API supports the `windowsHide` and `windowsVerbatimArguments` options. These options are now supported in Bun as well, thanks to [@nektro](https://github.com/nektro).
## []()[Bun.serve() extra byte](bun-v1.1.4.html#bun-serve-extra-byte)
A bug where Bun.serve() could potentially send an extra byte of duplicated data with certain input has been fixed, thanks to [@cirospaciari](https://github.com/cirospaciari).
This regression started in Bun v1.1.1 and we've improved our test coverage to prevent this from happening again.
## []()[Bun.which() case-insensitive file extension](bun-v1.1.4.html#bun-which-case-insensitive-file-extension)
On Windows, filenames are generally case-insensitive. Bun.which() now also matches case-insensitive file extensions on Windows. This means you can open `cmd.EXE` as well as `cmd.exe` (and all other permutations of case) on Windows.
## []()[`--cwd` flag works on Windows](bun-v1.1.4.html#cwd-flag-works-on-windows)
The `--cwd` flag now works as expected on Windows.
```
bun --cwd=.\my-app run hey
```
This changes the current working directory to `.\my-app` before running the `hey` script. This saves you from having to `cd` into the directory before running the script.
### []()[Runtime improvements](bun-v1.1.4.html#runtime-improvements)
## []()[New: `AbortSignal.any`](bun-v1.1.4.html#new-abortsignal-any)
Bun now supports [`AbortSignal.any`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/any_static), which lets you create a new `AbortSignal` that is aborted when any of the passed `AbortSignal` are signaled. It's sort of like `Promise.race` for `AbortSignal`s.
```
const first = new AbortController().signal;
const second = new AbortController().signal;
fetch("https://example.com", {
signal: first,
});
fetch("https://example.com", {
signal: second,
});
const abortSignal = AbortSignal.any([first, second]);
// Cancel this when either `first` or `second` is aborted
await fetch("https://example.com/slow", { signal: abortSignal });
```
This code comes directly from WebKit/Safari, so thanks to the WebKit team for implementing this feature.
## []()[Fixed: Memory leak in Web Streams impacting Next.js](bun-v1.1.4.html#fixed-memory-leak-in-web-streams-impacting-next-js)
A memory leak in Web Streams has been fixed. This bug could cause Next.js Standalone to leak memory when responding to requests.
Thanks to [@lithdew](https://github.com/lithdew) for fixing this.
## []()[Fixed: fetch() "Connection closed" bug](bun-v1.1.4.html#fixed-fetch-connection-closed-bug)
Some servers rely on TLS v1.2 renegotiation, which lets a server change how it authenticates a client after the connection has been established. This was deprecated in TLS v1.3, but many servers still use it. Previously, when encountering a server that used TLS renegotiation, Bun would throw a "Connection closed" error. We now allow TLS renegotiation for clients, but continue to not allow it for servers. For servers, TLS renegotiation is a DoS attack vector, BoringSSL does not support it, and is generally not recommended.
This bug sometimes manifested as receiving a `Connection closed` error when using `fetch()` in Bun.
Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this, and to [@lithdew](https://github.com/lithdew) for narrowing down the issue.
## []()[Fixed: escaped newlines in shell commands](bun-v1.1.4.html#fixed-escaped-newlines-in-shell-commands)
A bug where escaped newlines in shell commands did not match bash's behavior has been fixed, thanks to [@zackradisic](https://github.com/zackradisic). This bug impacted `bun run` on Windows as well as `Bun.$` at runtime. Thanks to [@zackradisic](https://github.com/zackradisic) for fixing this.
## []()[Thanks to 11 contributors!](bun-v1.1.4.html#thanks-to-11-contributors)
- [@cirospaciari](https://github.com/@cirospaciari)
- [@DaleSeo](https://github.com/@DaleSeo)
- [@dylan-conway](https://github.com/dylan-@conway)
- [@evanshortiss](https://github.com/@evanshortiss)
- [@gvilums](https://github.com/@gvilums)
- [@Jarred-Sumner](https://github.com/Jarred-@Sumner)
- [@jdalton](https://github.com/@jdalton)
- [@jdfwarrior](https://github.com/@jdfwarrior)
- [@nektro](https://github.com/@nektro)
- [@SunsetTechuila](https://github.com/@SunsetTechuila)
- [@zackradisic](https://github.com/@zackradisic)
```
```
* * *
#### [Bun v1.1.3](bun-v1.1.3.html)
#### [Bun v1.1.5](bun-v1.1.5.html)
On this page
- [`bun --filter` runs workspace scripts in parallel](bun-v1.1.4.html#bun-filter-runs-workspace-scripts-in-parallel)
- [Up to 50% faster reinstalls in `bun install`](bun-v1.1.4.html#up-to-50-faster-reinstalls-in-bun-install)
- [Fixed: Hoisting aliased packages](bun-v1.1.4.html#fixed-hoisting-aliased-packages)
- [Fixed: Sometimes flaky `bun install` in CI environments](bun-v1.1.4.html#fixed-sometimes-flaky-bun-install-in-ci-environments)
- [Node.js compatibility improvements](bun-v1.1.4.html#node-js-compatibility-improvements)
- [fs.close() callback is optional](bun-v1.1.4.html#fs-close-callback-is-optional)
- [fs.writeFile(fd, data) should not truncate](bun-v1.1.4.html#fs-writefile-fd-data-should-not-truncate)
- [FileHandle#appendFile appends](bun-v1.1.4.html#filehandle-appendfile-appends)
- [bun:sqlite improvmeents](bun-v1.1.4.html#bun-sqlite-improvmeents)
- [New: `using` Database & Statement](bun-v1.1.4.html#new-using-database-statement)
- [New: `Database#fileControl` method](bun-v1.1.4.html#new-database-filecontrol-method)
- [New: `Database#close(throwOnError: boolean = false)` argument](bun-v1.1.4.html#new-database-close-throwonerror-boolean-false-argument)
- [Fixed: Close database when garbage collected](bun-v1.1.4.html#fixed-close-database-when-garbage-collected)
- [Fixed: Bug with binding to duplicate column names in JOIN](bun-v1.1.4.html#fixed-bug-with-binding-to-duplicate-column-names-in-join)
- [Bundows improvements](bun-v1.1.4.html#bundows-improvements)
- [`windowsHide` & `windowsVerbatimArguments`](bun-v1.1.4.html#windowshide-windowsverbatimarguments)
- [Bun.serve() extra byte](bun-v1.1.4.html#bun-serve-extra-byte)
- [Bun.which() case-insensitive file extension](bun-v1.1.4.html#bun-which-case-insensitive-file-extension)
- [`--cwd` flag works on Windows](bun-v1.1.4.html#cwd-flag-works-on-windows)
- [Runtime improvements](bun-v1.1.4.html#runtime-improvements)
- [New: `AbortSignal.any`](bun-v1.1.4.html#new-abortsignal-any)
- [Fixed: Memory leak in Web Streams impacting Next.js](bun-v1.1.4.html#fixed-memory-leak-in-web-streams-impacting-next-js)
- [Fixed: fetch() "Connection closed" bug](bun-v1.1.4.html#fixed-fetch-connection-closed-bug)
- [Fixed: escaped newlines in shell commands](bun-v1.1.4.html#fixed-escaped-newlines-in-shell-commands)
- [Thanks to 11 contributors!](bun-v1.1.4.html#thanks-to-11-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.40.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.40
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · December 18, 2024
[](../rss.xml)
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
This release fixes 14 bugs. Adds `install.saveTextLockfile` option in bunfig.toml to make the text lockfile format the default. Fixes bugs in package-lock.json migration when manually changing npm resolutions to git URLs. Fixes a regression in process.on from Bun v1.1.39. Fixes an issue with BigInt in napi APIs impacting DuckDB. Improves reliability of installing git/github dependencies in bun install. Upgrades WebKit with security & reliability improvements.
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[New: `install.saveTextLockfile` in bunfig.toml](bun-v1.1.40.html#new-install-savetextlockfile-in-bunfig-toml)
In Bun v1.1.39, we introduced the [text-based `bun.lock` lockfile](bun-lock-text-lockfile.html) format for `bun install`. In Bun v1.2, we will make it the default.
To use `bun.lock` instead of `bun.lockb`:
```
bun install --save-text-lockfile
```
Several people have asked for a way to use the text-based lockfile format by default without waiting for v1.2.
You can now set `install.saveTextLockfile = true` in your `bunfig.toml` to make the text lockfile format the default.
~/.bunfig.toml
```
[install]
saveTextLockfile = true
```
You can place this in your global `~/.bunfig.toml`.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for implementing this!
## []()[Fixed: regression in process.on from Bun v1.1.39](bun-v1.1.40.html#fixed-regression-in-process-on-from-bun-v1-1-39)
A regression introduced in Bun v1.1.39 caused `process.on` when used in a Worker, in a single-file executable, or a macro to potentially crash. This has been fixed.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for implementing this!
## []()[Fixed: N-API BigInt handling bug impacting DuckDB](bun-v1.1.40.html#fixed-n-api-bigint-handling-bug-impacting-duckdb)
Our N-API implementation for `napi_create_bigint_words` was not handling trailing zeros consistently with Node.js & V8.
The `napi_get_value_bigint_uint64` and `napi_get_value_bigint_int64` functions were not setting the `lossless` boolean flag.
These have been fixed, thanks to [@190n](https://github.com/190n)!
## []()[Improved git/github dependency installation reliability](bun-v1.1.40.html#improved-git-github-dependency-installation-reliability)
In rare cases, `bun install` would hang or fail to install git/github dependencies.
What makes Git/GitHub dependencies tricky is we don't know their own dependencies until after we've downloaded the package (unlike npm which has a registry API we can ask ahead of time). To save you time, bandwidth, and disk space, `bun install` goes to great lengths to avoid downloading packages that ultimately won't be used or are already installed. Often `bun install` won't try to download a package until we try to install it, see it's not there in node\_modules, and see it's not there in the global store.
This release fixes a bug that could cause git dependencies to fail to transition from the downloading state to the installed state. This release also fixes a bug in package-lock.json migration when manually changing npm URLs to git URLs.
Thank to [@dylan-conway](https://github.com/dylan-conway) for implementing this!
## []()[WebKit upgrade](bun-v1.1.40.html#webkit-upgrade)
This WebKit upgrade includes reliability and security improvements.
- A lock could theoretically unlock too early
- An edgecase involving the DFG JIT with the `[[ToString]]` operation
- Setting a value in a typed array of integers in the DFG JIT could end up in an incorrect state in the global object when taking a slow path
### []()[Thanks to 4 contributors!](bun-v1.1.40.html#thanks-to-4-contributors)
- [@190n](https://github.com/190n)
- [@dylan-conway](https://github.com/dylan-conway)
- [@jarred-sumner](https://github.com/jarred-sumner)
- [@riskymh](https://github.com/riskymh)
* * *
#### [Bun v1.1.39](bun-v1.1.39.html)
#### [Bun v1.1.41](bun-v1.1.41.html)
On this page
- [New: `install.saveTextLockfile` in bunfig.toml](bun-v1.1.40.html#new-install-savetextlockfile-in-bunfig-toml)
- [Fixed: regression in process.on from Bun v1.1.39](bun-v1.1.40.html#fixed-regression-in-process-on-from-bun-v1-1-39)
- [Fixed: N-API BigInt handling bug impacting DuckDB](bun-v1.1.40.html#fixed-n-api-bigint-handling-bug-impacting-duckdb)
- [Improved git/github dependency installation reliability](bun-v1.1.40.html#improved-git-github-dependency-installation-reliability)
- [WebKit upgrade](bun-v1.1.40.html#webkit-upgrade)
- [Thanks to 4 contributors!](bun-v1.1.40.html#thanks-to-4-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.41.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.41
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · December 20, 2024
[](../rss.xml)
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
This release fixes 12 bugs (addressing 196 👍). JSDOM & happy-dom work more reliably due to node:vm compatibility improvements. bun build --compile gets the --windows-icon and --windows-hide-console options (Windows-only). bun install gets the --omit=dev|optional|peer options and in .npmrc. A hoisting edgecase in bun install is fixed
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[JSDOM, happy-dom, and vm compatibility improvements](bun-v1.1.41.html#jsdom-happy-dom-and-vm-compatibility-improvements)
We've made compatibility improvements to our `node:vm` implementation, and that makes `jsdom` and `happy-dom` work more reliably in Bun.
### []()[JSDOM fixes](bun-v1.1.41.html#jsdom-fixes)
Previously, the `runScripts: "outside-only"`, `runScripts: "dangerously"`, and `runInContext` options in JSDOM were not supported. Now they are.
[](https://github.com/user-attachments/assets/77a5ac98-c5fb-4733-acc8-cdc1b6c948ba)
### []()[happy-dom fixes](bun-v1.1.41.html#happy-dom-fixes)
`happy-dom` no longer throws an error when you call `window.requestAnimationFrame`, or when you call various other methods that depend on the `this` value being set correctly.
[](https://github.com/user-attachments/assets/bef277db-7d4c-433f-9871-238c7b0044eb)
## []()[New: Icons in single-file executables for Windows](bun-v1.1.41.html#new-icons-in-single-file-executables-for-windows)
[Single-file executables](../docs/bundler/executables.html) now support the `--windows-icon=./icon.ico` option to embed an icon in the executable on Windows.
```
bun build --compile --windows-icon=./icon.ico ./index.ts --outfile=app.exe
```
Thanks to [@paperclover](https://github.com/paperclover) for implementing this!
## []()[New: Hide the console window in single-file executables for Windows](bun-v1.1.41.html#new-hide-the-console-window-in-single-file-executables-for-windows)
You can now hide the console window on Windows when a [single-file executable](../docs/bundler/executables.html) is run.
```
bun build --compile --windows-hide-console ./index.ts --outfile=app.exe
```
## []()[New: throw: true in Bun.build](bun-v1.1.41.html#new-throw-true-in-bun-build)
When the build fails, the `throw: true` option in `Bun.build` throws an error instead of returning errors in the `logs` array.
```
const build = Bun.build({
entrypoints: ["./index.ts"],
outdir: "./dist",
throw: true,
});
```
We will make this behavior the default in Bun v1.2.
## []()[New: --omit=dev|optional|peer options in bun install](bun-v1.1.41.html#new-omit-dev-optional-peer-options-in-bun-install)
We want `bun install` to "just work" in existing projects using npm. We already support `package-lock.json` migration (and have for awhile), and this is another step towards that goal.
`bun install` now supports:
- `--omit=dev` to omit dev dependencies (similar to `--production`)
- `--omit=optional` to omit optional dependencies
- `--omit=peer` to omit peer dependencies
- ...and any combination of the above
We've also added support for `include` and `exclude` in `.npmrc`, and in `bunfig.toml`.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for implementing this!
## []()[New: expect().toHaveBeenCalledOnce()](bun-v1.1.41.html#new-expect-tohavebeencalledonce)
You can now use `expect().toHaveBeenCalledOnce()` to check that a mock function was called exactly once.
```
import { test, expect, mock } from "bun:test";
test("fn is called once", () => {
const fn = mock(() => {});
expect(fn).not.toHaveBeenCalledOnce();
fn();
expect(fn).toHaveBeenCalledOnce();
fn();
expect(fn).not.toHaveBeenCalledOnce();
});
```
## []()['use strict' is now CommonJS](bun-v1.1.41.html#use-strict-is-now-commonjs)
Some CLIs REALLY want to trick bundlers and get the current module's file path, do a runtime require, or check if the current module is the main module. They try all kinds of things to make it work, such as:
```
"use strict";
if (eval("require.main") === eval("module.main")) {
// ...
}
```
One of the hard parts about how Bun makes CommonJS and ESM interop "just work" is that there's a lot of ambiguity.
Consider this code:
```
console.log("123");
```
Is that CommonJS or ESM? No way to tell.
Okay, how about this?
```
console.log(module.require("path"));
```
CommonJS, because it's using `module.require` to get the `path` module.
And this?
```
import path from "path";
console.log(path);
```
ESM because it's using `import`.
And this?
```
import path from "path";
const fs = require("fs");
console.log(fs.readFileSync(path.resolve("package.json"), "utf8"));
```
ESM, because it's using `import`, and saying it's CommonJS due to the require would break the code. We want to simplify building stuff in JavaScript, so let's just say it's ESM and not be fussy.
And finally, how about this?
```
"use strict";
console.log(eval("module.require('path')"));
```
Previously, Bun would say "ESM" because it's what we default to when there's absolutely no way to tell (including when the file extension is ambiguous, no "type" field in package.json, no export, no import, no TLA, etc etc).
Now, Bun will say "CommonJS" because it had `"use strict"` at the top of the file.
ES modules are always strict mode, so an explicit `"use strict"` would only be useful to include if the file was originally intended to be CommonJS. Most build tools nowadays that output CommonJS will include the `"use strict"` directive at the top of the file. So we can use this as a last-chance heuristic when it's completely ambiguous whether the file is CommonJS or ESM.
Previously, an `eval("require.main")` would throw a `ReferenceError` because the spec-compliant behavior of `eval` inside of ESM is indirect (global scope), and even if it wasn't global scope, Bun replaces `require` with `import.meta.require` in ESM at transpilation time so that code would never work regardless. So, in the spirit of "your code should just work", we have added `"use strict"` at the top of the file to our repertoire of what we consider CommonJS.
## []()[Fixed: bun install progress bar shows total install count](bun-v1.1.41.html#fixed-bun-install-progress-bar-shows-total-install-count)
> In the next version of Bun
>
> A longstanding bug that sometimes caused this fraction to be impossible is fixed [pic.twitter.com/8heI6obyft](https://t.co/8heI6obyft)
>
> — Bun (@bunjavascript) [December 20, 2024](https://twitter.com/bunjavascript/status/1870094361184350400?ref_src=twsrc%5Etfw)
## []()[Fixed: potential infinite loop with cached disabled optional dependencies in bun install](bun-v1.1.41.html#fixed-potential-infinite-loop-with-cached-disabled-optional-dependencies-in-bun-install)
An infinite loop that could potentially occur caused by disabling optional dependencies and installing with a populated cache has been fixed.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this!
## []()[Fixed: unresolvable dependencies edgecase in bun install](bun-v1.1.41.html#fixed-unresolvable-dependencies-edgecase-in-bun-install)
When using platform-specific dependencies or disabling dependencies through `--production`, in certain rare cases `bun install` would hang due to incorrectly handling unresolvable dependencies.
This was caused by a spot where we were not sorting dependencies by their "behavior" (is it optional? peer? dev? etc). This led to inconsistent
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this!
## []()[Fixed: `--conditions=default` in bun build](bun-v1.1.41.html#fixed-conditions-default-in-bun-build)
A crash that could occur when using `--conditions=default` in `Bun.build` has been fixed. Note: the `default` condition is used by default in `Bun.build`.
Thanks to [@paperclover](https://github.com/paperclover) for fixing this!
## []()[Fixed: `util.styleText` supports color arrays](bun-v1.1.41.html#fixed-util-styletext-supports-color-arrays)
You can now pass an array of colors to `util.styleText` to style a string with multiple colors.
```
const styledText = util.styleText(
["red", "bold", "underline"],
"Hello, world!",
);
```
In Bun's CommonJS module loader, we were not handling the scenario where a module does not evaluate to a function. The transpiler always outputs a function. That being said, it's theoretically possible that a module could evaluate to something other than a function, and so we fixed it anyway.
As part of this, we also moved the step where it assigns the `module.require` and `module.require.resolve` function to occur after the outer function wrapper has been evaluated instead of before. There should in theory not be an observable behavior difference, but if you find anything please let us know!
## []()[Fixed: import namespaces and default imports for macros](bun-v1.1.41.html#fixed-import-namespaces-and-default-imports-for-macros)
You can now import namespaces and default imports for macros.
```
import myMacro from "at-build-time" with {type: "macro"};
import * as allMyMacros from "at-build-time" with {type: "macro"};
myMacro();
allMyMacros.myMacro();
```
Thanks to [@brainkim](https://github.com/brainkim) for fixing this!
### []()[Thanks to 6 contributors!](bun-v1.1.41.html#thanks-to-6-contributors)
- [@brainkim](https://github.com/brainkim)
- [@donisaac](https://github.com/donisaac)
- [@dylan-conway](https://github.com/dylan-conway)
- [@jarred-sumner](https://github.com/jarred-sumner)
- [@paperclover](https://github.com/paperclover)
- [@riskymh](https://github.com/riskymh)
* * *
#### [Bun v1.1.40](bun-v1.1.40.html)
#### [Bun v1.1.42](bun-v1.1.42.html)
On this page
- [JSDOM, happy-dom, and vm compatibility improvements](bun-v1.1.41.html#jsdom-happy-dom-and-vm-compatibility-improvements)
- [JSDOM fixes](bun-v1.1.41.html#jsdom-fixes)
- [happy-dom fixes](bun-v1.1.41.html#happy-dom-fixes)
- [New: Icons in single-file executables for Windows](bun-v1.1.41.html#new-icons-in-single-file-executables-for-windows)
- [New: Hide the console window in single-file executables for Windows](bun-v1.1.41.html#new-hide-the-console-window-in-single-file-executables-for-windows)
- [New: throw: true in Bun.build](bun-v1.1.41.html#new-throw-true-in-bun-build)
- [New: --omit=dev|optional|peer options in bun install](bun-v1.1.41.html#new-omit-dev-optional-peer-options-in-bun-install)
- [New: expect().toHaveBeenCalledOnce()](bun-v1.1.41.html#new-expect-tohavebeencalledonce)
- ['use strict' is now CommonJS](bun-v1.1.41.html#use-strict-is-now-commonjs)
- [Fixed: bun install progress bar shows total install count](bun-v1.1.41.html#fixed-bun-install-progress-bar-shows-total-install-count)
- [Fixed: potential infinite loop with cached disabled optional dependencies in bun install](bun-v1.1.41.html#fixed-potential-infinite-loop-with-cached-disabled-optional-dependencies-in-bun-install)
- [Fixed: unresolvable dependencies edgecase in bun install](bun-v1.1.41.html#fixed-unresolvable-dependencies-edgecase-in-bun-install)
- [Fixed: `--conditions=default` in bun build](bun-v1.1.41.html#fixed-conditions-default-in-bun-build)
- [Fixed: `util.styleText` supports color arrays](bun-v1.1.41.html#fixed-util-styletext-supports-color-arrays)
- [Fixed: unnecessary inline sourcemaps in VSCode](bun-v1.1.41.html#fixed-unnecessary-inline-sourcemaps-in-vscode)
- [Fixed: Theoretical crash in CommonJS module loading](bun-v1.1.41.html#fixed-theoretical-crash-in-commonjs-module-loading)
- [Fixed: import namespaces and default imports for macros](bun-v1.1.41.html#fixed-import-namespaces-and-default-imports-for-macros)
- [Thanks to 6 contributors!](bun-v1.1.41.html#thanks-to-6-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.42.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.42
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · December 21, 2024
[](../rss.xml)
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
This release fixes 1 regression from Bun v1.1.41 involving `"use strict"` in empty files and impacting Prisma.
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[Fixed: `"use strict"` regression](bun-v1.1.42.html#fixed-use-strict-regression)
Bun v1.1.41 introduced a regression where `"use strict"` in otherwise empty files could cause a crash. We've added regression tests to ensure this doesn't happen again.
* * *
#### [Bun v1.1.41](bun-v1.1.41.html)
#### [Bun v1.1.43](bun-v1.1.43.html)
On this page
- [Fixed: `"use strict"` regression](bun-v1.1.42.html#fixed-use-strict-regression)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.43.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.43
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · January 8, 2025
[](../rss.xml)
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
This release introduces 1st-class S3 support, HTML bundling, bun install --filter, V8 heap snapshots, bun install --lockfile-only, bun add --peer, 100% of node's path module Node.js test pass, 98% of zlib tests pass, Bun.file(path).stat(), Bun.file(path).delete(), along with many reliability improvements and bugfixes.
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[1st-class S3 support](bun-v1.1.43.html#1st-class-s3-support)
This release introduces 1st-class S3 Object Storage support in Bun.
Modern user-facing production servers frequently choose to store files in S3-like object storage services instead of the local POSIX filesystem. Decoupling storage capacity from compute capacity prevents an entire class of production reliability issues: low disk space, high p95 response times related to file system i/o, security issues related to persistent storage.
S3 is a de-facto standard that predates ES6 by a decade. The POSIX filesystem API was never designed for the internet age (non-blocking regular files aren't a thing! It's crazy!).
Bun's S3 API is designed to be feel similar to the web's `Response` and `Blob` APIs (like Bun's local filesystem APIs).
```
import { s3, write, S3Client } from "bun";
// Bun.s3 reads environment variables for credentials
// file() returns a lazy reference to a file on S3
const metadata = s3.file("123.json");
// Download from S3
const data = await metadata.json();
const text = await metadata.text();
const arrayBuffer = await metadata.arrayBuffer();
const uint8array = await metadata.bytes();
// Upload to S3
await metadata.write(JSON.stringify({ name: "John", age: 30 }));
await metadata.write(Bun.file("./123.json"));
// Presign a URL (synchronous - no network request needed)
const url = metadata.presign({
acl: "public-read",
expiresIn: 60 * 60 * 24, // 1 day
});
// Delete the file
await metadata.delete();
```
We added this API to Bun because many servers don't use `fs`, they use S3.
You can use Bun's S3 client with any S3-compatible object storage service, such as:
- AWS S3
- Google Cloud Storage
- DigitalOcean Spaces
- Cloudflare R2
- Backblaze B2
- MinIO
- ...and more
Learn more about Bun's S3 API [in the docs](../docs/api/s3.html).
## []()[HTML Bundler](bun-v1.1.43.html#html-bundler)
Bun now natively supports bundling HTML files along with their associated JavaScript, CSS, and assets. This makes it easier to build static sites and web applications with Bun.
```
bun build --experimental-html --experimental-css ./index.html --outdir=dist
```
> In the next version of Bun
>
> bun build supports bundling assets, JS, and CSS from .html files [pic.twitter.com/5VpweY1HMn](https://t.co/5VpweY1HMn)
>
> — Jarred Sumner (@jarredsumner) [December 22, 2024](https://twitter.com/jarredsumner/status/1870797521993539813?ref_src=twsrc%5Etfw)
This bundles stylesheets, JavaScript, and all other assets. Multiple nested levels of JavaScript `import` and `require` get bundled into one file. CSS files are parsed and concatenated into one file (whether using `@import` or multiple `<link>` tags).
In Bun v1.2, we'll remove the `--experimental-html` and `--experimental-css` flags and they'll be enabled by default.
## []()[`bun install --filter <pattern>`](bun-v1.1.43.html#bun-install-filter-pattern)
`bun install` gets `--filter` support. This lets you selectively install workspace packages within your monorepo.
[](https://github.com/user-attachments/assets/5579693c-1572-4e9f-9b30-2b2c463c128f)
Thanks to [@dylan-conway](https://github.com/dylan-conway) for implementing this!
## []()[V8 Heap Snapshots](bun-v1.1.43.html#v8-heap-snapshots)
Bun now supports outputting V8 heap snapshots. This lets you use Chrome DevTools to inspect the heap of your Bun application. This wasn't previously possible before because Bun doesn't use V8 as the JavaScript engine. Bun uses JavaScriptCore. To make this work, we've added support for this in our fork of WebKit/JavaScriptCore.
Relatedly, we've also added support for `v8.writeHeapSnapshot` and `v8.getHeapSnapshot` in `node:v8`.
```
import { writeHeapSnapshot, getHeapSnapshot } from "node:v8";
const path = writeHeapSnapshot();
console.log(path); // Outputs the path to the generated heap snapshot
const snapshot = await Bun.file(path).json();
console.log(snapshot); // Outputs the parsed heap snapshot data
```
> In the next version of Bun
>
> Bun.generateHeapSnapshot("v8") outputs V8's .heapsnapshot format, so you can use Chrome DevTools and VSCode to debug memory usage [pic.twitter.com/veIBqASLoi](https://t.co/veIBqASLoi)
>
> — Jarred Sumner (@jarredsumner) [January 2, 2025](https://twitter.com/jarredsumner/status/1874804829132095541?ref_src=twsrc%5Etfw)
## []()[Errors show more properties](bun-v1.1.43.html#errors-show-more-properties)
Previously, Bun hardcoded a small list of properties to display when printing top-level errors. Now we print all the own properties of the error.
Fixed:
```
❯ bun such.js
1 | const err = new Error("An example error");
^
error: An example error
wow: "wow",
such: "property",
very: "information",
at <file>.js:1:13
```
Previously, Bun would not show properties like `wow`, `such`, or `very` when displaying errors. Now it shows everything defined on the error object directly.
```
❯ bun-1.1.42 such.js
1 | const err = new Error("An example error");
^
error: An example error
at <file>.js:1:13
```
## []()[bun run](bun-v1.1.43.html#bun-run)
### []()[`-F` is for `--filter`](bun-v1.1.43.html#f-is-for-filter)
`bun run --filter='*pkg' <script>` now supports the `-F` shorthand
```
bun run -F=<pattern> <script>
bun run --filter=<pattern> <script>
bun -F <pattern> <script>
bun -F=<pattern> <script>
```
### []()[`--elide-lines=N` controls filter output line length](bun-v1.1.43.html#elide-lines-n-controls-filter-output-line-length)
The `--elide-lines` option in `bun run --filter` controls the number of output lines displayed when interactively running scripts in a terminal. This helps avoid missing errors in long scripts, while still showing the output of the script.
```
bun run --filter ./packages/dep0 --elide-lines=5 script
```
Thanks to [@martinamps](https://github.com/martinamps) for implementing this!
### []()[`pnpx` and `pnpm dlx` auto-replacement](bun-v1.1.43.html#pnpx-and-pnpm-dlx-auto-replacement)
When you use `bun run` to run package.json scripts, we swap out `yarn run`, `npm run`, and `pnpm run` with `bun run` (so that you don't have to update your package.json). Now we also replace `pnpx` and `pnpm dlx` with `bunx`.
Thanks to [@pfgithub](https://github.com/pfgithub) for implementing this!
## []()[bun install](bun-v1.1.43.html#bun-install)
### []()[New: slow postinstall script logging](bun-v1.1.43.html#new-slow-postinstall-script-logging)
Buggy postinstall scripts on npm can cause your install to hang.
To help identify the package causing the hang, `bun install` now logs the package name of any postinstall scripts that takes longer than 30 seconds to run.
If you run `bun install` with `--verbose`, it will log the package name every 2 seconds instead of every 30 seconds.
### []()[New: `bundle(d)Dependencies` in `bun install`](bun-v1.1.43.html#new-bundle-d-dependencies-in-bun-install)
Bun now supports handling `bundle(d)Dependencies` in the `bun install` command. This update allows users to specify dependencies that should be bundled together, streamlining package management. This makes it easier for users to create consistent and manageable projects, especially when dealing with multiple dependencies.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for implementing this!
### []()[New: `--lockfile-only` option for bun install](bun-v1.1.43.html#new-lockfile-only-option-for-bun-install)
You can now use the `--lockfile-only` option with the `bun install` command to generate a lockfile without installing any dependencies. This is useful when you want to update or create a lockfile based on your `package.json` without affecting the state of your `node_modules` directory.
[](https://github.com/user-attachments/assets/fcad5a9b-1a05-475c-978a-fe0ed0c294d1)
Thanks to [@dylan-conway](https://github.com/dylan-conway) for implementing this!
### []()[New: `--peer` option in `bun add`](bun-v1.1.43.html#new-peer-option-in-bun-add)
You can now add a package as a peer dependency using the `--peer` option with the `bun add` command. This functionality allows users to specify peer dependencies directly from their terminal, enhancing the usability of package management in Bun.
```
bun add --peer @types/bun
```
Thanks to [@riskymh](https://github.com/riskymh) for implementing this!
### []()[Fixed: bun.lock file permissions](bun-v1.1.43.html#fixed-bun-lock-file-permissions)
Bun's text-based lockfile was being marked as world-writable and executable, which was unnecessary.
This has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway)!
### []()[Fixed: `install.cache.dir` in bunfig.toml](bun-v1.1.43.html#fixed-install-cache-dir-in-bunfig-toml)
The `install.cache.dir` option now correctly reads the cache directory from your `bunfig.toml`. This change ensures that the cache directory can be customized through your configuration.
```
[install]
cache.dir = "./your_custom_cache_directory"
```
Thanks to [@chawyehsu](https://github.com/chawyehsu) for implementing this!
### []()[Fixed: crash in `bun patch --commit`](bun-v1.1.43.html#fixed-crash-in-bun-patch-commit)
A crash in `bun patch --commit` has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway)!
### []()[Fixed: quote-escaping in `bun.lock` package names](bun-v1.1.43.html#fixed-quote-escaping-in-bun-lock-package-names)
Invalid `"name"` fields in package.json files were being persisted in the `bun.lock` file without escaping the quote character. This has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway)!
## []()[Node.js compatibility improvements](bun-v1.1.43.html#node-js-compatibility-improvements)
### []()[100% of `node:path` tests now pass](bun-v1.1.43.html#100-of-node-path-tests-now-pass)
Bun's `node:path` module now passes 100% of Node.js' test suite.
#### Fixed: potential crash when joining long win32 paths in `node:path`
A crash that could occur when joining very long paths using the `node:path` module has been fixed, thanks to [@DonIsaac](https://github.com/DonIsaac)!
### []()[98.08% of `node:zlib` tests now pass](bun-v1.1.43.html#98-08-of-node-zlib-tests-now-pass)
All but 1 test in the `node:zlib` module now pass.
Thanks to [@nektro](https://github.com/nektro) for this!
#### Fixed: memory leak in node:zlib
A memory leak in the `node:zlib` module has been fixed. This particularly impacted Brotli compression.
#### Fixed: zlib dictionary option handling
The `dictionary` option in `zlib` now works as expected. This fixed an issue impacting some Minecraft servers using Bun.
```
const deflate = zlib.createDeflate({ dictionary: Buffer.from("...") });
```
### []()[Fixed: napi\_set\_last\_error method in Node-API](bun-v1.1.43.html#fixed-napi-set-last-error-method-in-node-api)
The `napi_set_last_error` method in Node-API now sets an appropriate error code prior to returning. Previously, we were not consistently setting the error code prior to returning from Node-API functions - which caused some native addons to not receive the correct error code after a failed function call.
Thanks to [@190n](https://github.com/190n) for implementing this!
### []()[Fixed: `process.kill` allows zero or negative PIDs](bun-v1.1.43.html#fixed-process-kill-allows-zero-or-negative-pids)
An incorrect validation was preventing `process.kill` from accepting negative PIDs. Negative PIDs let you kill an entire process group instead of just a single process.
```
const { spawn, exec } = require("child_process");
// Starting a process
const child = spawn("some-command");
// Killing the process using a negative PID
process.kill(-child.pid);
```
Thanks to [@nektro](https://github.com/nektro) for implementing this!
### []()[`--expose-gc` flag adds `globalThis.gc`](bun-v1.1.43.html#expose-gc-flag-adds-globalthis-gc)
Bun now implements the Node.js `--expose-gc` CLI flag, alongside the `Bun.gc()` method. This CLI flag adds `gc` to the global scope, which allows you to manually trigger garbage collection in your code.
```
bun --expose-gc <script.js>
```
The `Bun.gc()` method is the same as `globalThis.gc`.
### []()[Fixed: `process.memoryUsage().arrayBuffers`](bun-v1.1.43.html#fixed-process-memoryusage-arraybuffers)
Previously, `process.memoryUsage().arrayBuffers` was always reporting `0`. Now we do our best to report the correct number.
What's interesting about this is a difference in how JavaScriptCore and V8 handle `ArrayBuffer` memory. In JavaScriptCore, typed array's buffers are "owned" by the TypedArray type (a `Uint8Array` and not an `ArrayBuffer`, for example). They don't become "shared" between `Uint8Array` and `ArrayBuffer` (or other typed arrays) until either:
- The `.buffer` property was accessed (creating the `ArrayBuffer`).
- The `.subarray` method was called (creating a shared reference).
- The typed array size is > 512 bytes.
- The typed array was externally allocated outside of JavaScript (such as when reading a file in Bun)
When the ArrayBuffer's contents are not owned by JavaScriptCore, they aren't included in the `process.memoryUsage().arrayBuffers` statistic, and instead are accounted for in the `process.memoryUsage().external` statistic.
#### Improved: module.findSourceMap
`require("module").findSourceMap` no longer throws an error when called. Previously, this threw an error saying we don't implement `module.SourceMap` yet. It's still not implemented, but throwing an error caused issues with Next.js in certain cases - so now we return `undefined` instead, which matches Node.js' behavior when no source map is found.
## []()[bun build](bun-v1.1.43.html#bun-build)
### []()[Improved stack overflow detection](bun-v1.1.43.html#improved-stack-overflow-detection)
Bun's JavaScript parser now proactively checks if it's about to run out of stack space, and throws an artifical stack overflow error.
Fixed (now a recoverable error):
```
❯ bun lots-of-for-loop.js
286 | for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++) for (let i = 0; i < 1; i++)
^
error: Maximum call stack size exceeded
at lots-of-for-loop.js:286:49
```
Previously, bun would crash with a hard SIGILL, which is not recoverable.
```
bun: killed SIGILL (core dumped)
```
### []()[Fixed: large number of if statements led to stack overflow](bun-v1.1.43.html#fixed-large-number-of-if-statements-led-to-stack-overflow)
Two things caused stack overflows with large numbers of nested if statements:
1. The statement parsing step for `if` statements was always recursive, even if the `if` statement was not nested. This recursion used too much stack space. Now it's no longer recursive.
2. The statement visiting step in Bun's JavaScript parser was originally a ~1,300 line function. This used several kilobytes of stack space, which became a problem when recursing through heavily nested if/for loops. We split it into more functions and avoided recursion more frequently.
### []()[Fixed: `#bun` pragma](bun-v1.1.43.html#fixed-bun-pragma)
Ordinarily, bun transpiles every file at runtime. To avoid potentially transpiling the same file multiple times, bun looks for a `// @bun` pragma comment.
There was a bug where Bun's JavaScript lexer would sometimes interpret the string `#bun` present in comments as the `bun` pragma meant for disabling transpilation.
This has been fixed, thanks to [@DonIsaac](https://github.com/DonIsaac)!
### []()[Fixed: cross-compile for musl in `bun build --compile`](bun-v1.1.43.html#fixed-cross-compile-for-musl-in-bun-build-compile)
The code that parses the `--target` flag in `bun build --compile` wasn't updated for when we added musl support in Bun v1.1.40. This has been fixed, thanks to [@thecrypticace](https://github.com/thecrypticace).
### []()[Fixed: sourcemap comments CSS files](bun-v1.1.43.html#fixed-sourcemap-comments-css-files)
The `//# sourceMappingURL` comment meant for JavaScript files was being printed in CSS files. This has been fixed.
### []()[Fixed: crash when parsing malformed TypeScript enums](bun-v1.1.43.html#fixed-crash-when-parsing-malformed-typescript-enums)
A crash that occurred when handling malformed enums in the transpiler has been fixed.
```
// Example of a malformed enum that will generate a parse error
enum Foo { [2]: 'hi' }
```
Thanks to [@paperclover](https://github.com/paperclover) for implementing this!
## []()[Runtime improvements](bun-v1.1.43.html#runtime-improvements)
### []()[Override `"Content-Length"` and `Transfer-Encoding` in Bun.serve()](bun-v1.1.43.html#override-content-length-and-transfer-encoding-in-bun-serve)
Bun.serve now supports overriding the `"Content-Length"` and `Transfer-Encoding` headers.
This is particularly useful for `HEAD` requests, where you want to return a `Content-Length` but not actually send the body.
```
const app = Bun.serve({
port: 3000,
fetch(req) {
return new Response("Hello World", {
headers: { "Content-Length": "7" },
});
},
});
```
Thanks to [@cirospaciari](https://github.com/cirospaciari) for implementing this!
### []()[New: `stat` method in Bun.file(path)](bun-v1.1.43.html#new-stat-method-in-bun-file-path)
You can now use `stat` without `node:fs` in Bun.
```
import { file } from "bun";
await file("./path-to-file.txt").stat();
```
This returns useful information about the file, such as its size, type, and last modified date. This returns the same type as in `node:fs`'s `stat` function.
### []()[New: `delete` method in Bun.file(path)](bun-v1.1.43.html#new-delete-method-in-bun-file-path)
You can now delete files in Bun, without `node:fs`.
```
import { file } from "bun";
await file("./path-to-file.txt").delete();
```
### []()[More accurate heap snapshots](bun-v1.1.43.html#more-accurate-heap-snapshots)
The memory cost of adding entries to `performance.mark` and `performance.measure` is now reported accurately in heap snapshots.
### []()[Fixes to stack traces with eval and node:vm](bun-v1.1.43.html#fixes-to-stack-traces-with-eval-and-node-vm)
Ordinarily, Bun transpiles every file at runtime. This also means we have to sourcemap stack traces and error messages.
We don't transpile code for node:vm or for `eval` (it would break compatibility). However, in certain cases, when some of the stack frames in a stack trace were from `eval` or `node:vm` and some of them were from Bun, the trace could get incorrectly sourcemapped.
Also, the `//# sourceURL` comment was not always being respecteed in stack traces, which is particularly unhelpful for `eval` and `node:vm` where the sourceURL can be passed in (via comment for `eval`, and via options in `node:vm`).
This has been fixed.
> In the next version of Bun
>
> Several bugs involving stack traces and line numbers when using eval, node:vm, or //# sourceURL= URLs are fixed [pic.twitter.com/ENkRaGgeFH](https://t.co/ENkRaGgeFH)
>
> — Jarred Sumner (@jarredsumner) [January 7, 2025](https://twitter.com/jarredsumner/status/1876578496572764241?ref_src=twsrc%5Etfw)
### []()[Fixed: stack overflow in console.log](bun-v1.1.43.html#fixed-stack-overflow-in-console-log)
A stack overflow causing an unrecoverable crash that could occur in `console.log` has been fixed.
Now, `console.log` proactively checks for how much stack space remains, and throws a `StackOverflowError` if it's about to run out.
Along the way, we've also fixed several cases where Bun would use large amounts of stack space for file path buffers on Windows (Windows file paths go up to 64 KB)
### []()[Fixed: memory leak in `WebSocket` client](bun-v1.1.43.html#fixed-memory-leak-in-websocket-client)
A memory leak impacting the WebSocket client has been fixed.
> In the next verison of Bun
>
> A memory leak impacting the WebSocket client has been fixed.
>
> left: new
> right: previously [pic.twitter.com/XfxpmksZji](https://t.co/XfxpmksZji)
>
> — Jarred Sumner (@jarredsumner) [December 31, 2024](https://twitter.com/jarredsumner/status/1873996026455220300?ref_src=twsrc%5Etfw)
### []()[`remove` and `isRemoved` in HTMLRewriter's `DocType`](bun-v1.1.43.html#remove-and-isremoved-in-htmlrewriter-s-doctype)
Bun's `HTMLRewriter` implementation now includes `remove()` and `isRemoved()` methods. The `remove()` method allows users to delete the `<!DOCTYPE>` declaration from the HTML document during transformation, and the `isRemoved()` property is a boolean that tells you if the `<!DOCTYPE>` has been removed.
```
const html = "<!DOCTYPE html><html><head></head><body>Hello</body></html>";
const rewriter = new HTMLRewriter().onDocument({
doctype(doctype) {
doctype.remove();
console.log(doctype.removed); // Logs: true
},
});
const result = rewriter.transform(html);
console.log(result); // Logs: "<html><head></head><body>Hello</body></html>"
```
Thanks to [@kimberly](https://github.com/kimberly) for implementing this!
### []()[Fixed: formatting `Set` in Bun.inspect](bun-v1.1.43.html#fixed-formatting-set-in-bun-inspect)
The formatting of `Set` objects in the `Bun.inspect()` function has been corrected. This ensures that when a `Set` is passed to `Bun.inspect()`, it will now display its contents properly formatted.
```
import { it, expect } from "bun:test";
it("Set is propperly formatted in Bun.inspect()", () => {
const set = new Set(["foo", "bar"]);
const formatted = Bun.inspect({ set });
expect(formatted).toBe(`{
set: Set(2) {
"foo",
"bar",
},
}`);
});
```
Thanks to [@laesse](https://github.com/laesse) for implementing this!
### []()[Fixed: socket close behavior](bun-v1.1.43.html#fixed-socket-close-behavior)
In rare cases, the `close` callback for a socket could be called *after* the `end` callback. This has been fixed.
### []()[Fixed: Theroetical crash when iterating over properties](bun-v1.1.43.html#fixed-theroetical-crash-when-iterating-over-properties)
A bug in our JavaScriptCore <-> Zig bindings could lead to a crash when native code iterated through properties of an object in rare cases. This has been fixed.
### []()[Fixed: `export default <file-path>` in error messages](bun-v1.1.43.html#fixed-export-default-file-path-in-error-messages)
A bug that could cause bun to display "export default '<file-path>'" as the source code for an error message has been fixed.
## []()[Bun.sql is almost ready](bun-v1.1.43.html#bun-sql-is-almost-ready)
Over the last year, one of my side projects has been a fast, builtin PostgreSQL client for Bun, and it's almost ready.
```
import { sql } from "bun";
import { expect } from "bun:test";
const result = await sql`select 1 as x`;
expect(result).toEqual([{ x: 1 }]);
```
Bun.sql will be released in Bun v1.2 - coming in 13 days at the time of writing. You can try it in the canary build of Bun.
Here's what's new for `Bun.sql` in this release.
### []()[Fixed: duplicate column names & numeric column names](bun-v1.1.43.html#fixed-duplicate-column-names-numeric-column-names)
A crash that occurred when duplicate column names were returned in query results has been fixed.
```
const result = await sql`select 1 as x, 2 as x, 3 as x`;
expect(result).toEqual([{ x: 3 }]);
const result = await sql`select 1 as "1", 2 as "2", 3 as "3", 0 as "0"`;
expect(result).toEqual([{ "1": 1, "2": 2, "3": 3, "0": 0 }]);
```
Previously, we also wouldn't properly support numeric column names.
### []()[Fixed: JSONB support](bun-v1.1.43.html#fixed-jsonb-support)
Bun's builtin PostgreSQL client now supports the `jsonb` data type.
```
import { sql } from "bun";
import { expect } from "bun:test";
test("jsonb support", async () => {
const result = await sql`select '{"foo": "bar"}'::jsonb as x`;
expect(result).toEqual([{ x: { foo: "bar" } }]);
});
```
### []()[`onopen` and `onclose` callbacks](bun-v1.1.43.html#onopen-and-onclose-callbacks)
The `onopen` and `onclose` tell you when the database connection opened or closed.
```
import { SQL } from "bun";
const sql = new SQL({
url: "postgres://localhost:5432/mydb",
onopen: () => console.log("Connection opened"),
onclose: () => console.log("Connection closed"),
});
const [{ x }] = await sql`select 1 as x`;
console.log({ x });
await sql.close();
console.log("closed");
```
This logs:
```
Connection opened
{ x: 1 }
Connection closed
closed
```
Thanks to [@dylan-conway](https://github.com/dylan-conway) for this addition!
### []()[Error codes for PostgreSQL errors](bun-v1.1.43.html#error-codes-for-postgresql-errors)
The following error codes are now available for PostgreSQL errors.
- `"ERR_POSTGRES_AUTHENTICATION_FAILED_PBKDF2"`
- `"ERR_POSTGRES_CONNECTION_CLOSED"`
- `"ERR_POSTGRES_CONNECTION_TIMEOUT"`
- `"ERR_POSTGRES_EXPECTED_REQUEST"`
- `"ERR_POSTGRES_EXPECTED_STATEMENT"`
- `"ERR_POSTGRES_IDLE_TIMEOUT"`
- `"ERR_POSTGRES_INVALID_BACKEND_KEY_DATA"`
- `"ERR_POSTGRES_INVALID_BINARY_DATA"`
- `"ERR_POSTGRES_INVALID_BYTE_SEQUENCE"`
- `"ERR_POSTGRES_INVALID_BYTE_SEQUENCE_FOR_ENCODING"`
- `"ERR_POSTGRES_INVALID_CHARACTER"`
- `"ERR_POSTGRES_INVALID_MESSAGE"`
- `"ERR_POSTGRES_INVALID_MESSAGE_LENGTH"`
- `"ERR_POSTGRES_INVALID_QUERY_BINDING"`
- `"ERR_POSTGRES_INVALID_SERVER_KEY"`
- `"ERR_POSTGRES_INVALID_SERVER_SIGNATURE"`
- `"ERR_POSTGRES_LIFETIME_TIMEOUT"`
- `"ERR_POSTGRES_MULTIDIMENSIONAL_ARRAY_NOT_SUPPORTED_YET"`
- `"ERR_POSTGRES_NULLS_IN_ARRAY_NOT_SUPPORTED_YET"`
- `"ERR_POSTGRES_OVERFLOW"`
- `"ERR_POSTGRES_SASL_SIGNATURE_INVALID_BASE64"`
- `"ERR_POSTGRES_SASL_SIGNATURE_MISMATCH"`
- `"ERR_POSTGRES_SERVER_ERROR"`
- `"ERR_POSTGRES_SYNTAX_ERROR"`
- `"ERR_POSTGRES_TLS_NOT_AVAILABLE"`
- `"ERR_POSTGRES_TLS_UPGRADE_FAILED"`
- `"ERR_POSTGRES_UNEXPECTED_MESSAGE"`
- `"ERR_POSTGRES_UNKNOWN_AUTHENTICATION_METHOD"`
- `"ERR_POSTGRES_UNSUPPORTED_AUTHENTICATION_METHOD"`
- `"ERR_POSTGRES_UNSUPPORTED_BYTEA_FORMAT"`
- `"ERR_POSTGRES_UNSUPPORTED_INTEGER_SIZE"`
## []()[Other changes](bun-v1.1.43.html#other-changes)
- The list of completions used for `bun add` is now compressed, which saves about 100 KB.
- We rewrote the code that checks for unicode identifiers which shaved off about 250 KB.
### []()[Thanks to 22 contributors!](bun-v1.1.43.html#thanks-to-22-contributors)
- [@190n](https://github.com/190n)
- [@chawyehsu](https://github.com/chawyehsu)
- [@cirospaciari](https://github.com/cirospaciari)
- [@devanand-sharma](https://github.com/devanand-sharma)
- [@donisaac](https://github.com/donisaac)
- [@dylan-conway](https://github.com/dylan-conway)
- [@fel1x-developer](https://github.com/fel1x-developer)
- [@heimskr](https://github.com/heimskr)
- [@ianzone](https://github.com/ianzone)
- [@jarred-sumner](https://github.com/jarred-sumner)
- [@jbergstroem](https://github.com/jbergstroem)
- [@komiya-atsushi](https://github.com/komiya-atsushi)
- [@laesse](https://github.com/laesse)
- [@marcosrjjunior](https://github.com/marcosrjjunior)
- [@martinamps](https://github.com/martinamps)
- [@metonym](https://github.com/metonym)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@pfgithub](https://github.com/pfgithub)
- [@riskymh](https://github.com/riskymh)
- [@sirmews](https://github.com/sirmews)
- [@thecrypticace](https://github.com/thecrypticace)
* * *
#### [Bun v1.1.42](bun-v1.1.42.html)
#### [Bun v1.1.44](bun-v1.1.44.html)
On this page
- [1st-class S3 support](bun-v1.1.43.html#1st-class-s3-support)
- [HTML Bundler](bun-v1.1.43.html#html-bundler)
- [`bun install --filter <pattern>`](bun-v1.1.43.html#bun-install-filter-pattern)
- [V8 Heap Snapshots](bun-v1.1.43.html#v8-heap-snapshots)
- [Errors show more properties](bun-v1.1.43.html#errors-show-more-properties)
- [bun run](bun-v1.1.43.html#bun-run)
- [`-F` is for `--filter`](bun-v1.1.43.html#f-is-for-filter)
- [`--elide-lines=N` controls filter output line length](bun-v1.1.43.html#elide-lines-n-controls-filter-output-line-length)
- [`pnpx` and `pnpm dlx` auto-replacement](bun-v1.1.43.html#pnpx-and-pnpm-dlx-auto-replacement)
- [bun install](bun-v1.1.43.html#bun-install)
- [New: slow postinstall script logging](bun-v1.1.43.html#new-slow-postinstall-script-logging)
- [New: `bundle(d)Dependencies` in `bun install`](bun-v1.1.43.html#new-bundle-d-dependencies-in-bun-install)
- [New: `--lockfile-only` option for bun install](bun-v1.1.43.html#new-lockfile-only-option-for-bun-install)
- [New: `--peer` option in `bun add`](bun-v1.1.43.html#new-peer-option-in-bun-add)
- [Fixed: bun.lock file permissions](bun-v1.1.43.html#fixed-bun-lock-file-permissions)
- [Fixed: `install.cache.dir` in bunfig.toml](bun-v1.1.43.html#fixed-install-cache-dir-in-bunfig-toml)
- [Fixed: crash in `bun patch --commit`](bun-v1.1.43.html#fixed-crash-in-bun-patch-commit)
- [Fixed: quote-escaping in `bun.lock` package names](bun-v1.1.43.html#fixed-quote-escaping-in-bun-lock-package-names)
- [Node.js compatibility improvements](bun-v1.1.43.html#node-js-compatibility-improvements)
- [100% of `node:path` tests now pass](bun-v1.1.43.html#100-of-node-path-tests-now-pass)
- [98.08% of `node:zlib` tests now pass](bun-v1.1.43.html#98-08-of-node-zlib-tests-now-pass)
- [Fixed: napi\_set\_last\_error method in Node-API](bun-v1.1.43.html#fixed-napi-set-last-error-method-in-node-api)
- [Fixed: `process.kill` allows zero or negative PIDs](bun-v1.1.43.html#fixed-process-kill-allows-zero-or-negative-pids)
- [`--expose-gc` flag adds `globalThis.gc`](bun-v1.1.43.html#expose-gc-flag-adds-globalthis-gc)
- [Fixed: `process.memoryUsage().arrayBuffers`](bun-v1.1.43.html#fixed-process-memoryusage-arraybuffers)
- [bun build](bun-v1.1.43.html#bun-build)
- [Improved stack overflow detection](bun-v1.1.43.html#improved-stack-overflow-detection)
- [Fixed: large number of if statements led to stack overflow](bun-v1.1.43.html#fixed-large-number-of-if-statements-led-to-stack-overflow)
- [Fixed: `#bun` pragma](bun-v1.1.43.html#fixed-bun-pragma)
- [Fixed: cross-compile for musl in `bun build --compile`](bun-v1.1.43.html#fixed-cross-compile-for-musl-in-bun-build-compile)
- [Fixed: sourcemap comments CSS files](bun-v1.1.43.html#fixed-sourcemap-comments-css-files)
- [Fixed: crash when parsing malformed TypeScript enums](bun-v1.1.43.html#fixed-crash-when-parsing-malformed-typescript-enums)
- [Runtime improvements](bun-v1.1.43.html#runtime-improvements)
- [Override `"Content-Length"` and `Transfer-Encoding` in Bun.serve()](bun-v1.1.43.html#override-content-length-and-transfer-encoding-in-bun-serve)
- [New: `stat` method in Bun.file(path)](bun-v1.1.43.html#new-stat-method-in-bun-file-path)
- [New: `delete` method in Bun.file(path)](bun-v1.1.43.html#new-delete-method-in-bun-file-path)
- [More accurate heap snapshots](bun-v1.1.43.html#more-accurate-heap-snapshots)
- [Fixes to stack traces with eval and node:vm](bun-v1.1.43.html#fixes-to-stack-traces-with-eval-and-node-vm)
- [Fixed: stack overflow in console.log](bun-v1.1.43.html#fixed-stack-overflow-in-console-log)
- [Fixed: memory leak in `WebSocket` client](bun-v1.1.43.html#fixed-memory-leak-in-websocket-client)
- [`remove` and `isRemoved` in HTMLRewriter's `DocType`](bun-v1.1.43.html#remove-and-isremoved-in-htmlrewriter-s-doctype)
- [Fixed: formatting `Set` in Bun.inspect](bun-v1.1.43.html#fixed-formatting-set-in-bun-inspect)
- [Fixed: socket close behavior](bun-v1.1.43.html#fixed-socket-close-behavior)
- [Fixed: Theroetical crash when iterating over properties](bun-v1.1.43.html#fixed-theroetical-crash-when-iterating-over-properties)
- [Fixed: `export default <file-path>` in error messages](bun-v1.1.43.html#fixed-export-default-file-path-in-error-messages)
- [Bun.sql is almost ready](bun-v1.1.43.html#bun-sql-is-almost-ready)
- [Fixed: duplicate column names & numeric column names](bun-v1.1.43.html#fixed-duplicate-column-names-numeric-column-names)
- [Fixed: JSONB support](bun-v1.1.43.html#fixed-jsonb-support)
- [`onopen` and `onclose` callbacks](bun-v1.1.43.html#onopen-and-onclose-callbacks)
- [Error codes for PostgreSQL errors](bun-v1.1.43.html#error-codes-for-postgresql-errors)
- [Other changes](bun-v1.1.43.html#other-changes)
- [Thanks to 22 contributors!](bun-v1.1.43.html#thanks-to-22-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.44.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.44
* * *
[Ben Grant](https://github.com/190n) · January 16, 2025
[](../rss.xml)
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
This release fixes 43 bugs. You can now build frontend applications on-demand in Bun.serve(). Adds xxHash support to Bun.hash(). Adds support for reading bun.lock using import. Adds --no-install flag to bunx. Improves console.warn output. Fixes bugs in Bun's S3 client, HTMLRewriter, and node:fs compatibility improvements, and more.
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[Fullstack Dev Server](bun-v1.1.44.html#fullstack-dev-server)
With [HTML imports](../docs/bundler/fullstack.html#html-imports-are-routes), you can now run your frontend and backend together in a single incredibly fast `Bun.serve()` HTTP server. This makes it simpler to build modern frontend applications integrated with your backend.
> In the next version of Bun
>
> Bun.serve() gets initial support for bundling frontend apps on-demand [pic.twitter.com/51XcNXt3vy](https://t.co/51XcNXt3vy)
>
> — Jarred Sumner (@jarredsumner) [January 14, 2025](https://twitter.com/jarredsumner/status/1879170961632907630?ref_src=twsrc%5Etfw)
### []()[HTML imports](bun-v1.1.44.html#html-imports)
This release introduces support for importing HTML files in Bun behind the `--experimental-html` CLI flag. These HTML files are processed by [Bun's bundler](../docs/bundler.html) together with [`Bun.serve()`](../docs/api/http.html). You can use the `static` option to serve these HTML files as routes. `Bun.serve()` bundles the frontend application with zero configuration and adds bundled assets as static routes.
```
import mySinglePageApp from "./index.html";
import { s3 } from "bun";
Bun.serve({
static: {
// the "/" route goes to
"/": mySinglePageApp,
// ... more html imports go here
},
// Enable some logging & errors
development: true,
async fetch(req) {
// ... api endpoints go here
const path = getS3Path(req); // ...
return Response.redirect(s3.file(path).presign());
},
});
```
In [Bun v1.1.43](bun-v1.1.43.html), we added support for [HTML entrypoints](../docs/bundler/html.html) in [Bun's bundler](../docs/bundler.html). This release builds on that to add initial support in `Bun.serve()` to serve HTML files as routes.
You can use HTML imports to build single-page React applications on-demand in a shared backend server.
src/backend.ts
src/frontend.tsx
public/dashboard.html
src/styles.css
src/app.tsx
src/backend.ts
```
import dashboard from "./public/dashboard.html";
import { serve } from "bun";
serve({
static: {
"/": dashboard,
},
async fetch(req) {
// ...api requests
return new Response("hello world");
},
});
```
src/frontend.tsx
```
import "./styles.css";
import { createRoot } from "react-dom/client";
import { App } from "./app.tsx";
document.addEventListener("DOMContentLoaded", () => {
const root = createRoot(document.getElementById("root"));
root.render(<App />);
});
```
public/dashboard.html
```
<!DOCTYPE html>
<html>
<head>
<title>Dashboard</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="../src/frontend.tsx"></script>
</body>
</html>
```
src/styles.css
```
body {
background-color: red;
}
```
src/app.tsx
```
export function App() {
return <div>Hello World</div>;
}
```
This is still pretty early - there's no hot-module reloading support yet. But we'll get there.
## []()[`bunx --no-install`](bun-v1.1.44.html#bunx-no-install)
`bunx` now supports the `--no-install` flag, which will cause the command to only run if it has already been installed in the current path or the global prefix.
Thanks to [@DonIsaac](https://github.com/DonIsaac) for implementing this!
## []()[Read `bun.lock` with `import`](bun-v1.1.44.html#read-bun-lock-with-import)
You can now read the contents of [Bun's new text-based lockfile](bun-lock-text-lockfile.html) with an `import` statement.
```
import { lockfileVersion } from "./bun.lock";
console.log(lockfileVersion);
```
We've also added type definitions to `@types/bun` so that TypeScript understands how the lockfile is structured. And, since the new lockfile is a JSONC file, we also allow importing other `.jsonc` files as well.
Thanks to [@RiskyMH](https://github.com/RiskyMH) for implementing this!
## []()[xxHash support in `Bun.hash`](bun-v1.1.44.html#xxhash-support-in-bun-hash)
The `Bun.hash` namespace now includes `Bun.hash.xxHash32`, `Bun.hash.xxHash64`, and `Bun.hash.xxHash3`, implementing the [xxHash](https://xxhash.com/) family of fast non-cryptographic hash functions. These are suitable for applications where data must be hashed very quickly and some hash collisions are acceptable, such as integrity checks of data you trust has not been tampered with maliciously, but they should not be used for cryptographic purposes such as hashing passwords or untrusted data.
xxhash.ts
```
// Print a hash of stdin
const data = await new Response(Bun.stdin).arrayBuffer();
const hash: BigInt = Bun.hash.xxHash3(data);
// Format as 16 hexadecimal digits with leading zeroes
console.log(hash.toString(16).padStart(16, "0"));
```
```
cat xxhash.ts | bun xxhash.ts
```
```
aeac788911bfd3bb
```
```
xxhsum -H3 xxhash.ts # -H3 selects the xxHash3 algorithm
```
```
XXH3_aeac788911bfd3bb xxhash.ts
```
Thanks to [@versecafe](https://github.com/versecafe) for wiring up the Zig standard library functions to Bun!
## []()[Node.js compatibility improvements](bun-v1.1.44.html#node-js-compatibility-improvements)
### []()[`node:dns` > 90% Node.js tests passing](bun-v1.1.44.html#node-dns-90-node-js-tests-passing)
`node:dns` now passes > 90% of Node.js's own test suite.
Thanks to [@heimskr](https://github.com/heimskr) for making this happen!
### []()[`node:fs` fixes](bun-v1.1.44.html#node-fs-fixes)
We've fixed several bugs and inconsistencies compared to Node.js in our `node:fs` implementation, improving compatibility with existing Node.js projects and packages. We also now run a large chunk of Node.js's own tests for the `fs` module on every commit. This works out to about +10% more of Node.js's test suite for `fs` passing in Bun.
Thanks to [@paperclover](https://github.com/paperclover) for implementing this!
### []()[Fixed: attempt to assign to read-only property in Axios](bun-v1.1.44.html#fixed-attempt-to-assign-to-read-only-property-in-axios)
A property in `node:http` was incorrectly marked as read-only, leading Axios to throw an error in certain cases. This release fixes that bug.
### []()[Fixed: crash impacting `happy-dom` & `node:vm`](bun-v1.1.44.html#fixed-crash-impacting-happy-dom-node-vm)
A regression in Bun v1.1.43 caused a crash when using `happy-dom` or `node:vm`. This release fixes this crash and adds a test to prevent it from happening again.
### []()[Fixed: IPC with JSON serialization with Bun as the parent process](bun-v1.1.44.html#fixed-ipc-with-json-serialization-with-bun-as-the-parent-process)
Previously, Bun would send incorrectly-formatted messages to child processes if IPC was used with `serialization` set to `"json"`. Now it always sends JSON messages in this case.
Thanks to [@nektro](https://github.com/nektro) for fixing this!
## []()[Bugfixes](bun-v1.1.44.html#bugfixes)
This release also includes a number of bugfixes.
### []()[Fixed: `bun install --lockfile-only --silent` printing lockfile summary](bun-v1.1.44.html#fixed-bun-install-lockfile-only-silent-printing-lockfile-summary)
Previously, running `bun install --lockfile-only --silent` would still print a summary of the packages saved in the lockfile, despite the `--silent` option. Now the `--silent` option is respected.
Thanks to [@DonIsaac](https://github.com/DonIsaac) for fixing this!
### []()[Fixed: Regression with `expect.extend()`](bun-v1.1.44.html#fixed-regression-with-expect-extend)
A change to our JavaScriptCore bindings in Bun v1.1.43 caused `expect.extend()` to ignore properties on prototype objects, causing some test matcher libraries to not work properly. This release fixes this regression.
Thanks to [@pfgithub](https://github.com/pfgithub) for fixing this!
### []()[Fixed: missing `x-amz-acl` header in S3 client](bun-v1.1.44.html#fixed-missing-x-amz-acl-header-in-s3-client)
Bun's [S3 client](../docs/api/s3.html) was missing the `x-amz-acl` header in certain cases.
Thanks to [@robertshuford](https://github.com/robertshuford) for fixing this!
### []()[Fixed: `expect().toThrow()` now matches `expect().toThrow("")`](bun-v1.1.44.html#fixed-expect-tothrow-now-matches-expect-tothrow)
In Jest & Vitest, when you run `expect(a).toThrow("")`, it behaves the same as `expect(a).toThrow()`. In `bun:test`, it was throwing an error. We've changed this to match Jest & Vitest so that it's a little bit easier to migrate your tests.
Thanks to [@DonIsaac](https://github.com/DonIsaac) for fixing this!
### []()[Fixed: error handling in `HTMLRewriter`](bun-v1.1.44.html#fixed-error-handling-in-htmlrewriter)
A crash has been fixed in Bun's `HTMLRewriter` API when a JavaScript exception was thrown. Now these errors are propagated correctly.
### []()[Fixed: slicing S3 file with offset 0](bun-v1.1.44.html#fixed-slicing-s3-file-with-offset-0)
Calling `slice()` on a file returned by Bun's S3 client would previously have no effect with an offset set to zero. Now the file is properly truncated via an HTTP range request.
Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this!
### []()[Fixed: Missing authorization with private npm packages](bun-v1.1.44.html#fixed-missing-authorization-with-private-npm-packages)
When parsing `.npmrc` config files, prior versions of Bun did not apply auth configuration to scoped registries if a default registry had the same hostname as the scoped registry. For instance, if you need to access private packages on `npmjs.org` you would set a token so that npm's servers know you are allowed to access those packages:
.npmrc
```
//registry.npmjs.org/:_authToken=<AUTH_TOKEN>
```
Since `registry.npmjs.org` is one of the default registries, Bun would not send the authentication token and you would not have been able to download private packages. Now the configuration options are all applied correctly.
Thanks to [@robertshuford](https://github.com/robertshuford) for fixing this!
## []()[More improvements](bun-v1.1.44.html#more-improvements)
### []()[console.warn is yellow](bun-v1.1.44.html#console-warn-is-yellow)
When you `console.warn` an `Error` object, the `name` property is now yellow instead of red. This tells you that it was a warning and not an error.
[](https://github.com/user-attachments/assets/f7772323-b766-48ef-a004-8325c247e92a)
Additionally, when the name property is `"Error"`, it prints `"warn"` instead of `"error"` to make it clearer that it's a warning and not an error.
### []()[Consistent help message colorization](bun-v1.1.44.html#consistent-help-message-colorization)
The `--help` messages for Bun's subcommands are now more consistent in their formatting and colorization.
Thanks to [@fel1x-developer](https://github.com/fel1x-developer) for fixing this!
### []()[Help message for `bun exec --help`](bun-v1.1.44.html#help-message-for-bun-exec-help)
A bug in command-line parsing was causing `bun exec --help` to reuse the help message from `bun run`. Now it correctly prints its own help message.
Thanks to [@RiskyMH](https://github.com/RiskyMH) for fixing this!
### []()[Updated root certificates](bun-v1.1.44.html#updated-root-certificates)
Bun's built-in root certificates have been updated to NSS 3.107. These are the same certificates that shipped in Firefox 134.
Thanks to [@cirospaciari](https://github.com/cirospaciari) for implementing this!
### []()[Improved `bundleDependencies` support in `bun publish` and `bun pm pack`](bun-v1.1.44.html#improved-bundledependencies-support-in-bun-publish-and-bun-pm-pack)
The `bundleDependencies` (or `bundledDependencies`) option in `package.json` allows a package to include the source code of its dependencies in the tarball published to the registry, instead of requiring the dependencies to be downloaded separately. Bun previously recognized the array form of this option in `bun pm pack` and `bun pm publish`, which allows specifying a list of dependencies to be bundled. But we hadn't supported setting this flag to `true`, which is shorthand for specifying that all dependencies should be bundled. Now we do support this. We've also added support for bundling [scoped packages](https://docs.npmjs.com/creating-and-publishing-scoped-public-packages) as dependencies.
Thanks to [@RiskyMH](https://github.com/RiskyMH) for implementing this!
## []()[Thanks to 21 contributors!](bun-v1.1.44.html#thanks-to-21-contributors)
- [@190n](https://github.com/190n)
- [@arnaudbarre](https://github.com/arnaudbarre)
- [@cainba](https://github.com/cainba)
- [@cirospaciari](https://github.com/cirospaciari)
- [@citkane](https://github.com/citkane)
- [@donisaac](https://github.com/donisaac)
- [@dtinth](https://github.com/dtinth)
- [@fel1x-developer](https://github.com/fel1x-developer)
- [@gobd](https://github.com/gobd)
- [@heimskr](https://github.com/heimskr)
- [@jarred-sumner](https://github.com/jarred-sumner)
- [@kjjd84](https://github.com/kjjd84)
- [@lcrespom](https://github.com/lcrespom)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@pfgithub](https://github.com/pfgithub)
- [@riskymh](https://github.com/riskymh)
- [@robertshuford](https://github.com/robertshuford)
- [@sroussey](https://github.com/sroussey)
- [@versecafe](https://github.com/versecafe)
- [@yooneskh](https://github.com/yooneskh)
* * *
#### [Bun v1.1.43](bun-v1.1.43.html)
#### [Bun v1.1.45](bun-v1.1.45.html)
On this page
- [Fullstack Dev Server](bun-v1.1.44.html#fullstack-dev-server)
- [HTML imports](bun-v1.1.44.html#html-imports)
- [`bunx --no-install`](bun-v1.1.44.html#bunx-no-install)
- [Read `bun.lock` with `import`](bun-v1.1.44.html#read-bun-lock-with-import)
- [xxHash support in `Bun.hash`](bun-v1.1.44.html#xxhash-support-in-bun-hash)
- [Node.js compatibility improvements](bun-v1.1.44.html#node-js-compatibility-improvements)
- [`node:dns` > 90% Node.js tests passing](bun-v1.1.44.html#node-dns-90-node-js-tests-passing)
- [`node:fs` fixes](bun-v1.1.44.html#node-fs-fixes)
- [Fixed: attempt to assign to read-only property in Axios](bun-v1.1.44.html#fixed-attempt-to-assign-to-read-only-property-in-axios)
- [Fixed: crash impacting `happy-dom` & `node:vm`](bun-v1.1.44.html#fixed-crash-impacting-happy-dom-node-vm)
- [Fixed: IPC with JSON serialization with Bun as the parent process](bun-v1.1.44.html#fixed-ipc-with-json-serialization-with-bun-as-the-parent-process)
- [Bugfixes](bun-v1.1.44.html#bugfixes)
- [Fixed: `bun install --lockfile-only --silent` printing lockfile summary](bun-v1.1.44.html#fixed-bun-install-lockfile-only-silent-printing-lockfile-summary)
- [Fixed: Regression with `expect.extend()`](bun-v1.1.44.html#fixed-regression-with-expect-extend)
- [Fixed: missing `x-amz-acl` header in S3 client](bun-v1.1.44.html#fixed-missing-x-amz-acl-header-in-s3-client)
- [Fixed: `expect().toThrow()` now matches `expect().toThrow("")`](bun-v1.1.44.html#fixed-expect-tothrow-now-matches-expect-tothrow)
- [Fixed: error handling in `HTMLRewriter`](bun-v1.1.44.html#fixed-error-handling-in-htmlrewriter)
- [Fixed: slicing S3 file with offset 0](bun-v1.1.44.html#fixed-slicing-s3-file-with-offset-0)
- [Fixed: Missing authorization with private npm packages](bun-v1.1.44.html#fixed-missing-authorization-with-private-npm-packages)
- [More improvements](bun-v1.1.44.html#more-improvements)
- [console.warn is yellow](bun-v1.1.44.html#console-warn-is-yellow)
- [Consistent help message colorization](bun-v1.1.44.html#consistent-help-message-colorization)
- [Help message for `bun exec --help`](bun-v1.1.44.html#help-message-for-bun-exec-help)
- [Updated root certificates](bun-v1.1.44.html#updated-root-certificates)
- [Improved `bundleDependencies` support in `bun publish` and `bun pm pack`](bun-v1.1.44.html#improved-bundledependencies-support-in-bun-publish-and-bun-pm-pack)
- [Thanks to 21 contributors!](bun-v1.1.44.html#thanks-to-21-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.45.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.45
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · January 17, 2025
[](../rss.xml)
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
This release fixes 13 bugs (addressing 50 👍) and improves compatibility with Node.js. 82% of the 'streams' module tests from Node.js' test suite now pass in Bun. node:crypto now implements diffieHellman, getCipherInfo, and X509Certificate. The checkServerIdentity object now matches Node.js' format. Bugfixes in Bun's fs.mkdirSync method, importing with query strings.
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[node:stream compatibility improvements](bun-v1.1.45.html#node-stream-compatibility-improvements)
node:stream now passes 82% of Node.js' test suite. Several of the remaining test failures are testing Node.js internals that don't exist in Bun.
Thanks to [@nektro](https://github.com/nektro) for this!
## []()[node:crypto improvements](bun-v1.1.45.html#node-crypto-improvements)
### []()[`X509Certificate`](bun-v1.1.45.html#x509certificate)
This release implements `X509Certificate` in `node:crypto`.
```
import { X509Certificate } from "node:crypto";
// Create a new X.509 certificate from a string
const cert = new X509Certificate(
"-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
);
// Get the subject of the certificate
console.log(cert.subject); // Outputs the subject's distinguished name
```
Thanks to [@dylan-conway](https://github.com/dylan-conway) for this! And thanks to [@jasnell](https://github.com/jasnell) for the `ncrypt` wrapper library used by Bun, Cloudflare Workers, and Node.js.
### []()[`diffieHellman`](bun-v1.1.45.html#diffiehellman)
The `diffieHellman` method is now implemented in `node:crypto`.
### []()[`getCipherInfo`](bun-v1.1.45.html#getcipherinfo)
The `getCipherInfo` method is now implemented in `node:crypto`.
### []()[`Certificate`](bun-v1.1.45.html#certificate)
The `Certificate` class with static methods `exportPublicKey`, `exportChallenge`, and `verifySpkac` is now implemented in `node:crypto`.
### []()[checkServerIdentity fix](bun-v1.1.45.html#checkserveridentity-fix)
The X509 object returned by `checkServerIdentity` (used in node:http, node:tls, and also in `fetch`) now matches the format of the X509 object in Node.js. Some fields were strings in Bun and arrays of strings in Node.js, now they're arrays of strings in Bun as well.
### []()[Fixed: memory leak involving X509 certificates in node:tls](bun-v1.1.45.html#fixed-memory-leak-involving-x509-certificates-in-node-tls)
A memory leak involving X509 certificates in node:tls has been fixed.
## []()[Fixed: fs.mkdir recursive regression](bun-v1.1.45.html#fixed-fs-mkdir-recursive-regression)
A regression introduced in Bun v1.1.44 (while working on node:fs compatibility) caused `fs.mkdirSync` to throw an error when the target directory already exists. This commit fixes the regression.
```
it("fs.mkdirSync recursive should not error when the directory already exists, but should error when its a file", () => {
expect(() =>
mkdirSync(import.meta.dir, { recursive: true }),
).not.toThrowError();
expect(() => mkdirSync(import.meta.path, { recursive: true })).toThrowError();
});
```
## []()[Fixed: hang when importing duplicate modules with ?query strings](bun-v1.1.45.html#fixed-hang-when-importing-duplicate-modules-with-query-strings)
A regression introduced in Bun v1.1.21 caused Bun to hang when importing modules with query strings in the URL. This commit fixes the regression.
```
// This used to hang
import myModule from "./myModule.js";
import myModule2 from "./myModule.js?param=value";
// This did not hang
import myModule3 from "./myModule.js?param=value";
import myModule4 from "./myModule.js";
```
## []()[Thanks to 5 contributors!](bun-v1.1.45.html#thanks-to-5-contributors)
- [@jarred-sumner](https://github.com/jarred-sumner)
- [@nektro](https://github.com/nektro)
- [@rgarcia](https://github.com/rgarcia)
- [@riskymh](https://github.com/riskymh)
- [@zackradisic](https://github.com/zackradisic)
* * *
#### [Bun v1.1.44](bun-v1.1.44.html)
On this page
- [node:stream compatibility improvements](bun-v1.1.45.html#node-stream-compatibility-improvements)
- [node:crypto improvements](bun-v1.1.45.html#node-crypto-improvements)
- [`X509Certificate`](bun-v1.1.45.html#x509certificate)
- [`diffieHellman`](bun-v1.1.45.html#diffiehellman)
- [`getCipherInfo`](bun-v1.1.45.html#getcipherinfo)
- [`Certificate`](bun-v1.1.45.html#certificate)
- [checkServerIdentity fix](bun-v1.1.45.html#checkserveridentity-fix)
- [Fixed: memory leak involving X509 certificates in node:tls](bun-v1.1.45.html#fixed-memory-leak-involving-x509-certificates-in-node-tls)
- [Fixed: fs.mkdir recursive regression](bun-v1.1.45.html#fixed-fs-mkdir-recursive-regression)
- [Fixed: hang when importing duplicate modules with ?query strings](bun-v1.1.45.html#fixed-hang-when-importing-duplicate-modules-with-query-strings)
- [Thanks to 5 contributors!](bun-v1.1.45.html#thanks-to-5-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.5.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.5
* * *
[Ashcon Partovi](https://twitter.com/ashconpartovi) · April 26, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one.
Bun v1.1.5 fixes 64 bugs (addressing 101 👍). bun build --compile cross-compile standalone JavaScript & TypeScript executables to other platforms. import any file as text via the `type: "text"` import attribute. Introduces a new crash reporter. `package.json` doesn't error with comments or trailing commas. Fixes a bug where `bun run --filter` exited with 0. Fixes a bug in bun install with file: dependencies. Fixes bugs in `node:fs`, `node:tls`, `node:crypto`, `node:readline`, `node:http`, `node:worker_threads`.
#### Previous releases
- [`v1.1.4`](bun-v1.1.4.html) Bun v1.1.4 fixes 40 bugs (addressing 84 👍 reactions). `bun run --filter <workspace> <script>` lets you run multiple workspace scripts in parallel. Reinstalls get up to 50% faster in bun install. Important reliability fixes to bun install. bun:sqlite supports `using` for resource cleanup and has a few bugfixes. Memory leak impacting Next.js Standalone & Web Streams is fixed. Node.js compatibility improvements `fs` and `child_process`. Fix for "Connection closed" in fetch(). A few bugfixes for Bundows.
- [`v1.1.3`](bun-v1.1.3.html) Bun v1.1.3 fixes 5 bugs. bun install gets 50% faster on Windows. A bug that could cause bun install to hang in rare cases has been fixed. A bug where some errors in bun install would not produce a non-zero exit code has been fixed. A bug that could cause specific certain combinations of dependencies to fail to install has been fixed. A bug on Windows where CTRL + C on cmd.exe after exiting bun would not behave as expected has been fixed. A bug where missing permissions on Windows for reading a directory could lead to a crash has been fixed.
- [`v1.1.0`](bun-v1.1.html) Bundows. Windows support is here!
#### To install Bun:
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[Cross-compile standalone executables with `bun build --compile`](bun-v1.1.5.html#cross-compile-standalone-executables-with-bun-build-compile)
[Standalone executables](../docs/bundler/executables.html) in Bun now support cross-compilation.
To cross-compile a TypeScript or JavaScript application to a different platform, use the `--target` option with `bun build --compile`:
```
# Linux x64
bun build --compile --target=bun-linux-x64 app.ts
# Windows x64
bun build --compile --target=bun-windows-x64 app.ts
# macOS Silicon
bun build --compile --target=bun-darwin-arm64 app.ts
# Linux arm64
bun build --compile --target=bun-linux-arm64 app.ts
```
`bun build --compile` bundles & tree-shakes your entire application (including used node\_modules), plus Bun into a single executable that can be run on the target platform without dependencies.
This makes it simpler to deploy Bun to production.
- Build your app on your development machine and deploy it to a different platform without needing to install Bun on the target machine
- Build in Docker on Linux x64 and run on Linux arm64.
- Build a macOS CLI tool on a Linux machine, or a Windows CLI tool on a Macbook Pro.
- Your CI/CD pipeline can build a CLI tool for all platforms without needing to maintain multiple build machines.
## []()[package.json with comments and trailing commas](bun-v1.1.5.html#package-json-with-comments-and-trailing-commas)
Have you ever added something in `package.json` and forgot why 6 months later? Or wanted to explain to teammates why we need to use a specific version of a dependency? Have you ever had a merge conflict in a package.json file due to a comma?
> What JS ecosystem upgrade path would you prefer to permit comments in package.json?
>
> — Rob Palmer (@robpalmer2) [April 17, 2024](https://twitter.com/robpalmer2/status/1780495081637548305?ref_src=twsrc%5Etfw)
As of Bun v1.1.5, `bun install`, `bun run <script>`, `bun <file>`, and `bun build` no longer error when you use comments or trailing commas in package.json.
This package.json file will no longer error:
package.json
```
{
"name": "app",
"dependencies": {
// We need 0.30.8 because of a bug in 0.30.9
"drizzle-orm": "0.30.8",
},
}
```
This aligns the behavior of `package.json` in Bun with other popular JSON configuration files like TypeScript's `tsconfig.json` and `jsconfig.json`.
We know there many other tools that read package.json. To make this easier for other tools, we've added support for `require` and `import` to load package.json files with comments and trailing commas. This works in TypeScript files, JavaScript files in `bun build` and at runtime.
```
const pkg = require("./package.json");
const {
default: { name },
} = await import("./package.json");
```
For ecosystem compatibility, we don't recommend using this feature. But who knows, maybe one day it'll [get standardized](https://twitter.com/NicoloRibaudo/status/1780240914562056360) in the JSON spec.
### []()[bun.report is Bun's new crash reporter](bun-v1.1.5.html#bun-report-is-bun-s-new-crash-reporter)
To help us debug panics and crashes, we've implemented a compact new stack trace format for Zig and C++ crash reports. The crash report fits in a ~150 byte URL.
We wrote a whole blog post on this new feature, [bun.report is Bun's new crash reporter](bun-report-is-buns-new-crash-reporter.html).
[](bun-report-is-buns-new-crash-reporter.html)
### []()[New: import any file as text](bun-v1.1.5.html#new-import-any-file-as-text)
You can now import any file as a string using the `type: "text"` import attribute. This is useful when you want to import a file as a string, even if it doesn't have a `.txt` extension.
Like other imports in Bun, `text` imports support hot reloading and watch mode, so when you start Bun with `--hot` or `--watch`, Bun automatically reloads the file when it changes.
```
import html from "./index.html" with type { type: "text" };
console.log(html);
```
When used with `bun build --compile`, this embeds the file as a string in the executable.
Import Attributes are a [TC39 stage3 proposal](https://github.com/tc39/proposal-import-attributes) with implementations in multiple JavaScript engines.
##### toml, json, and file import attributes
We've also added support for the following import attributes:
- `json`
- `toml`
- `file`
Previously, a `--loader` needed to be passed to configure this behavior. Now you can use these import attributes directly.
```
// its a .foo file, but `type` makes it read as JSON
import json from "./config.foo" with { type: "json" };
// there's no toml extension, but `type` makes it read as toml.
import cfg from "./Configfile" with { type: "toml" };
console.log(cfg); // { "name": "app" }
console.log(json); // { "name": "app" } (converted to JSON object)
```
### []()[Bun.serve() now supports Server Name Indication (SNI)](bun-v1.1.5.html#bun-serve-now-supports-server-name-indication-sni)
You can now specify multiple `serverName` TLS entries in `Bun.serve`. This is useful when you want to serve multiple TLS certificates or hostnames on the same port.
```
import { serve } from "bun";
serve({
port: 443,
tls: [
{
cert: Bun.file("./example.pem"),
key: Bun.file("./example-key.pem"),
serverName: "*.example.com",
},
{
cert: Bun.file("./test.pem"),
key: Bun.file("./test-key.pem"),
serverName: "*.test.com",
},
],
fetch(request) {
return new Response("Using TLS!");
},
});
```
This also fixed a bug where `serverName` would not work, even with a single entry. Thanks to [@cirospaciari](https://github.com/cirospaciari) for fixing this bug.
### []()[Fixed: `bun run --filter` always exited with 0](bun-v1.1.5.html#fixed-bun-run-filter-always-exited-with-0)
In Bun v1.1.4, we introduced [`bun run --filter`](bun-v1.1.4.html#bun-filter-runs-workspace-scripts-in-parallel) which allows you to run multiple scripts in parallel. We fixed a bug where the `--filter` option was not returning a non-zero exit code when one of the scripts failed.
package.json
```
{
"scripts": {
"pass": "exit 0",
"fail": "exit 1"
}
}
```
```
bun run --filter "*"
```
```
echo $?
```
```
# Before: 0
# After: 1
```
Thanks to [@gvilums](https://github.com/gvilums) for fixing this bug.
### []()[Fixed: Absolute patterns in `Bun.Glob` not working](bun-v1.1.5.html#fixed-absolute-patterns-in-bun-glob-not-working)
There was a bug where glob patterns that contained an absolute path would not work with `Bun.Glob`.
```
import { Glob } from "bun";
const glob = new Glob("/tmp/*");
const matches = [...glob.scanSync("/tmp")];
console.log(matches.length);
// Before: 0 (incorrect)
// After: > 0 (correct)
```
Thanks to [@zackradisic](https://github.com/zackradisic) for fixing this bug.
### []()[Fixed: `bun build --compile` sometimes not respecting `--outfile`](bun-v1.1.5.html#fixed-bun-build-compile-sometimes-not-respecting-outfile)
There was a bug in `bun build --compile` that caused it to not respect the `--outfile` option when there was an external file that was being imported.
app.ts
```
import file from "./file.png";
```
```
bun build --compile app.ts --outfile build/app
```
```
# Before:
```
```
./app
```
```
# After:
```
```
./build/app
```
This has now been fixed.
### []()[Fixed: `dlopen` would not work file `file://` URLs](bun-v1.1.5.html#fixed-dlopen-would-not-work-file-file-urls)
We fixed a bug with `bun:ffi` where `dlopen` would not work with `file://` URLs. This was previously fixed with `process.dlopen`, but we missed it in `bun:ffi`.
This changed was made to make it easier to pass values directly from `import.meta.url`.
```
import { dlopen } from "bun:ffi";
const lib = dlopen(import.meta.resolve("./lib.so") /* ... symbols */);
```
We've also added support `bun build --compile` support for loading embedded `.dylib`, `.so`, and `.dll` files with `bun:ffi`. So you can embed native libraries into your standalone executables (which can also be cross-compiled from a different platform).
### []()[Fixed: `npm install -g bun` installs non-baseline build on Windows](bun-v1.1.5.html#fixed-npm-install-g-bun-installs-non-baseline-build-on-windows)
There was a bug in the script that runs on `npm install -g bun` that caused it to always install the baseline build on Windows, even if your machine supported non-baseline builds.
This has been fixed thanks to [@liudonghua123](https://github.com/liudonghua123).
### []()[Fixed: `bun build --define` not working with nested identifiers](bun-v1.1.5.html#fixed-bun-build-define-not-working-with-nested-identifiers)
There was a bug where `bun build --define` would incorrectly quote nested identifiers, preventing them from working properly.
app.js
```
console.log("hello!");
```
Before:
```
bun build --define "console.log=console.error"
```
```
# "console.error"("hello!");
```
After:
```
bun build --define "console.log=console.error"
```
```
# console.error("hello!");
```
Thanks to [@erikbrinkman](https://github.com/erikbrinkman) for fixing this bug.
### []()[Fixed: bun install with interesting file: URLs](bun-v1.1.5.html#fixed-bun-install-with-interesting-file-urls)
A bug where certain invalid `file:` URLs npm supports were not supported by `bun install` has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
### []()[Fixed: Bun.spawn error handling on Linux](bun-v1.1.5.html#fixed-bun-spawn-error-handling-on-linux)
Some Linux environments disable `pidfd_open` in surprising ways. When calling `pidfd_open`, we correctly handled `ENOSYS` before, but in this release we've made it treat `EPERM`, `EACCES` and a few other errors similarly to `ENOSYS` as well. We've also fixed a [race condition](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use) when a process exiting between spawning and opening the pidfd. This may fix some rare crashes on Linux in environments like GitLab CI.
## []()[Node.js compatibility improvements](bun-v1.1.5.html#node-js-compatibility-improvements)
This release also includes several Node.js compatibility improvements.
### []()[Fixed: `postMessage` in worker\_threads works when self.postMessage is overridden](bun-v1.1.5.html#fixed-postmessage-in-worker-threads-works-when-self-postmessage-is-overridden)
Bun implements the Node.js `worker_threads` module on top of the Web `Worker` API. Previously, a package overriding `self.postMessage` in a worker could cause `worker_threads` to not post messages correctly. This has been fixed, thanks to [@paperclover](https://github.com/paperclover).
### []()[Fixed: node:http client event emit order](bun-v1.1.5.html#fixed-node-http-client-event-emit-order)
The order of events emitted by `node:http` client has been fixed to match Node.js, thanks to [@nektro](https://github.com/nektro).
### []()[Fixed: `fs.existsSync` should never throw an error](bun-v1.1.5.html#fixed-fs-existssync-should-never-throw-an-error)
To match Node.js, we changed [`fs.existsSync`](bun-v1.1.5.html) to never throw an error, even when presented with invalid input. Here is a [comment](https://github.com/nodejs/node/blob/c82f3c9e80f0eeec4ae5b7aedd1183127abda4ad/lib/fs.js#L275-L279) explaining why from the source code of Node.js:
```
// fs.existsSync never throws, it only returns true or false.
// Since fs.existsSync never throws, users have established
// the expectation that passing invalid arguments to it, even like
// fs.existsSync(), would only get a false in return, so we cannot signal
// validation errors to users properly out of compatibility concerns.
```
```
import { existsSync } from "node:fs";
existsSync(); // false
existsSync({ not: "a", valid: "path" }); // false
existsSync(-10281); // false
```
### []()[Fixed: `Invalid stdio option` in `child_process.spawn`](bun-v1.1.5.html#fixed-invalid-stdio-option-in-child-process-spawn)
Previously, Bun would throw an error when passing a `ReadableStream`, like `process.stdin`, when spawning a subprocess using `child_process`.
```
import { spawn } from "child_process";
const child = spawn("echo", ["hello"], {
stdio: [process.stdin, process.stdout, process.stderr],
});
```
The following error has been fixed, thanks to [@nektro](https://github.com/nektro).
```
1 | import { spawn } from "child_process";
2 |
3 | const child = spawn("echo", ["hello"], {
^
error: Invalid stdio option "[object ReadStream]"
```
#### Fixed: `npm-run-all` now works
This also fixed a bug that prevented `npm-run-all` from working with Bun.
```
{
"name": "app",
"dependencies": {
"npm-run-all": "^4"
},
"scripts": {
"all": "npm-run-all --parallel dev build",
"dev": "echo 'Running dev!'",
"build": "echo 'Running build!'"
}
}
```
Before:
```
bun --bun run all
```
```
npm-run-all --parallel dev build
```
```
ERROR: Invalid stdio option "[object ReadStream]"
error: script "all" exited with code 1
```
After:
```
bun --bun run all
```
```
npm-run-all --parallel dev build
```
```
echo 'Running dev!'
```
```
echo 'Running build!'
```
```
Running dev!
Running build!
```
### []()[Fixed: Support for `sha3` and other crypto algorithms](bun-v1.1.5.html#fixed-support-for-sha3-and-other-crypto-algorithms)
Bun now supports the folowing crypto algorithms, to match support in Node.js:
- `sha3-224`
- `sha3-256`
- `sha3-384`
- `sha3-512`
- `sha512-224`
- `blake2b512`
```
import { createHash } from "crypto";
const hash = createHash("sha3-256");
hash.update("hello");
console.log(hash.digest("hex"));
```
### []()[Fixed: edgecase in fs.readSync arguments](bun-v1.1.5.html#fixed-edgecase-in-fs-readsync-arguments)
A bug where fs.readSync when passed offset and length arguments with no position has been fixed, thanks to [@nektro](https://github.com/nektro).
## []()[Bun for Windows improvements](bun-v1.1.5.html#bun-for-windows-improvements)
### []()[Fixed: Up/down arrow keys not working in readline](bun-v1.1.5.html#fixed-up-down-arrow-keys-not-working-in-readline)
A bug caused Bun to not correctly handle special keys like up and down arrow keys in `readline`.
This bug was caused by creating multiple instances of a `uv_tty_t` struct for the same file descriptor. We fixed this by avoiding this situation when the `fd` is stdin.
Thanks to [@paperclover](https://github.com/paperclover) for fixing this bug.
### []()[Fixed: potential hang in fs.watch on Windows](bun-v1.1.5.html#fixed-potential-hang-in-fs-watch-on-windows)
A bug caused Bun to potentially hang when using `fs.watch` on Windows. This has been fixed, thanks to [@paperclover](https://github.com/paperclover).
### []()[Fixed: bun upgrade on Windows](bun-v1.1.5.html#fixed-bun-upgrade-on-windows)
`bun upgrade` would sometimes not work on Windows due to a permissions error. We've fixed the permissions error, thanks to [@dylan-conway](https://github.com/dylan-conway).
### []()[Fixed: Rare crash on Windows when the process exits](bun-v1.1.5.html#fixed-rare-crash-on-windows-when-the-process-exits)
There was a rare crash that could occur on Windows where an exception would occur in a global C++ destructor, which would cause the process to crash.
This was hard to reproduce, but we fixed it thanks to [@dylan-conway](https://github.com/dylan-conway).
### []()[Fixed: Crash in Bun.escapeHTML on non-SIMD CPUs in certain cases](bun-v1.1.5.html#fixed-crash-in-bun-escapehtml-on-non-simd-cpus-in-certain-cases)
A crash that could occur in `Bun.escapeHTML` on non-SIMD CPUs in certain cases has been fixed.
### []()[Fixed: `bunx` without `.exe` not working on Windows](bun-v1.1.5.html#fixed-bunx-without-exe-not-working-on-windows)
There was a bug in Bun that caused it to not work on Windows if `bunx` was run without the `.exe` extension. The following error has been fixed:
```
bunx cowsay "Hello, world!"
```
```
error: Script not found "cowsay"
```
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this bug.
### []()[Fixed: bun install re-link workspaces on Windows](bun-v1.1.5.html#fixed-bun-install-re-link-workspaces-on-windows)
A bug where `bun install` would potentially return `EEXISTS` when re-linking workspaces on Windows has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
### []()[Upgraded BoringSSL](bun-v1.1.5.html#upgraded-boringssl)
We upgraded BoringSSL to the latest version.
### []()[Upgraded Mimalloc](bun-v1.1.5.html#upgraded-mimalloc)
We upgraded Mimalloc, the memory allocator used in Bun, to the latest version.
### []()[Upgraded JavaScriptCore](bun-v1.1.5.html#upgraded-javascriptcore)
We upgraded JavaScriptCore and that brings with it some optimizations to string concatenation.
## []()[Thank you to 16 contributors!](bun-v1.1.5.html#thank-you-to-16-contributors)
- [@boyer-victor](https://github.com/boyer-victor)
- [@cirospaciari](https://github.com/cirospaciari)
- [@Deckluhm](https://github.com/Deckluhm)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Electroid](https://github.com/Electroid)
- [@erikbrinkman](https://github.com/erikbrinkman)
- [@gvilums](https://github.com/gvilums)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@jwigert](https://github.com/jwigert)
- [@lafkpages](https://github.com/lafkpages)
- [@liudonghua123](https://github.com/liudonghua123)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@tuttarealstep](https://github.com/tuttarealstep)
- [@welfuture](https://github.com/welfuture)
- [@zackradisic](https://github.com/zackradisic)
* * *
#### [Bun v1.1.4](bun-v1.1.4.html)
#### [Bun v1.1.6](bun-v1.1.6.html)
On this page
- [Cross-compile standalone executables with `bun build --compile`](bun-v1.1.5.html#cross-compile-standalone-executables-with-bun-build-compile)
- [package.json with comments and trailing commas](bun-v1.1.5.html#package-json-with-comments-and-trailing-commas)
- [bun.report is Bun's new crash reporter](bun-v1.1.5.html#bun-report-is-bun-s-new-crash-reporter)
- [New: import any file as text](bun-v1.1.5.html#new-import-any-file-as-text)
- [Bun.serve() now supports Server Name Indication (SNI)](bun-v1.1.5.html#bun-serve-now-supports-server-name-indication-sni)
- [Fixed: `bun run --filter` always exited with 0](bun-v1.1.5.html#fixed-bun-run-filter-always-exited-with-0)
- [Fixed: Absolute patterns in `Bun.Glob` not working](bun-v1.1.5.html#fixed-absolute-patterns-in-bun-glob-not-working)
- [Fixed: `bun build --compile` sometimes not respecting `--outfile`](bun-v1.1.5.html#fixed-bun-build-compile-sometimes-not-respecting-outfile)
- [Fixed: `dlopen` would not work file `file://` URLs](bun-v1.1.5.html#fixed-dlopen-would-not-work-file-file-urls)
- [Fixed: `npm install -g bun` installs non-baseline build on Windows](bun-v1.1.5.html#fixed-npm-install-g-bun-installs-non-baseline-build-on-windows)
- [Fixed: `bun build --define` not working with nested identifiers](bun-v1.1.5.html#fixed-bun-build-define-not-working-with-nested-identifiers)
- [Fixed: bun install with interesting file: URLs](bun-v1.1.5.html#fixed-bun-install-with-interesting-file-urls)
- [Fixed: Bun.spawn error handling on Linux](bun-v1.1.5.html#fixed-bun-spawn-error-handling-on-linux)
- [Node.js compatibility improvements](bun-v1.1.5.html#node-js-compatibility-improvements)
- [Fixed: `postMessage` in worker\_threads works when self.postMessage is overridden](bun-v1.1.5.html#fixed-postmessage-in-worker-threads-works-when-self-postmessage-is-overridden)
- [Fixed: node:http client event emit order](bun-v1.1.5.html#fixed-node-http-client-event-emit-order)
- [Fixed: `fs.existsSync` should never throw an error](bun-v1.1.5.html#fixed-fs-existssync-should-never-throw-an-error)
- [Fixed: `Invalid stdio option` in `child_process.spawn`](bun-v1.1.5.html#fixed-invalid-stdio-option-in-child-process-spawn)
- [Fixed: Support for `sha3` and other crypto algorithms](bun-v1.1.5.html#fixed-support-for-sha3-and-other-crypto-algorithms)
- [Fixed: edgecase in fs.readSync arguments](bun-v1.1.5.html#fixed-edgecase-in-fs-readsync-arguments)
- [Bun for Windows improvements](bun-v1.1.5.html#bun-for-windows-improvements)
- [Fixed: Up/down arrow keys not working in readline](bun-v1.1.5.html#fixed-up-down-arrow-keys-not-working-in-readline)
- [Fixed: potential hang in fs.watch on Windows](bun-v1.1.5.html#fixed-potential-hang-in-fs-watch-on-windows)
- [Fixed: bun upgrade on Windows](bun-v1.1.5.html#fixed-bun-upgrade-on-windows)
- [Fixed: Rare crash on Windows when the process exits](bun-v1.1.5.html#fixed-rare-crash-on-windows-when-the-process-exits)
- [Fixed: Crash in Bun.escapeHTML on non-SIMD CPUs in certain cases](bun-v1.1.5.html#fixed-crash-in-bun-escapehtml-on-non-simd-cpus-in-certain-cases)
- [Fixed: `bunx` without `.exe` not working on Windows](bun-v1.1.5.html#fixed-bunx-without-exe-not-working-on-windows)
- [Fixed: bun install re-link workspaces on Windows](bun-v1.1.5.html#fixed-bun-install-re-link-workspaces-on-windows)
- [Upgraded BoringSSL](bun-v1.1.5.html#upgraded-boringssl)
- [Upgraded Mimalloc](bun-v1.1.5.html#upgraded-mimalloc)
- [Upgraded JavaScriptCore](bun-v1.1.5.html#upgraded-javascriptcore)
- [Thank you to 16 contributors!](bun-v1.1.5.html#thank-you-to-16-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.6.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.6
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · April 28, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one.
Bun v1.1.6 is here! This release fixes 10 bugs (addressing 512 👍 reactions). We've implemented UDP socket support & `node:dgram`. DataDog and ClickHouseDB now work. We've fixed a regression in `node:http` from v1.1.5. There are also Node.js compatibility improvements and bugfixes.
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
#### Previous releases
- [`v1.1.5`](bun-v1.1.5.html) fixes 64 bugs (addressing 101 👍). bun build --compile cross-compile standalone JavaScript & TypeScript executables to other platforms. import any file as text via the `type: "text"` import attribute. Introduces a new crash reporter. `package.json` doesn't error with comments or trailing commas. Fixes a bug where `bun run --filter` exited with 0. Fixes a bug in bun install with file: dependencies. Fixes bugs in `node:fs`, `node:tls`, `node:crypto`, `node:readline`, `node:http`, `node:worker_threads`
- [`v1.1.4`](bun-v1.1.4.html) fixes 40 bugs (addressing 84 👍 reactions). `bun run --filter <workspace> <script>` lets you run multiple workspace scripts in parallel. Reinstalls get up to 50% faster in bun install. Important reliability fixes to bun install. bun:sqlite supports `using` for resource cleanup and has a few bugfixes. Memory leak impacting Next.js Standalone & Web Streams is fixed. Node.js compatibility improvements `fs` and `child_process`. Fix for "Connection closed" in fetch(). A few bugfixes for Bundows.
- [`v1.1.0`](bun-v1.1.html) Bundows. Windows support is here!
#### To install Bun:
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[UDP Sockets](bun-v1.1.6.html#udp-sockets)
Bun now supports UDP sockets. UDP sockets are a low-level unreliable messaging protocol, often used by production monitoring tools, video/audio streaming tools, and games.
```
import { udpSocket } from "bun";
const server = await udpSocket({
socket: {
data(socket, buf, port, addr) {
console.log(`message from ${addr}:${port}:`);
console.log(buf.toString());
},
},
});
const client = await udpSocket({});
client.send("Hello!", server.port, "127.0.0.1");
```
Thanks to [@gvilums](https://github.com/gvilums) for implementing UDP socket soupport in Bun!
## []()[node:dgram is implemented](bun-v1.1.6.html#node-dgram-is-implemented)
`node:dgram` is the Node.js module for using UDP sockets. Building on top of Bun's new UDP socket support, `node:dgram` is now implemented. This was one of the most upvoted issues on Bun's GitHub repository.
send-10-messages.js
```
const dgram = require("dgram");
let count = 0;
const { promise, resolve } = Promise.withResolvers();
const server = dgram.createSocket("udp4");
server.on("message", (msg, {port, address}) => {
console.log(`server got: ${msg} from ${address}:${port}`);
if (count++ === 9) process.exit(0);
});
server.bind(41234);
const client = dgram.createSocket("udp4");
for (let i = 0; i < 10; i++) {
client.send("hello", 41234, "127.0.0.1");
}
await promise;
```
Thanks to [@gvilums](https://github.com/gvilums) for implementing `node:dgram` in Bun!
## []()[DataDog in Bun](bun-v1.1.6.html#datadog-in-bun)
DataDog's `dd-trace` module now works in Bun. DataDog is a popular infrastructure monitoring tool.
> In the next version of Bun[@datadoghq](https://twitter.com/datadoghq?ref_src=twsrc%5Etfw) + express seems to work [pic.twitter.com/szOIDs4fsc](https://t.co/szOIDs4fsc)
>
> — Bun (@bunjavascript) [April 27, 2024](https://twitter.com/bunjavascript/status/1784104050935644483?ref_src=twsrc%5Etfw)
Thanks to [@gvilums](https://github.com/gvilums) and @paperclover for getting DataDog to work in Bun!
## []()[ClickHouse in Bun](bun-v1.1.6.html#clickhouse-in-bun)
The official Node.js client for ClickHouse now works in Bun.
> In the next version of Bun
>
> ClickHouse works [pic.twitter.com/tT58vaDkUb](https://t.co/tT58vaDkUb)
>
> — meghan 🌻 (@nektro) [April 27, 2024](https://twitter.com/nektro/status/1784092005850906927?ref_src=twsrc%5Etfw)
Thanks to [@nektro](https://github.com/nektro) for getting ClickHouse to work in Bun!
## []()[SvelteKit in Bun](bun-v1.1.6.html#sveltekit-in-bun)
A bug impacting `fetch` when used with SvelteKit has been fixed.
When `fetch` was called with a `Request` subclass, Bun would skip calling the `method` or `url` getters and instead use the internal `method` and `url` properties. Since `SvelteKit`'s `Request` subclass overrides these properties, this meant we ignored the `method` property from the `Request` subclass.
```
class FooRequest extends Request {
get method() {
return "POST";
}
}
await fetch(new FooRequest("https://example.com"));
// This would be a GET request instead of a POST request!
```
This bug has now been fixed, and our test suite has been updated to prevent regressions.
## []()[Array#sort gets 15% - 135% faster](bun-v1.1.6.html#array-sort-gets-15-135-faster)
This release upgrades to the latest version of JavaScriptCore, and `Array.prototype.sort` is now 15% - 135% faster in Bun & Safari. Thanks to [@Constellation](https://github.com/Constellation).
```
❯ bun array-sort.mjs # New
cpu: Apple M3 Max
runtime: bun 1.1.6 (arm64-darwin)
benchmark time (avg) (min … max) p75 p99 p995
----------------------------------------------------------------------- -----------------------------
Array.sort (64 num, unsorted) 736.22 ns/iter (673.6 ns … 975.75 ns) 747.02 ns 975.75 ns 975.75 ns
Array.sort (64 num, pre-sorted) 377.94 ns/iter (370.2 ns … 395.56 ns) 380.33 ns 390.1 ns 395.56 ns
❯ bun-1.1.4 array-sort.mjs # Before
cpu: Apple M3 Max
runtime: bun 1.1.4 (arm64-darwin)
benchmark time (avg) (min … max) p75 p99 p995
----------------------------------------------------------------------- -----------------------------
Array.sort (64 num, unsorted) 1.14 µs/iter (1.03 µs … 1.65 µs) 1.19 µs 1.65 µs 1.65 µs
Array.sort (64 num, pre-sorted) 1.07 µs/iter (1.01 µs … 1.18 µs) 1.08 µs 1.18 µs 1.18 µs
❯ node array-sort.mjs # Node.js, for comparison
cpu: Apple M3 Max
runtime: node v22.0.0 (arm64-darwin)
benchmark time (avg) (min … max) p75 p99 p995
----------------------------------------------------------------------- -----------------------------
Array.sort (64 num, unsorted) 1.95 µs/iter (1.8 µs … 2.12 µs) 2.04 µs 2.12 µs 2.12 µs
Array.sort (64 num, pre-sorted) 689.28 ns/iter (677.4 ns … 719.66 ns) 694.22 ns 719.66 ns 719.66 ns
```
[View microbenchmark](https://github.com/oven-sh/bun/blob/84d81c3002bf68f913712b492a7aff988ad4c151/bench/snippets/array-sort.mjs)
## []()[`Module._resolveLookupPaths` in `node:module` is implemented](bun-v1.1.6.html#module-resolvelookuppaths-in-node-module-is-implemented)
The private Node.js API `Module._resolveLookupPaths` is now implemented in Bun. This API is used by `require-in-the-middle` to intercept `require` calls to instrument module loading.
Warning: when used by `dd-trace` [this may slow down your application's start time](https://github.com/DataDog/dd-trace-js/issues/3834).
## []()[node:http regression is fixed](bun-v1.1.6.html#node-http-regression-is-fixed)
A regression in node:http from v1.1.5 is fixed. The regression caused requests with errors to not propagate to the error event correctly. This regression impacted the `stripe` npm package, amongst others. Thanks to [@nektro](https://github.com/nektro) for fixing this regression!
## []()[Fixed: node:http listen callback had wrong `this` value](bun-v1.1.6.html#fixed-node-http-listen-callback-had-wrong-this-value)
A bug where the `this` value in the `listen` callback was incorrect has been fixed. The `this` value is now the server instance, as expected.
Thanks to [@nektro](https://github.com/nektro) for fixing this.
## []()[Fixed: cross-compilation extracting bug on Windows](bun-v1.1.6.html#fixed-cross-compilation-extracting-bug-on-windows)
A bug where `bun build --compile` would incorrectly extract the tarball on Windows has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
## []()[Fixed: `error.Unexpected` when upgrading bun across devices on Windows](bun-v1.1.6.html#fixed-error-unexpected-when-upgrading-bun-across-devices-on-windows)
The Windows NT error `NOT_SAME_DEVICE` was not correctly mapped to the posix error `EXDEV`, causing an `error.Unexpected` when upgrading Bun across different drive letters on Windows. This has been fixed.
## []()[Fixed: node:dns lookup didn't keep event loop alive on macOS](bun-v1.1.6.html#fixed-node-dns-lookup-didn-t-keep-event-loop-alive-on-macos)
Previously, the following code would not log `hiii` on macOS:
```
const dns = require("dns");
dns.lookup("google.com", (err, address, family) => {
console.log("hiii");
});
```
This has been fixed.
The bug was we were not draining microtasks after DNS lookups on macOS were completed. This caused the event loop to be empty, and the process to exit before the callback was called.
## []()[Fixed: Bug with TOML & JSON imports](bun-v1.1.6.html#fixed-bug-with-toml-json-imports)
A bug where `json` and `toml` imports would go through the CommonJS -> ESM conversion path when they were originally required has been fixed.
The following input:
```
console.log(require("./hello.toml"));
```
🔴 Bun v1.1.5 would output (bad):
```
Module {
__esModule: true,
default: {
hello: "world"
},
hello: {
world: "world"
}
}
```
🟢 Bun v1.1.6 now outputs (good):
```
{
hello: "world",
}
```
This should also slightly reduce the memory usage of TOML imports. Previously, we would generate a sourcemap for TOML along with source code, which was unnecessary. Now we just create the objects/values directly without emitting JavaScript source code.
## []()[Fixed: memory leak in Bun.write()](bun-v1.1.6.html#fixed-memory-leak-in-bun-write)
When using `Bun.write()` with large output, the memory for the input string or bytes was not correctly freed. This led to large memory growth over time. This has been fixed, and a memory leak test has been added to prevent this from regressing in the future.
## []()[Fixed: Crash in `napi_get_date_value`](bun-v1.1.6.html#fixed-crash-in-napi-get-date-value)
A crash in `napi_get_date_value` when an unexpected type was passed has been fixed. This crash impacted certain Node Native Addons.
## []()[Fixed: Possible crash in HTMLRewriter with Bun.file()](bun-v1.1.6.html#fixed-possible-crash-in-htmlrewriter-with-bun-file)
When using `HTMLRewriter` to transform HTML files on disk with `Bun.file()`, in certain cases Bun could crash or never fulfill a Promise. This has been fixed.
## []()[Fixed: edgecase with --define](bun-v1.1.6.html#fixed-edgecase-with-define)
A bug where `--define` when used on a global property would have incorrect output has been fixed, thanks to [@dylan-conway](https://github.com/dylan-conway).
## []()[Thank you to 9 contributors!](bun-v1.1.6.html#thank-you-to-9-contributors)
- [@Electroid](https://github.com/Electroid)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@KilianB](https://github.com/KilianB)
- [@dylan-conway](https://github.com/dylan-conway)
- [@gvilums](https://github.com/gvilums)
- [@jlucaso1](https://github.com/jlucaso1)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@yus-ham](https://github.com/yus-ham)
* * *
#### [Bun v1.1.5](bun-v1.1.5.html)
#### [Bun v1.1.7](bun-v1.1.7.html)
On this page
- [UDP Sockets](bun-v1.1.6.html#udp-sockets)
- [node:dgram is implemented](bun-v1.1.6.html#node-dgram-is-implemented)
- [DataDog in Bun](bun-v1.1.6.html#datadog-in-bun)
- [ClickHouse in Bun](bun-v1.1.6.html#clickhouse-in-bun)
- [SvelteKit in Bun](bun-v1.1.6.html#sveltekit-in-bun)
- [Array#sort gets 15% - 135% faster](bun-v1.1.6.html#array-sort-gets-15-135-faster)
- [`Module._resolveLookupPaths` in `node:module` is implemented](bun-v1.1.6.html#module-resolvelookuppaths-in-node-module-is-implemented)
- [node:http regression is fixed](bun-v1.1.6.html#node-http-regression-is-fixed)
- [Fixed: node:http listen callback had wrong `this` value](bun-v1.1.6.html#fixed-node-http-listen-callback-had-wrong-this-value)
- [Fixed: cross-compilation extracting bug on Windows](bun-v1.1.6.html#fixed-cross-compilation-extracting-bug-on-windows)
- [Fixed: `error.Unexpected` when upgrading bun across devices on Windows](bun-v1.1.6.html#fixed-error-unexpected-when-upgrading-bun-across-devices-on-windows)
- [Fixed: node:dns lookup didn't keep event loop alive on macOS](bun-v1.1.6.html#fixed-node-dns-lookup-didn-t-keep-event-loop-alive-on-macos)
- [Fixed: Bug with TOML & JSON imports](bun-v1.1.6.html#fixed-bug-with-toml-json-imports)
- [Fixed: memory leak in Bun.write()](bun-v1.1.6.html#fixed-memory-leak-in-bun-write)
- [Fixed: Crash in `napi_get_date_value`](bun-v1.1.6.html#fixed-crash-in-napi-get-date-value)
- [Fixed: Possible crash in HTMLRewriter with Bun.file()](bun-v1.1.6.html#fixed-possible-crash-in-htmlrewriter-with-bun-file)
- [Fixed: edgecase with --define](bun-v1.1.6.html#fixed-edgecase-with-define)
- [Thank you to 9 contributors!](bun-v1.1.6.html#thank-you-to-9-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.7.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.7
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · May 3, 2024
[](../rss.xml)
Bun is an incredibly fast JavaScript runtime, bundler, transpiler, and package manager — all in one.
Bun v1.1.7 is here! This release fixes 28 bugs (addressing 11 👍). Glob workspace names in bun install. Asymmetric matcher support in expect.extends() equals. bunx --version. Bugfixes to JSX transpilation, sourcemaps, cross-compilation of standalone executables, bun shell, RegExp, Worker on Windows, and Node.js compatibility improvements.
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
#### Previous releases
- [`v1.1.6`](bun-v1.1.6.html) fixes 10 bugs (addressing 512 👍 reactions). We've implemented UDP socket support & `node:dgram`. DataDog and ClickHouseDB now work. We've fixed a regression in `node:http` from v1.1.5. There are also Node.js compatibility improvements and bugfixes.
- [`v1.1.5`](bun-v1.1.5.html) fixes 64 bugs (addressing 101 👍). bun build --compile cross-compile standalone JavaScript & TypeScript executables to other platforms. import any file as text via the `type: "text"` import attribute. Introduces a new crash reporter. `package.json` doesn't error with comments or trailing commas. Fixes a bug where `bun run --filter` exited with 0. Fixes a bug in bun install with file: dependencies. Fixes bugs in `node:fs`, `node:tls`, `node:crypto`, `node:readline`, `node:http`, `node:worker_threads`
- [`v1.1.0`](bun-v1.1.html) Bundows. Windows support is here!
#### To install Bun:
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
## []()[Glob `workspace` names in `bun install`](bun-v1.1.7.html#glob-workspace-names-in-bun-install)
You can now use advanced glob patterns in `workspaces` in `package.json` to specify which directories to include in a monorepo. For example:
```
{
"name": "monorepo",
"workspaces": ["{app,packages,lib}/**"]
}
```
Previously, we only supported `/*` as a pattern or exact paths in `workspaces`. `workspaces` matching is now powered by [`Bun.Glob`](../docs/api/glob.html), so you can use any glob pattern supported by `Bun.Glob`.
Thanks to [@zackradisic](https://github.com/zackradisic) for implementing this feature!
## []()[Asymmetric matcher support in `expect.extends()` equals](bun-v1.1.7.html#asymmetric-matcher-support-in-expect-extends-equals)
You can now use asymmetric matchers within when using `this.equals` inside `expect.extends()` equals. For example:
```
import { test, expect } from "bun:test";
expect.extend({
toCustomEqual(actual, expected) {
return { pass: this.equals(actual, expected) };
},
});
test("asymmetric matchers", () => {
expect(1).toCustomEqual(expect.anything());
expect(1).toCustomEqual(expect.any(Number));
});
```
Previously, this would throw an error. Now, it works as expected.
Thanks to [@anchan828](https://github.com/anchan828) for implementing this feature!
## []()[bunx --version](bun-v1.1.7.html#bunx-version)
When you run `bunx --version`, Bun now prints the version number:
```
bunx --version
```
```
1.1.7
```
Previously, `bunx --version` would print the help menu:
```
bunx --version
```
```
Usage: bunx [...flags] <package>[@version] [...flags and arguments]
Execute an npm package executable (CLI), automatically installing into a global shared cache if not installed in node_modules.
Flags:
--bun Force the command to run with Bun instead of Node.js
Examples:
bunx prisma migrate
bunx prettier foo.js
bunx --bun vite dev foo.js
```
Thanks to [@Electroid](https://github.com/Electroid) for fixing this!
## []()[WebSocket close code 1015](bun-v1.1.7.html#websocket-close-code-1015)
When a `WebSocket` client connection fails to connect due to a TLS error, the close code is now `1015` instead of `1006`. This is more accurate and helps with debugging.
```
const ws = new WebSocket("wss://localhost:3000");
ws.on("close", ({ code, reason }) => {
console.log(code); // 1015
console.log(reason); // "TLS handshake failed"
});
```
Previously, the close code was `1006`, which is a generic error code.
## []()[Unhandled errors now print the Bun version](bun-v1.1.7.html#unhandled-errors-now-print-the-bun-version)
When a top-level error is thrown or promise is rejected, Bun now prints the Bun version at the end:
```
1 | function hi() {
2 | return 42;
3 | }
4 |
5 | function yo() {
6 | throw new Error("uh oh!");
^
error: uh oh!
at yo (error.js:6:9)
at hey (error.js:11:3)
at error.js:14:1
Bun v1.1.7 (macOS arm64)
```
This is useful when asking people for debugging help because it saves one question: "What version of Bun are you using?"
## []()[Better error message in Bun.build()](bun-v1.1.7.html#better-error-message-in-bun-build)
> In the next version of Bun
>
> This error message in bun build & [https://t.co/pesCwin4Tx](https://t.co/pesCwin4Tx)() shows more information, and a bug causing this happen when it shouldn't has been fixed.
>
> top: after, bottom: before [pic.twitter.com/tAQZa42JxH](https://t.co/tAQZa42JxH)
>
> — Bun (@bunjavascript) [May 3, 2024](https://twitter.com/bunjavascript/status/1786327136854491348?ref_src=twsrc%5Etfw)
## []()[Fixed: React "Duplicate key" warning in development](bun-v1.1.7.html#fixed-react-duplicate-key-warning-in-development)
> In the next version of Bun
>
> A transpiler bug causing React to print the "unique 'key' prop" warning has been fixed, thanks to [@JNYBGR](https://twitter.com/JNYBGR?ref_src=twsrc%5Etfw) [pic.twitter.com/7qvAOJT55E](https://t.co/7qvAOJT55E)
>
> — Bun (@bunjavascript) [May 3, 2024](https://twitter.com/bunjavascript/status/1786341472918511855?ref_src=twsrc%5Etfw)
## []()[Fixed: hang in Bun Shell `seq`, `basename`, `dirname` with empty output](bun-v1.1.7.html#fixed-hang-in-bun-shell-seq-basename-dirname-with-empty-output)
When `seq`, `basename`, or `dirname` were called with empty output in Bun Shell, it would hang indefinitely due to not closing the output stream. This has been fixed in Bun v1.1.7, thanks to [@RanoIP](https://github.com/RanoIP).
## []()[Fixed: Potential crash on start on Windows](bun-v1.1.7.html#fixed-potential-crash-on-start-on-windows)
An invalid memory access in the SIMD codepath within the Zig standard library function `std.mem.indexOfScalarPos` could lead to Bun crashing immediately during initialization on Windows. This has been fixed in Bun v1.1.7.
Additionally, we've added an optimization to code which searches for sentinel values in pointers to use the Windows `wcslen` and `strlen` functions where appropriate, instead of a slower handrolled implementation.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this!
## []()[Fixed: Potential crash after process spawn](bun-v1.1.7.html#fixed-potential-crash-after-process-spawn)
A crash that sometimes occurred when a spawned subprocess gets garbage collected before the stdin stream gets collected has been fixed in Bun v1.1.7.
Thanks to [@gvilums](https://github.com/gvilums) for fixing this!
## []()[Fixed: Crash while exiting with Worker](bun-v1.1.7.html#fixed-crash-while-exiting-with-worker)
A crash that could occur when Bun exits while a Worker is still running has been fixed in Bun v1.1.7. This crash was caused by threadlocal destructors running for each thread during `std::quick_exit`.
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this!
## []()[Fixed: Crash when reading directories on Windows](bun-v1.1.7.html#fixed-crash-when-reading-directories-on-windows)
When reading directories on Windows, Bun was assuming that the `FILE_DIRECTORY_INFORMATION` struct in the NT API was 8 bytes aligned, [per the Windows API documentation](https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/ns-ntifs-_file_directory_information#remarks). However, runtime safety checks proved this to be false. We have relaxed the alignment requirement for this struct in our code and this crash should no longer occur.
## []()[Fixed: Crash when out of memory on Windows](bun-v1.1.7.html#fixed-crash-when-out-of-memory-on-windows)
When the `mimalloc` memory allocator returned `NULL` due to running out of memory, Bun would crash due to an assertion failure like `mimalloc: allocated size is too small`. This assertion failure was only meant for development and testing, not for a release build (we enable assertions by default on Windows however).
This has been fixed in Bun v1.1.7.
This could most easily be reproduced by uploading a large file to a Bun.serve() server when the system was very low on memory or simulating low memory.
## []()[Fixed: Crash when WebSocket client has connection error on Windows](bun-v1.1.7.html#fixed-crash-when-websocket-client-has-connection-error-on-windows)
A crash that could occur when a `WebSocket` client connection fails to connect on Windows has been fixed. We've added a test to prevent this from regressing in the future.
## []()[Fixed: UDP socket now throws on valid port number](bun-v1.1.7.html#fixed-udp-socket-now-throws-on-valid-port-number)
In Bun v1.1.6 (the previous release), we introduced [Bun.udpSocket](../docs/api/udp.html) for UDP socket support.
Previously, all port numbers which weren't between 1 and 65535 would be treated as `0`, and a randomly assigned port would be used. Now, `Bun.udpSocket` throws an error if the provided port number is invalid.
Thanks to [@gvilums](https://github.com/gvilums) for fixing this!
## []()[Fixed: Stacktrace with incorrect line numbers](bun-v1.1.7.html#fixed-stacktrace-with-incorrect-line-numbers)
One bug causing stacktraces to sometimes show incorrect line numbers has been fixed in Bun v1.1.7 (note: there could be other bugs causing this issue).
This bug was caused by an uninitialized integer in C++ code. We are adding [`clang-analyzer`](https://clang-analyzer.llvm.org/) to Bun's CI to prevent this from happening again.
## []()[Fixed: sourcemap regression causing hang in `bun build`](bun-v1.1.7.html#fixed-sourcemap-regression-causing-hang-in-bun-build)
A sourcemap regression introduced in Bun v1.1.6 caused bun build to hang indefinitely. This has been fixed in Bun v1.1.7, and we've added an integration test to prevent this from regressing in the future.
Using `bun build --sourcemap=external` on a "hello world" express.js app like this would hang:
```
const express = require("express");
const app = express();
const port = 3000;
app.get("/", (req, res) => {
res.send("Hello World!");
});
app.listen(port, () => {
console.log(`Example app listening on port ${port}`);
});
```
We've added an integration test that ensures output from `bun build --compile --minify` can successfully run a simple express.js app.
## []()[Fixed: Cross-compilation of executables to & from Windows](bun-v1.1.7.html#fixed-cross-compilation-of-executables-to-from-windows)
Cross-compilation <> Windows had a filepath bug where we were assuming if the current platform was Windows or posix to use the file path prefix for that platform, instead of the cross-compilation target's platform. This bug was fixed, thanks to [@gvilums](https://github.com/gvilums).
## []()[Fixed: memory leak regression in unread server-side requests bodies](bun-v1.1.7.html#fixed-memory-leak-regression-in-unread-server-side-requests-bodies)
In Bun v1.0.30 - Bun v1.1.6, unread incoming HTTP request bodies to Bun.serve() were not being cleaned up properly. This also applied to `node:http` servers.
This meant that choosing not to read the incoming request's body could consume memory indefinitely. This has been fixed in Bun v1.1.7, thanks to [@cirospacari](https://github.com/cirospacari), and we've added regression tests to prevent this from happening again.
## []()[Fixed: fs.fdatasync missing `fd` in Error](bun-v1.1.7.html#fixed-fs-fdatasync-missing-fd-in-error)
When an error was thrown in `fs.fdatasync`, the `fd` property was missing from the error object. This has been fixed in Bun v1.1.7, thanks to [@nektro](https://github.com/nektro).
## []()[Fixed: custom inspect exception](bun-v1.1.7.html#fixed-custom-inspect-exception)
When a custom inspect function threw an exception, Bun would return `[native code]`. This was confusing. We wish we could change this to throw an error, but that would be a breaking change. Instead, we've made it print `[custom formatter threw an exception]` instead, which is slightly better but not what we'd prefer. In a future version of Bun, we will change this to throw an error but we do not want your code to potentially randomly break in a minor version update.
## []()[ServerWebSocket micro-optimization](bun-v1.1.7.html#serverwebsocket-micro-optimization)
The in-memory size of a `ServerWebSocket` representation in Zig has shrunk from 32 bytes to 24 bytes. You probably won't notice the memory savings, but it might make some functions run faster due to better cache locality.
## []()[console.log with custom inspect fn gets 8% faster](bun-v1.1.7.html#console-log-with-custom-inspect-fn-gets-8-faster)
> In the next version of Bun
>
> Using custom inspect functions in console.log/error gets 8% faster [pic.twitter.com/FLUwX0k6wB](https://t.co/FLUwX0k6wB)
>
> — Jarred Sumner (@jarredsumner) [May 3, 2024](https://twitter.com/jarredsumner/status/1786334857452519768?ref_src=twsrc%5Etfw)
## []()[Thank you to 17 contributors!](bun-v1.1.7.html#thank-you-to-17-contributors)
- [@anchan828](https://github.com/anchan828)
- [@cirospaciari](https://github.com/cirospaciari)
- [@codershiba](https://github.com/codershiba)
- [@DaleSeo](https://github.com/DaleSeo)
- [@dsernst](https://github.com/dsernst)
- [@dylan-conway](https://github.com/dylan-conway)
- [@Electroid](https://github.com/Electroid)
- [@fzn0x](https://github.com/fzn0x)
- [@gvilums](https://github.com/gvilums)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@JonnyBurger](https://github.com/JonnyBurger)
- [@mangs](https://github.com/mangs)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@RanolP](https://github.com/RanolP)
- [@windwiny](https://github.com/windwiny)
- [@zackradisic](https://github.com/zackradisic)
* * *
#### [Bun v1.1.6](bun-v1.1.6.html)
#### [Bun v1.1.8](bun-v1.1.8.html)
On this page
- [Glob `workspace` names in `bun install`](bun-v1.1.7.html#glob-workspace-names-in-bun-install)
- [Asymmetric matcher support in `expect.extends()` equals](bun-v1.1.7.html#asymmetric-matcher-support-in-expect-extends-equals)
- [bunx --version](bun-v1.1.7.html#bunx-version)
- [WebSocket close code 1015](bun-v1.1.7.html#websocket-close-code-1015)
- [Unhandled errors now print the Bun version](bun-v1.1.7.html#unhandled-errors-now-print-the-bun-version)
- [Better error message in Bun.build()](bun-v1.1.7.html#better-error-message-in-bun-build)
- [Fixed: React "Duplicate key" warning in development](bun-v1.1.7.html#fixed-react-duplicate-key-warning-in-development)
- [Fixed: hang in Bun Shell `seq`, `basename`, `dirname` with empty output](bun-v1.1.7.html#fixed-hang-in-bun-shell-seq-basename-dirname-with-empty-output)
- [Fixed: Potential crash on start on Windows](bun-v1.1.7.html#fixed-potential-crash-on-start-on-windows)
- [Fixed: Potential crash after process spawn](bun-v1.1.7.html#fixed-potential-crash-after-process-spawn)
- [Fixed: Crash while exiting with Worker](bun-v1.1.7.html#fixed-crash-while-exiting-with-worker)
- [Fixed: Crash when reading directories on Windows](bun-v1.1.7.html#fixed-crash-when-reading-directories-on-windows)
- [Fixed: Crash when out of memory on Windows](bun-v1.1.7.html#fixed-crash-when-out-of-memory-on-windows)
- [Fixed: Crash when WebSocket client has connection error on Windows](bun-v1.1.7.html#fixed-crash-when-websocket-client-has-connection-error-on-windows)
- [Fixed: UDP socket now throws on valid port number](bun-v1.1.7.html#fixed-udp-socket-now-throws-on-valid-port-number)
- [Fixed: Stacktrace with incorrect line numbers](bun-v1.1.7.html#fixed-stacktrace-with-incorrect-line-numbers)
- [Fixed: sourcemap regression causing hang in `bun build`](bun-v1.1.7.html#fixed-sourcemap-regression-causing-hang-in-bun-build)
- [Fixed: Cross-compilation of executables to & from Windows](bun-v1.1.7.html#fixed-cross-compilation-of-executables-to-from-windows)
- [Fixed: memory leak regression in unread server-side requests bodies](bun-v1.1.7.html#fixed-memory-leak-regression-in-unread-server-side-requests-bodies)
- [Fixed: fs.fdatasync missing `fd` in Error](bun-v1.1.7.html#fixed-fs-fdatasync-missing-fd-in-error)
- [Fixed: custom inspect exception](bun-v1.1.7.html#fixed-custom-inspect-exception)
- [ServerWebSocket micro-optimization](bun-v1.1.7.html#serverwebsocket-micro-optimization)
- [console.log with custom inspect fn gets 8% faster](bun-v1.1.7.html#console-log-with-custom-inspect-fn-gets-8-faster)
- [Thank you to 17 contributors!](bun-v1.1.7.html#thank-you-to-17-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.8.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun v1.1.8
* * *
[Ashcon Partovi](https://twitter.com/ashconpartovi) · May 10, 2024
[](../rss.xml)
Bun v1.1.8 is here! This release fixes 54 bugs (addressing 184 👍). Support for `process.on("uncaughtException")` and `process.on("unhandledRejection")`, `JSON.parse` gets faster, Brotli support in `node:zlib`, `[Symbol.dispose]` in Bun APIs, fixes lots of crashes on Windows, and many other bugfixes.
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
#### Previous releases
- [`v1.1.7`](bun-v1.1.7.html) fixes 28 bugs (addressing 11 👍). Glob workspace names in bun install. Asymmetric matcher support in expect.extends() equals. bunx --version. Bugfixes to JSX transpilation, sourcemaps, cross-compilation of standalone executables, bun shell, RegExp, Worker on Windows, and Node.js compatibility improvements.
- [`v1.1.6`](bun-v1.1.6.html) fixes 10 bugs (addressing 512 👍 reactions). We've implemented UDP socket support & `node:dgram`. DataDog and ClickHouseDB now work. We've fixed a regression in `node:http` from v1.1.5. There are also Node.js compatibility improvements and bugfixes.
- [`v1.1.0`](bun-v1.1.html) Bundows. Windows support is here!
#### To install Bun
curl
npm
powershell
scoop
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
npm
```
npm install -g bun
```
powershell
```
powershell -c "irm bun.sh/install.ps1|iex"
```
scoop
```
scoop install 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
```
### []()[New: Support for `process.on("uncaughtException")` and `process.on("unhandledRejection")`](bun-v1.1.8.html#new-support-for-process-on-uncaughtexception-and-process-on-unhandledrejection)
Bun now supports the `process.on("uncaughtException")` and `process.on("unhandledRejection")` events, which allow you to handle uncaught exceptions and unhandled promises in a more graceful way.
```
process.on("uncaughtException", (error) => {
console.error("Uncaught exception:", error);
});
process.nextTick(() => {
throw new Error("Oops!");
});
```
This also works for unhandled promises, which is useful for handling errors in asynchronous code.
```
process.on("unhandledRejection", (reason, promise) => {
console.error("Unhandled rejection:", reason);
});
await 42;
throw new Error("Oops!");
```
This should resolve issues with various npm packages, like `puppeteer`, that would clean up resources if an unhandled exception occurred.
Thanks to [@gvilums](https://github.com/gvilums) for adding this feature!
### []()[New: Brotli support for `node:zlib`](bun-v1.1.8.html#new-brotli-support-for-node-zlib)
Bun now implements the Brotli APIs in the `node:zlib` module, including `BrotliCompress()`, `BrotliDecompress()`, `brotliCompress()`, `brotliDecompress()`, and more!
```
import { brotliCompressSync, brotliDecompressSync } from "node:zlib";
const compressed = brotliCompressSync("Hello, world!");
console.log(compressed.toString("hex"));
// => 0b068048656c6c6f2c20776f726c642103
const decompressed = brotliDecompressSync(compressed);
console.log(decompressed.toString("utf8"));
// => Hello, world!
```
You can also use Brotli streams with the `zlib` module.
```
import { createBrotliCompress } from "node:zlib";
const compressor = createBrotliCompress();
compressor.write("Hello, world!");
compressor.end();
const compressed = compressor.read();
console.log(compressed.toString("hex"));
// => 0b068048656c6c6f2c20776f726c642103
```
#### Fixes a regression with `axios`
Adding support for Brotli also fixed a regression with `axios`, so it should now work again in Bun.
Thanks to [@nektro](https://github.com/nektro) for adding this feature!
### []()[New: Support for `[Symbol.dispose]` in Bun APIs](bun-v1.1.8.html#new-support-for-symbol-dispose-in-bun-apis)
Bun now supports the `[Symbol.dispose]` property on various APIs, including `Bun.spawn`, `Bun.serve`, `Bun.connect`, and `Bun.listen`. This allows you to define a variable with the `using` syntax, which is defined by the TC39 proposal for [Explicit resource management](https://github.com/tc39/proposal-explicit-resource-management) in JavaScript.
```
import { serve } from "bun";
{
using server = serve({
port: 0,
fetch(request) {
return new Response("Hello, world!");
},
});
doStuff(server);
}
function doStuff(server) {
// ...
}
```
In this example, the server is automatically closed when the `server` variable goes out of scope, even if an exception is thrown. This is useful for ensuring that resources are properly cleaned up, especially in tests.
```
import { spawn } from "bun";
import { test, expect } from "bun:test";
test("able to spawn a process", async () => {
using subprocess = spawn({
cmd: [process.execPath, "-e", "console.log('Hello, world!')"],
stdout: "pipe",
});
const stdout = new Response(subprocess.stdout).text();
expect(stdout).resolves.toBe("Hello, world!");
});
```
Thanks to [@paperclover](https://github.com/paperclover) for implementing this feature!
### []()[Faster: JSON.parse](bun-v1.1.8.html#faster-json-parse)
> In the next version of Bun & Safari
>
> • 6% faster JSON.parse(object)
> • 200% - 400% faster JSON.parse(long string)
>
> Thanks [@Constellation](https://twitter.com/Constellation?ref_src=twsrc%5Etfw)! [pic.twitter.com/uvBJUl8gOs](https://t.co/uvBJUl8gOs)
>
> — Bun (@bunjavascript) [May 10, 2024](https://twitter.com/bunjavascript/status/1788826914570019245?ref_src=twsrc%5Etfw)
### []()[Fixed: `Illegal instruction` on Windows](bun-v1.1.8.html#fixed-illegal-instruction-on-windows)
We fixed a bug in the build script of Bun that caused Windows dependencies to be built with the wrong CPU flags. This caused `Illegal instruction` errors with older CPUs on Windows.
> 6 line PR by [@paperclover\_dev](https://twitter.com/paperclover_dev?ref_src=twsrc%5Etfw) fixes a crash Windows users reported 80 times [pic.twitter.com/DmuHAgyd2j](https://t.co/DmuHAgyd2j)
>
> — Bun (@bunjavascript) [May 7, 2024](https://twitter.com/bunjavascript/status/1787939623370715434?ref_src=twsrc%5Etfw)
This bug resolved over 18 GitHub issues and was caught thanks to Bun's new [crash reporter](bun-report-is-buns-new-crash-reporter.html).
### []()[Fixed: Crash with `console.log` using a `%i` format string](bun-v1.1.8.html#fixed-crash-with-console-log-using-a-i-format-string)
We fixed a bug where `console.log` could crash using a `%i` format string that was out of bounds for the number of arguments.
```
console.log("Hello %i %i", [1, 2, 3, 4]);
// Before: <panic>
// Now: 'Hello NaN %i'
```
Thanks to [@paperclover](https://github.com/paperclover) for fixing this bug!
### []()[Fixed: Several `workspace dependency not found` errors](bun-v1.1.8.html#fixed-several-workspace-dependency-not-found-errors)
We fixed various issues that would cause `bun install` to fail with `workspace dependency not found` errors.
- The first bug was caused by adding a new workspace dependency to a workspace that did not define a `version` property in its `package.json`.
- The second bug was caused by manually adding a workspace dependency to the `packages` property in the workspace `package.json`, then attempting to run `bun install`.
We are still working on making workspaces better in Bun. If you still experience problems with workspaces, please [file an issue](../issues.html).
### []()[Fixed: Crash with `console.table` when being called repeatedly](bun-v1.1.8.html#fixed-crash-with-console-table-when-being-called-repeatedly)
We fixed a bug were the reference counting of strings using `console.table` was being incorrectly calculated, which could cause a crash.
```
for (let i = 0; i < 50; i++) {
console.table([{ n: 8 }]);
}
```
Thanks to [@dylan-conway](https://github.com/dylan-conway) for fixing this bug!
### []()[Fixed: Bug with `createReadStream` with a file descriptor and offset](bun-v1.1.8.html#fixed-bug-with-createreadstream-with-a-file-descriptor-and-offset)
We fixed a bug where using `createReadStream` with a file descriptor and start offset would cause the offset to be ignored.
```
import { openSync, createReadStream, writeSync } from "node:fs";
const fd = openSync("hello.txt", "w+");
const stream = createReadStream("", { fd: fd, start: 2 });
stream.on("data", (chunk) => {
// Before: "Hello, world!"
// Now: "llo, world!"
});
writeSync(fd, "Hello, world!");
```
Thanks to [@gvilums](https://github.com/gvilums) for fixing this bug!
### []()[Fixed: `confirm()` did not work on Windows](bun-v1.1.8.html#fixed-confirm-did-not-work-on-windows)
Bun implements the [`confirm()`](https://developer.mozilla.org/en-US/docs/Web/API/Window/confirm) Web API, which prompts the terminal for a confirmation message. We were not properly handling Windows line endings, so the confirmation would never be`true`.
```
if (confirm("Are you sure?")) {
console.log("Yes!");
} else {
console.log("No!");
}
```
This was fixed thanks to [@rcaselles](https://github.com/rcaselles).
### []()[Fixed: Bug with `os.cpus()` for some CPUs](bun-v1.1.8.html#fixed-bug-with-os-cpus-for-some-cpus)
We fixed a bug where `os.cpus()` would throw an error when the CPU string was too long.
```
import { cpus } from "node:os";
console.log(cpus());
// Before: <error: Failed to get cpu information>
// Now: [ { model: "Intel(R) Core(TM) i7-10875H CPU @ 2.30GHz", ... } ]
```
This was fixed thanks to [@dylan-conway](https://github.com/dylan-conway).
### []()[Fixed: Missing `agent` property on `ClientRequest`](bun-v1.1.8.html#fixed-missing-agent-property-on-clientrequest)
We fixed a bug where the `agent` property was missing on the `ClientRequest` class.
```
import { request } from "node:http";
const req = request("https://example.com");
console.log(req.agent);
// Before: undefined
// Now: <Agent>
```
Thanks to [@nektro](https://github.com/nektro) for fixing this bug!
### []()[Fixed: Redirecting stdout from `Bun.spawn()` to `Bun.serve()` was not working](bun-v1.1.8.html#fixed-redirecting-stdout-from-bun-spawn-to-bun-serve-was-not-working)
There was a bug where redirecting stdout from `Bun.spawn()` to `Bun.serve()` was not working. This has now been fixed.
```
import { spawn, serve } from "bun";
const server = serve({
port: 0,
async fetch(req) {
const { stdout } = spawn({
cmd: [process.execPath, "-e", 'console.write("Hello, world!")'],
stdout: "pipe",
});
return new Response(stdout);
},
});
const response = await fetch(server.url);
console.write(await response.text());
server.stop(true);
```
### []()[Fixed: `onread` not working in `node:net`](bun-v1.1.8.html#fixed-onread-not-working-in-node-net)
We added support for the `onread` event in the `node:net` module, which allows you to listen for incoming data on a socket.
```
import { connect } from "node:net";
const socket = connect({
host: "example.com",
port: 80,
onread: {
buffer: Buffer.alloc(1024),
callback(size, buffer) {
console.log("onread:", size);
},
},
});
socket.write("GET / HTTP/1.1\r\n\r\n");
// Before: <nothing>
// Now: onread: 504
```
Thanks to [@gvilums](https://github.com/gvilums) for fixing this bug!
### []()[Fixed: Crash in InlineCacheCompiler](bun-v1.1.8.html#fixed-crash-in-inlinecachecompiler)
A crash that could occur when a function was accessed in certain ways and subsequently garbage collected after some minutes of activity has been fixed. This crash was an upstream issue in the JavaScriptCore engine that began in Bun v1.1.7 and has now been resolved. Some users reported this crash occurring while using Next.js.
### []()[Fixed: Better stub for `node:inspector`](bun-v1.1.8.html#fixed-better-stub-for-node-inspector)
Bun does not support the `node:inspector` module, since it depends on the [Chrome DevTools protocol](https://chromedevtools.github.io/devtools-protocol/), which is similar but not the same as WebKit's protocol.
Previously, Bun would throw an unimplemented error when trying to use `inspector.url()`. Now, we have changed it to return `undefined`, which is the allowed behavior according to the [Node.js documentation](https://nodejs.org/api/inspector.html#inspector_inspector_url).
Some npm packages, like `typedoc`, use this API for feature detection. With these changes, those packages will now work with Bun.
```
import { url } from "node:inspector";
// ...
const isDebugging = () => !!url();
```
Thanks to [@Electroid](https://github.com/Electroid) for making this better!
### []()[Thank you to 12 contributors!](bun-v1.1.8.html#thank-you-to-12-contributors)
- [@dylan-conway](https://github.com/dylan-conway)
- [@e3dio](https://github.com/e3dio)
- [@Electroid](https://github.com/Electroid)
- [@gvilums](https://github.com/gvilums)
- [@henrikstorck](https://github.com/henrikstorck)
- [@Jarred-Sumner](https://github.com/Jarred-Sumner)
- [@jrmccannon](https://github.com/jrmccannon)
- [@mangs](https://github.com/mangs)
- [@nektro](https://github.com/nektro)
- [@paperclover](https://github.com/paperclover)
- [@rcaselles](https://github.com/rcaselles)
- [@yhdgms1](https://github.com/yhdgms1)
- [@zackradisic](https://github.com/zackradisic)
* * *
#### [Bun v1.1.7](bun-v1.1.7.html)
#### [Bun v1.1.9](bun-v1.1.9.html)
On this page
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.1.9.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/blog/bun-v1.1.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun 1.1
* * *
[Jarred](https://twitter.com/jarredsumner), [Chloe](https://github.com/paperclover), [Ashcon](https://twitter.com/ashconpartovi), [Dylan](https://github.com/dylan-conway), [Meghan](https://github.com/nektro), [Georgijs](https://github.com/gvilums), [Ciro](https://github.com/cirospaciari) · April 1, 2024
[](../rss.xml)
Bun is a fast, all-in-one toolkit for running, building, testing, and debugging JavaScript and TypeScript, from a single script to a full-stack application. If you're new to Bun, you can learn more in the [Bun 1.0](../1.0.html#bun-is-an-all-in-one-toolkit) blog post.
Bun 1.1 is huge update.
There's been over [1,700 commits](https://github.com/oven-sh/bun/compare/bun-v1.0.0...bun-v1.1.0) since Bun 1.0, and we've been working hard to make Bun more stable and more compatible with Node.js. We've fixed over a thousand bugs, added tons of new features and APIs, and now, Bun supports Windows!
## []()[Windows Support](bun-v1.1.html#windows-support)
You can now run Bun on Windows 10 and later! This is a huge milestone for us, and we're excited to bring Bun to a whole new group of developers.
Bun on Windows passes [98%](https://twitter.com/bunjavascript/status/1774036956474978507) of our own test suite for Bun on macOS and Linux. That means everything from the runtime, test runner, package manager, bundler — it all works on Windows.
To get started with Bun on Windows, run the following command in your terminal:
```
powershell -c "irm bun.sh/install.ps1 | iex"
```
### []()[`bun install` on Windows](bun-v1.1.html#bun-install-on-windows)
Bun has a built-in, npm-compatible package manager that installs packages. When installing a Vite React App, `bun install` runs 18x faster than `yarn` and 30x faster than `npm` on Windows.
[](../images/bun-install-on-windows.png)
Time spent installing dependencies in a vite react app using \`--ignore-scripts\` on Windows.
### []()[`bun run` on Windows](bun-v1.1.html#bun-run-on-windows)
You can also run scripts using `bun run`, which is a faster alternative to `npm run`. To make `bun run` even faster on Windows, we engineered a new file-format: `.bunx`.
The `.bunx` file is a cross-filesystem symlink that is able to start scripts or executables using Bun or Node.js. We decided to create this for several reasons:
- Symlinks are not guaranteed to work on Windows.
- Shebangs at the top of a file (`#!/usr/bin/env bun`) are not read on Windows.
- We want to avoid creating three permutations of each executable: `.cmd`, `.sh`, and `.ps1`.
- We want to avoid confusing "Terminate batch job? (Y/n)" prompts.
The end result is that `bun run` is 11x faster than `npm run`, and `bunx` is also 11x faster than `npx`.
[](../images/bun-run-on-windows.png)
Time spent running \`bunx cowsay\` vs \`npx cowsay\` on Windows.
Even if you only use Bun as a package manager and not a runtime, `.bunx` just works with Node.js. This also solves the annoying "Terminate batch job?" prompt that Windows developers are used to when sending ctrl-c to a running script.
[](../images/terminate-batch-job-bun.gif)
[](../images/terminate-batch-job-npm.gif)
### []()[`bun --watch` on Windows](bun-v1.1.html#bun-watch-on-windows)
Bun has built-in support `--watch` mode. This gives you a fast iteration cycle between making changes and having those changes affect your code. On Windows, we made to sure to optimize the time it takes between control-s and process reload.
[](../images/bun-test-watch-windows.gif)
On the left, making changes to a test file. On the right, \`bun test --watch\` on Windows.
### []()[Node.js APIs on Windows](bun-v1.1.html#node-js-apis-on-windows)
We've also spent time optimizing Node.js APIs to use the fastest syscalls available on Windows. For example, [`fs.readdir()`](https://nodejs.org/api/fs.html#fsreaddirpath-options-callback) on Bun is [58% faster](https://twitter.com/jarredsumner/status/1745742065647132748) than Node.js on Windows.
[](../images/fs-readdir-windows.png)
Time spent listing files in a directory, 1000 times on Windows.
While we haven't optimized *every* API, if you notice something on Windows that is slow or slower than Node.js, [file an issue](../issues.html) and we will figure out how to make it faster.
## []()[Bun is a JavaScript runtime](bun-v1.1.html#bun-is-a-javascript-runtime)
Windows support is just one anecdote when compared to the dozens of new features, APIs, and improvements we've made since Bun 1.0.
### []()[Large projects start 2x faster](bun-v1.1.html#large-projects-start-2x-faster)
Bun has built-in support for JavaScript, TypeScript, and JSX, powered by Bun's very own transpiler written in highly-optimized native code.
Since Bun 1.0, we've implemented a content-addressable cache for files larger than 50KB to avoid the performance overhead of transpiling the same files repeatedly.
This makes command-line tools, like `tsc`, run up to [2x faster](bun-v1.0.15.html#transpiler-cache-makes-clis-like-tsc-up-to-2x-faster) than in Bun 1.0.
[](../images/tsc-2x-faster.png)
Time spent running \`tsc --help\` in Bun and Node.js.
### []()[The Bun Shell](bun-v1.1.html#the-bun-shell)
Bun is now a cross-platform shell — like bash, but also on Windows.
JavaScript is the world's most popular scripting language. So, why is running shell scripts so complicated?
```
import { spawnSync } from "child_process";
// this is a lot more work than it could be
const { status, stdout, stderr } = spawnSync("ls", ["-l", "*.js"], {
encoding: "utf8",
});
```
Different platforms also have different shells, each with slightly different syntax rules, behavior, and even commands. For example, if you want to run a shell script using `cmd` on Windows:
- `rm -rf` doesn't work.
- `FOO=bar <command>` doesn't work.
- `which` doesn't exist. (it's called `where` instead)
The [Bun Shell](../docs/runtime/shell.html) is a lexer, parser, and interpreter that implements a bash-like programming language, along with a selection of core utilities like `ls`, `rm`, and `cat`.
The shell can also be run from JavaScript and TypeScript, using the `Bun.$` API.
```
import { $ } from "bun";
// pipe to stdout:
await $`ls *.js`;
// pipe to string:
const text = await $`ls *.js`.text();
```
The syntax makes it easy to pass arguments, buffers, and pipes between the shell and JavaScript.
```
const response = await fetch("https://example.com/");
// pipe a response as stdin,
// pipe the stdout back to JavaScript:
const stdout = await $`gzip -c < ${response}`.arrayBuffer();
```
Variables are also escaped to prevent command injection.
```
const filename = "foo.js; rm -rf /";
// ls: cannot access 'foo.js; rm -rf /':
// No such file or directory
await $`ls ${filename}`;
```
You can run shell scripts using the Bun Shell by running `bun run`.
```
bun run my-script.sh
```
The Bun Shell is enabled by default on Windows when running `package.json` scripts with `bun run`. To learn more, check out the [documentation](../docs/runtime/shell.html) or the announcement [blog post](the-bun-shell.html).
### []()[`Bun.Glob`](bun-v1.1.html#bun-glob)
Bun now has a built-in [Glob API](../docs/api/glob.html) for matching files and strings using glob patterns. It's similar to popular Node.js libraries like `fast-glob` and `micromatch`, except it matches strings [3x faster](bun-v1.0.14.html#bun-glob).
Use `glob.match()` to match a string against a glob pattern.
```
import { Glob } from "bun";
const glob = new Glob("**/*.ts");
const match = glob.match("src/index.ts"); // true
```
Use `glob.scan()` to list files that match a glob pattern, using an `AsyncIterator`.
```
const glob = new Glob("**/*.ts");
for await (const path of glob.scan("src")) {
console.log(path); // "src/index.ts", "src/utils.ts", ...
}
```
### []()[`Bun.Semver`](bun-v1.1.html#bun-semver)
Bun has a new [Semver API](../docs/api/semver.html) for parsing and sorting semver strings. It's similar to the popular `node-semver` package, except it's [20x faster](https://twitter.com/jarredsumner/status/1722225679570473173).
Use `semver.satisfies()` to check if a version satisfies a range.
```
import { semver } from "bun";
semver.satisfies("1.0.0", "^1.0.0"); // true
semver.satisfies("1.0.0", "^2.0.0"); // false
```
Use `semver.order()` to compare two versions, or sort an array of versions.
```
const versions = ["1.1.0", "0.0.1", "1.0.0"];
versions.sort(semver.order); // ["0.0.1", "1.0.0", "1.1.0"]
```
### []()[`Bun.stringWidth()`](bun-v1.1.html#bun-stringwidth)
Bun also supports a new string-width API for measuring the visible width of a string in a terminal. This is useful when you want to know how many columns a string will take up in a terminal.
It's similar to the popular `string-width` package, except it's [6000x faster](bun-v1.0.29.html#bun-stringwidth-6-756x-faster-string-width-replacement).
```
import { stringWidth } from "bun";
stringWidth("hello"); // 5
stringWidth("👋"); // 2
stringWidth("你好"); // 4
stringWidth("👩👩👧👦"); // 2
stringWidth("\u001b[31mhello\u001b[39m"); // 5
```
It supports ANSI escape codes, fullwidth characters, graphemes, and emojis. It also supports Latin1, UTF-16, and UTF-8 encodings, with optimized implementations for each.
### []()[`server.url`](bun-v1.1.html#server-url)
When you create an HTTP server using `Bun.serve()`, you can now get the URL of the server using the `server.url` property. This is useful for getting the formatted URL of a server in tests.
```
import { serve } from "bun";
const server = serve({
port: 0, // random port
fetch(request) {
return new Response();
},
});
console.log(`${server.url}`); // "http://localhost:1234/"
```
### []()[`server.requestIP()`](bun-v1.1.html#server-requestip)
You can also get the IP address of a HTTP request using the `server.requestIP()` method. This does not read headers like `X-Forwarded-For` or `X-Real-IP`. It simply returns the IP address of the socket, which may correspond to the IP address of a proxy.
```
import { serve } from "bun";
const server = serve({
port: 0,
fetch(request) {
console.log(server.requestIP(request)); // "127.0.0.1"
return new Response();
},
});
```
### []()[`subprocess.resourceUsage()`](bun-v1.1.html#subprocess-resourceusage)
When you spawn a subprocess using `Bun.spawn()`, you can now access the CPU and memory usage of a process using the `resourceUsage()` method. This is useful for monitoring the performance of a process.
```
import { spawnSync } from "bun";
const { resourceUsage } = spawnSync([
"bun",
"-e",
"console.log('Hello world!')",
]);
console.log(resourceUsage);
// {
// cpuTime: { user: 5578n, system: 4488n, total: 10066n },
// maxRSS: 22020096,
// ...
// }
```
### []()[`import.meta.env`](bun-v1.1.html#import-meta-env)
Bun now supports environment variables using `import.meta.env`. It's an alias of [`process.env`](https://nodejs.org/api/process.html#processenv) and `Bun.env`, and exists for compatibility with other tools in the JavaScript ecosystem, such as Vite.
```
import.meta.env.NODE_ENV; // "development"
```
## []()[Node.js compatibility](bun-v1.1.html#node-js-compatibility)
Bun aims to be a drop-in replacement for Node.js.
Node.js compatibility continues to remain a top priority for Bun. We've made a lot of improvements and fixes to Bun's support for Node.js APIs. Here are some of the highlights:
### []()[HTTP/2 client](bun-v1.1.html#http-2-client)
Bun now supports the [`node:http2`](https://nodejs.org/api/http2.html#http2) client APIs, which allow you to make outgoing HTTP/2 requests. This also means you can also use packages like `@grpc/grpc-js` to send gRPC requests over HTTP/2.
```
import { connect } from "node:http2";
const client = connect("https://example.com/");
const request = client.request({ ":path": "/" });
request.on("response", (headers, flags) => {
for (const name in headers) {
console.log(`${name}: ${headers[name]}`);
// "cache-control: max-age=604800", ...
}
});
request.on("end", () => {
client.close();
});
request.end();
```
We're still working on adding support for the HTTP/2 server, you can track our progress in this [issue](https://github.com/oven-sh/bun/issues/8823).
### []()[`Date.parse()` compatible with Node.js](bun-v1.1.html#date-parse-compatible-with-node-js)
Bun uses [JavaScriptCore](https://docs.webkit.org/Deep%20Dive/JSC/JavaScriptCore.html) as its JavaScript engine, as opposed to Node.js which uses [V8](https://v8.dev/). [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) parsing is complicated, and its behaviour varies greatly between engines.
For example, in Bun 1.0 the following `Date` would work in Node.js, but not in Bun:
```
const date = "2020-09-21 15:19:06 +00:00";
Date.parse(date); // Bun: Invalid Date
Date.parse(date); // Node.js: 1600701546000
```
To fix these inconsistencies, we ported the `Date` parser from V8 to Bun. This means that `Date.parse` and `new Date()` behave the same in Bun as it does in Node.js.
### []()[Recursive `fs.readdir()`](bun-v1.1.html#recursive-fs-readdir)
In Bun 1.0, we did not have support for the `recursive` option in [`fs.readdir()`](https://nodejs.org/api/fs.html#fsreaddirpath-options-callback). This was an oversight and caused subtle bugs with many packages.
Not only did we add support for the `recursive` option, but we also made is 22x faster than Node.js.
[](../images/fs-readdir-recursive.png)
Time spent listing files using recursive \`fs.readdir()\` in a large directory.
### []()[IPC support between Bun and Node.js](bun-v1.1.html#ipc-support-between-bun-and-node-js)
You can now send IPC messages between Bun and Node.js processes using the `ipc` option. This also fixed a bug that would have caused Bun to hang when using Next.js 14.1.
```
if (typeof Bun !== "undefined") {
const prefix = `[bun ${process.versions.bun} 🐇]`;
const node = Bun.spawn({
cmd: ["node", __filename],
ipc({ message }) {
console.log(message);
node.send({ message: `${prefix} 👋 hey node` });
node.kill();
},
stdio: ["inherit", "inherit", "inherit"],
serialization: "json",
});
node.send({ message: `${prefix} 👋 hey node` });
} else {
const prefix = `[node ${process.version}]`;
process.on("message", ({ message }) => {
console.log(message);
process.send({ message: `${prefix} 👋 hey bun` });
});
}
```
### []()[Undocumented Node.js APIs](bun-v1.1.html#undocumented-node-js-apis)
Node.js has *lots* of undocumented APIs that you wouldn't find from reading its documentation.
There are millions of npm packages, inevitably some of them will depend on obscure or undocumented APIs. Instead of leaving these packages to be broken or forgotten, we actually add these APIs to Bun so you don't need to rewrite your code.
For example, [`ServerResponse`](https://nodejs.org/api/http.html#class-httpserverresponse) has an undocumented `_headers` property that allows the HTTP headers to be modified as an object.
```
import { createServer } from "node:http";
createServer((req, res) => {
const { _headers } = res;
delete _headers["content-type"];
res._implicitHeader();
res.end();
});
```
This API was used in recent Astro release, which we then fixed in Bun. There was also an `_implicitHeader()` function, which was used by Express, and we also fixed that.
### []()[So much more](bun-v1.1.html#so-much-more)
There's also a ton of other Node.js APIs that we've either added or fixed, including:
ModuleAPIs*Top-level*Added [`import.meta.filename`](https://nodejs.org/api/esm.html#importmetafilename), [`import.meta.dirname`](https://nodejs.org/api/esm.html#importmetadirname), [`module.parent`](https://nodejs.org/api/modules.html#moduleparent)[`process`](https://nodejs.org/api/process.html)Added [`getReport()`](https://nodejs.org/api/process.html#processreport), `binding("tty_wrap")`[`node:util`](https://nodejs.org/api/util.html)Added [`domainToASCII()`](https://nodejs.org/api/url.html#urldomaintoasciidomain), [`domainToUnicode()`](https://nodejs.org/api/url.html#urldomaintounicodedomain), and [`styleText()`](https://nodejs.org/api/util.html#utilstyletextformat-text). Changed [`inspect()`](https://nodejs.org/api/util.html#utilinspectobject-options) to be more consistent with Node.js[`node:crypto`](https://nodejs.org/api/crypto.html)Added [`KeyObject`](https://nodejs.org/api/crypto.html#static-method-keyobjectfromkey), [`createPublicKey()`](https://nodejs.org/api/crypto.html#cryptocreatepublickeykey), [`createPrivateKey()`](https://nodejs.org/api/crypto.html#cryptocreateprivatekeykey),[`generateKeyPair()`](https://nodejs.org/api/crypto.html#cryptogeneratekeypairtype-options), [`generateKey()`](https://nodejs.org/api/crypto.html#cryptogeneratekeytype-options), [`sign()`](https://nodejs.org/api/crypto.html#signsignprivatekey-outputencoding), [`verify()`](https://nodejs.org/api/crypto.html#verifyverifyobject-signature-signatureencoding), and more[`node:fs`](https://nodejs.org/api/fs.html)Added [`openAsBlob()`](https://nodejs.org/api/fs.html#fsopenasblobpath-options), [`opendir()`](https://nodejs.org/api/fs.html#fsopendirpath-options-callback), [`fdatasync()`](https://nodejs.org/api/fs.html#fsfdatasyncfd-callback). Fixed [`FileHandle`](https://nodejs.org/api/fs.html#class-filehandle) not being returned with various APIs[`node:console`](https://nodejs.org/api/console.html)Added [`Console`](https://nodejs.org/api/console.html#class-console)[`node:dns`](https://nodejs.org/api/dns.html)Added [`lookupService()`](https://nodejs.org/api/dns.html#dnslookupserviceaddress-port-callback)[`node:http`](https://nodejs.org/api/http.html)Unix domain sockets via [`request()`](https://nodejs.org/api/http.html#httprequesturl-options-callback)[`node:events`](https://nodejs.org/api/events.html)Added [`on()`](https://nodejs.org/api/events.html#eventsonemitter-eventname-options)[`node:path`](https://nodejs.org/api/path.html)Fixed many bugs with Windows paths.[`node:vm`](https://nodejs.org/api/vm.html)Added [`createScript()`](https://nodejs.org/api/vm.html#vm-executing-javascript)[`node:os`](https://nodejs.org/api/os.html)Added [`availableParallelism()`](https://nodejs.org/api/os.html#os_os_availableparallelism)
## []()[Web APIs](bun-v1.1.html#web-apis)
Bun also supports the Web standard APIs, including [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) and [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response). This makes it easier to write code that works in both the browser and Bun.
Since Bun 1.0, we've made a lot of improvements and fixes to the Web APIs.
### []()[`WebSocket` is stable](bun-v1.1.html#websocket-is-stable)
Previously, [`WebSocket`](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/WebSocket) was marked as experimental due to protocol bugs, such as early disconnects and fragmentation issues.
In Bun 1.1, `WebSocket` is now stable and passes the industry-standard [Autobahn](https://www.google.com/search?q=autobahn%20websocket&sourceid=chrome&ie=UTF-8) conformance test suite. This fixes [dozens](https://github.com/oven-sh/bun/issues/6686) of bugs the `WebSocket` client and makes it more reliable for production use.
```
const ws = new WebSocket("wss://echo.websocket.org/");
ws.addEventListener("message", ({ data }) => {
console.log("Received:", data);
});
ws.addEventListener("open", () => {
ws.send("Hello!");
});
```
### []()[`performance.mark()`](bun-v1.1.html#performance-mark)
Bun now supports the [user-timings](https://developer.mozilla.org/en-US/docs/Web/API/Performance_API/User_timing) APIs, which includes APIs like `performance.mark()` and `performance.measure()`. This is useful for measuring the performance of your application.
```
performance.mark("start");
while (true) {
// ...
}
performance.mark("end");
performance.measure("task", "start", "end");
```
### []()[`fetch()` using Brotli compression](bun-v1.1.html#fetch-using-brotli-compression)
You can now use [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/fetch) to make requests with the `br` encoding. This is useful for making requests to servers that support Brotli compression.
```
const response = await fetch("https://example.com/", {
headers: {
"Accept-Encoding": "br",
},
});
```
### []()[`URL.canParse()`](bun-v1.1.html#url-canparse)
Bun now supports the recently-added [`URL.canParse()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/canParse_static) API. This makes it possible to check if a string is a valid URL without throwing an error.
```
URL.canParse("https://example.com:8080/"); // true
URL.canParse("apoksd!"); // false
```
### []()[`fetch()` over Unix sockets](bun-v1.1.html#fetch-over-unix-sockets)
Bun now supports sending [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/fetch) requests over a Unix socket.
```
const response = await fetch("http://localhost/info", {
unix: "/var/run/docker.sock",
});
const { ID } = await response.json();
console.log("Docker ID:", ID); // <uuid>
```
While this not an API that browsers will support, it's useful for server-side applications that need to communicate with services over a Unix socket, like the Docker daemon.
### []()[`Response` body as an `AsyncIterator`](bun-v1.1.html#response-body-as-an-asynciterator)
You can now pass an [`AsyncIterator`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncIterator) to the [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response/Response) constructor. This is useful for streaming data from a source that doesn't support `ReadableStream`.
```
const response = new Response({
async *[Symbol.asyncIterator]() {
yield "Hello, ";
yield Buffer.from("world!");
},
});
await response.text(); // "Hello, world!"
```
This is a non-standard extension to the `fetch()` API that Node.js supported, and was added to Bun for compatibility reasons.
### []()[Other changes](bun-v1.1.html#other-changes)
- Implemented [`console.table()`](https://developer.mozilla.org/en-US/docs/Web/API/console/table_static), [`console.timeLog()`](https://developer.mozilla.org/en-US/docs/Web/API/console/timelog_static)
- Supported `ignoreBOM` in [`TextEncoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder/TextEncoder)
## []()[Bun is an npm-compatible package manager](bun-v1.1.html#bun-is-an-npm-compatible-package-manager)
Even if you don't use Bun as a runtime, you can still use `bun install` as a package manager. Bun is an npm-compatible package manager that installs packages up to 29x faster than `npm`.
Since Bun 1.0, we have significantly improved the stability and performance of `bun install`. We've fixed hundreds of bugs, added new features, and improved the overall developer experience.
### []()[Lifecycle scripts](bun-v1.1.html#lifecycle-scripts)
If you ran into a bug using `bun install` in Bun 1.0, chances are it was related to lifecycle scripts. [Lifecycle scripts](https://docs.npmjs.com/cli/v10/using-npm/scripts#life-cycle-scripts) are scripts that run during the installation of a package, such as `postinstall`.
In Bun 1.1, we've fixed many of those bugs and completely overhauled how lifecycle scripts work.
#### Lifecycle scripts on Windows
On Windows, lifecycle scripts use the Bun Shell. That means you don't need helper libraries like:
- `rimraf`
- `cross-env`
- `node-which`
### []()[`trustedDependencies`](bun-v1.1.html#trusteddependencies)
By default, Bun does not run lifecycle scripts for packages that are not trusted. This is a security feature to prevent malicious scripts from running on your machine. Bun will only run scripts that are defined in the [`trustedDependencies`](../guides/install/trusted.html) list in your `package.json`.
When you first add a package, Bun will tell you if the package had a lifecycle script that did not run.
```
bun add v1.1.0
Saved lockfile
installed @biomejs/biome@1.6.1 with binaries:
- biome
1 package installed [55.00ms]
Blocked 1 postinstall. Run `bun pm untrusted` for details.
```
### []()[`bun pm untrusted`](bun-v1.1.html#bun-pm-untrusted)
If you want to see which scripts were blocked, you can run `bun pm untrusted`.
```
bun pm untrusted v1.1.0
./node_modules/@biomejs/biome @1.6.1
» [postinstall]: node scripts/postinstall.js
These dependencies had their lifecycle scripts blocked during install.
If you trust them and wish to run their scripts, use `bun pm trust`.
```
### []()[`bun pm trust`](bun-v1.1.html#bun-pm-trust)
If you trust the package, you can run `bun pm trust [package]`. If you want to trust every package, you can also run `bun pm trust --all`.
```
bun pm trust v1.1.0
./node_modules/@biomejs/biome @1.6.1
✓ [postinstall]: node scripts/postinstall.js
1 script ran across 1 package [71.00ms]
```
### []()[`bun add --trust`](bun-v1.1.html#bun-add-trust)
If you already know you want to trust a dependency, you can add it using `bun add --trust [package]`. This will add the package and it's transitive dependencies to your `trustedDependencies` list so you don't need to run `bun pm trust` for that package.
```
{
"dependencies": {
"@biomejs/biome": "1.6.1"
},
"trustedDependencies": [
"@biomejs/biome"
]
}
```
Bun includes a default allowlist of popular packages containing lifecycle scripts that are known to be safe. You can see the full list by running `bun pm default-trusted`.
Also, to reduce the performance impact of lifecycle scripts, we've made them run in parallel. This means that lifecycle scripts will run concurrently, which reduces the time it takes to install packages.
[](https://github.com/oven-sh/bun/assets/709451/4ad72f2f-6152-4e4e-b1d1-d832cefdd8f8)
### []()[`bun pm migrate`](bun-v1.1.html#bun-pm-migrate)
Bun uses a binary lockfile, `bun.lockb`, for faster installs with `bun install`.
You can now run `bun pm migrate` to convert a `package-lock.json` file to a `bun.lockb` file. This is useful if you want to do a one-time migration from npm to Bun.
```
bun pm migrate
```
```
[5.67ms] migrated lockfile from package-lock.json
21 packages installed [54.00ms]
```
You don't need to run this command if you're using `bun install`, as it will automatically migrate the lockfile if it detects a `package-lock.json` file.
## []()[Bun is a JavaScript bundler](bun-v1.1.html#bun-is-a-javascript-bundler)
Bun is a JavaScript and TypeScript bundler, transpiler, and minifier that can be used to bundle code for the browser, Node.js, and other platforms.
### []()[`bun build --target=node`](bun-v1.1.html#bun-build-target-node)
Bun can bundle code to run on Node.js using the `--target=node` flag.
```
var { promises } = require("node:fs");
var { join } = require("node:path");
promises.readFile(join(__dirname, "data.txt"));
```
In Bun 1.0, there were several bugs that prevented this from working correctly, such as not being able to require built-in modules like `node:fs` and `node:path`. Here's what that looked like in Bun 1.0:
```
bun-1.0 build --target=node app.ts --outfile=dist.mjs
```
```
node dist.mjs
```
```
TypeError: (intermediate value).require is not a function
at __require (file:///app.mjs:2:22)
at file:///app.mjs:7:20
at ModuleJob.run (node:internal/modules/esm/module_job:218:25)
at async ModuleLoader.import (node:internal/modules/esm/loader:329:24)
at async loadESM (node:internal/process/esm_loader:28:7)
at async handleMainPromise (node:internal/modules/run_main:113:12)
```
In Bun 1.1, these bugs have now been fixed.
```
bun build --target=node app.ts --outfile=dist.mjs
```
```
node dist.mjs
```
### []()[`bun build --compile`](bun-v1.1.html#bun-build-compile)
Bun can compile TypeScript and JavaScript files to a single-file executable using the `--compile` flag.
```
bun build --compile app.ts
```
```
./app
```
```
Hello, world!
```
In Bun 1.1, you can also embed NAPI (n-api) addons `.node` files. This is useful for bundling native Node.js modules, like `@anpi-rs/canvas`.
```
import { promises } from "fs";
import { createCanvas } from "@napi-rs/canvas";
const canvas = createCanvas(300, 320);
const data = await canvas.encode("png");
await promises.writeFile("empty.png", data);
```
Then you can compile and run your application as a single-file executable.
```
bun build --compile canvas.ts
```
```
./canvas # => simple.png
```
### []()[Macros](bun-v1.1.html#macros)
Bun has a powerful macro system that allows you to transform your code at compile-time. Macros can be used to generate code, optimize code, and even run code at compile-time.
In Bun 1.1, you can now import built-in modules at bundle-time.
#### Read a file into a string at bundle-time
```
import { readFileSync } from "node:fs"
with { type: "macro" };
export const contents = readFileSync("hello.txt", "utf8");
```
#### Spawn a process at bundle-time
```
import { spawnSync } from "node:child_process"
with { type: "macro" };
const result = spawnSync("echo", ["Hello, world!"], {encoding: "utf-8"}).stdout;
console.log(result); // "Hello, world!"
```
## []()[Bun is a test runner](bun-v1.1.html#bun-is-a-test-runner)
Bun has a built-in test module that makes it easy to write and run tests in JavaScript, TypeScript, and JSX. It supports the same APIs as Jest, which includes the [`expect()`](https://jestjs.io/docs/expect#expectvalue)-style APIs.
### []()[Matchers](bun-v1.1.html#matchers)
Matchers are assertions that you can use to test your code. Since Bun 1.0, we've added dozens of new `expect()` matchers, including:
```
import { expect } from "bun:test";
expect.hasAssertions();
expect.assertions(9);
expect({}).toBeObject();
expect([{ foo: "bar" }]).toContainEqual({ foo: "bar" });
expect(" foo ").toEqualIgnoringWhitespace("foo");
expect("foo").toBeOneOf(["foo", "bar"]);
expect({ foo: Math.PI }).toEqual({ foo: expect.closeTo(3.14) });
expect({ a: { b: 1 } }).toEqual({ a: expect.objectContaining({ b: 1 }) });
expect({ a: Promise.resolve("bar") }).toEqual({ a: expect.resolvesTo("bar") });
expect({ b: Promise.reject("bar") }).toEqual({ b: expect.rejectsTo("bar") });
expect.unreachable();
```
### []()[Custom matchers with `expect.extend()`](bun-v1.1.html#custom-matchers-with-expect-extend)
If there's a matcher that Bun doesn't support, you can create your own using [`expect.extend()`](https://jestjs.io/docs/expect#expectextendmatchers). This is useful when you want to define a custom matcher that is reusable across multiple tests.
```
import { test, expect } from "bun:test";
expect.extend({
toBeWithinRange(received, floor, ceiling) {
const pass = received >= floor && received <= ceiling;
if (pass) {
return {
message: () =>
`Expected ${received} not to be within range ${floor} - ${ceiling}`,
pass: true,
};
} else {
return {
message: () =>
`Expected ${received} to be within range ${floor} - ${ceiling}`,
pass: false,
};
}
},
});
test("toBeWithinRange()", () => {
expect(1).toBeWithinRange(1, 99); // ✅
expect(100).toBeWithinRange(1, 99); // ❌ Expected 100 to be within range 1 - 99
});
```
### []()[Module mocking](bun-v1.1.html#module-mocking)
Bun now supports module mocking.
- Unlike Jest, Bun is able to mock both ESM and CommonJS modules.
- If a module has already been imported, Bun is able to update the module *in-place*, which means that mocks work at runtime. Other test runners can't do this, since they set mocks at build time.
- You can override anything: local files, npm packages, and built-in modules.
file.js
package.js
built-in.js
file.js
```
import { mock, test, expect } from "bun:test";
import { fn } from "./mock";
test("mocking a local file", async () => {
mock.module("./mock", () => {
return {
fn: () => 42,
};
});
// fn is already imported, so it will be updated in-place
expect(fn()).toBe(42);
// also works with cjs
expect(require("./mock").fn()).toBe(42);
});
```
package.js
```
import { mock, test, expect } from "bun:test";
import stringWidth from "string-width";
test("mocking an npm package", async () => {
mock.module("string-width", () => {
return {
default: Bun.stringWidth,
};
});
const string = "hello";
expect(stringWidth()).toBe(5);
expect(require("string-width")()).toBe(5);
});
```
built-in.js
```
import { mock, test, expect } from "bun:test";
import { readFileSync } from "node:fs";
test("mocking a built-in module", async () => {
mock.module("node:fs", () => {
return {
readFileSync: () => "mocked!",
};
});
expect(readFileSync("./foo.txt")).toBe("mocked!");
expect(require("fs").readFileSync("./bar.txt")).toBe("mocked!");
});
```
## []()[Bun has built-in support for SQLite](bun-v1.1.html#bun-has-built-in-support-for-sqlite)
Since 1.0, Bun has had built-in support for [SQLite](https://www.sqlite.org/). It has an API that's inspired by `better-sqlite3`, but is written in native code to be faster.
```
import { Database } from "bun:sqlite";
const db = new Database(":memory:");
const query = db.query("select 'Bun' as runtime;");
query.get(); // { runtime: "Bun" }
```
Since then, there's been lots of new features and improvements to `bun:sqlite`.
### []()[Multi-statement queries](bun-v1.1.html#multi-statement-queries)
We've added support for multi-statement queries, which allows multiple SQL statements to be run in a single call to `run()` or `exec()` delimited by a `;`.
```
import { Database } from "bun:sqlite";
const db = new Database(":memory:");
db.run(`
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT
);
INSERT INTO users (name) VALUES ("Alice");
INSERT INTO users (name) VALUES ("Bob");
`);
```
### []()[Detailed errors](bun-v1.1.html#detailed-errors)
When an error is thrown from `bun:sqlite`, you'll now see more detailed errors, including the table and column name. In Bun 1.0, the error message was terse and did not contain extra details.
```
- error: constraint failed
+ SQLiteError: UNIQUE constraint failed: foo.bar
+ errno: 2067
+ code: "SQLITE_CONSTRAINT_UNIQUE"
at run (bun:sqlite:185:11)
at /index.js:7:1
```
### []()[Import databases](bun-v1.1.html#import-databases)
In Bun 1.1, you can now import a SQLite database using the `import` syntax. This uses the new [import attributes](https://nodejs.org/api/esm.html#import-attributes) feature to specify the type of import.
```
import db from "./users.db"
with { type: "sqlite" };
const { n } = db
.query("SELECT COUNT(id) AS n FROM users")
.get();
console.log(`Found ${n} users!`); // "Found 42 users!"
```
### []()[Embed databases](bun-v1.1.html#embed-databases)
You can also compile your application and SQLite database into a [single-file executable](../docs/bundler/executables.html#sqlite). To enable this, specify the `embed` property on the import, then use `bun build --compile` to build your app.
```
import db from "./users.db"
with { type: "sqlite", embed: "true" };
```
```
bun build --compile ./app.ts
```
```
./app
```
```
Found 42 users!
```
## []()[Bun makes JavaScript simpler](bun-v1.1.html#bun-makes-javascript-simpler)
We spent a lot of time thinking about the developer experience in Bun. We want to make it easy to write, run, and debug JavaScript and TypeScript code.
There are tons of improvements to commands, output, and error messages to make Bun easier to use.
### []()[Syntax-highlighted errors](bun-v1.1.html#syntax-highlighted-errors)
When an error is thrown in Bun, it prints a stack trace to the console with a multi-line source code preview. Now that source code preview gets syntax highlighted, which makes it easier to read.
[](https://github.com/oven-sh/bun/assets/709451/a95254d0-2652-433c-80e7-7faac1e38c2a)
A preview of errors with and without syntax highlighting.
### []()[Simplified stack traces](bun-v1.1.html#simplified-stack-traces)
Stack traces from `Error.stack` now include less noise, such as internal functions that are not relevant to the error. This makes it easier to see where the error occurred.
```
1 | throw new Error("Oops");
^
error: Oops
at /oops.js:1:7
at globalThis (/oops.js:3:14)
at overridableRequire (:1:20)
at /index.js:3:8
at globalThis (/index.js:3:8)
```
### []()[`bun --eval`](bun-v1.1.html#bun-eval)
You can run `bun --eval`, or `bun -e` for short, to evaluate a script without creating a file. Just like the rest of Bun, it supports top-level await, ESM, CommonJS, TypeScript, and JSX.
You can pass the script as a string.
```
bun -e 'console.log(Bun.version)'
```
```
1.1.0
```
Or you can pipe the script through stdin using `bun -`.
```
echo 'console.log(await fetch("https://example.com/"))' | bun -
```
```
Response (1.26 KB) {
status: 200, ...
}
```
### []()[`bun --print`](bun-v1.1.html#bun-print)
You can also use `bun --print`, which is the same as `bun -e`, except it prints the last statement using `console.log()`.
```
bun --print 'await Bun.file("package.json").json()'
```
```
{
name: "bun",
dependencies: { ... },
}
```
You can also omit `await` since Bun will detect dangling promises.
```
bun --print 'fetch("https://example.com/").then(r => r.text())'
```
```
<!DOCTYPE html>
...
```
### []()[`bun --env-file`](bun-v1.1.html#bun-env-file)
Bun detects and loads [`.env`](../docs/runtime/env.html) files by default, but now you can use `bun --env-file` to load a custom `.env` file. This is useful for testing different environments.
```
bun --env-file=custom.env src/index.ts
```
```
bun --env-file=.env.a --env-file=.env.b run build
```
You can use `--env-file` when running JavaScript files or when running package.json scripts.
## []()[Behaviour changes](bun-v1.1.html#behaviour-changes)
Bun 1.1 contains a few, minor tweaks in behaviour that you should be aware of, but we think are highly unlikely to break your code.
### []()[Longer network timeouts](bun-v1.1.html#longer-network-timeouts)
In Bun 1.0, the default network timeout for `fetch()` and `bun install` was 30 seconds.
Since [Bun 1.0.4](bun-v1.0.4.html#potentially-breaking-changes), the default network timeout has been increased to **5 minutes**. This aligns the default with Google Chrome and should help with high-latency connections.
You can also disable the timeout with `fetch()` using:
```
const response = await fetch("https://example.com/", {
timeout: false,
});
```
### []()[`Bun.write()` creates the parent directory](bun-v1.1.html#bun-write-creates-the-parent-directory)
Previously, `Bun.write()` would throw an error if the parent directory didn't exist.
```
import { write } from "bun";
await write("does/not/exist/hello.txt", "Hello!");
// ENOENT: No such file or directory
```
Since [Bun 1.0.16](bun-v1.0.16.html#bun-write-now-creates-the-parent-directory-if-it-doesn-t-exist), Bun will create the parent directory if it doesn't exist.
While this does not match the behaviour of APIs like `fs.writeFileSync()`, developers asked us to make this change so the API would be more intuituve to use and lead to a better developer experience.
Without this change, developers would have to write the following boilterplate code:
```
import { write } from "bun";
import { mkdir } from "node:fs/promises";
try {
await write("does/not/exist/hello.txt", "Hello!");
} catch (error) {
if (error.code === "ENOENT") {
await mkdir("does/not/exist", { recursive: true });
await write("does/not/exist/hello.txt", "Hello!");
} else {
throw error;
}
}
```
If you want to restore the old behavior, you can specify the `createPath` property.
```
import { write } from "bun";
await write("does/not/exist/hello.txt", "Hello, world!", { createPath: false });
// ENOENT: No such file or directory
```
### []()[Conditional exports does not include `worker`](bun-v1.1.html#conditional-exports-does-not-include-worker)
Packages can use [conditional exports](https://nodejs.org/api/packages.html#packages_conditional_exports) to specify different entry files for different environments. For example, a package might define a `browser` export for the browser and a `node` export for Node.js.
```
{
"exports": {
"node": "./node.js",
"browser": "./browser.js",
"worker": "./worker.js"
}
}
```
In Bun 1.0, Bun would select the first export using the following order: `bun`, `worker`, `node`.
In Bun 1.1, Bun will no longer select the `worker` export, since that is associated with [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API), which often assume a browser-like environment.
This change only applies when Bun is being used as a runtime, and fixes various bugs where a `worker` export would be selected before a more-applicable `node` export.
### []()[`NODE_ENV` is `undefined` by default](bun-v1.1.html#node-env-is-undefined-by-default)
In Node.js, [`process.env.NODE_ENV`](https://nodejs.org/en/learn/getting-started/nodejs-the-difference-between-development-and-production#nodejs-the-difference-between-development-and-production) is set to `undefined` by default.
Early in Bun's development, we set the default to be `development` which turned out to be a mistake. This is because developers often forget to set `NODE_ENV` to production, which can lead to development functionality being included in production builds.
In Bun 1.1, we changed the default `NODE_ENV` to `undefined` to match Node.js.
```
bun --print 'process.env.NODE_ENV'
```
```
undefined
```
```
NODE_ENV=development bun --print 'process.env.NODE_ENV'
```
```
development
```
### []()[`bun install [package]@latest`](bun-v1.1.html#bun-install-package-latest)
Previously, if you installed a package using the `latest` tag, it would write the literal string `latest` to your `package.json`. This was not intended and does not match the behavior of other package managers.
In Bun 1.1, the `latest` tag is resolved before being written to the `package.json`.
```
bun install lodash@latest
```
package.json
```
{
"dependencies": {
"lodash": "latest"
"lodash": "^4.17.21"
}
}
```
### []()[`Bun.$` rejects with non-zero exit code](bun-v1.1.html#bun-rejects-with-non-zero-exit-code)
The Bun shell was introduced in [Bun 1.0.24](bun-v1.0.24.html#bun-shell). When a subprocess exited, the promise resolved even if the exit code was non-zero.
```
import { $ } from "bun";
await $`cd /does/not/exist`;
// does not throw
```
This is often not the desired behavior, and would cause bugs to go unnoticed where a command failed but the promise resolved.
In Bun 1.1, the Bun shell will now reject with an error when the subprocess exits with a non-zero exit code.
```
import { $ } from "bun";
await $`cd /does/not/exist`;
// ShellError: cd /does/not/exist: No such file or directory
```
If you want to revert back to the previous behavior, you can call the `throws()` function.
```
import { $ } from "bun";
const { exitCode, stderr } = await $`cd /does/not/exist`.throws(false);
console.log(exitCode); // 1
console.log(stderr); // "cd: /does/not/exist: No such file or directory"
```
### []()[`import.meta.resolve()`](bun-v1.1.html#import-meta-resolve)
In Bun 1.0, [`import.meta.resolve()`](https://nodejs.org/api/esm.html#importmetaresolvespecifier) would asynchronously resolve to an absolute file path.
This matched the behavior of Node.js' original implementation. However, for Web API compatibility reasons, Node.js changed the API to be synchronous. And so, Bun has done the same.
```
import.meta.resolve("./foo.js"); // Before: Promise { "/path/to/foo.js" }
import.meta.resolve("./foo.js"); // After: "file:///path/to/foo.js"
```
## []()[A thousand bug fixes](bun-v1.1.html#a-thousand-bug-fixes)
Since Bun 1.0, we've fixed over a thousand bugs.
If you ran into an error using Bun 1.0, we'd encourage you to try again with Bun 1.1. And if there's still something we haven't fixed, please feel free to create a [new issue](../issues.html) or bump an existing one.
You can upgrade to Bun 1.1 with the following command:
```
bun upgrade
```
### []()[Notable fixes](bun-v1.1.html#notable-fixes)
Out of the thousands of bugs fixed, here are a few of the most common issues that you may have encountered, that have now been fixed.
- `Module not found` after running `bun install`.
- `WebSocket` errors or early disconnects.
- `Bun.file` would sometimes cause an `EBADF: Bad file descriptor` error.
- `bun install` would resolve an incorrect version if certain pre/post tags were present.
- `bun install --yarn` would sometimes generate invalid YAML.
- `Failed to start server. Is port in use?` inside Docker containers.
- `"pidfd_open(2)" system call is not supported` on Vercel and Google Cloud.
- `Bun.serve()` [not responding](https://github.com/oven-sh/bun/issues/3580) to HTTP requests with an `_` header.
- Listening to `0.0.0.0` would bind to IPv6 as well.
- `process.nextTick()` and `setImmediate()` would execute in a different order than Node.js.
## []()[Performance improvements](bun-v1.1.html#performance-improvements)
We are constantly making changes to Bun so it can be faster and more efficient. Follow [@bunjavascript](https://twitter.com/bunjavascript) to get the latest digest of "In the next version of Bun."
Here is a snippet of some of the performance improvements made since Bun 1.0:
- `Bun.write()` and `Bun.file().text()` are [3x faster](bun-v1.0.16.html#bun-write-and-bun-file-text-gets-3x-faster-under-concurrent-load) under concurrent load.
- `bunx esbuild` is [50x faster](bun-v1.0.17.html#bunx-esbuild-starts-50x-faster-than-npx-esbuild) than `npx esbuild`.
- `fs.cp()` and `fs.copyFile()` are [50% faster](bun-v1.0.34.html#50-faster-cross-mount-fs-cp-fs-copyfile-on-linux) on Linux across filesystems.
- `Bun.peek()` is [90x faster](bun-v1.0.19.html#bun-peek-gets-90x-faster) with a new implementation.
- `expect().toEqual()` is [100x faster](bun-v1.0.19.html#expect-map1-toequal-map2-gets-100x-faster) using `Map` and `Set` objects.
- `setTimeout()` and `setInterval()` are [4x faster](bun-v1.0.19.html#settimeout-setinterval-get-4x-higher-throughput) on Linux.
- `Bun.spawnSync()` is [50% faster](bun-v1.0.19.html#optimized-bun-spawnsync-for-large-input-on-linux) at buffering stdout on Linux.
- `node:http` is [14% faster](bun-v1.0.10.html#node-http-gets-14-faster) using a hello world benchmark.
- `fs.readdir()` is [40x faster](bun-v1.0.15.html#recursive-in-fs-readdir-is-40x-faster-than-node-js) than Node.js using the `recursive` option.
- `bun:sqlite` uses [4x less](bun-v1.0.21.html#bun-sqlite-uses-less-memory) memory.
- `fs.readlink()` uses [2x less](bun-v1.0.20.html#fs-readlink-uses-up-to-2x-less-memory) memory.
- `fs.stat()` uses [2x less](bun-v1.0.20.html#fs-stat-uses-up-to-2x-less-memory) memory.
- `FormData` uses [less memory](bun-v1.0.21.html#copy-on-write-file-uploads-on-linux) with copy-on-write file upload on Linux
## []()[Getting started](bun-v1.1.html#getting-started)
That's it — that's Bun 1.1, and this is still just the beginning for Bun.
We've made Bun faster, more reliable, fixed a thousand of bugs, added tons of new features and APIs, and now Bun supports Windows. To get started, run any of the following commands in your terminal.
### []()[Install Bun](bun-v1.1.html#install-bun)
curl
powershell
npm
brew
docker
curl
```
curl -fsSL https://bun.sh/install | bash
```
powershell
```
powershell -c "irm bun.sh/install.ps1 | iex"
```
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
```
### []()[Upgrade Bun](bun-v1.1.html#upgrade-bun)
```
bun upgrade
```
## []()[We're hiring](bun-v1.1.html#we-re-hiring)
We're hiring engineers, designers, and past or present contributors to JavaScript engines like V8, WebKit, Hermes, and SpiderMonkey to join our team in-person in San Francisco to build the future of JavaScript.
You can check out our [careers](../careers.html) page or send us an [email](mailto:jobs@bun.sh).
## []()[Thank you to 364 contributors!](bun-v1.1.html#thank-you-to-364-contributors)
Bun is free, open source, and MIT-licensed.
As such, that also means that we receive a wide range of open source contributions from the community. We'd like to thank everyone who has opened an issue, fixed a bug, or even contributed a feature.
- [@0x346e3730](https://github.com/0x346e3730)
- [@0xflotus](https://github.com/0xflotus)
- [@2hu12](https://github.com/2hu12)
- [@52](https://github.com/52)
- [@7f8ddd](https://github.com/7f8ddd)
- [@A-D-E-A](https://github.com/A-D-E-A)
- [@a4addel](https://github.com/a4addel)
- [@Aarav-Juneja](https://github.com/Aarav-Juneja)
- [@AaronDewes](https://github.com/AaronDewes)
- [@aarvinr](https://github.com/aarvinr)
- [@aayushbtw](https://github.com/aayushbtw)
- [@adrienbrault](https://github.com/adrienbrault)
- [@adtac](https://github.com/adtac)
- [@akash1412](https://github.com/akash1412)
- [@akumarujon](https://github.com/akumarujon)
- [@alangecker](https://github.com/alangecker)
- [@alexandertrefz](https://github.com/alexandertrefz)
- [@alexkates](https://github.com/alexkates)
- [@alexlamsl](https://github.com/alexlamsl)
- [@almmiko](https://github.com/almmiko)
- [@amartin96](https://github.com/amartin96)
- [@amt8u](https://github.com/amt8u)
- [@andyexeter](https://github.com/andyexeter)
- [@annervisser](https://github.com/annervisser)
- [@antongolub](https://github.com/antongolub)
- [@aquapi](https://github.com/aquapi)
- [@aralroca](https://github.com/aralroca)
- [@Arden144](https://github.com/Arden144)
- [@argosphil](https://github.com/argosphil)
- [@ArnaudBarre](https://github.com/ArnaudBarre)
- [@arturovt](https://github.com/arturovt)
- [@ashoener](https://github.com/ashoener)
- [@asilvas](https://github.com/asilvas)
- [@asomethings](https://github.com/asomethings)
- [@aszenz](https://github.com/aszenz)
- [@audothomas](https://github.com/audothomas)
- [@AugusDogus](https://github.com/AugusDogus)
- [@AvantaR](https://github.com/AvantaR)
- [@axlEscalada](https://github.com/axlEscalada)
- [@babarkhuroo](https://github.com/babarkhuroo)
- [@baboon-king](https://github.com/baboon-king)
- [@bdenham](https://github.com/bdenham)
- [@BeeMargarida](https://github.com/BeeMargarida)
- [@benjervis](https://github.com/benjervis)
- [@BeyondMagic](https://github.com/BeyondMagic)
- [@bh1337x](https://github.com/bh1337x)
- [@birkskyum](https://github.com/birkskyum)
- [@bjon](https://github.com/bjon)
- [@blimmer](https://github.com/blimmer)
- [@booniepepper](https://github.com/booniepepper)
- [@brablc](https://github.com/brablc)
- [@bradymadden97](https://github.com/bradymadden97)
- [@brettgoulder](https://github.com/brettgoulder)
- [@brianknight10](https://github.com/brianknight10)
- [@BrookJeynes](https://github.com/BrookJeynes)
- [@brookslybrand](https://github.com/brookslybrand)
- [@Brooooooklyn](https://github.com/Brooooooklyn)
- [@browner12](https://github.com/browner12)
- [@bru02](https://github.com/bru02)
- [@buffaybu](https://github.com/buffaybu)
- [@buhrmi](https://github.com/buhrmi)
- [@Cadienvan](https://github.com/Cadienvan)
- [@camero2734](https://github.com/camero2734)
- [@capaj](https://github.com/capaj)
- [@cdfzo](https://github.com/cdfzo)
- [@cena-ko](https://github.com/cena-ko)
- [@cfal](https://github.com/cfal)
- [@CGQAQ](https://github.com/CGQAQ)
- [@chawyehsu](https://github.com/chawyehsu)
- [@chocolateboy](https://github.com/chocolateboy)
- [@chrisbodhi](https://github.com/chrisbodhi)
- [@chrishutchinson](https://github.com/chrishutchinson)
- [@ciceropablo](https://github.com/ciceropablo)
- [@Cilooth](https://github.com/Cilooth)
- [@clay-curry](https://github.com/clay-curry)
- [@codehz](https://github.com/codehz)
- [@colinhacks](https://github.com/colinhacks)
- [@Connormiha](https://github.com/Connormiha)
- [@coratgerl](https://github.com/coratgerl)
- [@cornedor](https://github.com/cornedor)
- [@CyberFlameGO](https://github.com/CyberFlameGO)
- [@cyfdecyf](https://github.com/cyfdecyf)
- [@cyfung1031](https://github.com/cyfung1031)
- [@DaleSeo](https://github.com/DaleSeo)
- [@danadajian](https://github.com/danadajian)
- [@DarthDanAmesh](https://github.com/DarthDanAmesh)
- [@davidmhewitt](https://github.com/davidmhewitt)
- [@davlgd](https://github.com/davlgd)
- [@Dawntraoz](https://github.com/Dawntraoz)
- [@desm](https://github.com/desm)
- [@DevinJohw](https://github.com/DevinJohw)
- [@dfabulich](https://github.com/dfabulich)
- [@dfaio](https://github.com/dfaio)
- [@Didas-git](https://github.com/Didas-git)
- [@diogo405](https://github.com/diogo405)
- [@dmitri-gb](https://github.com/dmitri-gb)
- [@DontBreakAlex](https://github.com/DontBreakAlex)
- [@dotspencer](https://github.com/dotspencer)
- [@dottedmag](https://github.com/dottedmag)
- [@DuGlaser](https://github.com/DuGlaser)
- [@dylang](https://github.com/dylang)
- [@e253](https://github.com/e253)
- [@ebidel](https://github.com/ebidel)
- [@eduardvercaemer](https://github.com/eduardvercaemer)
- [@eemelipa](https://github.com/eemelipa)
- [@eknowles](https://github.com/eknowles)
- [@EladBezalel](https://github.com/EladBezalel)
- [@eliot-akira](https://github.com/eliot-akira)
- [@emlez](https://github.com/emlez)
- [@eriklangille](https://github.com/eriklangille)
- [@ErikOnBike](https://github.com/ErikOnBike)
- [@eroblaze](https://github.com/eroblaze)
- [@eventualbuddha](https://github.com/eventualbuddha)
- [@fdb](https://github.com/fdb)
- [@fecony](https://github.com/fecony)
- [@fehnomenal](https://github.com/fehnomenal)
- [@FireSquid6](https://github.com/FireSquid6)
- [@fmajestic](https://github.com/fmajestic)
- [@fneco](https://github.com/fneco)
- [@FortyGazelle700](https://github.com/FortyGazelle700)
- [@G-Rath](https://github.com/G-Rath)
- [@gabry-ts](https://github.com/gabry-ts)
- [@gamedevsam](https://github.com/gamedevsam)
- [@gaurishhs](https://github.com/gaurishhs)
- [@ggobbe](https://github.com/ggobbe)
- [@gnuns](https://github.com/gnuns)
- [@gtramontina](https://github.com/gtramontina)
- [@guarner8](https://github.com/guarner8)
- [@guest271314](https://github.com/guest271314)
- [@h2210316651](https://github.com/h2210316651)
- [@Hamcker](https://github.com/Hamcker)
- [@Hanaasagi](https://github.com/Hanaasagi)
- [@hborchardt](https://github.com/hborchardt)
- [@HForGames](https://github.com/HForGames)
- [@hiadamk](https://github.com/hiadamk)
- [@HK-SHAO](https://github.com/HK-SHAO)
- [@hugo-syn](https://github.com/hugo-syn)
- [@huseeiin](https://github.com/huseeiin)
- [@hustLer2k](https://github.com/hustLer2k)
- [@I-A-S](https://github.com/I-A-S)
- [@igorshapiro](https://github.com/igorshapiro)
- [@igorwessel](https://github.com/igorwessel)
- [@iidebyo](https://github.com/iidebyo)
- [@Illyism](https://github.com/Illyism)
- [@ImBIOS](https://github.com/ImBIOS)
- [@imcatwhocode](https://github.com/imcatwhocode)
- [@ImLunaHey](https://github.com/ImLunaHey)
- [@jaas666](https://github.com/jaas666)
- [@jakeboone02](https://github.com/jakeboone02)
- [@jakeg](https://github.com/jakeg)
- [@james-elicx](https://github.com/james-elicx)
- [@jamesgordo](https://github.com/jamesgordo)
- [@jasperkelder](https://github.com/jasperkelder)
- [@jcarpe](https://github.com/jcarpe)
- [@jcbhmr](https://github.com/jcbhmr)
- [@jecquas](https://github.com/jecquas)
- [@JeremyFunk](https://github.com/JeremyFunk)
- [@jeroenpg](https://github.com/jeroenpg)
- [@jeroenvanrensen](https://github.com/jeroenvanrensen)
- [@jerome-benoit](https://github.com/jerome-benoit)
- [@jhmaster2000](https://github.com/jhmaster2000)
- [@JibranKalia](https://github.com/JibranKalia)
- [@JoaoAlisson](https://github.com/JoaoAlisson)
- [@joeyw](https://github.com/joeyw)
- [@johnpyp](https://github.com/johnpyp)
- [@jonahsnider](https://github.com/jonahsnider)
- [@jonathantneal](https://github.com/jonathantneal)
- [@JorgeJimenez15](https://github.com/JorgeJimenez15)
- [@joseph082](https://github.com/joseph082)
- [@jrz](https://github.com/jrz)
- [@jsparkdev](https://github.com/jsparkdev)
- [@jt3k](https://github.com/jt3k)
- [@jumoog](https://github.com/jumoog)
- [@kaioduarte](https://github.com/kaioduarte)
- [@kantuni](https://github.com/kantuni)
- [@karlbohlmark](https://github.com/karlbohlmark)
- [@karmabadger](https://github.com/karmabadger)
- [@keepdying](https://github.com/keepdying)
- [@kingofdreams777](https://github.com/kingofdreams777)
- [@kitsuned](https://github.com/kitsuned)
- [@klatka](https://github.com/klatka)
- [@knightspore](https://github.com/knightspore)
- [@kosperera](https://github.com/kosperera)
- [@kpracuk](https://github.com/kpracuk)
- [@krk](https://github.com/krk)
- [@kryparnold](https://github.com/kryparnold)
- [@kucukkanat](https://github.com/kucukkanat)
- [@kunokareal](https://github.com/kunokareal)
- [@kyr0](https://github.com/kyr0)
- [@L422Y](https://github.com/L422Y)
- [@LapsTimeOFF](https://github.com/LapsTimeOFF)
- [@lei-rs](https://github.com/lei-rs)
- [@lgarron](https://github.com/lgarron)
- [@lino-levan](https://github.com/lino-levan)
- [@lithdew](https://github.com/lithdew)
- [@liz3](https://github.com/liz3)
- [@Longju000](https://github.com/Longju000)
- [@lorenzodonadio](https://github.com/lorenzodonadio)
- [@lpinca](https://github.com/lpinca)
- [@lqqyt2423](https://github.com/lqqyt2423)
- [@lucasmichot](https://github.com/lucasmichot)
- [@LukasKastern](https://github.com/LukasKastern)
- [@lukeingalls](https://github.com/lukeingalls)
- [@m1212e](https://github.com/m1212e)
- [@malthe](https://github.com/malthe)
- [@markusn](https://github.com/markusn)
- [@Marukome0743](https://github.com/Marukome0743)
- [@marvinruder](https://github.com/marvinruder)
- [@maschwenk](https://github.com/maschwenk)
- [@MasterGordon](https://github.com/MasterGordon)
- [@masterujjval](https://github.com/masterujjval)
- [@mathiasrw](https://github.com/mathiasrw)
- [@MatricalDefunkt](https://github.com/MatricalDefunkt)
- [@matthewyu01](https://github.com/matthewyu01)
- [@maxmilton](https://github.com/maxmilton)
- [@meck93](https://github.com/meck93)
- [@mi4uu](https://github.com/mi4uu)
- [@miccou](https://github.com/miccou)
- [@mimikun](https://github.com/mimikun)
- [@mkayander](https://github.com/mkayander)
- [@mkossoris](https://github.com/mkossoris)
- [@morisk](https://github.com/morisk)
- [@mountainash](https://github.com/mountainash)
- [@moznion](https://github.com/moznion)
- [@mroyme](https://github.com/mroyme)
- [@MuhibAhmed](https://github.com/MuhibAhmed)
- [@nangchan](https://github.com/nangchan)
- [@nathanhammond](https://github.com/nathanhammond)
- [@nazeelashraf](https://github.com/nazeelashraf)
- [@nellfs](https://github.com/nellfs)
- [@nil1511](https://github.com/nil1511)
- [@nithinkjoy-tech](https://github.com/nithinkjoy-tech)
- [@NReilingh](https://github.com/NReilingh)
- [@nshen](https://github.com/nshen)
- [@nullun](https://github.com/nullun)
- [@nxzq](https://github.com/nxzq)
- [@nygmaaa](https://github.com/nygmaaa)
- [@o-az](https://github.com/o-az)
- [@o2sevruk](https://github.com/o2sevruk)
- [@oguimbal](https://github.com/oguimbal)
- [@Osmose](https://github.com/Osmose)
- [@otgerrogla](https://github.com/otgerrogla)
- [@otterDeveloper](https://github.com/otterDeveloper)
- [@owlcode](https://github.com/owlcode)
- [@pacexy](https://github.com/pacexy)
- [@pan93412](https://github.com/pan93412)
- [@Pandapip1](https://github.com/Pandapip1)
- [@panva](https://github.com/panva)
- [@paperless](https://github.com/paperless)
- [@Parzival-3141](https://github.com/Parzival-3141)
- [@PaulaBurgheleaGithub](https://github.com/PaulaBurgheleaGithub)
- [@paulbaumgart](https://github.com/paulbaumgart)
- [@PaulRBerg](https://github.com/PaulRBerg)
- [@ped](https://github.com/ped)
- [@Pedromdsn](https://github.com/Pedromdsn)
- [@perpetualsquid](https://github.com/perpetualsquid)
- [@pesterev](https://github.com/pesterev)
- [@pfgithub](https://github.com/pfgithub)
- [@philolo1](https://github.com/philolo1)
- [@pierre-cm](https://github.com/pierre-cm)
- [@Pierre-Mike](https://github.com/Pierre-Mike)
- [@pnodet](https://github.com/pnodet)
- [@polarathene](https://github.com/polarathene)
- [@PondWader](https://github.com/PondWader)
- [@prabhatexit0](https://github.com/prabhatexit0)
- [@Primexz](https://github.com/Primexz)
- [@qhariN](https://github.com/qhariN)
- [@RaisinTen](https://github.com/RaisinTen)
- [@rajatdua](https://github.com/rajatdua)
- [@RaresAil](https://github.com/RaresAil)
- [@rauny-brandao](https://github.com/rauny-brandao)
- [@rhyzx](https://github.com/rhyzx)
- [@RiskyMH](https://github.com/RiskyMH)
- [@risu729](https://github.com/risu729)
- [@RodrigoDornelles](https://github.com/RodrigoDornelles)
- [@rohanmayya](https://github.com/rohanmayya)
- [@RohitKaushal7](https://github.com/RohitKaushal7)
- [@rtxanson](https://github.com/rtxanson)
- [@ruihe774](https://github.com/ruihe774)
- [@rupurt](https://github.com/rupurt)
- [@ryands17](https://github.com/ryands17)
- [@s-rigaud](https://github.com/s-rigaud)
- [@s0h311](https://github.com/s0h311)
- [@saklani](https://github.com/saklani)
- [@samfundev](https://github.com/samfundev)
- [@samualtnorman](https://github.com/samualtnorman)
- [@sanyamkamat](https://github.com/sanyamkamat)
- [@scotttrinh](https://github.com/scotttrinh)
- [@SeedyROM](https://github.com/SeedyROM)
- [@sequencerr](https://github.com/sequencerr)
- [@sharpobject](https://github.com/sharpobject)
- [@shinichy](https://github.com/shinichy)
- [@silversquirl](https://github.com/silversquirl)
- [@simylein](https://github.com/simylein)
- [@sirenkovladd](https://github.com/sirenkovladd)
- [@sirhypernova](https://github.com/sirhypernova)
- [@sitiom](https://github.com/sitiom)
- [@Slikon](https://github.com/Slikon)
- [@Smoothieewastaken](https://github.com/Smoothieewastaken)
- [@sonyarianto](https://github.com/sonyarianto)
- [@Southpaw1496](https://github.com/Southpaw1496)
- [@spicyzboss](https://github.com/spicyzboss)
- [@sroussey](https://github.com/sroussey)
- [@sstephant](https://github.com/sstephant)
- [@starsep](https://github.com/starsep)
- [@stav](https://github.com/stav)
- [@styfle](https://github.com/styfle)
- [@SukkaW](https://github.com/SukkaW)
- [@sum117](https://github.com/sum117)
- [@techvlad](https://github.com/techvlad)
- [@thapasusheel](https://github.com/thapasusheel)
- [@ThatOneBro](https://github.com/ThatOneBro)
- [@ThatOneCalculator](https://github.com/ThatOneCalculator)
- [@therealrinku](https://github.com/therealrinku)
- [@thunfisch987](https://github.com/thunfisch987)
- [@tikotzky](https://github.com/tikotzky)
- [@tk120404](https://github.com/tk120404)
- [@tobycm](https://github.com/tobycm)
- [@tom-sherman](https://github.com/tom-sherman)
- [@tomredman](https://github.com/tomredman)
- [@toneyzhen](https://github.com/toneyzhen)
- [@toshok](https://github.com/toshok)
- [@traviscooper](https://github.com/traviscooper)
- [@trnxdev](https://github.com/trnxdev)
- [@tsndr](https://github.com/tsndr)
- [@TwanLuttik](https://github.com/TwanLuttik)
- [@twlite](https://github.com/twlite)
- [@VietnamecDevelopment](https://github.com/VietnamecDevelopment)
- [@Vilsol](https://github.com/Vilsol)
- [@vinnichase](https://github.com/vinnichase)
- [@vitalspace](https://github.com/vitalspace)
- [@vitoorgomes](https://github.com/vitoorgomes)
- [@vitordino](https://github.com/vitordino)
- [@vjpr](https://github.com/vjpr)
- [@vladaman](https://github.com/vladaman)
- [@vlechemin](https://github.com/vlechemin)
- [@Voldemat](https://github.com/Voldemat)
- [@vthemelis](https://github.com/vthemelis)
- [@vveisard](https://github.com/vveisard)
- [@wbjohn](https://github.com/wbjohn)
- [@weyert](https://github.com/weyert)
- [@whygee-dev](https://github.com/whygee-dev)
- [@winghouchan](https://github.com/winghouchan)
- [@WingLim](https://github.com/WingLim)
- [@wobsoriano](https://github.com/wobsoriano)
- [@xbjfk](https://github.com/xbjfk)
- [@xHyroM](https://github.com/xHyroM)
- [@ximex](https://github.com/ximex)
- [@xlc](https://github.com/xlc)
- [@xNaCly](https://github.com/xNaCly)
- [@yadav-saurabh](https://github.com/yadav-saurabh)
- [@yamcodes](https://github.com/yamcodes)
- [@Yash-Singh1](https://github.com/Yash-Singh1)
- [@YashoSharma](https://github.com/YashoSharma)
- [@yharaskrik](https://github.com/yharaskrik)
- [@Yonben](https://github.com/Yonben)
- [@yschroe](https://github.com/yschroe)
- [@yukulele](https://github.com/yukulele)
- [@yus-ham](https://github.com/yus-ham)
- [@zack466](https://github.com/zack466)
- [@zenshixd](https://github.com/zenshixd)
- [@zieka](https://github.com/zieka)
- [@zongzi531](https://github.com/zongzi531)
- [@ZTL-UwU](https://github.com/ZTL-UwU)
* * *
#### [Bun v1.1.1](bun-v1.1.1.html)
On this page
- [Windows Support](bun-v1.1.html#windows-support)
- [`bun install` on Windows](bun-v1.1.html#bun-install-on-windows)
- [`bun run` on Windows](bun-v1.1.html#bun-run-on-windows)
- [`bun --watch` on Windows](bun-v1.1.html#bun-watch-on-windows)
- [Node.js APIs on Windows](bun-v1.1.html#node-js-apis-on-windows)
- [Bun is a JavaScript runtime](bun-v1.1.html#bun-is-a-javascript-runtime)
- [Large projects start 2x faster](bun-v1.1.html#large-projects-start-2x-faster)
- [The Bun Shell](bun-v1.1.html#the-bun-shell)
- [`Bun.Glob`](bun-v1.1.html#bun-glob)
- [`Bun.Semver`](bun-v1.1.html#bun-semver)
- [`Bun.stringWidth()`](bun-v1.1.html#bun-stringwidth)
- [`server.url`](bun-v1.1.html#server-url)
- [`server.requestIP()`](bun-v1.1.html#server-requestip)
- [`subprocess.resourceUsage()`](bun-v1.1.html#subprocess-resourceusage)
- [`import.meta.env`](bun-v1.1.html#import-meta-env)
- [Node.js compatibility](bun-v1.1.html#node-js-compatibility)
- [HTTP/2 client](bun-v1.1.html#http-2-client)
- [`Date.parse()` compatible with Node.js](bun-v1.1.html#date-parse-compatible-with-node-js)
- [Recursive `fs.readdir()`](bun-v1.1.html#recursive-fs-readdir)
- [IPC support between Bun and Node.js](bun-v1.1.html#ipc-support-between-bun-and-node-js)
- [Undocumented Node.js APIs](bun-v1.1.html#undocumented-node-js-apis)
- [So much more](bun-v1.1.html#so-much-more)
- [Web APIs](bun-v1.1.html#web-apis)
- [`WebSocket` is stable](bun-v1.1.html#websocket-is-stable)
- [`performance.mark()`](bun-v1.1.html#performance-mark)
- [`fetch()` using Brotli compression](bun-v1.1.html#fetch-using-brotli-compression)
- [`URL.canParse()`](bun-v1.1.html#url-canparse)
- [`fetch()` over Unix sockets](bun-v1.1.html#fetch-over-unix-sockets)
- [`Response` body as an `AsyncIterator`](bun-v1.1.html#response-body-as-an-asynciterator)
- [Other changes](bun-v1.1.html#other-changes)
- [Bun is an npm-compatible package manager](bun-v1.1.html#bun-is-an-npm-compatible-package-manager)
- [Lifecycle scripts](bun-v1.1.html#lifecycle-scripts)
- [`trustedDependencies`](bun-v1.1.html#trusteddependencies)
- [`bun pm untrusted`](bun-v1.1.html#bun-pm-untrusted)
- [`bun pm trust`](bun-v1.1.html#bun-pm-trust)
- [`bun add --trust`](bun-v1.1.html#bun-add-trust)
- [`bun pm migrate`](bun-v1.1.html#bun-pm-migrate)
- [Bun is a JavaScript bundler](bun-v1.1.html#bun-is-a-javascript-bundler)
- [`bun build --target=node`](bun-v1.1.html#bun-build-target-node)
- [`bun build --compile`](bun-v1.1.html#bun-build-compile)
- [Macros](bun-v1.1.html#macros)
- [Bun is a test runner](bun-v1.1.html#bun-is-a-test-runner)
- [Matchers](bun-v1.1.html#matchers)
- [Custom matchers with `expect.extend()`](bun-v1.1.html#custom-matchers-with-expect-extend)
- [Module mocking](bun-v1.1.html#module-mocking)
- [Bun has built-in support for SQLite](bun-v1.1.html#bun-has-built-in-support-for-sqlite)
- [Multi-statement queries](bun-v1.1.html#multi-statement-queries)
- [Detailed errors](bun-v1.1.html#detailed-errors)
- [Import databases](bun-v1.1.html#import-databases)
- [Embed databases](bun-v1.1.html#embed-databases)
- [Bun makes JavaScript simpler](bun-v1.1.html#bun-makes-javascript-simpler)
- [Syntax-highlighted errors](bun-v1.1.html#syntax-highlighted-errors)
- [Simplified stack traces](bun-v1.1.html#simplified-stack-traces)
- [`bun --eval`](bun-v1.1.html#bun-eval)
- [`bun --print`](bun-v1.1.html#bun-print)
- [`bun --env-file`](bun-v1.1.html#bun-env-file)
- [Behaviour changes](bun-v1.1.html#behaviour-changes)
- [Longer network timeouts](bun-v1.1.html#longer-network-timeouts)
- [`Bun.write()` creates the parent directory](bun-v1.1.html#bun-write-creates-the-parent-directory)
- [Conditional exports does not include `worker`](bun-v1.1.html#conditional-exports-does-not-include-worker)
- [`NODE_ENV` is `undefined` by default](bun-v1.1.html#node-env-is-undefined-by-default)
- [`bun install [package]@latest`](bun-v1.1.html#bun-install-package-latest)
- [`Bun.$` rejects with non-zero exit code](bun-v1.1.html#bun-rejects-with-non-zero-exit-code)
- [`import.meta.resolve()`](bun-v1.1.html#import-meta-resolve)
- [A thousand bug fixes](bun-v1.1.html#a-thousand-bug-fixes)
- [Notable fixes](bun-v1.1.html#notable-fixes)
- [Performance improvements](bun-v1.1.html#performance-improvements)
- [Getting started](bun-v1.1.html#getting-started)
- [Install Bun](bun-v1.1.html#install-bun)
- [Upgrade Bun](bun-v1.1.html#upgrade-bun)
- [We're hiring](bun-v1.1.html#we-re-hiring)
- [Thank you to 364 contributors!](bun-v1.1.html#thank-you-to-364-contributors)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/bun-v1.2.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Bun 1.2
* * *
[Ashcon Partovi](https://twitter.com/ashconpartovi) · January 22, 2025
[](../rss.xml)
Bun is complete toolkit for building and testing full-stack JavaScript and TypeScript applications. If you're new to Bun, you can learn more from the [Bun 1.0](../1.0.html#bun-is-an-all-in-one-toolkit) blog post.
## []()[Bun 1.2](bun-v1.2.html#bun-1-2)
Bun 1.2 is a huge update, and we're excited to share it with you.
Here's the tl;dr of what changed in Bun 1.2:
- There's a major update on Bun's progress towards [Node.js compatibility](bun-v1.2.html#node-js-compatibility)
- Bun now has a built-in S3 object storage API: [`Bun.s3`](bun-v1.2.html#s3-support-with-bun-s3)
- Bun now has a built-in Postgres client: [`Bun.sql`](bun-v1.2.html#postgres-support-with-bun-sql) (with MySQL coming soon)
- `bun install` now uses a text-based lockfile: [`bun.lock`](bun-v1.2.html#bun-is-a-package-manager)
We also made Express [3x faster](bun-v1.2.html#express-is-3x-faster) in Bun.
## []()[Node.js compatibility](bun-v1.2.html#node-js-compatibility)
Bun is designed as a drop-in replacement for Node.js.
In Bun 1.2, we started to run the Node.js test suite for every change we make to Bun. Since then, we've fixed thousands of bugs and the following Node.js modules now pass over 90% of their tests with Bun.
[](https://github.com/user-attachments/assets/83919108-1bfa-41e3-9001-fa9624f3c554)
For each of these Node modules, Bun passes over 90% of the Node.js test suite.
Here's how we did it.
### []()[How do you measure compatibility?](bun-v1.2.html#how-do-you-measure-compatibility)
In Bun 1.2, we changed how we test and improve Bun's compatibility with Node.js. Previously, we prioritized and fixed Node.js bugs as they were reported, usually from GitHub issues where someone tried to use an npm package that didn't work in Bun.
While this fixed actual bugs real users ran into, it was too much of a "wack-a-mole" approach. It discouraged doing the large refactors necessary for us to have a shot at 100% Node.js compatibility.
That's when we thought: what if we just run the Node.js test suite?
[](https://github.com/user-attachments/assets/ee1c977f-8d85-4038-9cab-8f38a1bc81d6)
There are so many tests in the Node.js repository, that the files can't all be listed on GitHub.
### []()[Running Node.js tests in Bun](bun-v1.2.html#running-node-js-tests-in-bun)
Node.js has thousands of test files in its repository, with most of them in the [`test/parallel`](https://github.com/nodejs/node/tree/main/test/parallel) directory. While it might seem simple enough to "just run" their tests, it's more involved than you might think.
#### Internal APIs
For example, many tests rely on the internal implementation details of Node.js. In the following test, `getnameinfo` is stubbed to always error, to test the error handling of `dns.lookupService()`.
test/parallel/test-dns-lookupService.js
```
const { internalBinding } = require("internal/test/binding");
const cares = internalBinding("cares_wrap");
const { UV_ENOENT } = internalBinding("uv");
cares.getnameinfo = () => UV_ENOENT;
```
To run this test in Bun, we had to replace the internal bindings with our own stubs.
test/parallel/test-dns-lookupService.js
```
Bun.dns.lookupService = (addr, port) => {
const error = new Error(`getnameinfo ENOENT ${addr}`);
error.code = "ENOENT";
error.syscall = "getnameinfo";
throw error;
};
```
#### Error messages
There are also Node.js tests that check the *exact* string of error messages. And while Node.js usually doesn't change error messages, they don't guarantee it won't change between releases.
```
const common = require("../common");
const assert = require("assert");
assert.throws(
() => Buffer.allocUnsafe(5).copy(Buffer.allocUnsafe(5), -1, 0),
{
name: 'RangeError',
code: 'ERR_OUT_OF_RANGE',
message: 'The value of "targetStart" is out of range. It must be >= 0. Received -1'
}
);
```
To work around this, we had to change the assertion logic in some tests to check the `name` and `code`, instead of the `message`. This is also the standard practice for checking error types in Node.js. Additionally, we sometimes update the message when Bun provides more info for the user than Node.js.
```
{
name: "RangeError",
code: "ERR_OUT_OF_RANGE",
message: 'The value of "targetStart" is out of range. It must be >= 0. Received -1'
message: 'The value of "targetStart" is out of range. It must be >= 0 and <= 5. Received -1'
},
```
While we do try to match the error messages of Node.js as much as possible, there are times where we want to provide a more helpful error message, as long as the `name` and `code` are the same.
#### Progress so far
We've ported thousands of files from the Node.js test suite to Bun. That means for every commit we make to Bun, we run the Node.js test suite to ensure compatibility.
[](https://github.com/user-attachments/assets/c04ef5b9-a8d6-4be7-90a8-6f632aefbe17)
A screenshot of Bun's CI where we run the Node.js test suite for every commit.
Every day, we are adding more and more passing Node.js tests to Bun, and we're excited to share more progress on Node.js compatibility very soon.
In addition to fixing existing Node.js APIs, we've also added support for the following Node.js modules.
### []()[`node:http2` server](bun-v1.2.html#node-http2-server)
You can now use [`node:http2`](https://nodejs.org/api/http2.html#core-api) to create HTTP/2 servers. HTTP/2 is also necessary for gRPC servers, which are also now supported in Bun. Previously, there was only support for the HTTP/2 client.
```
import { createSecureServer } from "node:http2";
import { readFileSync } from "node:fs";
const server = createSecureServer({
key: readFileSync("key.pem"),
cert: readFileSync("cert.pem"),
});
server.on("stream", (stream, headers) => {
stream.respond({
":status": 200,
"content-type": "text/html; charset=utf-8",
});
stream.end("<h1>Hello from Bun!</h1>");
});
server.listen(3000);
```
In Bun 1.2, the HTTP/2 server is [2x faster](https://twitter.com/bunjavascript/status/1847014951661326396) than in Node.js. When we support new APIs to Bun, we spend a lot of time tuning performance to ensure that it not only works, but it's also faster.
[](https://github.com/user-attachments/assets/30ebbbc3-13e1-4fb5-a3a8-a0e7374ca094)
Benchmark of a "hello world" node:http2 server running in Bun 1.2 and Node.js 22.13.
### []()[`node:dgram`](bun-v1.2.html#node-dgram)
You can now bind and connect to UDP sockets using [`node:dgram`](https://nodejs.org/api/dgram.html#udpdatagram-sockets). UDP is a low-level unreliable messaging protocol, often used by telemetry providers and game engines.
```
import { createSocket } from "node:dgram";
const server = createSocket("udp4");
const client = createSocket("udp4");
server.on("listening", () => {
const { port, address } = server.address();
for (let i = 0; i < 10; i++) {
client.send(`data ${i}`, port, address);
}
server.unref();
});
server.on("message", (data, { address, port }) => {
console.log(`Received: data=${data} source=${address}:${port}`);
client.unref();
});
server.bind();
```
This allows packages like DataDog's [`dd-trace`](https://github.com/DataDog/dd-trace-js) and [`@clickhouse/client`](https://github.com/ClickHouse/clickhouse-js) to work in Bun 1.2.
### []()[`node:cluster`](bun-v1.2.html#node-cluster)
You can use [`node:cluster`](https://nodejs.org/api/cluster.html#cluster) to spawn multiple instances of Bun. This is often used to enable higher throughput by running tasks across multiple CPU cores.
Here's an example of how you can create a multi-threaded HTTP server using `cluster`:
- The primary worker spawns `n` child workers (usually equal to the number of CPU cores)
- Each child worker listens on the same port (using [`reusePort`](https://lwn.net/Articles/542629/))
- Incoming HTTP requests are load balanced across the child workers
```
import cluster from "node:cluster";
import { createServer } from "node:http";
import { cpus } from "node:os";
if (cluster.isPrimary) {
console.log(`Primary ${process.pid} is running`);
// Start N workers for the number of CPUs
for (let i = 0; i < cpus().length; i++) {
cluster.fork();
}
cluster.on("exit", (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} exited`);
});
} else {
// Incoming requests are handled by the pool of workers
// instead of the primary worker.
createServer((req, res) => {
res.writeHead(200);
res.end(`Hello from worker ${process.pid}`);
}).listen(3000);
console.log(`Worker ${process.pid} started`);
}
```
Note that `reusePort` is only effective on Linux. On Windows and macOS, the operating system does not load balance HTTP connections as one would expect.
### []()[`node:zlib`](bun-v1.2.html#node-zlib)
In Bun 1.2, we rewrote the entire [`node:zlib`](https://nodejs.org/api/zlib.html#zlib) module from JavaScript to native code. This not only fixed a bunch of bugs, but it made it [2x faster](https://x.com/bunjavascript/status/1832370723895247277) than Bun 1.1.
[](https://github.com/user-attachments/assets/cc3760d5-352c-4f7a-a75b-2f48fec52dfa)
Benchmark of inflateSync using node:zlib in Bun and Node.js.
We also added support for [Brotli](https://github.com/google/brotli) in `node:zlib`, which was missing in Bun 1.1.
```
import { brotliCompressSync, brotliDecompressSync } from "node:zlib";
const compressed = brotliCompressSync("Hello, world!");
compressed.toString("hex"); // "0b068048656c6c6f2c20776f726c642103"
const decompressed = brotliDecompressSync(compressed);
decompressed.toString("utf8"); // "Hello, world!"
```
### []()[C++ addons using V8 APIs](bun-v1.2.html#c-addons-using-v8-apis)
If you want to use [C++ addons](https://nodejs.org/api/addons.html#c-addons) alongside your JavaScript code, the easiest way is to use [N-API](../docs/api/node-api.html).
However, before N-API existed, some packages used the internal V8 C++ APIs in Node.js. What makes this complicated is that Node.js and Bun use different JavaScript engines: Node.js uses [V8](https://v8.dev/) (used by Chrome), and Bun uses [JavaScriptCore](https://docs.webkit.org/Deep%20Dive/JSC/JavaScriptCore.html) (used by Safari).
Previously, npm packages like [`cpu-features`](https://www.npmjs.com/package/cpu-features), which rely on these V8 APIs, would not work in Bun.
```
require("cpu-features")();
```
```
dyld[94465]: missing symbol called
fish: Job 1, 'bun index.ts' terminated by signal SIGABRT (Abort)
```
To fix this, we undertook the unprecedented engineering effort of implementing V8's public C++ API in JavaScriptCore, so these packages can "just work" in Bun. It's so complicated and nerdy to explain, we wrote a [3-part blog](how-bun-supports-v8-apis-without-using-v8-part-1.html) series on how we supported the V8 APIs... without using V8.
In Bun 1.2, packages like `cpu-features` can be imported and just work.
```
$ bun index.ts
{
arch: "aarch64",
flags: {
fp: true,
asimd: true,
// ...
},
}
```
The V8 C++ APIs are *very* complicated to support, so most packages will still have missing features. We're continuing to improve support, so packages like `node-canvas@v2` and `node-sqlite3` can work in the future.
### []()[`node:v8`](bun-v1.2.html#node-v8)
In addition to the V8 C++ APIs, we've also added support for heap snapshots using [`node:v8`](https://nodejs.org/api/v8.html).
```
import { writeHeapSnapshot } from "node:v8";
// Writes a heap snapshot to the current working directory in the form:
// `Heap-{date}-{pid}.heapsnapshot`
writeHeapSnapshot();
```
In Bun 1.2, you can use [`getHeapSnapshot`](https://nodejs.org/api/v8.html#v8getheapsnapshot) and [`writeHeapSnapshot`](https://nodejs.org/api/v8.html#v8writeheapsnapshot) to read and write V8 heap snapshots. This allows you to use Chrome DevTools to inspect the heap of Bun.
[](https://github.com/user-attachments/assets/d953c24c-b124-4baf-95e1-60482cb2d8e0)
You can view a heap snapshot of Bun using Chrome DevTools.
### []()[Express is 3x faster](bun-v1.2.html#express-is-3x-faster)
While compatibility is important for fixing bugs, it also helps us fix performance issues in Bun.
In Bun 1.2, the popular `express` framework can serve HTTP requests up to [3x faster](https://x.com/bunjavascript/status/1820610675296940227) than in Node.js. This was made possible by improving compatibility with `node:http`, and optimizing Bun's HTTP server.
[](https://github.com/user-attachments/assets/2c47977c-f099-4c5f-ae24-e4a259e0b240)
## []()[S3 support with `Bun.s3`](bun-v1.2.html#s3-support-with-bun-s3)
Bun aims to be a cloud-first JavaScript runtime. That means supporting all the tools and services you need to run a production application in the cloud.
Modern applications store files in object storage, instead of the local POSIX file system. When end-users upload a file attachment to a website, it's not being stored on the server's local disk, it's being stored in a S3 bucket. Decoupling storage from compute prevents an entire class of reliability issues: low disk space, high p95 response times from busy I/O, and security issues with shared file storage.
S3 is the [defacto-standard](https://en.wikipedia.org/wiki/De_facto_standard) for object storage in the cloud. The [S3 APIs](https://docs.aws.amazon.com/AmazonS3/latest/API/API_Operations_Amazon_Simple_Storage_Service.html) are implemented by a variety of cloud services, including Amazon S3, Google Cloud Storage, Cloudflare R2, and dozens more.
That's why Bun 1.2 adds built-in support for S3. You can read, write, and delete files from an S3 bucket using APIs that are compatible with Web standards like `Blob`.
### []()[Reading files from S3](bun-v1.2.html#reading-files-from-s3)
You can use the new [`Bun.s3`](../docs/api/s3.html#bun-s3client-bun-s3) API to access the default [`S3Client`](../docs/api/s3.html#bun-s3client-bun-s3). The client provides a `file()` method that returns a lazy-reference to an S3 file, which is the same API as Bun's [`File`](../docs/api/file-io.html#reading-files-bun-file).
```
import { s3 } from "bun";
const file = s3.file("folder/my-file.txt");
// file instanceof Blob
const content = await file.text();
// or:
// file.json()
// file.arrayBuffer()
// file.stream()
```
### []()[5x faster than Node.js](bun-v1.2.html#5x-faster-than-node-js)
Bun's S3 client is written in native code, instead of JavaScript. When you compare it to using packages like `@aws-sdk/client-s3` with Node.js, it's 5x faster at downloading files from a S3 bucket.
[](../bun-s3-node.gif)
Left: Bun 1.2 with Bun.s3. Right: Node.js with @aws-sdk/client-s3.
### []()[Writing files to S3](bun-v1.2.html#writing-files-to-s3)
You can use the [`write()`](../docs/api/s3.html#writing-uploading-files-to-s3) method to upload a file to S3. It's that simple:
```
import { s3 } from "bun";
const file = s3.file("folder/my-file.txt");
await file.write("hello s3!");
// or:
// file.write(new Uint8Array([1, 2, 3]));
// file.write(new Blob(["hello s3!"]));
// file.write(new Response("hello s3!"));
```
For larger files, you can use the [`writer()`](../docs/api/s3.html#writing-uploading-files-to-s3) method to obtain a file writer that does a [multi-part upload](https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html), so you don't have to worry about the details.
```
import { s3 } from "bun";
const file = s3.file("folder/my-file.txt");
const writer = file.writer();
for (let i = 0; i < 1000; i++) {
writer.write(String(i).repeat(1024));
}
await writer.end();
```
### []()[Presigned URLs](bun-v1.2.html#presigned-urls)
When your production service needs to let users upload files to your server, it's often more reliable for the user to upload directly to S3 instead of your server acting as an intermediary.
To make this work, you use the [`presign()`](../docs/api/s3.html#presigning-urls) method to generate a [presigned URL](https://docs.aws.amazon.com/AmazonS3/latest/userguide/using-presigned-url.html) for a file. This generates a URL with a signature that allows a user to securely upload that specific file to S3, without exposing your credentials or granting them unnecessary access to your bucket.
```
import { s3 } from "bun";
const url = s3.presign("folder/my-file.txt", {
expiresIn: 3600, // 1 hour
acl: "public-read",
});
```
### []()[Using `Bun.serve()`](bun-v1.2.html#using-bun-serve)
Since Bun's S3 APIs extend the `File` API, you can use [`Bun.serve()`](../docs/api/http.html#bun-serve) to serve S3 files over HTTP.
```
import { serve, s3 } from "bun";
serve({
port: 3000,
async fetch(request) {
const { url } = request;
const { pathname } = new URL(url);
// ...
if (pathname === "/favicon.ico") {
const file = s3.file("assets/favicon.ico");
return new Response(file);
}
// ...
},
});
```
When you use `new Response(s3.file(...))`, instead of downloading the S3 file to your server and sending it back to the user, Bun redirects the user to the presigned URL for the S3 file.
```
Response (0 KB) {
status: 302,
headers: Headers {
"location": "https://s3.amazonaws.com/my-bucket/assets/favicon.ico?...",
},
redirected: true,
}
```
This saves you memory, time, and the bandwidth cost of downloading the file to your server.
### []()[Using `Bun.file()`](bun-v1.2.html#using-bun-file)
If you want to access S3 files using the same code as the local file-system, you can reference them using the `s3://` URL protocol. It's the same concept as using `file://` to reference local files.
```
import { file } from "bun";
async function createFile(url, content) {
const fileObject = file(url);
if (await fileObject.exists()) {
return;
}
await fileObject.write(content);
}
await createFile("s3://folder/my-file.txt", "hello s3!");
await createFile("file://folder/my-file.txt", "hello posix!");
```
### []()[Using `fetch()`](bun-v1.2.html#using-fetch)
You can even use `fetch()` to read, write, and delete files from S3.
```
// Upload to S3
await fetch("s3://folder/my-file.txt", {
method: "PUT",
body: "hello s3!",
});
// Download from S3
const response = await fetch("s3://folder/my-file.txt");
const content = await response.text(); // "hello s3!"
// Delete from S3
await fetch("s3://folder/my-file.txt", {
method: "DELETE",
});
```
### []()[Using `S3Client`](bun-v1.2.html#using-s3client)
When you import `Bun.s3`, it returns a default client that is configured using [well-known](../docs/api/s3.html#credentials) environment variables, such as `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`.
```
import { s3, S3Client } from "bun";
// s3 instanceof S3Client
```
You can also create your own [`S3Client`](../docs/api/s3.html#s3client-objects), then set it as the default.
```
import { S3Client } from "bun";
const client = new S3Client({
accessKeyId: "my-access-key-id",
secretAccessKey: "my-secret-access-key",
region: "auto",
endpoint: "https://<account-id>.r2.cloudflarestorage.com",
bucket: "my-bucket",
});
// Sets the default client to be your custom client
Bun.s3 = client;
```
## []()[Postgres support with `Bun.sql`](bun-v1.2.html#postgres-support-with-bun-sql)
Just like object storage, another datastore that production applications often need is a SQL database.
Since the beginning, Bun has had a built-in [SQ*Lite*](../docs/api/sqlite.html) client. SQLite is great for smaller applications and quick scripts, where you don't want to worry about the hastle of setting up a production database.
In Bun 1.2, we're expanding Bun's support for SQL databases by introducing [`Bun.sql`](../docs/api/sql.html), a built-in SQL client with Postgres support. We also have a [pull request](https://github.com/oven-sh/bun/pull/15274) to add MySQL support very soon.
[](https://github.com/user-attachments/assets/ecb31227-e5e7-43a6-aff8-47452cf81578)
### []()[Using `Bun.sql`](bun-v1.2.html#using-bun-sql)
You can use [`Bun.sql`](../docs/api/sql.html) to run SQL queries using [tagged-template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals). This allows you to pass JavaScript values as parameters to your SQL queries.
Most importantly, it escapes strings and uses prepared statements for you to prevent SQL injection.
```
import { sql } from "bun";
const users = [
{ name: "Alice", age: 25 },
{ name: "Bob", age: 65 },
];
await sql`
INSERT INTO users (name, age)
VALUES ${sql(users)}
`;
```
Reading rows is just as easy. Results are returned as an array of objects, with the column name as the key.
```
import { sql } from "bun";
const seniorAge = 65;
const seniorUsers = await sql`
SELECT name, age FROM users
WHERE age >= ${seniorAge}
`;
console.log(seniorUsers); // [{ name: "Bob", age: 65 }]
```
### []()[50% faster than other clients](bun-v1.2.html#50-faster-than-other-clients)
`Bun.sql` is written in native code with optimizations like:
- Automatic prepared statements
- Query pipelining
- Binary wire protocol support
- Connection pooling
- Structure caching
Optimizations stack like buffs in World of Warcraft.
The result is that `Bun.sql` is up to 50% faster at reading rows than using the most popular Postgres clients with Node.js.
[](https://github.com/user-attachments/assets/09066ce9-aacd-439c-ab28-f2640c0ce814)
### []()[Migrate from `postgres.js` to `Bun.sql`](bun-v1.2.html#migrate-from-postgres-js-to-bun-sql)
The `Bun.sql` APIs are inspired by the popular [`postgres.js`](https://github.com/porsager/postgres) package. This makes it easy to migrate your existing code to using Bun's built-in SQL client.
```
import { postgres } from "postgres";
import { postgres } from "bun";
const sql = postgres({
host: "localhost",
port: 5432,
database: "mydb",
user: "...",
password: "...",
});
const users = await sql`SELECT name, age FROM users LIMIT 1`;
console.log(users); // [{ name: "Alice", age: 25 }]
```
## []()[Bun is a package manager](bun-v1.2.html#bun-is-a-package-manager)
Bun is a npm-compatible package manager that makes it easy to install and update your node modules. You can use [`bun install`](../docs/cli/install.html) to install dependencies, even if you're using Node.js as a runtime.
### []()[Replace `npm install` with `bun install`](bun-v1.2.html#replace-npm-install-with-bun-install)
```
$ npm install
$ bun install
```
In Bun 1.2, we've made the biggest change yet to the package manager.
### []()[Problems with `bun.lockb`](bun-v1.2.html#problems-with-bun-lockb)
Since the beginning, Bun has used a binary lockfile: `bun.lockb`.
Unlike other package managers that use text-based lockfiles, like JSON or YAML, a binary lockfile allowed us to make `bun install` almost 30x faster than `npm`.
However, we found that there were a lot of paper cuts when using a binary lockfile. First, you couldn't view the contents of the lockfile on GitHub and other platforms. This sucked.
[](https://github.com/user-attachments/assets/c6c937c1-9074-427e-a1d2-82c7c871538e)
What happens if you receive a pull request from an external contributor that changes the `bun.lockb` file? Do you trust it? Probably not.
That's also assuming there isn't a merge conflict! Which for a binary lockfile, is almost impossible to resolve, aside from manually deleting the lockfiles and running `bun install` again.
[](https://github.com/user-attachments/assets/e97db642-1499-40c5-b17f-3a932157d0f2)
This also made it hard for tools to read the lockfile. For example, dependency management tools like [Dependabot](https://github.com/dependabot/dependabot-core) would need an API to parse the lockfile, and we didn't offer one.
[](https://github.com/user-attachments/assets/65ed123a-8e56-4550-ae0b-9967520e805e)
Bun will continue to support `bun.lockb` for a *long* time. However, for all these reasons, we've decided to switch to a text-based lockfile as the default in Bun 1.2.
### []()[Introducing `bun.lock`](bun-v1.2.html#introducing-bun-lock)
In Bun 1.2, we're introducing a new, text-based lockfile: [`bun.lock`](../docs/install/lockfile.html).
You can migrate to the new lockfile by using the `--save-text-lockfile` flag.
```
bun install --save-text-lockfile
```
`bun.lock` is a JSONC file, which is JSON with added support for comments and trailing commas.
bun.lock
```
// bun.lock
{
"lockfileVersion": 0,
"packages": [
["express@4.21.2", /* ... */, "sha512-..."],
["body-parser@1.20.3", /* ... */],
/* ... and more */
],
"workspaces": { /* ... */ },
}
```
This makes it much easier to view diffs in pull requests, and trailing commas make it much less likely to cause merge conflicts.
[](https://github.com/user-attachments/assets/c873d6fe-3b44-47ca-81fd-913d9ace7b8e)
For new projects without a lockfile, Bun will generate a new `bun.lock` file.
For existing projects with a `bun.lockb` file, Bun will continue to support the binary lockfile, *without migration to the new lockfile*. We will continue to support the binary lockfile for a *long* time, so you can continue to use commands, like `bun add` and `bun update`, and it will update your `bun.lockb` file.
### []()[`bun install` gets 30% faster](bun-v1.2.html#bun-install-gets-30-faster)
You might think that after we migrated to a text-based lockfile, `bun install` would be slower. Wrong!
Most software projects get slower as more features are added, Bun is not one of those projects. We spent a lot of time tuning and optimizing Bun, so we could make `bun install` *even* faster.
That's why in Bun 1.2, `bun install` is 30% faster than Bun 1.1
[](https://github.com/user-attachments/assets/679db20c-dfc1-4a36-b656-8abc16733c55)
### []()[JSONC support in `package.json`](bun-v1.2.html#jsonc-support-in-package-json)
Have you ever added something to your `package.json` and forgot why months later? Or wanted to explain to your teammates why a dependency needs a specific version? Or have you ever had a merge conflict in a package.json file due to a comma?
Often these problems are due to the fact that `package.json` is a JSON file, and that means you can't use comments or trailing commas in it.
package.json
```
{
"dependencies": {
// this would cause a syntax error
"express": "4.21.2"
}
}
```
This is a bad experience. Modern tools like TypeScript allow for comments and trailing commas in their configuration files, `tsconfig.json` for example, and it's great. We also asked the community on your thoughts, and it seemed that the status-quo needed to change.
> What JS ecosystem upgrade path would you prefer to permit comments in package.json?
>
> — Rob Palmer (@robpalmer2) [April 17, 2024](https://twitter.com/robpalmer2/status/1780495081637548305?ref_src=twsrc%5Etfw)
In Bun 1.2, you can use comments and trailing commas in your `package.json`. It just works.
package.json
```
{
"name": "app",
"dependencies": {
// We need 0.30.8 because of a bug in 0.30.9
"drizzle-orm": "0.30.8", /* <- trailing comma */
},
}
```
Since there are many tools that read `package.json` files, we've added support to `require()` or `import()` these files with comments and trailing commas. You don't need to change your code.
```
const pkg = require("./package.json");
const {
default: { name },
} = await import("./package.json");
```
Since this isn't widely supported in the JavaScript ecosystem, we'd advice you to use this feature "at your own risk." However, we think this is the right direction to go: to make things easier for you.
### []()[`.npmrc` support](bun-v1.2.html#npmrc-support)
In Bun 1.2, we added support for reading npm's config file: [`.npmrc`](../docs/install/npmrc.html).
You can use `.npmrc` to configure your npm registry and configure scoped packages. This is often necessary for corporate environments, where you might need to authenticate to a private registry.
.npmrc
```
@my-company:registry=https://packages.my-company.com
@my-org:registry=https://packages.my-company.com/my-org
```
Bun will look for an `.npmrc` file in your project's root directory, and in your home directory.
### []()[`bun run --filter`](bun-v1.2.html#bun-run-filter)
You can now use `bun run --filter` to run a script in multiple workspaces at the same time.
```
bun run --filter='*' dev
```
This will run the `dev` script, concurrently, in all workspaces that match the glob pattern. It will also interleave the output of each script, so you can see the output of each workspace as it runs.
[](https://github.com/oven-sh/bun/assets/48869301/2a103e42-9921-4c33-948f-a1ad6e6bac71)
You can also pass multiple filters to `--filter`, and you can just use `bun` instead of `bun run`.
```
bun --filter 'api/*' --filter 'frontend/*' dev
```
### []()[`bun outdated`](bun-v1.2.html#bun-outdated)
You can now view which dependencies are out-of-date using [`bun outdated`](../docs/cli/outdated.html).
[](https://github.com/user-attachments/assets/cb41e234-d0f6-4830-9864-fb87bd568cfe)
It will show a list of your `package.json` dependencies, and which versions are out-of-date. The "update" column shows the next semver-matching version, and the "latest" column shows the latest version.
If you notice there's a specific dependency you want to update, you can use `bun update`.
```
bun update @typescript-eslint/parser # Updates to "7.18.0"
```
```
bun update @typescript-eslint/parser --latest # Updates to "8.2.0"
```
You can also filter which dependencies you want to check for updates. Just make sure to quote patterns, so your shell doesn't expand them as glob patterns!
```
bun outdated "is-*" # check is-even, is-odd, etc.
```
```
bun outdated "@discordjs/*" # check @discordjs/voice, @discordjs/rest, etc.
```
```
bun outdated jquery --filter="foo" # check jquery in the `foo` workspace
```
### []()[`bun publish`](bun-v1.2.html#bun-publish)
You can now publish npm packages using [`bun publish`](../docs/cli/publish.html).
[](https://github.com/user-attachments/assets/3ab14008-f874-4f70-aa12-0be550f6fda5)
It's a drop-in replacement for `npm publish`, and supports many of the same features like:
- Reading [`.npmrc`](../docs/install/npmrc.html) files for authentication.
- Packing tarballs, accounting for `.gitignore` and `.npmignore` files in multiple directories.
- OTP / Two-factor authentication.
- Handling edgecases with package.json fields like `bin`, `files`, etc.
- Handling missing `README` files carefully.
We've also added support for commands that are useful for publishing, like:
- [`bun pm whoami`](../docs/cli/pm.html#whoami), which prints your npm username.
- [`bun pm pack`](../docs/cli/pm.html#pack), which creates an npm package tarball for publishing or installing locally.
### []()[`bun patch`](bun-v1.2.html#bun-patch)
Sometimes, your dependencies have bugs or missing features. While you could fork the package, make your changes, and publish it — that's a lot of work. What if you don't want to maintain a fork?
In Bun 1.2, we've added support for patching dependencies. Here's how it works:
1. Run `bun patch <package>` to patch a package.
2. Edit the files in the `node_modules/<package>` directory.
3. Run `bun patch --commit <package>` to save your changes. That's it!
Bun generates a `.patch` file with your changes in the `patches/` directory, which is automatically applied on `bun install`. You can then commit the patch file to your repository, and share it with your team.
For example, you could create a patch to replace a dependency with your own code.
./patches/is-even@1.0.0.patch
```
diff --git a/index.js b/index.js
index 832d92223a9ec491364ee10dcbe3ad495446ab80..2a61f0dd2f476a4a30631c570e6c8d2d148d419a 100644
--- a/index.js
+++ b/index.js
@@ -1,14 +1 @@
- 'use strict';
-
- var isOdd = require('is-odd');
-
- module.exports = function isEven(i) {
- return !isOdd(i);
- };
+ module.exports = (i) => (i % 2 === 0)
```
Bun clones the package from the `node_modules` directory with a fresh copy of itself. This allows you to safely make edits to files in the package's directory without impacting shared file caches.
### []()[Easier to use](bun-v1.2.html#easier-to-use)
We've also made a bunch of small improvements to make `bun install` easier to use.
#### CA certificates
You can now configure CA certificates for `bun install`. This is useful when you need to install packages from your company's private registry, or if you want to use self-signed certificate.
bunfig.toml
```
[install]
# The CA certificate as a string
ca = "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"
# A path to a CA certificate file. The file can contain multiple certificates.
cafile = "path/to/cafile"
```
If you don't want to change your [`bunfig.toml`](../docs/runtime/bunfig.html#install-ca-and-install-cafile) file, you can also use the `--ca` and `--cafile` flags.
```
bun install --cafile=/path/to/cafile
```
```
bun install --ca="..."
```
If you are using an existing [`.npmrc`](../docs/install/npmrc.html) file, you can also configure CA certificates there.
.npmrc
```
cafile=/path/to/cafile
ca="..."
```
#### `bundleDependencies` support
You can now use [`bundleDependencies`](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#bundledependencies) in your `package.json`.
package.json
```
{
"bundleDependencies": ["is-even"]
}
```
These are dependencies that you expect to already exist in your `node_modules` folder, and are not installed like other dependencies.
#### `bun add` respects `package.json` indentation
We fixed a bug where `bun add` would not respect the spacing and indentation in your `package.json`. Bun will now preserve the indentation of your `package.json`, no matter how wacky it is.
```
bun add is-odd
```
package.json
```
// an intentionally wacky package.json
{
"dependencies": {
"is-even": "1.0.0",
"is-odd": "1.0.0"
}
}
```
#### `--omit=dev|optional|peer` support
Bun now supports the `--omit` flag with `bun install`, which allows you to omit dev, optional, or peer dependencies.
```
bun install --omit=dev # omit dev dependencies
```
```
bun install --omit=optional # omit optional dependencies
```
```
bun install --omit=peer # omit peer dependencies
```
```
bun install --omit=dev --omit=optional # omit dev and optional dependencies
```
## []()[Bun is a test runner](bun-v1.2.html#bun-is-a-test-runner)
Bun has a built-in test runner that makes it easy to write and run tests in JavaScript, TypeScript, and JSX. It supports many of the same APIs as Jest and Vitest, which includes the [`expect()`](https://jestjs.io/docs/expect#expect)-style APIs.
In Bun 1.2, we've made a lot of improvements to `bun test`.
### []()[JUnit support](bun-v1.2.html#junit-support)
To use `bun test` with CI/CD tools like Jenkins, CircleCI, and GitLab CI, you can use the `--reporter` option to output test results to a JUnit XML file.
```
bun test --reporter=junit --reporter-outfile=junit.xml
```
junit.xml
```
<?xml version="1.0" encoding="UTF-8"?>
<testsuites name="bun test" tests="1" assertions="1" failures="1" time="0.001">
<testsuite name="index.test.ts" tests="1" assertions="1" failures="1" time="0.001">
<!-- ... -->
</testsuite>
</testsuites>
```
You can also enable JUnit reporting by adding the following to your [`bunfig.toml`](../docs/runtime/bunfig.html) file.
bunfig.toml
```
[test.reporter]
junit = "junit.xml"
```
### []()[LCOV support](bun-v1.2.html#lcov-support)
You can use `bun test --coverage` to generate a text-based coverage report of your tests.
In Bun 1.2, we added support for LCOV coverage reporting. [LCOV](https://github.com/linux-test-project/lcov) is a standard format for code coverage reports, and is used by many tools like Codecov.
```
bun test --coverage --coverage-reporter=lcov
```
By default, this outputs a `lcov.info` coverage report file in the `coverage` directory. You can change the coverage directory with `--coverage-dir`.
If you want to always enable coverage reporting, you can add the following to your [`bunfig.toml`](../docs/runtime/bunfig.html) file.
bunfig.toml
```
[test]
coverage = true
coverageReporter = ["lcov"] # default ["text"]
coverageDir = "./path/to/folder" # default "./coverage"
```
### []()[Inline snapshots](bun-v1.2.html#inline-snapshots)
You can now use [inline snapshots](https://jestjs.io/docs/snapshot-testing#inline-snapshots) using `expect().toMatchInlineSnapshot()`.
Unlike [`toMatchSnapshot()`](https://jestjs.io/docs/expect#tomatchsnapshotpropertymatchers-hint), which stores the snapshot in a separate file, [`toMatchInlineSnapshot()`](https://jestjs.io/docs/expect#tomatchinlinesnapshotpropertymatchers-inlinesnapshot) stores snapshots directly in the test file. This makes it easier see, and even change your snapshots.
First, write a test that uses `toMatchInlineSnapshot()`.
snapshot.test.ts
```
import { expect, test } from "bun:test";
test("toMatchInlineSnapshot()", () => {
expect(new Date()).toMatchInlineSnapshot();
});
```
Next, update the snapshot with `bun test -u`, which is short for `--update-snapshots`.
```
bun test -u
```
Then, voilà! Bun has updated the test file with your snapshot.
snapshot.test.ts
```
import { expect, test } from "bun:test";
test("toMatchInlineSnapshot()", () => {
expect(new Date()).toMatchInlineSnapshot();
expect(new Date()).toMatchInlineSnapshot(`2025-01-18T02:35:53.332Z`);
});
```
You can also use these matchers, which do a similar thing:
- [`toThrowErrorMatchingSnapshot()`](https://jestjs.io/docs/expect#tothrowerrormatchingsnapshothint)
- [`toThrowErrorMatchingInlineSnapshot()`](https://jestjs.io/docs/expect#tothrowerrormatchinginlinesnapshotinlinesnapshot)
### []()[`test.only()`](bun-v1.2.html#test-only)
You can use [`test.only()`](https://jestjs.io/docs/api#testonlyname-fn-timeout) to run a single test, excluding all other tests. This is useful when you're debugging a specific test, and don't want to run the entire test suite.
```
import { test } from "bun:test";
test.only("test a", () => {
/* Only run this test */
});
test("test b", () => {
/* Don't run this test */
});
```
Previously, for this to work in Bun, you had to use the `--only` flag.
```
bun test --only
```
This was annoying, you'd usually forget to do it, and test runners like Jest don't need it! In Bun 1.2, we've made this "just work", without the need for flags.
```
bun test
```
### []()[New `expect()` matchers](bun-v1.2.html#new-expect-matchers)
In Bun 1.2, we added a bunch of matchers to the [`expect()`](https://jestjs.io/docs/expect) API. These are the same matchers that are implemented by Jest, Vitest, or the [`jest-extended`](https://jest-extended.jestcommunity.dev/) library.
You can use [`toContainValue()`](https://jest-extended.jestcommunity.dev/docs/matchers/object/#tocontainvaluevalue) and derivatives to check if an object contains a value.
```
const object = new Set(["bun", "node", "npm"]);
expect(object).toContainValue("bun");
expect(object).toContainValues(["bun", "node"]);
expect(object).toContainAllValues(["bun", "node", "npm"]);
expect(object).not.toContainAnyValues(["done"]);
```
Or, use [`toContainKey()`](https://jest-extended.jestcommunity.dev/docs/matchers/object/#tocontainkeykey) and derivatives to check if an object contains a key.
```
const object = new Map([
["bun", "1.2.0"],
["node", "22.13.0"],
["npm", "9.1.2"],
]);
expect(object).toContainKey("bun");
expect(object).toContainKeys(["bun", "node"]);
expect(object).toContainAllKeys(["bun", "node", "npm"]);
expect(object).not.toContainAnyKeys(["done"]);
```
You can also use [`toHaveReturned()`](https://jestjs.io/docs/expect#tohavereturned) and derivatives to check if a mocked function has returned a value.
```
import { jest, test, expect } from "bun:test";
test("toHaveReturned()", () => {
const mock = jest.fn(() => "foo");
mock();
expect(mock).toHaveReturned();
mock();
expect(mock).toHaveReturnedTimes(2);
});
```
### []()[Custom error messages](bun-v1.2.html#custom-error-messages)
We've also added support for custom error messages using `expect()`.
You can now pass a string as the second argument to `expect()`, which will be used as the error message. This is useful when you want to document what the assertion is checking.
example.test.ts
```
import { test, expect } from 'bun:test';
test("custom error message", () => {
expect(0.1 + 0.2).toBe(0.3);
expect(0.1 + 0.2, "Floating point has precision error").toBe(0.3);
});
```
```
1 | import { test, expect } from 'bun:test';
2 |
3 | test("custom error message", () => {
4 | expect(0.1 + 0.2, "Floating point has precision error").toBe(0.3);
^
error: expect(received).toBe(expected)
error: Floating point has precision error
Expected: 0.3
Received: 0.30000000000000004
```
### []()[`jest.setTimeout()`](bun-v1.2.html#jest-settimeout)
You can now use Jest's [`setTimeout()`](https://jestjs.io/docs/jest-object#jestsettimeouttimeout) API to change the default timeout for tests in the current scope or module, instead of setting the timeout for each test.
```
jest.setTimeout(60 * 1000); // 1 minute
test("do something that takes a long time", async () => {
await Bun.sleep(Infinity);
});
```
You can also import `setDefaultTimeout()` from Bun's test APIs, which does the same thing. We chose a different name to avoid confusion with the global `setTimeout()` function.
```
import { setDefaultTimeout } from "bun:test";
setDefaultTimeout(60 * 1000); // 1 minute
```
## []()[Bun is a JavaScript bundler](bun-v1.2.html#bun-is-a-javascript-bundler)
Bun is a JavaScript and TypeScript bundler, transpiler, and minifier that can be used to bundle code for the browser, Node.js, and other platforms.
### []()[HTML imports](bun-v1.2.html#html-imports)
In Bun 1.2, we've added support for HTML imports. This allows you to replace your entire frontend toolchain with a single import statement.
To get started, pass an HTML import to the `static` option in `Bun.serve`:
```
import homepage from "./index.html";
Bun.serve({
static: {
"/": homepage,
},
async fetch(req) {
// ... api requests
},
});
```
When you make a request to `/`, Bun automatically bundles the `<script>` and `<link>` tags in the HTML files, exposes them as static routes, and serves the result.
An index.html file like this:
index.html
```
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
<link rel="stylesheet" href="./reset.css" />
<link rel="stylesheet" href="./styles.css" />
</head>
<body>
<div id="root"></div>
<script type="module" src="./sentry-and-preloads.ts"></script>
<script type="module" src="./my-app.tsx"></script>
</body>
</html>
```
Becomes something like this:
index.html
```
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
<link rel="stylesheet" href="/index-[hash].css" />
</head>
<body>
<div id="root"></div>
<script type="module" src="/index-[hash].js"></script>
</body>
</html>
```
To read more about HTML imports and how they're implemented, check out the [HTML imports](../docs/bundler/fullstack.html) documentation.
### []()[Standalone executables](bun-v1.2.html#standalone-executables)
You can use [`bun build --compile`](../docs/bundler/executables.html) to compile your application, and Bun, into a standalone executable.
In Bun 1.2, we've added support for cross-compilation. This allows you to build a Windows or macOS binary on a Linux machine, and vice versa.
You can run the following command on a macOS or Linux machine, and it will compile a Windows binary.
```
bun build --compile --target=bun-windows-x64 app.ts
```
```
[8ms] bundle 1 modules
[1485ms] compile app.exe bun-windows-x64-v1.2.0
```
For Windows specific builds, you can customize the icon and hide the console window.
```
bun build --compile --windows-icon=./icon.ico --windows-hide-console app.ts
```
### []()[Bytecode caching](bun-v1.2.html#bytecode-caching)
You can also use [`bun build --bytecode`](../docs/bundler.html#bytecode) flag to generate a bytecode cache. This improves the startup time of applications like `eslint` to be [2x faster](https://x.com/jarredsumner/status/1840729983528137043).
```
bun build --bytecode --compile app.ts
```
```
./app
```
```
Hello, world!
```
You can also use the bytecode cache without `--compile`.
```
bun build --bytecode --outdir=dist app.ts
```
```
ls dist
```
```
app.js app.jsc
```
When Bun generates output files, it will also generate `.jsc` files, which contain the bytecode cache of its respective `.js` file. Both files are necessary to run, as the bytecode compilation doesn't currently compile async functions, generators, or eval.
The bytecode cache can be 8x larger than the source code, so this makes startup faster at a cost of increased disk space.
### []()[CommonJS output format](bun-v1.2.html#commonjs-output-format)
You can now set the output format to CommonJS with `bun build`. Previously, only ESM was supported.
```
bun build --format=cjs app.ts
```
This makes it easier to create libraries and applications meant for older versions of Node.js.
app.ts
app.js
app.ts
```
// app.ts
export default "Hello, world!";
```
app.js
```
var __defProp = Object.defineProperty;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __moduleCache = /* @__PURE__ */ new WeakMap;
var __toCommonJS = (from) => {
var entry = __moduleCache.get(from), desc;
if (entry)
return entry;
entry = __defProp({}, "__esModule", { value: true });
if (from && typeof from === "object" || typeof from === "function")
__getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
get: () => from[key],
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
}));
__moduleCache.set(from, entry);
return entry;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, {
get: all[name],
enumerable: true,
configurable: true,
set: (newValue) => all[name] = () => newValue
});
};
// app.js
var exports_site = {};
__export(exports_site, {
default: () => site_default
});
module.exports = __toCommonJS(exports_site);
var site_default = "Hello, world!";
```
### []()[Better CommonJS detection](bun-v1.2.html#better-commonjs-detection)
Some packages *really* want to trick bundlers and get the current module's file path, do a runtime require, or check if the current module is the main module. They try all kinds of things to make it work, such as:
```
"use strict";
if (eval("require.main") === eval("module.main")) {
// ...
}
```
Bun supports both CommonJS and ESM; in fact, you can use `require()` and `import` in the same file. However, one of the challenges of supporting both is that there's a lot of ambiguity.
Consider the following code, is it CommonJS or ESM?
```
console.log("123");
```
There's no way to tell. Then, how about this?
```
console.log(module.require("path"));
```
CommonJS, because it's using `module.require()` to get the `path` module. And this?
```
import path from "path";
console.log(path);
```
ESM, because it's using `import`. But, what about this?
```
import path from "path";
const fs = require("fs");
console.log(fs.readFileSync(path.resolve("package.json"), "utf8"));
```
ESM, because it's using `import`. If we said it was CommonJS due to the require, then the `import` would break the code. We want to simplify building stuff in JavaScript, so let's just say it's ESM and not be fussy.
Finally, what about this?
```
"use strict";
console.log(eval("module.require('path')"));
```
Previously, Bun would have said ESM, because it's the default when there's no way to tell (including when the file extension is ambiguous, there's no "type" field in package.json, no export, no import, etc).
In Bun 1.2, Bun will say CommonJS, because of the "use strict" directive at the top of the file. ESM is always in strict mode, so an explicit "use strict" would be redundant.
Also, most build tools that output CommonJS include "use strict" at the top of the file. So we can now use this as a last-chance heuristic when it's completely ambiguous whether the file is CommonJS or ESM.
### []()[Plugin API](bun-v1.2.html#plugin-api)
Bun has a universal [plugin API](../docs/bundler/plugins.html) for extending the bundler *and* the runtime.
You can use plugins to intercept `import()` statements, add custom loaders for extensions like `.yaml`, and implement frameworks for Bun.
### []()[`onBeforeParse()`](bun-v1.2.html#onbeforeparse)
In Bun 1.2, we're introducing a new lifecycle hook for plugins, [`onBeforeParse()`](../docs/bundler/plugins.html#onbeforeparse).
Unlike the existing lifecycle hooks that run JavaScript code, this hook must be a [N-API addon](../docs/api/node-api.html), which can be implemented in a compiled language like Rust, C/C++, or Zig.
The hook is called immediately before parsing, without cloning the source code, without undergoing string conversion, and with practically zero overhead.
For example, you can create a Rust plugin that replaces all occurrences of `foo` with `bar`.
```
bun add -g @napi-rs/cli
```
```
napi new
```
```
cargo add bun-native-plugin
```
From there, you can implement the `onBeforeParse()` hook. These are advanced APIs, primarily designed for plugin and framework authors who want to use native code to make their plugins really fast.
lib.rs
build.ts
lib.rs
```
use bun_native_plugin::{define_bun_plugin, OnBeforeParse, bun, Result, anyhow, BunLoader};
use napi_derive::napi;
define_bun_plugin!("foo-bar-plugin");
#[bun]
pub fn replace_foo_with_bar(handle: &mut OnBeforeParse) -> Result<()> {
let input_source_code = handle.input_source_code()?;
let output_source_code = input_source_code.replace("foo", "bar");
handle.set_output_source_code(output_source_code, BunLoader::BUN_LOADER_JSX);
Ok(())
}
```
build.ts
```
import { build } from "bun";
import fooBarPlugin from "./foo-bar-plugin";
await build({
entrypoints: ["./app.tsx"],
plugins: [
{
name: "foo-bar-plugin",
setup(build) {
build.onBeforeParse(
{
namespace: "file",
filter: "**/*.tsx",
},
{
napiModule: fooBarPlugin,
symbol: "replace_foo_with_bar",
},
);
},
},
],
});
```
### []()[Other changes](bun-v1.2.html#other-changes)
We also made a lot of other improvements to `bun build` and the `Bun.build()` APIs.
#### Inject environment variables
You can now inject environment variables from your system environment into your bundle.
CLI
JavaScript
CLI
```
bun build --env="PUBLIC_*" app.tsx
```
JavaScript
```
import { build } from "bun";
await build({
entrypoints: ["./app.tsx"],
outdir: "./out",
// Environment variables starting with "PUBLIC_"
// will be injected in the build as process.env.PUBLIC_*
env: "PUBLIC_*",
});
```
#### `bun build --drop`
You can use `--drop` to remove function calls from your JavaScript bundle. For example, if you pass `--drop=console`, all calls to `console.log()` will be removed from your code.
JavaScript
CLI
JavaScript
```
import { build } from "bun";
await build({
entrypoints: ["./index.tsx"],
outdir: "./out",
drop: ["console", "anyIdentifier.or.propertyAccess"],
});
```
CLI
```
bun build ./index.tsx --outdir ./out --drop=console --drop=anyIdentifier.or.propertyAccess
```
#### Banner and footer
You can now use the banner and footer options in `bun build` to add content above or below the bundle.
CLI
JavaScript
CLI
```
bun build --banner "/* Banner! */" --footer "/* Footer! */" app.ts
```
JavaScript
```
import { build } from "bun";
await build({
entrypoints: ["./app.ts"],
outdir: "./dist",
banner: "/* Banner! */",
footer: "/* Footer! */",
});
```
This is useful for appending content above or below the bundle, such as a license or copyright notice.
```
/**
* Banner!
*/
export default "Hello, world!";
/**
* Footer!
*/
```
#### `Bun.embeddedFiles()`
You can use the new `Bun.embeddedFiles()` API to see a list of all embedded files in a standalone executable, compiled with `bun build --compile`.
```
import { embeddedFiles } from "bun";
for (const file of embeddedFiles) {
console.log(file.name); // "logo.png"
console.log(file.size); // 1234
console.log(await file.bytes()); // Uint8Array(1234) [...]
}
```
#### `require.main === module`
Previously, using `require.main === module` would mark the module as CommonJS. Now, Bun rewrites this into `import.meta.main`, meaning you can use this pattern alongside import statements.
```
import * as fs from "fs";
if (typeof require !== "undefined" && require.main === module) {
console.log("main!", fs);
}
```
#### `--ignore-dce-annotations`
Some JavaScript tools support special annotations that can influence behavior during dead-code elimination. For example, the `@__PURE__` annotation tells bundlers that a function call is pure (regardless of whether it actually is), and that the call can be removed if it is not used.
```
let button = /* @__PURE__ */ React.createElement(Button, null);
```
Sometimes, a library may include incorrect annotations, which can cause Bun to remove side effects which were needed.
To workaround these issue, you can use the `--ignore-dce-annotations` flag when running `bun build` to ignore all annotations. This should only be used if dead-code elimination breaks bundles, and fixing the annotations should be preferred to leaving this flag on.
#### `--packages=external`
You can now control if package dependencies are included in your bundle or not. If the import does not start with `.`, `..` or `/`, then it is considered a package.
CLI
JavaScript
CLI
```
bun build ./index.ts --packages external
```
JavaScript
```
await Bun.build({
entrypoints: ["./index.ts"],
packages: "external",
});
```
This is useful when bundling libraries. It lets you reduce the number of files your users have to download, while continuing to support peer or external dependencies.
## []()[Built-in CSS parser](bun-v1.2.html#built-in-css-parser)
In Bun 1.2, we implemented a new CSS parser and bundler in Bun.
It's derived from the great work of [LightningCSS](https://github.com/parcel-bundler/lightningcss), and re-written from Rust to Zig so it can be integrated with Bun's custom JavaScript and TypeScript parser, bundler, and runtime.
Bun is an complete toolkit for running and building JavaScript and TypeScript. One of the missing pieces of Bun's built-in JavaScript bundler, `bun build`, is support for bundling and minifying CSS.
### []()[How it works](bun-v1.2.html#how-it-works)
CSS bundlers combine multiple CSS files and assets referenced using directives like `url`, `@import`, `@font-face`, into a single CSS file you can send to browsers, avoiding a waterfall of network requests.
index.css
foo.css
bar.css
index.css
```
@import "foo.css";
@import "bar.css";
```
foo.css
```
.foo {
background: red;
}
```
bar.css
```
.bar {
background: blue;
}
```
To see how it works, you can try it using `bun build`.
```
bun build ./index.css
```
You'll see how the CSS files are combined into a single CSS file.
dist.css
```
/** foo.css */
.foo {
background: red;
}
/** bar.css */
.bar {
background: blue;
}
```
### []()[Import `.css` files from JavaScript](bun-v1.2.html#import-css-files-from-javascript)
We've also made it possible to import `.css` files in your JavaScript and TypeScript code. This will create an additional CSS entrypoint that combines all the CSS files imported from a JavaScript module graph, along with `@import` rules.
index.ts
```
import "./style.css";
import MyComponent from "./MyComponent.tsx";
// ... rest of your app
```
In this example, if `MyComponent.tsx` imports another CSS file, instead of adding extra `.css` files to the bundle, all the CSS imported per entrypoint is flattened into a single CSS file.
shell
```
bun build ./index.ts --outdir=dist
```
```
index.js 0.10 KB
index.css 0.10 KB
[5ms] bundle 4 modules
```
### []()[Using `Bun.build()`](bun-v1.2.html#using-bun-build)
You can also bundle CSS using the programmatic `Bun.build()` API. This allows you to bundle both CSS and JavaScript in the same build, with the same API.
api.ts
```
import { build } from "bun";
const results = await build({
entrypoints: ["./index.css"],
outdir: "./dist",
});
console.log(results);
```
## []()[Bun APIs](bun-v1.2.html#bun-apis)
In addition to supporting Node.js and Web APIs, Bun also has a growing standard library that makes it easy to do common tasks, without adding more external dependencies.
### []()[Static routes in `Bun.serve()`](bun-v1.2.html#static-routes-in-bun-serve)
Bun has a built-in HTTP server that makes it easy to respond to HTTP requests using standard APIs like `Request` and `Response`. In Bun 1.2, we added support for static routes using the new `static` property.
To define a static route, pass the request path as the key and a `Response` object as the value.
```
import { serve } from "bun";
serve({
static: {
"/health-check": new Response("Ok!"),
"/old-link": Response.redirect("/new-link", 301),
"/api/version": Response.json(
{
app: require("./package.json").version,
bun: Bun.version,
},
{
headers: { "X-Powered-By": "bun" },
},
),
},
async fetch(request) {
return new Response("Dynamic!");
},
});
```
Static routes are up to [40% faster](https://x.com/jarredsumner/status/1828042864531833035) than doing it yourself in the `fetch()` handler. The response body, headers, and status code are cached in memory, so there's no JavaScript allocation or garbage collection.
If you want to reload the static routes, you can use the `reload()` method. This is useful if you want to update the static routes on a schedule, or when a file changes.
```
import { serve } from "bun";
const server = serve({
static: {
"/": new Response("Static!"),
},
async fetch(request) {
return new Response("Dynamic!");
},
});
setInterval(() => {
const date = new Date().toISOString();
server.reload({
static: {
"/": new Response(`Static! Updated at ${date}`),
},
});
}, 1000);
```
### []()[`Bun.udpSocket()`](bun-v1.2.html#bun-udpsocket)
While we added support for `node:dgram` in Bun 1.2, we also introduced UDP socket support in Bun's APIs. [`Bun.udpSocket()`](../docs/api/udp.html) is a faster, modern alternative and is similar to the existing [`Bun.listen()`](../docs/api/tcp.html) API.
```
import { udpSocket } from "bun";
const server = await udpSocket({
socket: {
data(socket, data, port, addr) {
console.log(`Received data from ${addr}:${port}:`, data.toString());
},
},
});
const client = await udpSocket({ port: 0 });
client.send("Hello!", server.port, "127.0.0.1");
```
Bun's UDP socket API is built for performance. Unlike Node.js, it can send multiple UDP datagrams with a single syscall, and supports responding to backpressure from the operating system.
```
const socket = await Bun.udpSocket({
port: 0,
socket: {
drain(socket) {
// Socket is no longer under backpressure
},
},
});
// Send multiple UDP datagrams with a single syscall:
// [ <data>, <port>, <address> ][]
socket.sendMany([
["Hello", 12345, "127.0.0.1"],
["from", 12346, "127.0.0.1"],
["Bun 1.2", 12347, "127.0.0.1"],
]);
```
This is great for building game servers that need to broadcast game state updates to every peer.
### []()[`Bun.file()`](bun-v1.2.html#bun-file)
Bun has a built-in [`Bun.file()`](../docs/api/file-io.html#reading-files-bun-file) API that makes it easy to read and write files. It extends the Web-standard `Blob` API, and makes it easier to work with files in a server environment.
In Bun 1.2, we've added support for even more `Bun.file()` APIs.
#### `delete()`
You can now delete files using the `delete()` method. An alias of `unlink()` is also supported.
```
import { file } from "bun";
await file("./package.json").delete();
await file("./node_modules").unlink();
```
#### `stat()`
You can now use the `stat()` method to get a file's metadata. This returns the same [`Stats`](https://nodejs.org/api/fs.html#class-fsstats) object as `fs.stat()` in Node.js.
```
import { file } from "bun";
const stat = await file("./package.json").stat();
console.log(stat.size); // => 1024
console.log(stat.mode); // => 33206
console.log(stat.isFile()); // => true
console.log(stat.isDirectory()); // => false
console.log(stat.ctime); // => 2025-01-21T16:00:00+00:00
```
#### Support for S3 files
With newly added built-in support for S3, you can use the same `Bun.file()` APIs with a S3 file.
```
import { s3 } from "bun";
const stat = await s3("s3://folder/my-file.txt").stat();
console.log(stat.size); // => 1024
console.log(stat.type); // => "text/plain;charset=utf-8"
await s3("s3://folder/").unlink();
```
### []()[`Bun.color()`](bun-v1.2.html#bun-color)
To support CSS with `bun build`, we implemented our own CSS parser in Bun 1.2. In doing this work, we decided to expose some useful APIs for working with colors.
You can use [`Bun.color()`](../docs/api/color.html) to parse, normalize, and convert colors into a variety of formats. It supports CSS, ANSI color codes, RGB, HSL, and more.
```
import { color } from "bun";
color("#ff0000", "css"); // => "red"
color("rgb(255, 0, 0)", "css"); // => "red"
color("red", "ansi"); // => "\x1b[31m"
color("#f00", "ansi-16m"); // => "\x1b[38;2;255;0;0m"
color(0xff0000, "ansi-256"); // => "\u001b[38;5;196m"
color({ r: 255, g: 0, b: 0 }, "number"); // => 16711680
color("hsl(0, 0%, 50%)", "{rgba}"); // => { r: 128, g: 128, b: 128, a: 1 }
```
### []()[`dns.prefetch()`](bun-v1.2.html#dns-prefetch)
You can use the new [`dns.prefetch()`](../docs/api/dns.html#dns-prefetch) API to prefetch DNS records before they are needed. This is useful if you want to pre-warm the DNS cache on startup.
```
import { dns } from "bun";
// ...on startup
dns.prefetch("example.com");
// ...later on
await fetch("https://example.com/");
```
This will prefetch the DNS record for example.com and make it available for use in `fetch()` requests. You can also use the [`dns.getCacheStats()`](../docs/api/dns.html#dns-getcachestats) API to observe the DNS cache.
```
import { dns } from "bun";
await fetch("https://example.com/");
console.log(dns.getCacheStats());
// {
// cacheHitsCompleted: 0,
// cacheHitsInflight: 0,
// cacheMisses: 1,
// size: 1,
// errors: 0,
// totalCount: 1,
// }
```
### []()[Helpful utilities](bun-v1.2.html#helpful-utilities)
We also added a few random utilities to Bun's APIs.
#### `Bun.inspect.table()`
You can now use `Bun.inspect.table()` to format tabular data into a string. It's similar to [`console.table`](https://developer.mozilla.org/en-US/docs/Web/API/console/table_static), except it returns a string rather than printing to the console.
```
console.log(
Bun.inspect.table([
{ a: 1, b: 2, c: 3 },
{ a: 4, b: 5, c: 6 },
{ a: 7, b: 8, c: 9 },
]),
);
// ┌───┬───┬───┬───┐
// │ │ a │ b │ c │
// ├───┼───┼───┼───┤
// │ 0 │ 1 │ 2 │ 3 │
// │ 1 │ 4 │ 5 │ 6 │
// │ 2 │ 7 │ 8 │ 9 │
// └───┴───┴───┴───┘
```
#### `Bun.randomUUIDv7()`
You can use `Bun.randomUUIDv7()` to generate a [UUID v7](https://www.ietf.org/archive/id/draft-peabody-dispatch-new-uuid-format-01.html#name-uuidv7-layout-and-bit-order), a monotonic UUID suitable for sorting and databases.
index.ts
```
import { randomUUIDv7 } from "bun";
const uuid = randomUUIDv7();
// => "0192ce11-26d5-7dc3-9305-1426de888c5a"
```
## []()[New in Bun's built-in SQLite client](bun-v1.2.html#new-in-bun-s-built-in-sqlite-client)
Bun has a built-in [SQLite client](../docs/api/sqlite.html) that makes it easy to query SQLite databases. In Bun 1.2, we've added a few new features to make it even easier to use.
### []()[ORM-less object mapping](bun-v1.2.html#orm-less-object-mapping)
When you query a SQL database, you often want to map your query results to a JavaScript object. That's why there's so many popular [ORM](https://www.prisma.io/dataguide/types/relational/what-is-an-orm#do-i-need-an-orm) (Object-Relational Mapping) packages like Prisma and TypeORM.
You can now use [`query.as(Class)`](../docs/api/sqlite.html#as-class-map-query-results-to-a-class) to map query results to instances of a class. This lets you attach methods, getters, and setters without using an ORM.
```
import { Database } from "bun:sqlite";
class Tweet {
id: number;
text: string;
username: string;
get isMe() {
return this.username === "jarredsumner";
}
}
const db = new Database("tweets.db");
const tweets = db.query("SELECT * FROM tweets").as(Tweet);
for (const tweet of tweets.all()) {
if (!tweet.isMe) {
console.log(`${tweet.username}: ${tweet.text}`);
}
}
```
For performance reasons, class constructors, default initializers, and private fields are not supported. Instead, it uses the equivalent of `Object.create()` to create a new object with the class's prototype and assigns the values of the row to it.
It's also important to note that this is *not* an ORM. It doesn't manage relationships, generate SQL queries, or anything like that. However, it does remove a lot of boilerplate to get JavaScript objects from SQLite!
### []()[Iterable queries](bun-v1.2.html#iterable-queries)
You can now use [`query.iterate()`](../docs/api/sqlite.html#iterate-iterator) to get an iterator that yields rows as they are returned from the database. This is useful when you want to process rows at a time, without loading them all into memory.
```
import { Database } from "bun:sqlite";
class User {
id: number;
email: string;
}
const db = new Database("users.db");
const rows = db.query("SELECT * FROM users").as(User).iterate();
for (const row of rows) {
console.log(row);
}
```
You can also iterate over the query using a `for` loop, without calling `iterate()`.
```
for (const row of db.query("SELECT * FROM users")) {
console.log(row); // { id: 1, email: "hello@bun.sh" }
}
```
### []()[Strict query parameters](bun-v1.2.html#strict-query-parameters)
You can now omit the `$`, `@`, or `:` prefix when passing JavaScript values as query parameters.
```
import { Database } from "bun:sqlite";
const db = new Database(":memory:", {
strict: false,
strict: true,
});
const query = db.query(`select $message;`);
query.all({
$message: "Hello world"
message: "Hello world"
});
```
To use this behavior, enable the [`strict`](../docs/api/sqlite.html#strict-mode) option. This will allow you to omit the `$`, `@`, or `:` prefixes, and will throw an error if a parameter is missing.
### []()[Tracking changed rows](bun-v1.2.html#tracking-changed-rows)
You can now access the number of rows changed and the last inserted row ID when running queries.
```
import { Database } from "bun:sqlite";
const db = new Database(":memory:");
db.run(`CREATE TABLE users (id INTEGER, username TEXT)`);
const { changes, lastInsertRowid } = db.run(
`INSERT INTO users VALUES (1, 'jarredsumner')`,
);
console.log({
changes, // => 1
lastInsertRowid, // => 1
});
```
### []()[BigInt support](bun-v1.2.html#bigint-support)
If you want to use 64-bit integers, you can enable the [`safeIntegers`](../docs/api/sqlite.html#safeintegers-true) option. This will return integers as as a `BigInt`, instead of a truncated `number`.
```
import { Database } from "bun:sqlite";
const db = new Database(":memory:", { safeIntegers: true });
const query = db.query(
`SELECT ${BigInt(Number.MAX_SAFE_INTEGER) + 1n} as maxInteger`,
);
const { maxInteger } = query.get();
console.log(maxInteger); // => 9007199254740992n
```
You can also enable this on a per-query basis using the [`safeIntegers()`](../docs/api/sqlite.html#safeintegers-true) method.
```
import { Database } from "bun:sqlite";
const db = new Database(":memory:", { strict: true });
const query = db.query("SELECT $value as value").safeIntegers(true);
const { value } = query.get({
value: BigInt(Number.MAX_SAFE_INTEGER) + 1n,
});
console.log(value); // => 9007199254740992n
```
### []()[Reliable cleanup with `using`](bun-v1.2.html#reliable-cleanup-with-using)
With JavaScript's [`using`](https://github.com/tc39/proposal-explicit-resource-management?tab=readme-ov-file#ecmascript-explicit-resource-management) syntax, you can automatically close statements and databases when their variables go out of scope. This allows you to clean up database resources, even if there's a thrown error. [Read on](bun-v1.2.html#resource-management-with-using) for more details on Bun's support for this new JavaScript feature.
```
import { Database } from "bun:sqlite";
{
using db = new Database("file.db");
using query = db.query("SELECT * FROM users");
for (const row of query.all()) {
throw new Error("Oops!"); // no try/catch block needed!
}
}
// scope ends here, so `db` and `query` are automatically closed
```
## []()[Compile and run C from JavaScript](bun-v1.2.html#compile-and-run-c-from-javascript)
We've added experimental support for compiling and running C from JavaScript. This is a simple way to use C system libraries from JavaScript *without a build step*.
random.c
random.ts
random.c
```
#include <stdio.h>
#include <stdlib.h>
int random() {
return rand() + 42;
}
```
random.ts
```
import { cc } from "bun:ffi";
const { symbols: { random } } = cc({
source: "./random.c",
symbols: {
random: {
returns: "int",
args: [],
},
},
});
console.log(random()); // 42
```
### []()[Why is this useful?](bun-v1.2.html#why-is-this-useful)
For advanced use-cases or where performance is really important, you sometimes need to use system libraries from JavaScript. Today, the most common way to do this is by compiling a [N-API addon](https://nodejs.org/api/n-api.html) using [`node-gyp`](https://github.com/nodejs/node-gyp). You might notice if a package uses this, because it runs a postinstall script when you install it.
However, this isn't a great experience. Your system needs a modern version of Python and a C compiler, which is usually installed using a command like `apt install build-essential`.
And hopefully you don't run into a compiler or node-gyp error, which can be quite frustrating.
```
gyp ERR! command "/usr/bin/node" "/tmp/node-gyp@latest--bunx/node_modules/.bin/node-gyp" "configure" "build"
gyp ERR! cwd /bun/test/node_modules/bktree-fast
gyp ERR! node -v v12.22.9
gyp ERR! node-gyp -v v9.4.0
gyp ERR! Node-gyp failed to build your package.
gyp ERR! Try to update npm and/or node-gyp and if it does not help file an issue with the package author.
error: "node-gyp" exited with code 7 (SIGBUS)
```
### []()[How does it work?](bun-v1.2.html#how-does-it-work)
In case you didn't know, Bun embeds a built-in C compiler called [`tinycc`](https://github.com/TinyCC/tinycc). Surprise!
Unlike traditional C compilers, like `gcc` or `clang`, that can take seconds to compile a simple program, `tinycc` compiles simple C code in milliseconds. This makes it possible for Bun to compile your C code on-demand, without a build step.
Using the [`bun:ffi`](../docs/api/cc.html) APIs, you can compile and run C code from JavaScript. Here's an example project that uses the [N-API](../docs/api/node-api.html) to return a JavaScript string from C code.
hello-napi.c
hello-napi.js
hello-napi.c
```
#include <node/node_api.h>
napi_value hello_napi(napi_env env) {
napi_value result;
napi_create_string_utf8(env, "Hello, N-API!", NAPI_AUTO_LENGTH, &result);
return result;
}
```
hello-napi.js
```
import { cc } from "bun:ffi";
import source from "./hello-napi.c" with { type: "file" };
const hello = cc({
source,
symbols: {
hello_napi: {
args: ["napi_env"],
returns: "napi_value",
},
},
});
console.log(hello());
// => "Hello, N-API!"
```
Instead of requiring a build step with `node-gyp`, as long as you have Bun, this just works.
## []()[musl support](bun-v1.2.html#musl-support)
In Bun 1.2, we've introduced a new build of Bun that works on Linux distros that use the [musl libc](https://www.musl-libc.org/) instead of glibc, like [Alpine Linux](https://www.alpinelinux.org/). This is supported on both Linux x64 and aarch64.
You can also use the [alpine version](https://hub.docker.com/r/oven/bun) of Bun in Docker.
```
docker run --rm -it oven/bun:alpine bun --print 'Bun.file("/etc/alpine-release").text()'
```
```
3.20.5
```
While musl enables smaller container images, it tends to perform slightly slower than the glibc version of Bun. We recommend using glibc unless you have a specific reason to use musl.
## []()[JavaScript features](bun-v1.2.html#javascript-features)
JavaScript is a language that is constantly evolving. In Bun 1.2, even more JavaScript features are available thanks to the collaboration of the [TC39](https://tc39.es) committees, and the hard work of the [WebKit](https://webkit.org) team.
### []()[Import attributes](bun-v1.2.html#import-attributes)
You can now specify an [import attribute](https://github.com/tc39/proposal-import-attributes) when importing a file. This is useful when you want to import a file that isn't JavaScript code, like a JSON object or a text file.
```
import json from "./package.json" with { type: "json" };
typeof json; // "object"
import html from "./index.html" with { type: "text" };
typeof html; // "string"
import toml from "./bunfig.toml" with { type: "toml" };
typeof toml; // "object"
```
You can also specify import attributes using `import()`.
```
const { default: json } = await import("./package.json", {
with: { type: "json" },
});
typeof json; // "object"
```
### []()[Resource management with `using`](bun-v1.2.html#resource-management-with-using)
With the newly introduced [`using`](https://github.com/tc39/proposal-explicit-resource-management?tab=readme-ov-file#ecmascript-explicit-resource-management) syntax in JavaScript, you can automatically close resources when a variable goes out of scope.
Instead of defining a variable with `let` or `const`, you can now define a variable with `using`.
```
import { serve } from "bun";
{
using server = serve({
port: 0,
fetch(request) {
return new Response("Hello, world!");
},
});
doStuff(server);
}
function doStuff(server) {
// ...
}
```
In this example, the server is automatically closed when the `server` variable goes out of scope, even if an exception is thrown. This is useful for ensuring that resources are properly cleaned up, especially in tests.
To support this, an object's prototype must define a `[Symbol.dispose]` method, or `[Symbol.asyncDispose]` method if it's an async resource.
```
class Resource {
[Symbol.dispose]() { /* ... */ }
}
using resource = new Resource();
class AsyncResource {
async [Symbol.asyncDispose]() { /* ... */ }
}
await using asyncResource = new AsyncResource();
```
We've also added support for `using` in dozens of Bun APIs, including `Bun.spawn()`, `Bun.serve()`, `Bun.connect()`, `Bun.listen()`, and `bun:sqlite`.
```
import { spawn } from "bun";
import { test, expect } from "bun:test";
test("able to spawn a process", async () => {
using subprocess = spawn({
cmd: [process.execPath, "-e", "console.log('Hello, world!')"],
stdout: "pipe",
});
// Even if this expectation fails, the subprocess will still be closed.
const stdout = new Response(subprocess.stdout).text();
await expect(stdout).resolves.toBe("Hello, world!");
});
```
### []()[`Promise.withResolvers()`](bun-v1.2.html#promise-withresolvers)
You can use [`Promise.withResolvers()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers) to create a promise that resolves or rejects when you call the `resolve` or `reject` functions.
```
const { promise, resolve, reject } = Promise.withResolvers();
setTimeout(() => resolve(), 1000);
await promise;
```
This is a useful alternative to `new Promise()`, since you don't need to create a new scope.
```
const promise = new Promise((resolve, reject) => {
setTimeout(() => resolve(), 1000);
});
await promise;
```
### []()[`Promise.try()`](bun-v1.2.html#promise-try)
You can use [`Promise.try()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/try) to create a promise that wraps a synchronous or asynchronous function.
```
const syncFn = () => 1 + 1;
const asyncFn = async (a, b) => 1 + a + b;
await Promise.try(syncFn); // => 2
await Promise.try(asyncFn, 2, 3); // => 6
```
This is useful if you don't know if a function is synchronous or asynchronous. Previously, you would have to do something like this:
```
await new Promise((resolve) => resolve(syncFn()));
await new Promise((resolve) => resolve(asyncFn(2, 3)));
```
### []()[`Error.isError()`](bun-v1.2.html#error-iserror)
You can now check if an object is an `Error` instance using [`Error.isError()`](https://github.com/tc39/proposal-is-error/tree/main?tab=readme-ov-file#erroriserror).
```
Error.isError(new Error()); // => true
Error.isError({}); // => false
Error.isError(new (class Error {})()); // => false
Error.isError({ [Symbol.toStringTag]: "Error" }); // => false
```
This is more correct than using `instanceof` because the prototype chain can be tampered with, and `instanceof` can return false-negatives when using `node:vm`.
```
import { runInNewContext } from "node:vm";
const crossRealmError = runInNewContext("new Error()");
crossRealmError instanceof Error; // => false
Error.isError(crossRealmError); // => true
```
These APIs are standard alternatives to the usage of `Buffer.toString("hex")` in Node.js.
### []()[Iterator helpers](bun-v1.2.html#iterator-helpers)
There are new APIs that make it easier to work with JavaScript iterators and generators.
#### `iterator.map(fn)`
Returns an iterator that yields the results of the `fn` function applied to each value of the original iterator, similar to `Array.prototype.map`.
```
function* range(start: number, end: number): Generator<number> {
for (let i = start; i < end; i++) {
yield i;
}
}
const result = range(3, 5).map((x) => x * 2);
result.next(); // { value: 6, done: false }
```
#### `iterator.flatMap(fn)`
Returns an iterator that yields the values of the original iterator, but flattens the results of the `fn` function, similar to `Array.prototype.flatMap`.
```
function* randomThoughts(): Generator<string> {
yield "Bun is written in Zig";
yield "Bun runs JavaScript and TypeScript";
}
const result = randomThoughts().flatMap((x) => x.split(" "));
result.next(); // { value: "Bun", done: false }
result.next(); // { value: "is", done: false }
// ...
result.next(); // { value: "TypeScript", done: false }
```
#### `iterator.filter(fn)`
Returns an iterator that only yields values that pass the `fn` predicate, similar to `Array.prototype.filter`.
```
function* range(start: number, end: number): Generator<number> {
for (let i = start; i < end; i++) {
yield i;
}
}
const result = range(3, 5).filter((x) => x % 2 === 0);
result.next(); // { value: 4, done: false }
```
#### `iterator.take(n)`
Returns an iterator that yields the first `n` values of the original iterator.
```
function* odds(): Generator<number> {
let i = 1;
while (true) {
yield i;
i += 2;
}
}
const result = odds().take(1);
result.next(); // { value: 1, done: false }
result.next(); // { done: true }
```
#### `iterator.drop(n)`
Returns an iterator that yields all values of the original iterator, except the first `n` values.
```
function* evens(): Generator<number> {
let i = 0;
while (true) {
yield i;
i += 2;
}
}
const result = evens().drop(2);
result.next(); // { value: 4, done: false }
result.next(); // { value: 6, done: false }
```
#### `iterator.reduce(fn, initialValue)`
Reduces the values of an iterator with a function, similar to `Array.prototype.reduce`.
```
function* powersOfTwo(): Generator<number> {
let i = 1;
while (true) {
yield i;
i *= 2;
}
}
const result = powersOfTwo()
.take(5)
.reduce((acc, x) => acc + x, 0);
console.log(result); // 15
```
#### `iterator.toArray()`
Returns an array that contains all the values of the original iterator. Make sure that the iterator is finite, otherwise this will cause an infinite loop.
```
function* range(start: number, end: number): Generator<number> {
for (let i = start; i < end; i++) {
yield i;
}
}
const result = range(1, 5).toArray();
console.log(result); // [1, 2, 3, 4]
```
#### `iterator.forEach(fn)`
Calls the `fn` function on each value of the original iterator, similar to `Array.prototype.forEach`.
```
function* randomThoughts(): Generator<string> {
yield "Bun is written in Zig";
yield "Bun runs JavaScript and TypeScript";
}
const result = randomThoughts().forEach((x) => console.log(x));
// Bun is written in Zig
// Bun runs JavaScript and TypeScript
```
#### `iterator.find(fn)`
Returns the first value of the original iterator that passes the `fn` predicate, similar to `Array.prototype.find`. If no such value exists, it returns `undefined`.
```
function* range(start: number, end: number): Generator<number> {
for (let i = start; i < end; i++) {
yield i;
}
}
const result = range(0, 99).find((x) => x % 100 === 0);
console.log(result); // undefined
```
### []()[`Float16Array`](bun-v1.2.html#float16array)
There's now support for 16-bit floating point arrays using [`Float16Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float16Array). While 16-bit floating point numbers are less precise than 32-bit floating point numbers, they are much more memory efficient.
```
const float16 = new Float16Array(3);
const float32 = new Float32Array(3);
for (let i = 0; i < 3; i++) {
float16[i] = i + 0.123;
float32[i] = i + 0.123;
}
console.log(float16); // Float16Array(3) [ 0, 1.123046875, 2.123046875 ]
console.log(float32); // Float32Array(3) [ 0, 1.1230000257492065, 2.122999906539917 ]
```
## []()[Web APIs](bun-v1.2.html#web-apis)
In addition to new JavaScript features, there are also new Web-standard APIs that you can use in Bun.
### []()[`TextDecoderStream`](bun-v1.2.html#textdecoderstream)
You can now use [`TextDecoderStream`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoderStream) and [`TextEncoderStream`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoderStream) to encode and decode streams of data. These APIs are the streaming equivalents of [`TextDecoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder) and [`TextEncoder`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder).
You can use `TextDecoderStream` to decode a stream of bytes into a stream of UTF-8 strings.
```
const response = await fetch("https://example.com");
const body = response.body.pipeThrough(new TextDecoderStream());
for await (const chunk of body) {
console.log(chunk); // typeof chunk === "string"
}
```
Or you can use `TextEncoderStream` to encode a stream of UTF-8 strings into a stream of bytes. In Bun, this is up to [30x faster](https://twitter.com/jarredsumner/status/1822221334056935771) than in Node.js.
```
const stream = new ReadableStream({
start(controller) {
controller.enqueue("Hello, world!");
controller.close();
},
});
const body = stream.pipeThrough(new TextEncoderStream());
for await (const chunk of body) {
console.log(chunk); // chunk instanceof Uint8Array
}
```
### []()[`TextDecoder` with `stream` option](bun-v1.2.html#textdecoder-with-stream-option)
There is also support for the `stream` option in `TextDecoder`. This tells the decoder that chunks are part of a larger stream, and it should not throw an error if chunk is not a complete UTF-8 code point.
```
const decoder = new TextDecoder("utf-8");
const first = decoder.decode(new Uint8Array([226, 153]), { stream: true });
const second = decoder.decode(new Uint8Array([165]), { stream: true });
console.log(first); // ""
console.log(second); // "♥"
```
### []()[`bytes()` API](bun-v1.2.html#bytes-api)
You can now use the `bytes()` method on streams, which returns a `Uint8Array` of the stream's data.
```
const response = await fetch("https://example.com/");
const bytes = await response.bytes();
console.log(bytes); // Uint8Array(1256) [ 60, 33, ... ]
```
Previously, you'd have to use `arrayBuffer()`, then create a new `Uint8Array`:
```
const blob = new Blob(["Hello, world!"]);
const buffer = await blob.arrayBuffer();
const bytes = new Uint8Array(buffer);
```
The `bytes()` method is supported by several APIs, including `Response`, `Blob`, and `Bun.file()`.
```
import { file } from "bun";
const content = await file("./hello.txt").bytes();
console.log(content); // Uint8Array(1256) [ 60, 33, ... ]
```
### []()[Streaming `fetch()` uploads](bun-v1.2.html#streaming-fetch-uploads)
You can now send a [`fetch()`](https://developer.mozilla.org/en-US/docs/Web/API/fetch) request with a streaming body. This is useful for uploading large files, or streams of data where the content length is not known ahead of time.
```
await fetch("https://example.com/upload", {
method: "POST",
body: async function* () {
yield "Hello";
yield " ";
yield "world!";
},
});
```
### []()[`console.group()`](bun-v1.2.html#console-group)
You can now use [`console.group()`](https://developer.mozilla.org/en-US/docs/Web/API/console/group_static) and [`console.groupEnd()`](https://developer.mozilla.org/en-US/docs/Web/API/console/groupEnd_static) to create a nested log messages. Previously, these were not implemented in Bun, and it would do nothing.
index.js
```
console.group("begin");
console.log("indent!");
console.groupEnd();
// begin
// indent!
```
### []()[`URL.createObjectURL()`](bun-v1.2.html#url-createobjecturl)
There is now support for [`URL.createObjectURL()`](https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL), which creates a URL from a Blob object. These urls can then be used in APIs like `fetch()`, `Worker`, and `import()`.
When combined with `Worker`, it allows for an easy way to spawn additional threads without creating a new separate URL for the worker's script. Since worker scripts also run through Bun's transpiler, TypeScript syntax is supported.
worker.ts
```
const code = `
const foo: number = 123;
postMessage({ foo } satisfies Data);
`;
const blob = new File([code], "worker.ts");
const url = URL.createObjectURL(blob);
const worker = new Worker(url);
worker.onmessage = ({ data }) => {
console.log("Received data:", data);
};
```
### []()[`AbortSignal.any()`](bun-v1.2.html#abortsignal-any)
You can use [`AbortSignal.any()`](https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/any_static) to combine multiple instances of `AbortSignal`. If one of the child signals is aborted, the parent signal is also aborted.
```
const { signal: firstSignal } = new AbortController();
fetch("https://example.com/", { signal: firstSignal });
const { signal: secondSignal } = new AbortController();
fetch("https://example.com/", { signal: secondSignal });
// Cancels if either `firstSignal` or `secondSignal` is aborted
const signal = AbortSignal.any([firstSignal, secondSignal]);
await fetch("https://example.com/slow", { signal });
```
## []()[Behaviour changes](bun-v1.2.html#behaviour-changes)
Bun 1.2 contains a few behaviour tweaks to that you should be aware of, but we think is unlikely to break your code. We avoid making these changes unless we think the status-quo is *so broken* that it's worth it.
### []()[`bun run` uses the correct directory](bun-v1.2.html#bun-run-uses-the-correct-directory)
Previously, when you ran a `package.json` script using `bun run`, the working directory of the script was the same as the current working directory of your shell.
In most cases, you don't notice a difference, because your shell's working directory is *usually* the same as the parent directory of your `package.json` file.
```
cd /path/to/project
```
```
ls
```
```
package.json
```
```
bun run pwd
```
```
/path/to/project
```
However, if you `cd` into a different directory, you'll notice the difference.
```
cd dist
```
```
bun run pwd
```
```
/path/to/project/dist
```
This does not match what other package managers do, like `npm` or `yarn`, and more-often-than-not causes unexpected behaviour.
In Bun 1.2, the working directory of the script is now the parent directory of the `package.json` file, instead of the current working directory of your shell.
```
cd /path/to/project/dist
```
```
bun run pwd
```
```
/path/to/project/dist
/path/to/project
```
### []()[Uncaught errors in `bun test`](bun-v1.2.html#uncaught-errors-in-bun-test)
Previously, `bun test` would not fail when there was an uncaught error or rejection between test cases.
```
import { test, expect } from "bun:test";
test("should have failed, but didn't", () => {
setTimeout(() => {
throw new Error("Oops!");
}, 1);
});
```
In Bun 1.2, this has now been fixed, and `bun test` will report the failure.
```
# Unhandled error between tests
-------------------------------
1 | import { test, expect } from "bun:test";
2 |
3 | test("should have failed, but didn't", () => {
4 | setTimeout(() => {
5 | throw new Error("Oops!");
^
error: Oops!
at foo.test.ts:5:11
-------------------------------
```
### []()[`server.stop()` returns a Promise](bun-v1.2.html#server-stop-returns-a-promise)
Previously, there was no way to gracefully wait for connections to close from Bun's HTTP server.
To make this possible, we made `stop()` return a promise, which resolves when in-flight HTTP connections are closed.
```
interface Server {
stop(): void;
stop(): Promise<void>;
}
```
### []()[`Bun.build()` rejects when it fails](bun-v1.2.html#bun-build-rejects-when-it-fails)
Previously, when `Bun.build()` would fail, it would report the error in the `logs` array. This was often confusing, because the promise would resolve successfully.
```
import { build } from "bun";
const result = await build({
entrypoints: ["./bad.ts"],
});
console.log(result.logs[0]); // error: ModuleNotFound resolving "./bad.ts" (entry point)
```
In Bun 1.2, `Bun.build()` will now reject when it fails, instead of returning errors in the `logs` array.
```
const result = build({
entrypoints: ["./bad.ts"],
});
await result; // error: ModuleNotFound resolving "./bad.ts" (entry point)
```
If you want to restore to the old behaviour, you can set the `throw: false` option.
```
const result = await build({
entrypoints: ["./bad.ts"],
throw: false,
});
```
### []()[`bun -p` is an alias for `bun --print`](bun-v1.2.html#bun-p-is-an-alias-for-bun-print)
Previously, `bun -p` was an alias for `bun --port`, which was used to change the port of `Bun.serve()`. The alias was added before Bun supported `bun --print`.
To match Node.js, we've changed `bun -p` to be an alias for `bun --print`.
```
bun -p 'new Date()'
```
```
2025-01-17T22:55:27.659Z
```
### []()[`bun build --sourcemap`](bun-v1.2.html#bun-build-sourcemap)
Previously, using `bun build --sourcemap` would default to inlined source maps.
```
bun build --sourcemap ./index.ts --outfile ./index.js
```
index.js
```
console.log("Hello Bun!");
```
index.js.map
```
{
"version": 3,
"sources": ["index.ts"],
// ...
}
```
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/commonjs-is-not-going-away.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# CommonJS is not going away
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · June 30, 2023
[](../rss.xml)
We're hiring C/C++ and Zig engineers to build the future of JavaScript! [Join our team →](../careers.html)
Some may be surprised to see the [recent](bun-v0.6.5.html) [release](bun-v0.6.10.html) [notes](bun-v0.6.12.html) for Bun mention CommonJS support. After all, CommonJS is a legacy module system, and the future of JavaScript is ES Modules (ESM), right? As a "forward-thinking" "next-gen" runtime, why would Bun put so much effort into improving CommonJS support?
> The latest about ESM on npm: ESM is now at 9%, dual at 3.8, faux ESM at 13.7%, and CJS at 73.6%.
>
> This data includes only the most popular npm packages (1m+ downloads per week and/or 500+ others depend on it), excluding the TypeScript types/* packages. [pic.twitter.com/kdZg5tM9N6](https://t.co/kdZg5tM9N6)
>
> — Titus 🇵🇸 (@wooorm) [November 5, 2022](https://twitter.com/wooorm/status/1588905279206621184?ref_src=twsrc%5Etfw)
Because CommonJS is here to stay, and that's okay! We think that better tooling can solve today's developer experience issues with CommonJS and ESM interop.
## []()[The situation, explained](commonjs-is-not-going-away.html#the-situation-explained)
As you might imagine, it's often desirable to split your application into multiple files. When you do this, you need a way to reference code in other files.
The *CommonJS* module format was developed in 2009 and popularized by Node.js. Files can assign properties to a special variable called `exports`. Then, other files can reference properties from the `exports` object by "requiring" the file with a special `require` function.
a.js
b.js
a.js
```
const b = require("./b.js");
b.sayHi(); // prints "hi"
```
b.js
```
exports.sayHi = () => {
console.log("hi");
};
```
To overly simplify how this works: when a file is `require`d, the file is *executed* and the properties of the `exports` object are made available to the importer. CommonJS is designed for server-side JavaScript (in fact, it was originally named *ServerJS*), where it's expected that all files are available on the local filesystem. This is what it means for CommonJS to be *synchronous* — you can conceptualize `require()` as a "blocking" operation that reads the imported file and runs it, then hands control back to the importer.
ECMAScript modules were introduced in 2015 as part of ES6. An ES module declares its exports with the `export` keyword. The `import` keyword is used to import from other files. Unlike `exports/require`, both `import` and `export` statements can only occur at the *top level* of a file.
a.js
b.js
a.js
```
import { sayHi } from "./b.js"
sayHi(); // prints "hi"
```
b.js
```
export const sayHi = () => {
console.log("hi");
};
```
Because ES modules are designed to work in browsers, it's expected that files are loaded over the network. This is what it means for ES modules to be *asynchronous*. Given an ES module, a browser can see what it imports and exports *without running the file*. Commonly, the entire module graph will be resolved (which may potentially involve multiple round-trip network requests) before any code is executed.
## []()[The case for CommonJS](commonjs-is-not-going-away.html#the-case-for-commonjs)
### []()[CommonJS starts faster](commonjs-is-not-going-away.html#commonjs-starts-faster)
ES modules are slower for larger applications. Unlike require, you either need load the entire module graph when using statements or await each import with expressions. For example, if you want to lazy-load a package for use in a function, your code *must* return a promise (which can introduce additional microticks and overhead).
```
async function transpileEsm(code) {
const { transform } = await import("@babel/core");
// ... return must be a Promise
}
function transpileCjs(code) {
const { transform } = require("@babel/core");
// ... return is sync
}
```
ES Modules are slower by design. They need two passes in order to bind imports to exports. The entire module graph gets parsed and analyzed, *then* the code gets evaluated. This is split into distinct steps. It's what makes "live bindings" in ES Modules possible.
Consider these two simple files.
babel.cjs
babel.mjs
babel.cjs
```
require("@babel/core")
```
babel.mjs
```
import "@babel/core";
```
Babel is a package that consists of a huge number of files, so comparing the runtime of these two files is a decent way to evaluate performance costs associated with module resolution. The results:
[](https://github.com/oven-sh/bun/assets/3084745/87414629-c433-4141-ba19-08a9d4451196)
With Bun, loading Babel with CommonJS is roughly 2.4x faster than with ES modules.
There's a difference of 85ms. In the context of serverless cold starts, that is massive. With Node.js the difference was 1.8x (~60ms).
### []()[Incremental loading](commonjs-is-not-going-away.html#incremental-loading)
CommonJS allows for dynamic module loading—you can `require()` a file conditionally, or `require()` a dynamically constructed path/specifier, or `require()` in the body of a function. This flexibility can be advantageous in scenarios where dynamic loading is required, such as plugin systems or lazy-loading specific components based on user interactions.
ES modules provide a dynamic `import()` function with similar properties. In some sense, its existence is a testament to the fact that the CommonJS's dynamic approach has utility and is valued by developers.
### []()[It's already here](commonjs-is-not-going-away.html#it-s-already-here)
Millions of modules published to npm already use CommonJS. Many of these are both: (a) are no longer actively maintained, and (b) are critically important to existing projects. We will never hit a point where *all* packages can be expected to use ES modules. A runtime or framework that doesn't support CommonJS is leaving a huge amount of value on the table.
## []()[CommonJS in Bun](commonjs-is-not-going-away.html#commonjs-in-bun)
As of Bun v0.6.5, the Bun runtime natively implements CommonJS. Previously, Bun transpiled CommonJS files to a special "synchronous ESM" format.
### []()[Importing CommonJS from ESM](commonjs-is-not-going-away.html#importing-commonjs-from-esm)
You can `import` or `require` CommonJS modules from ESM modules.
```
import { stuff } from "./my-commonjs.cjs";
import Stuff from "./my-commonjs.cjs";
const myStuff = require("./my-commonjs.cjs");
```
Recently, Bun also added support for the [`__esModule` annotation](https://github.com/oven-sh/bun/pull/3393).
module.js
```
exports.__esModule = true;
exports.default = 5;
exports.foo = "foo";
```
This is a de-facto mechanism for a CommonJS module to indicate (in conjunction with `"type": "module"` in `package.json`) that `exports.default` should be interpreted as the *default export*. When `__esModule` is set in a CommonJS module, a *default `import`* (`import a from "./a.js"`) will import the `exports.default` property. Without the annotation, a default import will import the entire `exports` object.
With the annotation:
```
// with __esModule: true
import mod, { foo } from "./module.js";
mod; // 5
foo; // "foo"
```
Without the annotation:
```
// without __esModule
import mod, { foo } from "./module.js";
mod; // { default: 5 }
mod.default; // 5
foo; // "foo"
```
This is a de-facto standard way for a CommonJS module to indicate that `exports.default` should be interpreted as the *default export*.
## []()[In summary](commonjs-is-not-going-away.html#in-summary)
CommonJS is already here to stay. Not only that, it has real reasons to exist. We love ES modules here at Bun, but pragmatism is important. CommonJS is not a relic of a bygone era, and Bun treats it as a first-class citizen today.
On this page
- [The situation, explained](commonjs-is-not-going-away.html#the-situation-explained)
- [The case for CommonJS](commonjs-is-not-going-away.html#the-case-for-commonjs)
- [CommonJS starts faster](commonjs-is-not-going-away.html#commonjs-starts-faster)
- [Incremental loading](commonjs-is-not-going-away.html#incremental-loading)
- [It's already here](commonjs-is-not-going-away.html#it-s-already-here)
- [CommonJS in Bun](commonjs-is-not-going-away.html#commonjs-in-bun)
- [Importing CommonJS from ESM](commonjs-is-not-going-away.html#importing-commonjs-from-esm)
- [In summary](commonjs-is-not-going-away.html#in-summary)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/compile-and-run-c-in-js.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# Compile and run C in JavaScript
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · September 18, 2024
[](../rss.xml)
From compression to cryptography to networking to the web browser you're reading this on, the world runs on C. If it's not written in C, it speaks the C ABI (C++, Rust, Zig, etc) and is available as a C library. C and the C ABI are the past, present, and future of systems programming.
**That's why in Bun v1.1.28, we introduced experimental support for compiling and running native C from JavaScript**
hello.c
hello.ts
hello.c
```
#include <stdio.h>
void hello() {
printf("You can now compile & run C in Bun!\n");
}
```
hello.ts
```
import { cc } from "bun:ffi";
export const {
symbols: { hello },
} = cc({
source: "./hello.c",
symbols: {
hello: {
returns: "void",
args: [],
},
},
});
hello();
```
On Twitter, many people asked the same question:
"Why would I want to compile and run C programs from JavaScript?"
Previously, you had two options for using systems libraries from JavaScript:
1. Writing a N-API (napi) addon or V8 C++ API library addon
2. Compiling to WASM/WASI via emscripten or wasm-pack
## []()[What's wrong with N-API (napi)?](compile-and-run-c-in-js.html#what-s-wrong-with-n-api-napi)
N-API (napi) is a runtime agnostic C API for exposing native libraries to JavaScript. Bun and Node.js implement it. Before napi, native addons mostly used the V8 C++ API which meant potentially breaking changes each time Node.js updated V8.
### []()[Compiling native addons breaks CI](compile-and-run-c-in-js.html#compiling-native-addons-breaks-ci)
Native addons usually rely on a `"postinstall"` script to compile N-API addons with `node-gyp`. `node-gyp` depends on Python 3 and a recent C++ compiler.
For many, needing to install Python 3 and a C++ compiler in CI to build a frontend JavaScript app is an unwelcome surprise.
[](https://github.com/oven-sh/bun/issues/9807)
### []()[Compiling native addons is complicated for maintainers](compile-and-run-c-in-js.html#compiling-native-addons-is-complicated-for-maintainers)
To address this, some libraries prebuild their packages leveraging the [`"os"`](https://docs.npmjs.com/cli/v10/configuring-npm/package-json/#os) and [`"cpu"`](https://docs.npmjs.com/cli/v10/configuring-npm/package-json/#cpu) fields in package.json. Moving that complexity from users to maintainers is good for the ecosystem, but maintaining a build matrix of 10 different build targets is not simple.
@napi-rs/canvas/package.json
```
"optionalDependencies": {
"@napi-rs/canvas-win32-x64-msvc": "0.1.55",
"@napi-rs/canvas-darwin-x64": "0.1.55",
"@napi-rs/canvas-linux-x64-gnu": "0.1.55",
"@napi-rs/canvas-linux-arm-gnueabihf": "0.1.55",
"@napi-rs/canvas-linux-x64-musl": "0.1.55",
"@napi-rs/canvas-linux-arm64-gnu": "0.1.55",
"@napi-rs/canvas-linux-arm64-musl": "0.1.55",
"@napi-rs/canvas-darwin-arm64": "0.1.55",
"@napi-rs/canvas-android-arm64": "0.1.55"
}
```
### []()[JavaScript → N-API function calls: 3x overhead](compile-and-run-c-in-js.html#javascript-n-api-function-calls-3x-overhead)
In exchange for more complicated builds, what do we get?
JavaScript → Native call overheadMechanism7ns - 15nsN-API2nsJavaScriptCore C++ API (lower bound)
Using the JavaScriptCore C++ API, a simple noop function costs 2ns per call. Using N-API, a noop function costs 7ns per call.
**Why are we paying a 3x performance hit for this?**
Unfortunately, this is an API design issue in napi. To make napi runtime-agnostic, simple operations like reading an integer from a JavaScript value involve a dynamic library function call. To make napi language-agnostic, runtime type-checking for arguments happens in every dynamic library function call. More complicated operations involve many memory allocations (or GC'd object allocations) and multiple layers of pointer indirection. N-API was never designed to be fast.
JavaScript is the world's most popular programming language. Can we do better?
## []()[What about WebAssembly?](compile-and-run-c-in-js.html#what-about-webassembly)
To workaround the N-API build complexity and performance issues, some projects choose to compile their native addon to WebAssembly and import it in JavaScript.
Since JavaScript engines can inline function calls crossing the WebAssembly <> JavaScript boundary, this can work.
However, for system libraries, **WebAssembly's isolated memory model comes with serious tradeoffs**.
#### Isolation means no system calls
WebAssembly can only access functions the runtime exposes to it. Usually, that's JavaScript.
What about libraries that depend on system APIs like the [macOS Keychain API](https://developer.apple.com/documentation/security/keychain-services) (for securely storing/retrieving passwords) or [audio recording](https://learn.microsoft.com/en-us/windows/win32/directshow/audio-capture)? What if your CLI wants to use the Windows Registry?
#### Isolation means clone everything
Modern processors support about 280 TB of addressible memory (48 bits). WebAssembly is 32-bit and can only access its own memory.
That means by default, passing strings and binary data JavaScript <=> WebAssembly must clone every time. For many projects, this negates any performance gain from leveraging WebAssembly.
* * *
What if N-API and WebAssembly weren't the only options for server-side JavaScript? What if we could compile and run native C from JavaScript with shared memory, and near-zero call overhead?
## []()[Compile and run native C from JavaScript](compile-and-run-c-in-js.html#compile-and-run-native-c-from-javascript)
Here's a quick example that compiles a random number generator in C and runs it in JavaScript.
myRandom.c
```
#include <stdio.h>
#include <stdlib.h>
int myRandom() {
return rand() + 42;
}
```
The JavaScript code that compiles and runs C:
main.js
```
import { cc } from "bun:ffi";
export const {
symbols: { myRandom },
} = cc({
source: "./myRandom.c",
symbols: {
myRandom: {
returns: "int",
args: [],
},
},
});
console.log("myRandom() =", myRandom());
```
And finally, the output:
```
bun ./main.js
```
```
myRandom() = 43
```
### []()[How does this work?](compile-and-run-c-in-js.html#how-does-this-work)
`bun:ffi` uses TinyCC to compile, link, and relocate C programs in-memory. From there, it generates inline function wrappers that convert JavaScript primitive types <=> C primitive types.
For example, to convert an `int` in C to JavaScriptCore's EncodedJSValue representation, the code essentially does this:
```
static int64_t int32_to_js(int32_t input) {
return 0xfffe000000000000ll | (uint32_t)input;
}
```
Unlike N-API, these type conversions happen automatically and with zero dynamic dispatch overhead. Since these wrappers are generated at C compile time, we can safely inline type conversions without worrying about compatibility issues and without sacrificing performance.
### []()[`bun:ffi` compiles quickly](compile-and-run-c-in-js.html#bun-ffi-compiles-quickly)
If you've used `clang` or `gcc` before, you might be thinking:
**clang/gcc user**: "great 🙄 now I have to wait 10 seconds to compile C every time I run this JS."
Let's measure how long this takes to compile with `bun:ffi`:
main.js
```
import { cc } from "bun:ffi";
console.time("Compile ./myRandom.c");
export const {
symbols: { myRandom },
} = cc({
source: "./myRandom.c",
symbols: {
myRandom: {
returns: "int",
args: [],
},
},
});
console.timeEnd("Compile ./myRandom.c");
```
And the output:
```
bun ./main.js
```
```
[5.16ms] Compile ./myRandom.c
myRandom() = 43
```
That's 5.16ms. Thanks to [TinyCC](https://bellard.org/tcc/), compiling C in Bun is fast. We wouldn't be comfortable shipping this if it took 10 seconds to compile.
### []()[`bun:ffi` is low-overhead](compile-and-run-c-in-js.html#bun-ffi-is-low-overhead)
Foreign Function Interface (FFI) has a reputation for being slow. In Bun, things are different.
Before we measure it in Bun, let's understand an upper-bound of how fast it could get. For simplicity, let's use Google's benchmark library (which requires a .cpp file):
bench.cpp
```
#include <stdio.h>
#include <stdlib.h>
#include <benchmark/benchmark.h>
int myRandom() {
return rand() + 42;
}
static void BM_MyRandom(benchmark::State& state) {
for (auto _ : state) {
benchmark::DoNotOptimize(myRandom());
}
}
BENCHMARK(BM_MyRandom);
BENCHMARK_MAIN();
```
And the output:
```
clang++ ./bench.cpp -L/opt/homebrew/lib -l benchmark -O3 -I/opt/homebrew/include -o bench
```
```
./bench
```
```
------------------------------------------------------
Benchmark Time CPU Iterations
------------------------------------------------------
BM_MyRandom 4.67 ns 4.66 ns 150144353
```
So that's 4 nanoseconds per call in C/C++. This represents the ceiling of how fast it could possibly get.
How long does it take with `bun:ffi`?
bench.js
```
import { bench, run } from 'mitata';
import { myRandom } from './main';
bench('myRandom', () => {
myRandom();
});
run();
```
On my machine, the result is:
```
bun ./bench.js
```
```
cpu: Apple M3 Max
runtime: bun 1.1.28 (arm64-darwin)
benchmark time (avg) (min … max) p75 p99 p999
------------------------------------------------- -----------------------------
myRandom 6.26 ns/iter (6.16 ns … 17.68 ns) 6.23 ns 7.67 ns 10.17 ns
```
6 nanoseconds. So, `bun:ffi` has a per-call overhead of only 6ns - 4ns = 2ns.
## []()[What can you build with this?](compile-and-run-c-in-js.html#what-can-you-build-with-this)
bun:ffi can use dynamically-linked shared libraries.
#### Convert short videos with ffmpeg 3x faster
By avoiding the overhead of spawning a new process and allocating a lot of memory for each video, you can convert short videos 3x faster.
ffmpeg.js
mp4.c
ffmpeg.js
```
import { cc, ptr } from "bun:ffi";
import source from "./mp4.c" with {type: 'file'};
import { basename, extname, join } from "path";
console.time(`Compile ./mp4.c`);
const {
symbols: { convert_file_to_mp4 },
} = cc({
source,
library: ["c", "avcodec", "swscale", "avformat"],
symbols: {
convert_file_to_mp4: {
returns: "int",
args: ["cstring", "cstring"],
},
},
});
console.timeEnd(`Compile ./mp4.c`);
const outname = join(
process.cwd(),
basename(process.argv.at(2), extname(process.argv.at(2))) + ".mp4"
);
const input = Buffer.from(process.argv.at(2) + "\0");
const output = Buffer.from(outname + "\0");
for (let i = 0; i < 10; i++) {
console.time(`Convert ${process.argv.at(2)} to ${outname}`);
const result = convert_file_to_mp4(ptr(input), ptr(output));
if (result == 0) {
console.timeEnd(`Convert ${process.argv.at(2)} to ${outname}`);
}
}
```
mp4.c
```
#include <dlfcn.h>
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
#include <libavutil/imgutils.h>
#include <libavutil/opt.h>
#include <libswscale/swscale.h>
#include <stdio.h>
#include <stdlib.h>
int to_mp4(void *buf, size_t buflen, void **out, size_t *outlen) {
AVFormatContext *input_ctx = NULL, *output_ctx = NULL;
AVIOContext *input_io_ctx = NULL, *output_io_ctx = NULL;
uint8_t *output_buffer = NULL;
int ret = 0;
int64_t *last_dts = NULL;
// Register all codecs and formats
// Create input IO context
input_io_ctx = avio_alloc_context(buf, buflen, 0, NULL, NULL, NULL, NULL);
if (!input_io_ctx) {
ret = AVERROR(ENOMEM);
goto end;
}
// Allocate input format context
input_ctx = avformat_alloc_context();
if (!input_ctx) {
ret = AVERROR(ENOMEM);
goto end;
}
input_ctx->pb = input_io_ctx;
// Open input
if ((ret = avformat_open_input(&input_ctx, NULL, NULL, NULL)) < 0) {
goto end;
}
// Retrieve stream information
if ((ret = avformat_find_stream_info(input_ctx, NULL)) < 0) {
goto end;
}
// Allocate output format context
avformat_alloc_output_context2(&output_ctx, NULL, "mp4", NULL);
if (!output_ctx) {
ret = AVERROR(ENOMEM);
goto end;
}
// Create output IO context
ret = avio_open_dyn_buf(&output_ctx->pb);
if (ret < 0) {
goto end;
}
// Copy streams
for (int i = 0; i < input_ctx->nb_streams; i++) {
AVStream *in_stream = input_ctx->streams[i];
AVStream *out_stream = avformat_new_stream(output_ctx, NULL);
if (!out_stream) {
ret = AVERROR(ENOMEM);
goto end;
}
ret = avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar);
if (ret < 0) {
goto end;
}
out_stream->codecpar->codec_tag = 0;
}
// Write header
ret = avformat_write_header(output_ctx, NULL);
if (ret < 0) {
goto end;
}
// Allocate last_dts array
last_dts = calloc(input_ctx->nb_streams, sizeof(int64_t));
if (!last_dts) {
ret = AVERROR(ENOMEM);
goto end;
}
// Copy packets
AVPacket pkt;
while (1) {
ret = av_read_frame(input_ctx, &pkt);
if (ret < 0) {
break;
}
AVStream *in_stream = input_ctx->streams[pkt.stream_index];
AVStream *out_stream = output_ctx->streams[pkt.stream_index];
// Convert timestamps
pkt.pts =
av_rescale_q_rnd(pkt.pts, in_stream->time_base, out_stream->time_base,
AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
pkt.dts =
av_rescale_q_rnd(pkt.dts, in_stream->time_base, out_stream->time_base,
AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX);
pkt.duration =
av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);
// Ensure monotonically increasing DTS
if (pkt.dts <= last_dts[pkt.stream_index]) {
pkt.dts = last_dts[pkt.stream_index] + 1;
pkt.pts = FFMAX(pkt.pts, pkt.dts);
}
last_dts[pkt.stream_index] = pkt.dts;
pkt.pos = -1;
ret = av_interleaved_write_frame(output_ctx, &pkt);
if (ret < 0) {
char errbuf[AV_ERROR_MAX_STRING_SIZE];
av_strerror(ret, errbuf, AV_ERROR_MAX_STRING_SIZE);
fprintf(stderr, "Error writing frame: %s\n", errbuf);
break;
}
av_packet_unref(&pkt);
}
// Write trailer
ret = av_write_trailer(output_ctx);
if (ret < 0) {
goto end;
}
// Get the output buffer
*outlen = avio_close_dyn_buf(output_ctx->pb, &output_buffer);
*out = output_buffer;
output_ctx->pb = NULL; // Set to NULL to prevent double free
ret = 0; // Success
end:
if (input_ctx) {
avformat_close_input(&input_ctx);
}
if (output_ctx) {
avformat_free_context(output_ctx);
}
if (input_io_ctx) {
av_freep(&input_io_ctx->buffer);
av_freep(&input_io_ctx);
}
return ret;
}
int convert_file_to_mp4(const char *input_filename,
const char *output_filename) {
FILE *input_file = NULL;
FILE *output_file = NULL;
uint8_t *input_buffer = NULL;
uint8_t *output_buffer = NULL;
size_t input_size = 0;
size_t output_size = 0;
int ret = 0;
// Open the input file
input_file = fopen(input_filename, "rb");
if (!input_file) {
perror("Could not open input file");
return -1;
}
// Get the size of the input file
fseek(input_file, 0, SEEK_END);
input_size = ftell(input_file);
fseek(input_file, 0, SEEK_SET);
// Allocate memory for the input buffer
input_buffer = (uint8_t *)malloc(input_size);
if (!input_buffer) {
perror("Could not allocate input buffer");
ret = -1;
goto cleanup;
}
// Read the input file into the buffer
if (fread(input_buffer, 1, input_size, input_file) != input_size) {
perror("Could not read input file");
ret = -1;
goto cleanup;
}
// Call the to_mp4 function to convert the buffer
ret = to_mp4(input_buffer, input_size, (void **)&output_buffer, &output_size);
if (ret < 0) {
fprintf(stderr, "Error converting to MP4\n");
goto cleanup;
}
// Open the output file
output_file = fopen(output_filename, "wb");
if (!output_file) {
perror("Could not open output file");
ret = -1;
goto cleanup;
}
// Write the output buffer to the file
if (fwrite(output_buffer, 1, output_size, output_file) != output_size) {
perror("Could not write output file");
ret = -1;
goto cleanup;
}
cleanup:
if (output_buffer) {
av_free(output_buffer);
}
if (input_file) {
fclose(input_file);
}
if (output_file) {
fclose(output_file);
}
return ret;
}
// for running it standalone
int main(const int argc, const char **argv) {
if (argc != 3) {
printf("Usage: %s <input_file> <output_file>\n", argv[0]);
return -1;
}
const char *input_filename = argv[1];
const char *output_filename = argv[2];
int result = convert_file_to_mp4(input_filename, output_filename);
if (result == 0) {
printf("Conversion successful!\n");
} else {
printf("Conversion failed!\n");
}
return result;
}
```
#### Securely save & load passwords with the macOS Keychain API
macOS has a builtin Keychain API for securely storing & retrieving passwords, but this isn't exposed to JavaScript. Instead of figuring out how to wrap this with N-API, getting CMake configured with node-gyp, what if you could just write a few lines of C in your JS project and be done with it?
keychain.js
keychain.c
keychain.js
```
import { cc, ptr, CString } from "bun:ffi";
const {
symbols: { setPassword, getPassword, deletePassword },
} = cc({
source: "./keychain.c",
flags: [
"-framework",
"Security",
"-framework",
"CoreFoundation",
"-framework",
"Foundation",
],
symbols: {
setPassword: {
args: ["cstring", "cstring", "cstring"],
returns: "i32",
},
getPassword: {
args: ["cstring", "cstring", "ptr", "ptr"],
returns: "i32",
},
deletePassword: {
args: ["cstring", "cstring"],
returns: "i32",
},
},
});
var service = Buffer.from("com.bun.test.keychain\0");
var account = Buffer.from("bun\0");
var password = Buffer.alloc(1024);
password.write("password\0");
var passwordPtr = new BigUint64Array(1);
passwordPtr[0] = BigInt(ptr(password));
var passwordLength = new Uint32Array(1);
setPassword(ptr(service), ptr(account), ptr(password));
passwordLength[0] = 1024;
password.fill(0);
getPassword(ptr(service), ptr(account), ptr(passwordPtr), ptr(passwordLength));
const result = new CString(
Number(passwordPtr[0]),
0,
passwordLength[0]
);
console.log(result);
```
keychain.c
```
#include <Security/Security.h>
#include <stdio.h>
#include <string.h>
// Function to set a password in the keychain
OSStatus setPassword(const char* service, const char* account, const char* password) {
SecKeychainItemRef item = NULL;
OSStatus status = SecKeychainFindGenericPassword(
NULL,
strlen(service), service,
strlen(account), account,
NULL, NULL,
&item
);
if (status == errSecSuccess) {
// Update existing item
status = SecKeychainItemModifyAttributesAndData(
item,
NULL,
strlen(password),
password
);
CFRelease(item);
} else if (status == errSecItemNotFound) {
// Add new item
status = SecKeychainAddGenericPassword(
NULL,
strlen(service), service,
strlen(account), account,
strlen(password), password,
NULL
);
}
return status;
}
// Function to get a password from the keychain
OSStatus getPassword(const char* service, const char* account, char** password, UInt32* passwordLength) {
return SecKeychainFindGenericPassword(
NULL,
strlen(service), service,
strlen(account), account,
passwordLength, (void**)password,
NULL
);
}
// Function to delete a password from the keychain
OSStatus deletePassword(const char* service, const char* account) {
SecKeychainItemRef item = NULL;
OSStatus status = SecKeychainFindGenericPassword(
NULL,
strlen(service), service,
strlen(account), account,
NULL, NULL,
&item
);
if (status == errSecSuccess) {
status = SecKeychainItemDelete(item);
CFRelease(item);
}
return status;
}
```
## []()[What is this good for?](compile-and-run-c-in-js.html#what-is-this-good-for)
This is a low-boilerplate way to use C libraries and system libraries from JavaScript. The same project that runs the JavaScript can also run the C without a separate build step.
It's good for glue code that binds C or C-like libraries to JavaScript. Sometimes, you want to use a C library or system API from JavaScript, and that library was never meant to be used from JavaScript.
Writing some C to wrap that sort of code into a JavaScript-friendly API is usually the easiest way to go because:
- The examples are in C, not in JavaScript through FFI.
- Using FFI means you have to mentally translate between JavaScript and C. It's easier to use pointers in C than to use pointers in FFI through typed arrays in JavaScript. So, why not make it easier on yourself?
#### What is this not for?
Every tool has tradeoffs.
- You probably don't want to use this to compile large C projects like PostgresSQL or SQLite. TinyCC compiles to decently performant C, but it won't do advanced optimizations that Clang or GCC does like autovectorization or very specialized CPU instructions.
- You probably won't get much of a performance gain from micro-optimizing small parts of your codebase through C, but happy to be proven wrong!
On this page
- [What's wrong with N-API (napi)?](compile-and-run-c-in-js.html#what-s-wrong-with-n-api-napi)
- [Compiling native addons breaks CI](compile-and-run-c-in-js.html#compiling-native-addons-breaks-ci)
- [Compiling native addons is complicated for maintainers](compile-and-run-c-in-js.html#compiling-native-addons-is-complicated-for-maintainers)
- [JavaScript → N-API function calls: 3x overhead](compile-and-run-c-in-js.html#javascript-n-api-function-calls-3x-overhead)
- [What about WebAssembly?](compile-and-run-c-in-js.html#what-about-webassembly)
- [Compile and run native C from JavaScript](compile-and-run-c-in-js.html#compile-and-run-native-c-from-javascript)
- [How does this work?](compile-and-run-c-in-js.html#how-does-this-work)
- [`bun:ffi` compiles quickly](compile-and-run-c-in-js.html#bun-ffi-compiles-quickly)
- [`bun:ffi` is low-overhead](compile-and-run-c-in-js.html#bun-ffi-is-low-overhead)
- [What can you build with this?](compile-and-run-c-in-js.html#what-can-you-build-with-this)
- [What is this good for?](compile-and-run-c-in-js.html#what-is-this-good-for)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/how-bun-supports-v8-apis-without-using-v8-part-1.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# How Bun supports V8 APIs without using V8 (part 1)
* * *
[Ben Grant](https://github.com/190n) · September 30, 2024
[](../rss.xml)
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
When packages work in Node.js but don't work in Bun, we consider that a bug in Bun.
Native C & C++ APIs are often used in the JavaScript ecosystem for performance-critical libraries like 2D Canvas, database drivers, CPU detection, and more. Bun and Node.js implement `Node-API` (napi), which is the recommended engine-independent C API for interfacing with JavaScript.
But, a number of popular native modules directly use the [V8 engine APIs exposed by Node.js](https://nodejs.org/api/addons.html). At the time of writing, [the issue requesting V8 API support](https://github.com/oven-sh/bun/issues/4290) is the 11th-highest open issue on Bun's tracker when sorted by thumbs-up.
This is challenging for Bun because we use JavaScriptCore as the JavaScript engine (used in Safari), unlike Node.js which uses V8 (used in Chrome). JavaScriptCore is an entirely different JavaScript engine implementation with different design choices.
JavaScriptCoreV8Garbage collectorNon-moving, conservativeMoving, preciseValue representation`JSC::JSValue``v8::Local<T>`Value lifetimeStack-scanningHandle scopes...many many more.........
Previously, when loading one of the packages that relied on V8 C++ APIs in Bun, you would sometimes see an error like this:
```
bun ./index.js
```
```
dyld[26946]: missing symbol called
```
Since Bun v1.1.25, we've been implementing a steadily-growing list of V8's C++ APIs using JavaScriptCore. This unblocks popular Node.js native modules like `cpu-features` in Bun. Here's how we're doing that.
## []()[JavaScriptCore vs. V8 API example](how-bun-supports-v8-apis-without-using-v8-part-1.html#javascriptcore-vs-v8-api-example)
First, for a high-level overview, let's look at some sample code using the JSC API and its equivalent in the V8 API. We'll write a function that takes two numbers from JavaScript and returns their product. If the user provides fewer or more than two arguments, or either argument is not a number, we'll return `undefined`. Note that we're only showing the C++ function implementation, but in reality there would be more glue code required to register this as a function that can be called from JavaScript.
JavaScriptCore:
jsc-multiply.cpp
```
EncodedJSValue JSC_HOST_CALL_ATTRIBUTES multiply(JSGlobalObject* globalObject, CallFrame* callFrame) {
if (callFrame->argumentCount() != 2) {
return JSValue::encode(jsUndefined());
}
JSValue arg1 = callFrame->argument(0);
JSValue arg2 = callFrame->argument(1);
if (!arg1.isNumber() || !arg2.isNumber()) {
return JSValue::encode(jsUndefined());
}
double number1 = arg1.asNumber();
double number2 = arg2.asNumber();
EncodedJSValue returnValue = JSValue::encode(jsNumber(number1 * number2));
return returnValue;
}
```
V8 version:
v8-multiply.cc
```
void multiply(const FunctionCallbackInfo<Value>& info) {
Isolate* isolate = info.GetIsolate();
if (info.Length() != 2) {
return;
}
Local<Value> arg1 = info[0];
Local<Value> arg2 = info[1];
if (!arg1->IsNumber() || !arg2->IsNumber()) {
return;
}
double number1 = arg1.As<Number>()->Value();
double number2 = arg2.As<Number>()->Value();
Local<Number> returnValue = Number::New(isolate, number1 * number2);
info.GetReturnValue().Set(returnValue);
}
```
These both carry out the same basic operations:
- check the number of arguments
- check the types of the arguments
- convert both arguments into C++ `double`s
- multiply the arguments
- convert the result to a JavaScript number
- return the result
But they do it in different ways.
### []()[Value Representation, part 1](how-bun-supports-v8-apis-without-using-v8-part-1.html#value-representation-part-1)
One of the first major differences is how JavaScript values are represented in both engines. JSC uses `JSValue`, which is an 8-byte (Bun only supports 64-bit CPUs) class that can represent any JavaScript type. We also see `EncodedJSValue`, which is an integer the same size as a `JSValue` used for passing across ABI boundaries (`JSValue::encode` just reinterprets the same bits as a different type).
In V8, on the other hand, you'll usually see the template class `Local<T>`, which is also 8 bytes. `Local<T>` overloads `T* operator*()` and `T* operator->()` which lets native code treat it like a pointer to `T`. Pay attention to the usage of `.` and `->` in V8 code for this reason: `.` means we are calling a function on the `Local`, but `->` means we are calling a function on the wrapped type. `Local<Value>` is the most generic form of this for representing any value JavaScript can use. Before doing almost anything with a `Local<Value>`, you need to convert it to a `Local` of some specific type. Here, we call:
- `bool Value::IsNumber()` to check the type of both arguments
- `Local<S> Local<T>::As<S>()` to forcibly cast them to `Local<Number>` (this would be undefined behavior if they were not numbers)
- `double Number::Value()` to extract a C++ `double` from the JavaScript numbers
### []()[API Comparison](how-bun-supports-v8-apis-without-using-v8-part-1.html#api-comparison)
The fact that our V8 values are `Local` has important lifetime implications, but we'll get into that, as well as the details of how `JSValue` and `Local` are implemented, later. For now, let's look back at the `multiply` functions and go over some of the other similarities and differences between V8 and JSC.
- Both take an object (`CallFrame` and `FunctionCallbackInfo`) to represent information passed from JavaScript to our function. We use both to get the number of arguments and then the arguments themselves (V8 uses `operator[]` for the second step which is why it looks like array indexing). That object is also how we would access the value of `this` in both APIs, if we needed it.
- Our JSC function returns `EncodedJSValue`, which is how we indicate what we return to JavaScript. In V8, our function itself returns `void` and we use `info.GetReturnValue().Set(...)` to return a value (if we don't call this, it defaults to `undefined`).
- Our JSC function is annotated with `JSC_HOST_CALL_ATTRIBUTES`. This macro expands to a compiler-specific attribute which ensures the calling convention of our function is correct. JSC uses Unix's System V calling convention for JIT-compiled machine code. This makes their code generation simpler as they don't have to generate code using two different calling conventions, but it also means that any native function called by JavaScript needs to use the right calling convention. Otherwise, the native function would look for its arguments in registers other than the ones that the JIT-compiled code placed them in. V8 has no equivalent to this since it always uses the standard calling convention for a given platform.
- Our JSC function is given a pointer to a `JSGlobalObject`. This is a class which encapsulates both the global scope accessible by JavaScript, as well as global state used by native functions that interact with JSC. Bun subclasses JSC's generic version of this to add our own globally-accessible functionality, such as [the `Bun` object](https://github.com/oven-sh/bun/blob/fe62a614046948ebba260bed87db96287e67921f/src/bun.js/bindings/ZigGlobalObject.h#L570) (`Zig::GlobalObject` is 7,528 bytes!). We'll also see usage of `JSC::VM`, which you can access from the global object, and encapsulates more of the execution state of JavaScript code. While neither is exactly equivalent, two similar V8 types we see are `Isolate` and `Context`. For us, the important details are that an isolate can contain multiple contexts, but only one of those contexts has JavaScript running in it at a given time (since two threads can't share an isolate). [This article from V8](https://chromium.googlesource.com/chromium/src/+/refs/tags/128.0.6613.92/third_party/blink/renderer/bindings/core/v8/V8BindingDesign.md) has more details about the distinction. The isolate isn't passed directly into our V8 native function, but we can easily get it from the `FunctionCallbackInfo`, and we can also ask the isolate to tell us the current context if we need that.
- In V8 we had to pass the isolate to convert the multiplication result into a `Local<Number>`, while in JSC we didn't supply any extra parameters to `jsNumber`. In V8 we even have to do this for values like booleans, `null`, and `undefined`, while in JSC those all have simple functions that return a `JSValue` directly and don't depend on the `JSGlobalObject` or `VM`. We'll see later why these seemingly simple functions require access to the current isolate.
## []()[Implementing V8 Functions, First Attempt](how-bun-supports-v8-apis-without-using-v8-part-1.html#implementing-v8-functions-first-attempt)
Since V8's `Local` and JSC's `JSValue` are both 8 bytes, I started by trying to simply reinterpret between the two. `Local<T>::operator*()` and `Local<T>::operator->()` just return the contents as a pointer (we can't actually change the implementation of those functions as they are declared inline in the V8 headers, but copying the implementation into Bun's code will help us write other V8 functions that work on `Local`s):
v8.h
```
namespace v8 {
template<class T>
class Local final {
public:
T* ptr;
T* operator*() const { return ptr; }
};
}
```
In our implementation, the `T*` won't really be a pointer to `T`. Instead, it'll be a reinterpreted `JSValue`. This means that our classes that represent V8 values (like `Number`) don't actually contain any fields (this is the case in V8 as well, which should have concerned me at the time). Instead, they will receive a `this` pointer that is actually just a `JSValue`:
v8.h
```
class Number {
public:
BUN_EXPORT static Local<Number> New(Isolate* isolate, double value);
BUN_EXPORT double Value() const;
};
Local<Number> Number::New(Isolate* isolate, double value)
{
JSC::JSValue jsv = JSC::jsDoubleNumber(value);
JSC::EncodedJSValue encoded = JSC::JSValue::encode(jsv);
auto ptr = reinterpret_cast<Number*>(encoded);
return Local<Number> { ptr };
}
double Number::Value() const
{
auto encoded = reinterpret_cast<JSC::EncodedJSValue>(this);
JSC::JSValue jsv = JSC::JSValue::decode(encoded);
return jsv.asNumber();
}
```
Perhaps surprisingly, this actually worked! And it kept working for a while. I wrote tests for these APIs which printed the same results in Node.js and in Bun (although they had to be wrapped in a Node-API function as I hadn't yet implemented Node.js's way of loading a native module). Sadly, the fundamental flaw with this design became clear while I was trying to implement objects.
### []()[Problems](how-bun-supports-v8-apis-without-using-v8-part-1.html#problems)
V8 has a class called `ObjectTemplate` which can be created by native code and then used to construct multiple objects, which can be passed to JavaScript. These objects support a feature called *internal fields*, which are fields indexed by a number that can be accessed by native code but not by JavaScript. And you can use the `ObjectTemplate` to configure how many internal fields should be present on the objects it creates. Native modules can use internal fields to return "handle" objects to JavaScript that represent native resources without letting JavaScript mess with the internal state of these resources.
The problem became obvious (well, somewhat obvious) when I first tried to test accessing internal fields on objects. I had already noticed that `v8::Object::GetInternalField` is an inline function which performs some checks and then calls `v8::Object::SlowGetInternalField` if they fail. Since the inline function will get its definition from V8 header files and that code is compiled into any native module, we can't control what it does. I had hoped that the slow path would usually be taken, and it would call the `SlowGetInternalField` function that we can control (which is not inline). But the first time I tested internal fields, I got a segfault inside V8's inline function.
Let's take a look at [V8's implementation](https://github.com/v8/v8/blob/8ab91836885699b9ef686c3a30df4778501ef7d1/include/v8-object.h#L741-L764):
v8-object.h
```
namespace v8 {
class V8_EXPORT Object : public Value {
public:
// ...
V8_INLINE Local<Data> GetInternalField(int index);
// ...
};
// ...
Local<Data> Object::GetInternalField(int index) {
#ifndef V8_ENABLE_CHECKS
using A = internal::Address;
using I = internal::Internals;
A obj = internal::ValueHelper::ValueAsAddress(this);
// Fast path: If the object is a plain JSObject, which is the common case, we
// know where to find the internal fields and can return the value directly.
int instance_type = I::GetInstanceType(obj);
if (I::CanHaveInternalField(instance_type)) {
int offset = I::kJSAPIObjectWithEmbedderSlotsHeaderSize +
(I::kEmbedderDataSlotSize * index);
A value = I::ReadRawField<A>(obj, offset);
#ifdef V8_COMPRESS_POINTERS
// We read the full pointer value and then decompress it in order to avoid
// dealing with potential endiannes issues.
value = I::DecompressTaggedField(obj, static_cast<uint32_t>(value));
#endif
auto isolate = reinterpret_cast<v8::Isolate*>(
internal::IsolateFromNeverReadOnlySpaceObject(obj));
return Local<Data>::New(isolate, value);
}
#endif
return SlowGetInternalField(index);
}
}
```
Luckily, with my native module built in debug mode I could still step into and through the inline function and see a proper stack trace as if the function were not inlined. The crash occurred inside `ValueAsAddress`, which is also inlined. Let's refactor this function a little so it's easier to see what's going on. In Node.js's headers, neither `V8_ENABLE_CHECKS` nor `V8_COMPRESS_POINTERS` is defined, so the code in the outer `#ifndef` will be expanded but not the code in the inner `#ifdef`. `internal::Address` is a type alias for `uintptr_t`. Here are some definitions of inlined functions that this calls:
#### [`ValueAsAddress`](https://github.com/v8/v8/blob/8ab91836885699b9ef686c3a30df4778501ef7d1/include/v8-internal.h#L1352-L1355)
v8-internal.h
```
template <typename T>
V8_INLINE static Address ValueAsAddress(const T* value) {
return *reinterpret_cast<const Address*>(value);
}
```
#### [`GetInstanceType`](https://github.com/v8/v8/blob/8ab91836885699b9ef686c3a30df4778501ef7d1/include/v8-internal.h#L862-L868)
v8-internal.h
```
V8_INLINE static int GetInstanceType(Address obj) {
Address map = ReadTaggedPointerField(obj, kHeapObjectMapOffset);
#ifdef V8_MAP_PACKING
// omitted
#endif
return ReadRawField<uint16_t>(map, kMapInstanceTypeOffset);
}
```
#### [`ReadRawField` and `ReadTaggedPointerField`](https://github.com/v8/v8/blob/8ab91836885699b9ef686c3a30df4778501ef7d1/include/v8-internal.h#L983-L1009)
v8-internal.h
```
template <typename T>
V8_INLINE static T ReadRawField(Address heap_object_ptr, int offset) {
Address addr = heap_object_ptr + offset - kHeapObjectTag;
#ifdef V8_COMPRESS_POINTERS
// omitted
#endif
return *reinterpret_cast<const T*>(addr);
}
V8_INLINE static Address ReadTaggedPointerField(Address heap_object_ptr,
int offset) {
#ifdef V8_COMPRESS_POINTERS
// omitted
#else
return ReadRawField<Address>(heap_object_ptr, offset);
#endif
}
```
`kHeapObjectTag` is 1, `kHeapObjectMapOffset` is 0, and `kMapInstanceTypeOffset` is 12 on platforms Bun supports.
Let's first rewrite `GetInternalField` to use `ReadRawField` directly:
v8-object.h
```
Local<Data> Object::GetInternalField(int index) {
using A = internal::Address;
using I = internal::Internals;
A obj = internal::ValueHelper::ValueAsAddress(this);
int instance_type = I::GetInstanceType(obj);
A obj = *reinterpret_cast<const A*>(this);
A map = ReadRawField<Address>(obj, 0);
int instance_type = ReadRawField<uint16_t>(map, 12);
if (I::CanHaveInternalField(instance_type)) {
// omitted
}
return SlowGetInternalField(index);
}
```
All `ReadRawField` does is subtract `kHeapObjectTag` from the address passed in, add the offset, and then convert the resulting address to a pointer and dereference it. So we can rewrite this further as:
v8-object.h
```
Local<Data> Object::GetInternalField(int index) {
using A = internal::Address;
using I = internal::Internals;
A obj = *reinterpret_cast<const A*>(this);
A map = ReadRawField<Address>(obj, 0);
int instance_type = I::GetInstanceType(obj);
A map = *reinterpret_cast<const A*>(obj - 1 + 0);
int instance_type = *reinterpret_cast<const uint16_t*>(map - 1 + 12);
if (I::CanHaveInternalField(instance_type)) {
// omitted
}
return SlowGetInternalField(index);
}
```
So, we...
- reinterpret `this` (which has the type `Object*`, although it isn't really) as a pointer to an `Address`, and dereference that pointer to get `obj`
- subtract 1 from `obj`, and read an address from that location to get `map`
- add 11 to `map`, and read 2 bytes from that location to get the instance type
Remember that in the current implementation, `this` isn't a pointer to an `Address` at all, it's a `JSValue`. So V8 will blindly dereference whatever the `JSValue` looks like as a pointer, dereference it *again* to find whatever `map` is, and then dereference *that* to get the instance type. And remember, this is all code that gets compiled into each native module. We can't change any of it.
At this point, I figured my best hope was to somehow set up these pointers just enough that V8 would find an `instance_type` which makes `CanHaveInternalField` return `false` (if that function returns `true`, `GetInternalField` reads the internal field at a direct pointer offset, which would be even harder to make work under JSC than everything else we've seen). Then, it would always call `SlowGetInternalField`, which I can control the implementation of because it's not inline. But even getting to this point is hard and requires throwing out our initial scheme of storing `JSValue`s directly in `Local`s.
Let's go back to basics and look more closely at how `JSValue`s and `Local`s are represented.
## []()[Value Representation, part 2](how-bun-supports-v8-apis-without-using-v8-part-1.html#value-representation-part-2)
JavaScript engines face the challenge of representing a dynamic type system, where a value may change its type at any moment, while being implemented in a static type system where every variable's type must be known by the compiler.
The representation of numbers is also an important choice in JavaScript engines. According to the specification, JavaScript numbers behave like IEEE 754 double-precision floating-point numbers (`double` in C or C++, and `f64` in Zig or Rust). Bitwise operations do have to convert the number to an integer to manipulate its bits, but the result of such operations still needs to behave like a double (`(5 << 1) / 4` must be `2.5`). So the easiest implementation would be to always store JavaScript numbers as doubles, and only briefly convert them to an integer and then back to a double.
However, storing all numbers as doubles has a severe performance cost. Doubles are a lot slower to operate on than integers, and most of the numbers used by a typical program are integers anyway (numbers like array indices). So almost every JavaScript engine contains an optimization to represent numbers as integers where possible. This can be done without breaking the specification, as long as you're careful to convert the numbers back to doubles where necessary. You also need to make sure not to allow representing values that a `double` can't represent. For instance, it'd be inappropriate to use 64-bit integers, because those have greater precision than a `double` for very large integers. On 64-bit platforms, and when V8's pointer compression is disabled, JSC and V8 both use a signed 32-bit integer for this optimization.
V8 and JSC have both come up value representations that can use only 8 bytes while distinguishing between common kinds of values. Let's look at JSC's solution first.
### []()[JSValue](how-bun-supports-v8-apis-without-using-v8-part-1.html#jsvalue)
A `JSValue` takes up 64 bits, and can represent any of these:
- A 64-bit double-precision float
- A 48-bit `JSCell` pointer. `JSCell` is the base class for any JavaScript value allocated on the heap.
- A 32-bit signed integer
- `false`, `true`, `undefined`, or `null`
How do they do this? JSC uses a technique called *NaN boxing*. This takes advantage of the fact that, in the double-precision representation of NaN, there are 51 unused bits. Libraries and hardware floating-point implementations generally set these to zero, so any nonzero value in these bits can be used to encode a non-floating-point value. JSC sets the upper two of these bits for non-float representations, so that the lower 49 can be set to anything without being confused for a real NaN. JSC uses the uppermost bit of these 49 to distinguish between a 48-bit pointer (no 64-bit platform we support actually uses more than 48 bits for memory addressing) and a 32-bit integer. `false`, `true`, `undefined`, and `null` are represented as specific invalid pointers.
What I've described above implements NaN boxing where the non-double values are represented as valid double-precision encodings of NaN. However, doing that forces some of the high bits to be set in all non-double values, which is inconvenient for pointers as we'd have to zero out those bits before dereferencing the pointer. JSC's last trick is to subtract 2^49 from the double-precision value encoded as described above. This makes the kinds of values we've talked about fall into the following ranges:
```
Pointer { 0000:PPPP:PPPP:PPPP
/ 0002:****:****:****
Double { ...
\ FFFC:****:****:****
Integer { FFFE:0000:IIII:IIII
```
Since pointers now have their upper bits set to zero, after checking that a `JSValue` is a pointer it can be used directly. Doubles and integers only require simple integer math to be converted to their true values.
If that didn't make much sense (or even if it did), I recommend consulting [this comment in the header that defines `JSValue`](https://github.com/WebKit/WebKit/blob/2a4cf936370c9d32f4f3df96ea84047ed1575b3c/Source/JavaScriptCore/runtime/JSCJSValue.h#L418-L476) which explains the scheme very well.
### []()[Tagged Pointers](how-bun-supports-v8-apis-without-using-v8-part-1.html#tagged-pointers)
V8 uses a scheme called *pointer tagging*. The lower 2 bits of a pointer are used to indicate what kind of value it is. This is okay because all objects allocated by V8's garbage collector are at least 4-byte aligned, so the lower 2 bits in a valid address would always be zero. On 64-bit platforms (the only ones Bun supports), the lowermost bit is set to 1 if a value is a pointer, and the second-lowest bit is set to 1 if the pointer is weak. If the value is not a pointer, the lower 32 bits are all set to zero, and the upper 32 bits store a signed integer value (which V8 calls a "small integer" or "Smi"):
```
|----- 32 bits -----|----- 32 bits -----|
Pointer: |________________address______________w1|
Smi: |____int32_value____|0000000000000000000|
```
You may notice that doubles don't fit into this scheme. V8 stores doubles in a separate allocation called a `HeapNumber`. We'll look at how V8 handles booleans, `null`, and `undefined` in part 3.
To read more about V8's value representation, see [`tagged.h`](https://github.com/v8/v8/blob/8ab91836885699b9ef686c3a30df4778501ef7d1/src/objects/tagged.h#L24-L66) as well as [Igor Sheludko and Santiago Aboy Solanes's blog post explaining pointer compression](https://v8.dev/blog/pointer-compression). Pointer compression is an optional build-time V8 feature which changes the size of a tagged pointer to 32 bits, even on 64-bit platforms. Node.js does not enable pointer compression, so Bun does not have to mimic that representation, but that article still contains a good explanation of the non-compressed scheme as well as interesting details about the tradeoffs of pointer compression.
### []()[Local and Handle Scope](how-bun-supports-v8-apis-without-using-v8-part-1.html#local-and-handle-scope)
Now we understand tagged pointers, but what's in a `Local`?
V8 (unlike JSC) uses a *moving garbage collector*. This means that the garbage collector may need to change an object's location in memory. To do that, it needs to locate all references to the object and change the addresses to the object's new location. This isn't feasible with C code using raw pointers. Instead, V8 stores the tagged pointers we discussed above in *handle scopes*. A `HandleScope` manages a group of object references, or handles. It maintains storage for all their addresses, which the garbage collector can see. A `Local`, in turn, stores a pointer to the address that is stored in the handle scope. When a native function needs to access data from a `Local`, it has to dereference the pointer to the address, and then dereference that address to go to the actual object. When the garbage collector needs to move an object, it can simply look through all the handle scopes for pointers matching the object's old address and replace those pointers with the new address.
What about integers? Those still use the handle scope, but the tagged pointer stored in the handle scope will have the low bits set to zero, indicating that it is a 32-bit signed integer rather than a pointer. The GC knows it can skip over those handles.
Handle scopes are always stored in stack memory, and they themselves also make up a stack: when you create a `HandleScope`, it keeps a reference to the previous one, and when you exit the scope in which the `HandleScope` was created, it releases all the handles it contained and makes the previous one active again. The stack of handle scopes doesn't always match the native call stack, though, because you can always create handles in the currently active handle scope even if you didn't create your own in the current function.
### []()[Maps](how-bun-supports-v8-apis-without-using-v8-part-1.html#maps)
V8 uses objects called `Map`s (not to be confused with JavaScript maps) to represent the layout of heap-allocated JavaScript types. JSC has a similar concept called a `Structure`. Fortunately, we don't need to worry about too many implementation details; only enough to make the `GetInstanceType` function work. From that function's code, we know:
- Every object has, as its first field, a tagged pointer to its `Map`
- The `Map` has a two-byte integer at offset 12 to represent the instance type
Since `Map`s are heap objects, each one also has a pointer to its `Map` as the first field. These all point to the same `Map`, which is the map that describes the layout of a `Map`. I haven't seen a scenario where inline V8 functions rely on this, but I've implemented that field too because it wasn't difficult.
### []()[Putting it all together: V8 memory layout](how-bun-supports-v8-apis-without-using-v8-part-1.html#putting-it-all-together-v8-memory-layout)
As an example, let's see what the memory looks like after running the following code in Node.js (right before `baz` returns):
```
void foo(const FunctionCallbackInfo<Value>& info) {
Isolate* isolate = info.GetIsolate();
HandleScope foo_scope(isolate);
Local<String> foo_string = String::NewFromUtf8(isolate, "hello").ToLocalChecked();
bar(isolate);
}
void bar(Isolate* isolate) {
Local<Number> bar_number = Number::New(isolate, 2.0);
baz(isolate);
}
void baz(Isolate* isolate) {
HandleScope baz_scope(isolate);
Local<Number> baz_number = Number::New(isolate, 3.5);
}
```
[](../images/v8layout.drawio.svg)
Notice how everything stored in the handle scope uses the tagged pointer representation discussed in the previous section, which is why the memory addresses of heap objects are stored as odd numbers. The handles for `foo_string` and `baz_number` have their lowest 2 bits set to `01` to indicate that they are strong pointers. But to get the actual addresses they refer to, we have to change those bits to zero, resulting in the objects' actual locations written after "@."
Under "Heap," we can see which `Map` each object points to. These pointers to `Map`s are of course tagged pointers, so they also have the least significant bit set. The string and heap number also of course have more fields after the map pointer, but those fields (luckily) aren't a part of the layout that we have to match, so they aren't shown here.
Before we can do anything useful with the V8 API, we'll need to come up with a way to make JSC's types fit in this diagram the way that V8 expects them to. We'll also need to make sure that JSC's garbage collector can find all the V8 values that a native addon has created, so that it doesn't delete them while they can still be accessed. Finally, we'll need to implement a lot of extra types for V8 concepts that JSC doesn't precisely expose.
## []()[Coming up](how-bun-supports-v8-apis-without-using-v8-part-1.html#coming-up)
In [the next part of this series](how-bun-supports-v8-apis-without-using-v8-part-2.html), we'll look at how Bun can manipulate JSC types to match the layout expected by V8, while trying to avoid undue slowdown or wasted memory.
## []()[Links](how-bun-supports-v8-apis-without-using-v8-part-1.html#links)
- [Getting started with embedding V8](https://v8.dev/docs/embed): overview of many V8 APIs from a user's perspective, with some internal details
- [Pointer Compression in V8](https://v8.dev/blog/pointer-compression): explanation of the value representation in V8 with and without pointer compression (which makes tagged pointers only take up 32 bits even on 64-bit systems), and details of the implementation of optimized routines to compress and decompress pointers. Node.js has not enabled pointer compression, but Chromium and Electron have.
- [`tagged.h`](https://github.com/v8/v8/blob/8ab91836885699b9ef686c3a30df4778501ef7d1/src/objects/tagged.h#L24-L66): implementation of V8's pointer tagging system
- [Design of V8 bindings](https://chromium.googlesource.com/chromium/src/+/refs/tags/128.0.6613.92/third_party/blink/renderer/bindings/core/v8/V8BindingDesign.md): describes from the perspective of V8's use in Chromium the difference between concepts like Isolates and Contexts
- [`JSCJSValue.h`](https://github.com/WebKit/WebKit/blob/2a4cf936370c9d32f4f3df96ea84047ed1575b3c/Source/JavaScriptCore/runtime/JSCJSValue.h#L418-L476): details the 32- and 64-bit (only the latter is relevant for Bun) encodings of JSC's basic value type
- [*Crafting Interpreters* on NaN boxing](https://craftinginterpreters.com/optimization.html#nan-boxing): more detailed justification and explanation of one technique used by JSC to compactly represent values of different types
- [value representation in javascript implementations](https://wingolog.org/archives/2011/05/18/value-representation-in-javascript-implementations): survey of different value representations used by production JavaScript interpreters and their tradeoffs
On this page
- [JavaScriptCore vs. V8 API example](how-bun-supports-v8-apis-without-using-v8-part-1.html#javascriptcore-vs-v8-api-example)
- [Value Representation, part 1](how-bun-supports-v8-apis-without-using-v8-part-1.html#value-representation-part-1)
- [API Comparison](how-bun-supports-v8-apis-without-using-v8-part-1.html#api-comparison)
- [Implementing V8 Functions, First Attempt](how-bun-supports-v8-apis-without-using-v8-part-1.html#implementing-v8-functions-first-attempt)
- [Problems](how-bun-supports-v8-apis-without-using-v8-part-1.html#problems)
- [Value Representation, part 2](how-bun-supports-v8-apis-without-using-v8-part-1.html#value-representation-part-2)
- [JSValue](how-bun-supports-v8-apis-without-using-v8-part-1.html#jsvalue)
- [Tagged Pointers](how-bun-supports-v8-apis-without-using-v8-part-1.html#tagged-pointers)
- [Local and Handle Scope](how-bun-supports-v8-apis-without-using-v8-part-1.html#local-and-handle-scope)
- [Maps](how-bun-supports-v8-apis-without-using-v8-part-1.html#maps)
- [Putting it all together: V8 memory layout](how-bun-supports-v8-apis-without-using-v8-part-1.html#putting-it-all-together-v8-memory-layout)
- [Coming up](how-bun-supports-v8-apis-without-using-v8-part-1.html#coming-up)
- [Links](how-bun-supports-v8-apis-without-using-v8-part-1.html#links)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/how-bun-supports-v8-apis-without-using-v8-part-2.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# How Bun supports V8 APIs without using V8 (part 2)
* * *
[Ben Grant](https://github.com/190n) · November 5, 2024
[](../rss.xml)
We're hiring [systems engineers](../careers.html) in San Francisco to build the future of JavaScript!
In [the first part of this series](how-bun-supports-v8-apis-without-using-v8-part-1.html), we compared the C++ APIs used to interact with JavaScriptCore and V8, which are the JavaScript engines used by Bun and Node.js respectively. At the end we saw an overview of the memory layout used by V8 to represent the objects in a program:
```
void foo(const FunctionCallbackInfo<Value>& info) {
Isolate* isolate = info.GetIsolate();
HandleScope foo_scope(isolate);
Local<String> foo_string = String::NewFromUtf8(isolate, "hello").ToLocalChecked();
bar(isolate);
}
void bar(Isolate* isolate) {
Local<Number> bar_number = Number::New(isolate, 2.0);
baz(isolate);
}
void baz(Isolate* isolate) {
HandleScope baz_scope(isolate);
Local<Number> baz_number = Number::New(isolate, 3.5);
}
```
[](../images/v8layout.drawio.svg)
Since V8's API contains a lot of inline functions that assume a layout like this is used, we'll need to arrange our JSC types in a similar way to ensure that native modules precompiled for the V8 API still work.
## []()[Mimicking V8 Representation in JSC](how-bun-supports-v8-apis-without-using-v8-part-2.html#mimicking-v8-representation-in-jsc)
So how can we create a layout that looks like V8's while using JSC types? Let's recap the important properties that inline V8 functions expect:
- Every `Local` contains a pointer into memory managed by the currently-active `HandleScope`
- The `HandleScope` contains tagged pointers, which either store a signed 32-bit integer inline or point to an object on the heap
- Each object on the heap begins with a tagged pointer to its map
- Each map has an instance type at offset 12
### []()[Tagged Pointers](how-bun-supports-v8-apis-without-using-v8-part-2.html#tagged-pointers)
To start, we need to represent tagged pointers. Recall that a tagged pointer is a 64-bit address which can represent either a 32-bit signed integer (a "Smi"), a strong pointer, or a weak pointer. I wrote a simple `struct` that wraps a `uintptr_t` and is used to represent tagged pointers, so that we can add helper methods and constructors. [The implementation is not too complicated](https://github.com/oven-sh/bun/blob/1385f9f68653ca632fe9abd2f977381dfdfcfd5c/src/bun.js/bindings/v8/shim/TaggedPointer.h). You can construct a tagged pointer from a pointer or a Smi (both of which handle setting the tag bits correctly), query what type it is, and access it as pointer or Smi.
Now we could actually implement `v8::Number` in the case where the number is a Smi without too much extra work. All we'd need is a handle scope to provide memory where these tagged pointers can be allocated. However, the more difficult case for objects is still lurking, so let's tackle that first (also, it will end up affecting how we implement handle scopes).
### []()[Maps](how-bun-supports-v8-apis-without-using-v8-part-2.html#maps)
V8 and JSC use `Map` and `Structure` respectively for an important optimization: if two JavaScript objects have the same property names and types, they can be represented as something more like a C `struct`, with properties at fixed offsets one after the other, rather than as a completely dynamic hash table. This makes property accesses much faster and makes it easier for JIT compilers to generate code that accesses properties. Hence, these classes both get dynamically allocated and instantiated many times as JavaScript is running. Fortunately, for our V8 functionality we don't need a 1:1 association with a fake `Map` set up to match every `Structure`. We only need `Map`s to cover the cases where inline V8 functions expect something from the instance type. For instance, we have one `Map` shared by all objects whose only purpose is to force V8 to call `SlowGetInternalField` instead of trying to look up internal fields directly. There are a few other `Map`s we create for various reasons, but we don't need to create any of them dynamically, so they're all just static constants.
Here's the rough definition of `Map`:
Map.h
```
enum class InstanceType : uint16_t {
// ...
};
struct Map {
// the structure of the map itself (always points to map_map)
TaggedPointer m_metaMap;
// TBD whether we need to put anything here to please inlined V8 functions
uint32_t m_unused;
InstanceType m_instanceType;
// the map used by maps
static const Map map_map;
// other Map declarations follow...
Map(InstanceType instance_type)
: m_metaMap(const_cast<Map*>(&map_map))
, m_unused(0xaaaaaaaa)
, m_instanceType(instance_type)
{
}
};
const Map Map::map_map(InstanceType::Object);
```
### []()[Objects](how-bun-supports-v8-apis-without-using-v8-part-2.html#objects)
To please V8, we need to keep a tagged pointer to the `Map` in the first 8 bytes of each object. However, JSC also stores metadata at the start of each `JSCell` object. Those can't both occupy the same memory. How can we rectify this?
We could create a new type of object, not visible to JSC's garbage collector, which combines a map pointer for V8 as well as a `JSCell` pointer so that our code can find the JSC object:
```
struct ObjectLayout {
TaggedPointer tagged_map;
JSCell* ptr;
};
```
This would work, but we'd have to allocate a new `ObjectLayout` for every V8 object. Not only would this be inefficient, it'd be error-prone because we'd need to manage the memory for all these objects ourselves without help from the garbage collector.
Instead, what if we stored both these fields inside the handle scope? We already need to set aside 8 bytes in the handle scope for each V8 value, to store the tagged pointer. If we set aside 24 bytes instead, we can store the handle, the map pointer, and the JSC object pointer all next to each other.
Handle.h
```
struct ObjectLayout {
TaggedPointer m_taggedMap;
JSCell* m_ptr;
};
struct Handle {
TaggedPointer m_toV8Object;
ObjectLayout m_object;
};
```
With this scheme, `Local`s hold a pointer to the `to_v8_object` field. If `to_v8_object` is an integer, then the `ObjectLayout` is ignored. If it's a pointer, it points to the `tagged_map` field of the `ObjectLayout` so that V8 code can find the map pointer where it expects.
Here's how the layout of this will look when we're done, using the same program at the top of this article:
[](../images/jsclayout.drawio.svg)
The main difference with how the layout works under V8 is that the contents of `ObjectLayout`, which in V8 were a separate heap allocation (and included the object's actual fields, like the string contents), are now stored in memory managed by the handle scopes. But you can also see how, from the perspective of V8 code, our layout should *appear* similar. For instance, that code can still follow the `to_v8_object` tagged pointer to find an object that has a `Map` pointer as its first field. It doesn't matter that `to_v8_object` happens to always point forward by 8 bytes.
The following diagram shows the pointers that are followed in order to look up the instance type from a `Local` handle, in either the V8 layout (above) or the fake V8 layout we have implemented in Bun (below). While the instance types are different in this case, both are considered strings which is all we care about.
[](../images/v8-jsc-layout-comparison.drawio.svg)
`Handle` has a few different constructors. The invariant that must be maintained is that if `to_v8_object` is not a Smi, it must contain the address of `object`. I implemented the C++ copy constructor and assignment operator to help ensure this:
Handle.cpp
```
Handle::Handle(const Handle& that)
{
*this = that;
}
Handle& Handle::operator=(const Handle& that)
{
object = that.object;
if (that.m_toV8Object.tag() == TaggedPointer::Tag::Smi) {
m_toV8Object = that.m_toV8Object;
} else {
// calls TaggedPointer(void*), which also sets up the tag bit
m_toV8Object = &this->m_object;
}
return *this;
}
```
What about our handle scope? It has to act as a growable array of `Handle`s, and it has to mark itself as the current handle scope in its constructor and restore the previous handle scope in its destructor. Remember that unlike the other V8 types we've been looking at, `HandleScope` is stack-allocated and has a size of 24 bytes. This is actually just the right size to store:
- A pointer to the `Isolate` (what even is an `Isolate` when we are using JSC? I'll address that later)
- A pointer to the previous `HandleScope`
- A pointer to a class implementing the actual storage of handles, `HandleScopeBuffer`
The only trick to implementing `HandleScopeBuffer` is that we expect every handle to have an active pointer to it somewhere on the stack. If some code creates a lot of handles, we need to be able to grow the array without moving any of our existing handles. We'll solve this in a scalable way later. For now, we can make `HandleScopeBuffer` hold a fixed-size array of `Handle`s, track how many are used, and crash if we run out of room. This is enough for simple tests of other V8 functionality to work.
## []()[Implementing V8 Functions, Second Attempt](how-bun-supports-v8-apis-without-using-v8-part-2.html#implementing-v8-functions-second-attempt)
### []()[New `Local`](how-bun-supports-v8-apis-without-using-v8-part-2.html#new-local)
The first thing we'll do is change the definition of `Local` slightly so it's clearer what it actually represents:
V8Local.h
```
template<class T>
class Local final {
public:
T* ptr;
TaggedPointer* m_location;
Local(TaggedPointer* slot)
: m_location(slot)
{
}
T* operator*() const { return ptr; }
T* operator*() const { return reinterpret_cast<T*>(m_location); }
};
```
We'll have to be wary when implementing functions on V8 classes, because `this` will not actually point to an instance of the class. Fortunately, the V8 classes don't actually contain any fields, so it's not possible for us to accidentally dereference `this` by referring to a field. V8 uses separate internal classes to store the actual data for these types, and that's what I've done too.
### []()[`v8::Number` Implementation](how-bun-supports-v8-apis-without-using-v8-part-2.html#v8-number-implementation)
Let's think about how to implement those `v8::Number` functions again:
V8Number.h
```
class Number : public Primitive {
public:
BUN_EXPORT static Local<Number> New(Isolate* isolate, double value);
BUN_EXPORT double Value() const;
};
```
Additionally, let's only worry about Smi numbers. We'll start with `Value()` which is simpler. Remember that it'll be called with `this` being a pointer to the tagged pointer stored in the handle. So we need to:
- Dereference `this` to get the tagged pointer
- Check that the tagged pointer is a Smi
- Convert the Smi representation to a native integer, and then to a `double`
Let's try it:
V8Number.cpp
```
double Number::Value() const {
TaggedPointer tagged = *reinterpret_cast<const TaggedPointer*>(this);
int32_t smi;
ASSERT(tagged.getSmi(smi));
return smi;
}
```
And... it works! Well, we can't really see it working without `Number::New`, so you'll have to trust me. The version actually used in Bun is similar, but uses helper functions for a lot of those operations and supports doubles (we'll see how later).
Now, what do we need to do in `Number::New()`?
1. Assert that the provided `double value` fits in the range of `int32_t` (since full `double` values are a different case that we're not trying to handle yet)
2. Figure out the currently-active handle scope in `isolate`
3. Create a new handle
4. Set the handle's tagged pointer value (`to_v8_object`) to a Smi representing `value` (the handle will have space in it for a map pointer and `JSCell` pointer too, but we don't need to set those)
5. Return a `Local` containing a pointer to the tagged pointer in the handle
Before we can do this we'll have to figure out what an `Isolate` should be. Many V8 functions, especially those that allocate new objects, are passed a pointer to an `Isolate`. So we should make it be something that is useful for our own implementations that use JSC. Before I even started at Bun, [some basic V8 functions had been implemented](https://github.com/oven-sh/bun/blob/fe5e19da596840ca14e1665f284a6929acfeb3e5/src/bun.js/bindings/v8.cpp) using a pointer to the global object for both the isolate and the context, so I stuck with that while initially getting more of the V8 API up.
Now we need a way to get the current handle scope from the global object. We could add a field directly, but since I was adding lots of fields for V8, I put them all in a `v8::GlobalInternals` class to keep track of state specific to Bun's V8 API support. This ensures that we don't bloat the global object too much if the V8 API is not used. The global object just has a lazily-initialized pointer to the global internals.
With those details in mind, we can finally implement the correct version of `Number::New()`:
V8Number.cpp
```
Local<Number> Number::New(Isolate* isolate, double value) {
// 1.
double int_part;
// check that there is no fractional part
RELEASE_ASSERT_WITH_MESSAGE(std::modf(value, &int_part) == 0.0, "TODO handle doubles in Number::New");
// check that the integer part fits in the range of int32_t
RELEASE_ASSERT_WITH_MESSAGE(int_part >= INT32_MIN && int_part <= INT32_MAX, "TODO handle doubles in Number::New");
int32_t smi = static_cast<int32_t>(value);
// 2.
Zig::GlobalObject* globalObject = reinterpret_cast<Zig::GlobalObject*>(isolate);
HandleScope* handleScope = globalObject->V8GlobalInternals()->currentHandleScope();
// 3.
Handle& handle = handleScope->createEmptyHandle();
// 4.
handle.to_v8_object = TaggedPointer(smi);
// 5.
return Local<Number>(&handle.to_v8_object);
}
```
And this works! This code does the same thing as Bun's current implementation, except the actual version is simpler due to the use of helper functions.
### []()[Some `v8::Object` functions](how-bun-supports-v8-apis-without-using-v8-part-2.html#some-v8-object-functions)
I'm not going to wade through the implementation of every single V8 function. However, let's at least look at some of the functions that work with objects, because those are what caused us so much trouble last time and forced us to reconsider how to represent V8 values in JSC.
#### Representing objects with internal fields
Remember internal fields from earlier? To recap: objects can be created with a fixed number of fields that can be quickly accessed with an integer index. These fields are only visible to native code, and can be used by native addons to associate internal state with JavaScript objects without letting JavaScript code mess with that state.
Normal V8 objects don't have internal fields by default. The only way to create a V8 object with internal fields is to configure the internal field count on an `ObjectTemplate`, which will apply to all the objects you create using that template. This is lucky for us, as it means we don't need to support internal fields on every JSC object. Instead, we can just create a special class for an object that has internal fields, and have the `ObjectTemplate` implementation create that kind of object.
InternalFieldObject.h
```
class InternalFieldObject : public JSC::JSDestructibleObject {
public:
// ...
using FieldContainer = WTF::Vector<JSC::JSValue, 2>;
FieldContainer* internalFields() { return &m_fields; }
// ...
private:
FieldContainer m_fields;
};
```
We use a `JSValue` to represent each internal field. This is better than using V8 types like `Local`, because each `Local` is only valid as long as the handle scope it was created in exists. We need to make sure that values inside objects don't get deleted, as a common use case for internal fields is to assign them on an object that you are returning to JavaScript, and then read them later in a different native function that the object is passed into.
As for the container type, `WTF::Vector` is a dynamic array with a fixed inline capacity. So in this case, it can hold up to 2 `JSValue`s without allocating, or it will allocate space on the heap if we need to store more.
#### Accessing internal fields
Now let's look at how to expose internal fields to native modules. These are the functions we need to implement:
V8Object.h
```
namespace v8 {
class Object : public Value {
public:
// ...
BUN_EXPORT void SetInternalField(int index, Local<Data> data);
private:
BUN_EXPORT Local<Data> SlowGetInternalField(int index);
};
}
```
[`Data`](https://v8.github.io/api/head/classv8_1_1Data.html) is V8's base class for anything on the heap. V8 declares `SlowGetInternalField` as `private` since it only exists to be called by the inline `GetInternalField` that [caused us so much trouble](how-bun-supports-v8-apis-without-using-v8-part-1.html#problems). Our implementation actually has to be private too because otherwise the [mangled symbol name](https://en.wikipedia.org/wiki/Name_mangling) would be wrong on Windows:
```
// public: class v8::Local<class v8::Data> __cdecl v8::Object::SlowGetInternalField(int) __ptr64
// (incorrect)
?SlowGetInternalField@Object@v8@@QEAA?AV?$Local@VData@v8@@@2@H@Z
^
// private: class v8::Local<class v8::Data> __cdecl v8::Object::SlowGetInternalField(int) __ptr64
// (correct)
?SlowGetInternalField@Object@v8@@AEAA?AV?$Local@VData@v8@@@2@H@Z
^
```
On Linux and macOS, the mangled name is `_ZN2v86Object20SlowGetInternalFieldEi` no matter what, which does not include visibility or return type information.
Let's see the [implementation of `SetInternalField`](https://github.com/oven-sh/bun/blob/babc907bfe5ff2825e3e98d5544a49150920796e/src/bun.js/bindings/v8/V8Object.cpp#L63-L69):
V8Object.cpp
```
void Object::SetInternalField(int index, Local<Data> data)
{
FieldContainer* fields = getInternalFieldsContainer(this);
RELEASE_ASSERT(fields, "object has no internal fields");
RELEASE_ASSERT(index >= 0 && index < fields->size(), "internal field index is out of bounds");
fields->at(index) = data->localToJSValue(Isolate::GetCurrent()->globalInternals());
}
```
We call a helper function to access the vector of internal fields, which I'll show in a second. It returns `nullptr` if the object does not have one (that is, if the object is not an instance of `InternalFieldObject`). In V8, *setting* internal fields that don't exist is a fatal error, so we include assertions to check for that case.
If the index is correct, we call `Data::localToJSValue` on `data` so that we have a `JSValue` that we can store in the internal field. That's a function I implemented which, assuming it was called on a `Local`, handles the different V8 types and produces a `JSValue`. This is used in many, many places, and it can be easily called from within our implementations of V8 types as they all subclass `Data`. Here's the initial version which could only handle integers or pointers (the real implementation is more complex now):
V8Data.h
```
class Data {
JSC::JSValue localToJSValue(GlobalInternals* globalInternals) const
{
// access the tagged pointer that the Local contains a pointer to
TaggedPointer root = *reinterpret_cast<const TaggedPointer*>(this);
if (root.tag() == TaggedPointer::Tag::Smi) {
// integer
return JSC::jsNumber(root.getSmiUnchecked());
} else {
// pointer, so we have to skip over the V8 map pointer to find the actual JSCell pointer
ObjectLayout* v8_object = root.getPtr<ObjectLayout>();
return JSC::JSValue(v8_object->ptr);
}
}
};
```
What about [`SlowGetInternalField`](https://github.com/oven-sh/bun/blob/babc907bfe5ff2825e3e98d5544a49150920796e/src/bun.js/bindings/v8/V8Object.cpp#L76-L86)?
V8Object.cpp
```
Local<Data> Object::SlowGetInternalField(int index)
{
FieldContainer* fields = getInternalFieldsContainer(this);
JSObject* js_object = localToObjectPointer<JSObject>();
HandleScope* handleScope = Isolate::fromGlobalObject(JSC::jsDynamicCast<Zig::GlobalObject*>(js_object->globalObject()))->currentHandleScope();
if (fields && index >= 0 && index < fields->size()) {
JSValue field = fields->at(index);
return handleScope->createLocal<Data>(field);
}
return handleScope->createLocal<Data>(JSC::jsUndefined());
}
```
This one is supposed to return `undefined` according to V8 if the object has no internal fields, or the index is out-of-bounds. We'll look at how to represent JavaScript values like `undefined` soon.
For the rest of the function, there's a lot of indirection which makes things look complicated, but the actual operations aren't too tricky. The template `localToObjectPointer` gives us a pointer to a specific `JSCell` subclass, in this case an object. From there we can access the global object (which is a generic `JSGlobalObject`), cast it to Bun's specific global object, cast *that* to an `Isolate` which is an easy way to access information needed by V8 functions, and get the current handle scope. We need the handle scope so that this function can return a `Local` allocated within that handle scope. Once we have the fields container and the handle scope, we perform a bounds check, access the `JSValue` version of this field, and use the handle scope to turn it into a `Local`.
In case it helps, here's a diagram of the pointers that this function traverses in order to find the `InternalFieldObject` and the `HandleScope`:
[](../images/slowgetinternalfield-layout.drawio.svg)
This is the first time we're seeing the function `HandleScope::createLocal`. Lots of the current V8 APIs use this function to generate their return values. It handles a few cases based on the type of `JSValue` passed in:
- For 32-bit integers, it creates a handle where the tagged pointer is a Smi
- For pointers to objects, it sets up a handle with one of a couple different `Map`s depending on the type of the object. Then it stores the actual JSC object pointer after the `Map` pointer, and makes the tagged pointer at the start of the handle point to the map field as V8 expects.
- We'll discuss later how doubles, `true`, `false`, `null`, and `undefined` get represented.
Once the handle has been set up, `createLocal` returns a pointer to that handle, wrapped in the `Local` class.
## []()[Node.js-style Module Registration](how-bun-supports-v8-apis-without-using-v8-part-2.html#node-js-style-module-registration)
At this point, I was able to start implementing many more V8 functions on basic types. But all the tests were still using an odd hybrid configuration, with functions registered via Node-API but calling the specific V8 functions instead of Node-API functions. Remember that Node-API is the engine-agnostic way to write native addons, instead of using the V8 API directly. To fix this situation I added support for registering a native addon the same way it's done in Node.js, which both makes the structure of the tests cleaner and is also of course necessary for any real V8 module to work.
I won't get into the implementation of that, because it's not very different from Node-API, but for posterity I'll describe how a Node.js native module gets loaded. There are two ways:
- Modules may expose a function called `node_register_module_vXYZ`, where `XYZ` is the ABI version of Node.js the module was compiled for (see [this table](https://github.com/nodejs/node/blob/main/doc/abi_version_registry.json); Bun currently uses 127 to match Node.js 22). This function is passed three parameters: `Local<Object> exports` and `Local<Value> module`, which correspond to `exports` and `module` in a CommonJS module, and `Local<Context> context`, which allows modules to access the current context (and by extension the isolate) if they need it. Most modules simply use `v8::Object` functions to assign properties onto `exports`.
- Modules may use a *static constructor*, which is a function that's automatically called by the system's dynamic linker while the module is being loaded. This is a feature that exists to support calling constructors on `static` instances of C++ classes to initialize them correctly. When this static constructor is called, it in turn calls `void node_module_register(void* mod)`, a function exposed by Node.js and now by Bun. The static constructor passes into `node_module_register` a pointer to a `struct module`, to describe details of the module being loaded and provide the implementation. That struct contains:
- An `int` indicating the expected ABI version (loading a module compiled for the wrong version throws a JavaScript exception)
- The name of the source file where the module was declared, and the name of the module itself
- Two function pointers, as modules can be registered with or without passing the context into the registration function. The `exports` and `module` parameters are the same as in the `node_register_module_vXYZ` version, the `context` is omitted in one of the function signatures, and both also have a `void *priv` which allows passing extra data into the registration function
- An opaque pointer, which is passed into the registration function to allow extra data to be carried around
Most native modules don't deal with the gory details above themselves; instead, they use [macros from Node.js's public headers](https://github.com/nodejs/node/blob/v22.6.0/src/node.h#L1224-L1241), which happen to use the static constructor version instead of the predetermined function name. As such, so far I've only implemented the static constructor path to load modules, although it won't be very difficult to add support for the other way as well.
## []()[Coming up](how-bun-supports-v8-apis-without-using-v8-part-2.html#coming-up)
That's all we have time for today! In the final part of this series, we'll look at how to play nice with JSC's garbage collector (spoiler: the implementation I've shown so far is deeply broken), how to represent other JavaScript values like doubles, booleans, `null`, and `undefined`, and some other miscellaneous parts of the V8 compatibility layer. See you then.
On this page
- [Mimicking V8 Representation in JSC](how-bun-supports-v8-apis-without-using-v8-part-2.html#mimicking-v8-representation-in-jsc)
- [Tagged Pointers](how-bun-supports-v8-apis-without-using-v8-part-2.html#tagged-pointers)
- [Maps](how-bun-supports-v8-apis-without-using-v8-part-2.html#maps)
- [Objects](how-bun-supports-v8-apis-without-using-v8-part-2.html#objects)
- [Implementing V8 Functions, Second Attempt](how-bun-supports-v8-apis-without-using-v8-part-2.html#implementing-v8-functions-second-attempt)
- [New `Local`](how-bun-supports-v8-apis-without-using-v8-part-2.html#new-local)
- [`v8::Number` Implementation](how-bun-supports-v8-apis-without-using-v8-part-2.html#v8-number-implementation)
- [Some `v8::Object` functions](how-bun-supports-v8-apis-without-using-v8-part-2.html#some-v8-object-functions)
- [Node.js-style Module Registration](how-bun-supports-v8-apis-without-using-v8-part-2.html#node-js-style-module-registration)
- [Coming up](how-bun-supports-v8-apis-without-using-v8-part-2.html#coming-up)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog/the-bun-shell.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
# The Bun Shell
* * *
[Jarred Sumner](https://twitter.com/jarredsumner) · January 20, 2024
[](../rss.xml)
JavaScript is the world's most popular scripting language.
So why is it hard to run shell scripts in JavaScript?
```
import { spawnSync } from "child_process";
// this is a lot more work than it could be
const { status, stdout, stderr } = spawnSync("ls", ["-l", "*.js"], {
encoding: "utf8",
});
```
You could use APIs to do something similar:
```
import { readdir } from "fs/promises";
(await readdir(".", { withFileTypes: true })).filter((a) =>
a.name.endsWith(".js"),
);
```
But, that's still not quite as simple as a shell script:
```
ls *.js
```
## []()[Why existing shells don't work in JavaScript](the-bun-shell.html#why-existing-shells-don-t-work-in-javascript)
Shells like `bash` or `sh` have been around for decades.
Shells are a solved problem!!
- Hacker News Commenter, probably.
But, they don't work well in JavaScript. Why?
macOS (zsh), Linux (bash), and Windows (cmd) all have slightly different shells with different syntaxes and different commands. The commands available on each platform are different, and even the same command can have different flags and behaviors.
To date, npm's solution is to rely on the community to polyfill missing commands with JavaScript implementations.
### []()[`rm -rf` doesn't work on Windows](the-bun-shell.html#rm-rf-doesn-t-work-on-windows)
`rimraf`, the cross-platform JavaScript implementation of `rm -rf`, is downloaded 60 million times per week:
[](https://github.com/oven-sh/bun/assets/709451/a201e61c-2131-4982-9be6-ffdf2a37db7e)
### []()[Environment variables like `FOO=bar <script>` doesn't work on Windows](the-bun-shell.html#environment-variables-like-foo-bar-script-doesn-t-work-on-windows)
Setting an environment variable is different on each platform. Instead of running `FOO=bar`, you probably use & install `cross-env`:
[](https://github.com/oven-sh/bun/assets/709451/ab42d9b3-0fa7-4abe-beae-ca26a48e9d75)
### []()[`which` is `where` on Windows](the-bun-shell.html#which-is-where-on-windows)
Thus, another package with 60 million weekly downloads was born:
[](https://github.com/oven-sh/bun/assets/709451/e6659440-f322-47a8-99fe-ec9e3bec104e)
### []()[Shells also take too long to start](the-bun-shell.html#shells-also-take-too-long-to-start)
How long does it take to spawn a shell?
On a Linux x64 Hetzner Arch Linux machine, it takes about 7ms:
```
$ hyperfine --warmup 3 'bash -c "echo hello"' 'sh -c "echo hello"' -N
Benchmark 1: bash -c 'echo hello'
Time (mean ± σ): 7.3 ms ± 1.5 ms [User: 5.1 ms, System: 1.9 ms]
Range (min … max): 1.7 ms … 9.4 ms 529 runs
Benchmark 2: sh -c 'echo hello'
Time (mean ± σ): 7.2 ms ± 1.6 ms [User: 4.8 ms, System: 2.1 ms]
Range (min … max): 1.5 ms … 9.6 ms 327 runs
```
If your intent is to run a single command, starting the shell can take longer than running the command itself. If you're running many commands in a loop, that gets expensive quickly.
You could try embedding a shell, but that's really complicated and their license may not be compatible with your project.
## []()[Are all these polyfills really necessary?](the-bun-shell.html#are-all-these-polyfills-really-necessary)
In the world of 2009 - 2016, when JavaScript was still relatively new and experimental, relying on the community to polyfill missing functionality made a lot of sense. But it's 2024 now. JavaScript on the server is mature and widely adopted. The JavaScript ecosystem understands the requirements today in a way nobody did in 2009.
We can do better.
## []()[Introducing the Bun Shell](the-bun-shell.html#introducing-the-bun-shell)
The Bun Shell is a new experimental embedded language and interpreter in Bun that allows you to run cross-platform shell scripts in JavaScript & TypeScript.
```
import { $ } from "bun";
// to stdout:
await $`ls *.js`;
// to string:
const text = await $`ls *.js`.text();
```
You can use JavaScript variables in your shell scripts:
```
import { $ } from "bun";
const resp = await fetch("https://example.com");
const stdout = await $`gzip -c < ${resp}`.arrayBuffer();
```
For security, all **template variables are escaped**:
```
const filename = "foo.js; rm -rf /";
// This will run `ls 'foo.js; rm -rf /'`
const results = await $`ls ${filename}`;
console.log(results.exitCode); // 1
console.log(results.stderr.toString()); // ls: cannot access 'foo.js; rm -rf /': No such file or directory
```
Using Bun Shell feels like regular JavaScript. You can redirect stdout to buffers:
```
import { $ } from "bun";
const buffer = Buffer.alloc(1024);
await $`ls *.js > ${buffer}`;
console.log(buffer.toString("utf8"));
```
You can redirect stdout to a file:
```
import { $, file } from "bun";
// as a file()
await $`ls *.js > ${file("output.txt")}`;
// or as a file path string, if you prefer:
await $`ls *.js > output.txt`;
await $`ls *.js > ${"output.txt"}`;
```
You can pipe stdout to another command:
```
import { $ } from "bun";
await $`ls *.js | grep foo`;
```
You can even use `Response` as stdin:
```
import { $ } from "bun";
const buffer = new Response("bar\n foo\n bar\n foo\n");
await $`grep foo < ${buffer}`;
```
Builtin commands like `cd`, `echo`, and `rm` are available:
```
import { $ } from "bun";
await $`cd .. && rm -rf node_modules/rimraf`;
```
It works on Windows, macOS, and Linux. We've implemented many common commands and features like globbing, environment variables, redirection, piping, and more.
It's designed as a drop-in replacement for simple shell scripts. In Bun for Windows, it will power `package.json` "scripts" in `bun run`.
For fun, you can also use it as a standalone shell script interpreter:
```
echo "cat package.json" > script.bun.sh
```
```
bun script.bun.sh
```
### []()[How do I install it?](the-bun-shell.html#how-do-i-install-it)
**Bun Shell is built into Bun**. If you already have Bun v1.0.24 or later installed, you can use it today:
```
bun --version
```
```
1.0.24
```
If you don't have Bun installed, you can install it with curl:
```
curl -fsSL https://bun.sh/install | bash
```
Or with npm:
```
npm install -g bun
```
On this page
- [Why existing shells don't work in JavaScript](the-bun-shell.html#why-existing-shells-don-t-work-in-javascript)
- [`rm -rf` doesn't work on Windows](the-bun-shell.html#rm-rf-doesn-t-work-on-windows)
- [Environment variables like `FOO=bar <script>` doesn't work on Windows](the-bun-shell.html#environment-variables-like-foo-bar-script-doesn-t-work-on-windows)
- [`which` is `where` on Windows](the-bun-shell.html#which-is-where-on-windows)
- [Shells also take too long to start](the-bun-shell.html#shells-also-take-too-long-to-start)
- [Are all these polyfills really necessary?](the-bun-shell.html#are-all-these-polyfills-really-necessary)
- [Introducing the Bun Shell](the-bun-shell.html#introducing-the-bun-shell)
- [How do I install it?](the-bun-shell.html#how-do-i-install-it)
Resources
[Docs](../docs/index.html)
[Guides](../guides.html)
[Discord](../discord.html)
[GitHub](https://github.com/oven-sh/bun)
[Blog](../blog.html)
[](../rss.xml)
Toolkit
[Runtime](../docs/cli/run.html)
[Package manager](../docs/cli/install.html)
[Test runner](../docs/cli/test.html)
[Bundler](../docs/bundler.html)
[Package runner](../docs/cli/bunx.html)
Project
[Bun 1.0](../1.0.html)
[Bun 1.1](bun-v1.1.html)
[Bun 1.2](bun-v1.2.html)
[Roadmap](https://github.com/oven-sh/bun/issues/159)
[Contributing](../docs/project/contributing.html)
[License](../docs/project/licensing.html)
Baked with ❤️ in San Francisco
[We're hiring →](../careers.html)
=== bun.sh/blog.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/binary-data.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/cc.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/color.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/console.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/dns.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/fetch.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/ffi.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/file-io.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/file-system-router.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/glob.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/globals.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/hashing.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/html-rewriter.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/http.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/import-meta.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/node-api.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/s3.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/semver.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/spawn.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/sql.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/sqlite.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/streams.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/tcp.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/test.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/transpiler.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/udp.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/utils.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/websockets.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/api/workers.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/bundler/executables.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/bundler/fullstack.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/bundler/html.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/bundler/loaders.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/bundler/macros.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/bundler/plugins.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/bundler/vs-esbuild.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/bundler.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/cli/add.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/cli/bun-create.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/cli/bunx.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/cli/filter.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/cli/init.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/cli/install.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/cli/link.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/cli/outdated.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/cli/pm.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/cli/publish.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/cli/remove.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/cli/run.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/cli/test.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/cli/update.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/index.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/install/cache.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/install/lifecycle.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/install/lockfile.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/install/npmrc.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/install/overrides.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/install/patch.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/install/registries.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/install/workspaces.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/installation.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/project/benchmarking.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/project/bindgen.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/project/building-windows.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/project/contributing.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/project/licensing.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/project/roadmap.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/quickstart.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/runtime/autoimport.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/runtime/bun-apis.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/runtime/bunfig.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/runtime/debugger.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/runtime/env.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/runtime/hot.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/runtime/jsx.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/runtime/loaders.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/runtime/modules.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/runtime/nodejs-apis.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/runtime/plugins.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/runtime/shell.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/runtime/typescript.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/runtime/web-apis.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/test/coverage.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/test/dom.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/test/hot.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/test/lifecycle.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/test/mocks.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/test/snapshots.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/test/time.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/test/writing.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs/typescript.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/docs.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/arraybuffer-to-array.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/arraybuffer-to-blob.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/arraybuffer-to-buffer.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/arraybuffer-to-string.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/arraybuffer-to-typedarray.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/blob-to-arraybuffer.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/blob-to-dataview.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/blob-to-stream.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/blob-to-string.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/blob-to-typedarray.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/buffer-to-arraybuffer.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/buffer-to-blob.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/buffer-to-readablestream.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/buffer-to-string.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/buffer-to-typedarray.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/dataview-to-string.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/typedarray-to-arraybuffer.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/typedarray-to-blob.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/typedarray-to-buffer.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/typedarray-to-dataview.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/typedarray-to-readablestream.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary/typedarray-to-string.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/binary.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/astro.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/discordjs.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/docker.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/drizzle.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/edgedb.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/elysia.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/express.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/hono.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/mongoose.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/neon-drizzle.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/neon-serverless-postgres.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/nextjs.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/nuxt.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/pm2.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/prisma.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/qwik.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/react.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/remix.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/render.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/sentry.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/solidstart.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/ssr-react.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/stric.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/sveltekit.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/systemd.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem/vite.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/ecosystem.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/http/cluster.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/http/fetch-unix.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/http/fetch.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/http/file-uploads.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/http/hot.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/http/proxy.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/http/server.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/http/simple.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/http/stream-file.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/http/stream-iterator.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/http/stream-node-streams-in-bun.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/http/tls.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/http.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install/add-dev.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install/add-git.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install/add-optional.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install/add-peer.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install/add-tarball.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install/add.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install/azure-artifacts.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install/cicd.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install/custom-registry.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install/from-npm-install-to-bun-install.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install/git-diff-bun-lockfile.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install/jfrog-artifactory.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install/npm-alias.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install/registry-scope.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install/trusted.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install/workspaces.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install/yarnlock.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/install.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/process/argv.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/process/ctrl-c.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/process/ipc.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/process/nanoseconds.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/process/os-signals.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/process/spawn-stderr.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/process/spawn-stdout.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/process/spawn.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/process/stdin.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/process.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/read-file/arraybuffer.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/read-file/buffer.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/read-file/exists.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/read-file/json.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/read-file/mime.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/read-file/stream.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/read-file/string.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/read-file/uint8array.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/read-file/watch.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/read-file.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/runtime/cicd.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/runtime/define-constant.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/runtime/import-html.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/runtime/import-json.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/runtime/import-toml.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/runtime/read-env.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/runtime/set-env.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/runtime/shell.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/runtime/timezone.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/runtime/tsconfig-paths.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/runtime/typescript.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/runtime/vscode-debugger.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/runtime/web-debugger.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/runtime.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/streams/node-readable-to-arraybuffer.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/streams/node-readable-to-blob.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/streams/node-readable-to-json.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/streams/node-readable-to-string.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/streams/node-readable-to-uint8array.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/streams/to-array.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/streams/to-arraybuffer.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/streams/to-blob.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/streams/to-buffer.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/streams/to-json.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/streams/to-string.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/streams/to-typedarray.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/streams.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/bail.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/coverage-threshold.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/coverage.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/happy-dom.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/migrate-from-jest.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/mock-clock.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/mock-functions.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/rerun-each.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/run-tests.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/skip-tests.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/snapshot.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/spy-on.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/svelte-test.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/testing-library.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/timeout.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/todo-tests.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/update-snapshots.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test/watch-mode.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/test.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util/base64.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util/deep-equals.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util/deflate.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util/detect-bun.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util/entrypoint.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util/escape-html.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util/file-url-to-path.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util/gzip.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util/hash-a-password.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util/import-meta-dir.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util/import-meta-file.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util/import-meta-path.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util/main.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util/path-to-file-url.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util/sleep.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util/version.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util/which-path-to-executable-bin.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/util.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/websocket/compression.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/websocket/context.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/websocket/pubsub.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/websocket/simple.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/websocket.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/write-file/append.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/write-file/basic.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/write-file/blob.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/write-file/cat.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/write-file/file-cp.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/write-file/filesink.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/write-file/response.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/write-file/stdout.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/write-file/stream.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/write-file/unlink.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides/write-file.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/guides.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/index.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
Sainder
Jan 17
@Sainder\_Pradipt
Bun
Lic
Jan 18
@Lik228
bun
Martin Navrátil
Jan 17
@martin\_nav_
Bun....
SaltyAom
Jan 17
@saltyAom
bun
reaxios
Jan 17
@reaxios
bun install bun
kyge
Jan 17
@0xkyge
bun
James Landrum
Jan 17
@JamesRLandrum
Node
orlowdev
Jan 17
@orlowdev
Yeah, bun, but my code does not have dependencies.
hola
Jan 17
@jdggggyujhbc
bun
std::venom
Jan 17
@std\_venom
Bun
tiago
Jan 19
@tiagorangel23
should have used Bun instead of npm
46officials
Jan 19
@46officials
Bun
yuki
Jan 19
@staticdots
Bun
Stefan
Jan 17
@stefangarofalo
Bun
Samuel
Jan 17
@samueldans0
Bun always
Divin Prince
Jan 17
@divinprnc
Yeah Bun
Gibson
Jan 16
@GibsonSMurray
bun
Oggie Sutrisna
Jan 16
@oggiesutrisna
bun
emanon
Jan 16
@0x\_emanon
✅ bun
yuki
Jan 16
@staticdots
bun
SpiritBear
Jan 16
@0xSpiritBear
bun
Ayu
Jan 12
@Ayuu2809
Bun good 🧅
Hirbod
Jan 19
@hirbod\_dev
For everything. Yes. I even run with bunx expo run:ios etc
Luis Paolini
Jan 18
@DigitalLuiggi
Jus use @bunjavascript
buraks
Jan 18
@buraks\_\_\__
I use bun patch and I love it!
fahadali
Jan 8
@fahadali503
Bun
Aiden Bai
Jan 1
@aidenybai
2025 will be the year of JS/TS and @bunjavascript is why
Catalin
Jan 1
@catalinmpit
Bun is goated
MadMax
Jan 3
@dr\_\_madmax
@bunjavascript is yet to get enough appreciation it deserves.
Baggi/e
Jan 3
@ManiSohi
Performant TS/JS backend needs more love Elysia for the win
Michael Feldstein
Dec 18
@msfeldstein
holy shit bun is the solution to spending all day mucking around with typescript/module/commonjs/import bullshit and just running scripts
Sainder
Jan 17
@Sainder\_Pradipt
Bun
Lic
Jan 18
@Lik228
bun
Martin Navrátil
Jan 17
@martin\_nav_
Bun....
SaltyAom
Jan 17
@saltyAom
bun
reaxios
Jan 17
@reaxios
bun install bun
kyge
Jan 17
@0xkyge
bun
James Landrum
Jan 17
@JamesRLandrum
Node
orlowdev
Jan 17
@orlowdev
Yeah, bun, but my code does not have dependencies.
hola
Jan 17
@jdggggyujhbc
bun
std::venom
Jan 17
@std\_venom
Bun
tiago
Jan 19
@tiagorangel23
should have used Bun instead of npm
46officials
Jan 19
@46officials
Bun
yuki
Jan 19
@staticdots
Bun
Stefan
Jan 17
@stefangarofalo
Bun
Samuel
Jan 17
@samueldans0
Bun always
Divin Prince
Jan 17
@divinprnc
Yeah Bun
Gibson
Jan 16
@GibsonSMurray
bun
Oggie Sutrisna
Jan 16
@oggiesutrisna
bun
emanon
Jan 16
@0x\_emanon
✅ bun
yuki
Jan 16
@staticdots
bun
SpiritBear
Jan 16
@0xSpiritBear
bun
Ayu
Jan 12
@Ayuu2809
Bun good 🧅
Hirbod
Jan 19
@hirbod\_dev
For everything. Yes. I even run with bunx expo run:ios etc
Luis Paolini
Jan 18
@DigitalLuiggi
Jus use @bunjavascript
buraks
Jan 18
@buraks\_\_\__
I use bun patch and I love it!
fahadali
Jan 8
@fahadali503
Bun
Aiden Bai
Jan 1
@aidenybai
2025 will be the year of JS/TS and @bunjavascript is why
Catalin
Jan 1
@catalinmpit
Bun is goated
MadMax
Jan 3
@dr\_\_madmax
@bunjavascript is yet to get enough appreciation it deserves.
Baggi/e
Jan 3
@ManiSohi
Performant TS/JS backend needs more love docsearch({ appId: '2527C13E0N', apiKey: '4efc87205e1fce4a1f267cadcab42cb2', indexName: 'bun', container: '#docsearchbox', });
=== bun.sh/nodejs.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }
=== bun.sh/package-manager.html ===
"@context": "https://schema.org", "@type": "WebSite", "name": "Bun", "alternateName": "Bun", "url": "https://bun.sh" }