---
title: Bun v1.1.41
description: "Fixes 12 bugs (addressing 196 👍). JSDOM & happy-dom work more reliably due to node:vm compatibility improvements. Single-file executables on Windows now support custom icons and hiding the console. throw: true in Bun.build throws an error instead of returning errors. bun install gets the --omit=dev|optional|peer options and in .npmrc. A hoisting edgecase in bun install is fixed"
date: "2024-12-20T13:57:57.212Z"
author: jarred
---

{% callout %}
We're hiring [systems engineers](/careers) in San Francisco to build the future of JavaScript!
{% /callout %}

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

{% codetabs %}

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

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

```sh#powershell
$ powershell -c "irm bun.sh/install.ps1|iex"
```

```sh#scoop
$ scoop install bun
```

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

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

{% /codetabs %}

#### To upgrade Bun

```sh
$ bun upgrade
```

## 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

Previously, the `runScripts: "outside-only"`, `runScripts: "dangerously"`, and `runInContext` options in JSDOM were not supported. Now they are.

{% image src="https://github.com/user-attachments/assets/77a5ac98-c5fb-4733-acc8-cdc1b6c948ba" width="600px" /%}

### 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.

{% image src="https://github.com/user-attachments/assets/bef277db-7d4c-433f-9871-238c7b0044eb" width="600px" /%}

## New: Icons in single-file executables for Windows

[Single-file executables](/docs/bundler/executables) now support the `--windows-icon=./icon.ico` option to embed an icon in the executable on Windows.

```sh
$ 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

You can now hide the console window on Windows when a [single-file executable](/docs/bundler/executables) is run.

```sh
$ bun build --compile --windows-hide-console ./index.ts --outfile=app.exe
```

## 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.

```ts
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

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()

You can now use `expect().toHaveBeenCalledOnce()` to check that a mock function was called exactly once.

```ts
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

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:

```js
"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:

```js
console.log("123");
```

Is that CommonJS or ESM? No way to tell.

Okay, how about this?

```js
console.log(module.require("path"));
```

CommonJS, because it's using `module.require` to get the `path` module.

And this?

```js
import path from "path";
console.log(path);
```

ESM because it's using `import`.

And this?

```js
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?

```js
"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

{% raw %}

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">In the next version of Bun<br><br>A longstanding bug that sometimes caused this fraction to be impossible is fixed <a href="https://t.co/8heI6obyft">pic.twitter.com/8heI6obyft</a></p>&mdash; Bun (@bunjavascript) <a href="https://twitter.com/bunjavascript/status/1870094361184350400?ref_src=twsrc%5Etfw">December 20, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

{% /raw %}

## 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

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

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

You can now pass an array of colors to `util.styleText` to style a string with multiple colors.

```ts
const styledText = util.styleText(
  ["red", "bold", "underline"],
  "Hello, world!",
);
```

This aligns the behavior with Node.js

## Fixed: unnecessary inline sourcemaps in VSCode

When you have Bun's official VSCode extension installed, Bun automatically reports runtime errors in the "problems" tab of VSCode to give you real-time in-editor error reporting.

This involves a WebKit inspector connection that occurs when you ordinarily launch Bun from your VSCode terminal.

When the debugger is connected, Bun internally appends inline sourcemaps to transpiled JavaScript files so the debugger can find the original source code and map errors, messages, breakpoints files, etc. This is important for debugging, but it costs you memory and startup time to append these base64-encoded sourcemaps to every single file that loads.

These sourcemaps are only necessary for the debugger, and not for the "problems" tab feature in VSCode (which sends over pre-sourcemapped errors instead of sourcemapping in the extension). This release disables inline sourcemaps when only the "problems" tab is being used.

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

## Fixed: Theoretical crash in CommonJS module loading

A hypothetical crash that could occur in CommonJS module loading has been fixed.

Bun transpiles every file before it loads.

CommonJS modules have a function wrapper that looks something like this:

```js
(function (exports, require, module, __filename, __dirname) {
  // module code
});
```

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

You can now import namespaces and default imports for macros.

```ts
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!

- [@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)
