We're hiring systems engineers 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 -fsSL https://bun.sh/install | bash
npm install -g bun
powershell -c "irm bun.sh/install.ps1|iex"
scoop install bun
brew tap oven-sh/bun
brew install bun
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 for VSCode 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:
- Install Bun for VSCode
- Open a terminal in VSCode
- Run
bun test --watch
,bun run foo.ts
, or any other script - Watch errors reported in the "Problems" tab
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
andRangeError
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 for implementing this.
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
:
{
"name": "foo",
"exports": {
".": "./foo.js"
}
}
import * as foo from 'foo';
export const bar = foo;
The following code in index.js
will print true
:
import * as foo from 'foo';
console.log(foo.bar === foo); // true
Implemented thanks to @SunsetTechuila!
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
— Bun (@bunjavascript) November 20, 2024
A slow memory leak impacting napi & Prisma has been fixed pic.twitter.com/Dl1ZeXEFmj
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!
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:
{
"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!
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:
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
div {
color: red;
}
@import url('blue.css');
This and many other errors have been improved in this release. A snippet of the changes:
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!
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!
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
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!
const hugeFile = Bun.file('huge-file.txt'); // throws ENOMEM
console.log(hugeFile.size);
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!
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.
import { expect, test } from "bun:test";
test("snapshot `foo`", () => {
const foo: string = "hello ${}!";
expect(bar).toMatchSnapshot();
});
Fixed thanks to @pfgithub!
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!
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!
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!
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
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
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!
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