## Summary
Fixes#25640
- Fixed bug where compiled binaries with `autoloadBunfig: false` would
still load `bunfig.toml` when `execArgv` was also provided
- The issue was that `Command.init(.AutoCommand)` was called to parse
execArgv, which loaded bunfig before checking the disable flag
## Test plan
- [x] Added tests for `autoloadBunfig: false` with `execArgv` in
`test/bundler/bundler_compile_autoload.test.ts`
- [x] Verified tests pass with debug build: `bun bd test
test/bundler/bundler_compile_autoload.test.ts`
- [x] Verified tests fail with system bun (demonstrates fix works):
`USE_SYSTEM_BUN=1 bun test test/bundler/bundler_compile_autoload.test.ts
-t "AutoloadBunfigDisabledWithExecArgv"`
- [x] All existing autoload tests still pass (22 tests total)
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
- Fixed lazy-loaded chunks from dynamic imports not appearing in
`frontend.files` when using `--splitting` with `--compile` in fullstack
builds
- Updated `computeChunks.zig` to mark non-entry-point chunks as browser
chunks when they contain browser-targeted files
- Updated `HTMLImportManifest.zig` to include browser chunks from server
builds in the files manifest
Fixes#25628
## Test plan
- [ ] Added regression test `test/regression/issue/25628.test.ts` that
verifies lazy chunks appear in `frontend.files`
- [ ] Manually verified: system bun reports `CHUNK_COUNT:1` (bug), debug
bun reports `CHUNK_COUNT:2` (fix)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
When moduleLoaderEvaluate finishes evaluating a module, it checks if the
module is the eval entry point to store the result. However, the condition
was checking `Bun__VM__specifierIsEvalEntryPoint(...)` before checking
`!scope.exception()`.
This caused an exception validation failure because specifierIsEvalEntryPoint
converts the JSValue key to a string (via toBunString which calls String.fromJS),
and calling fromJS while an exception is pending is invalid.
The fix swaps the order to check for exception first, leveraging short-circuit
evaluation to avoid calling specifierIsEvalEntryPoint when an exception exists.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
- CSS logical border-radius properties (`border-start-start-radius`,
`border-start-end-radius`, `border-end-end-radius`,
`border-end-start-radius`) were being silently dropped when processed by
the CSS bundler
- The bug was in `src/css/properties/border_radius.zig` where
`VendorPrefix{}` (all fields false) was used instead of `VendorPrefix{
.none = true }` when computing prefixes for logical properties
- This caused the properties to be dropped by a later `isEmpty()` check
since an empty prefix struct was returned
## Test plan
- [x] Added regression test `test/regression/issue/25785.test.ts`
- [x] Verified test fails with system Bun (`USE_SYSTEM_BUN=1 bun test`)
- [x] Verified test passes with fixed bun-debug (`bun bd test`)
Fixes#25785🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
## Summary
- Fixes#25972: TestReporter domain events not firing when debugger
connects after test discovery
When a debugger client connects and enables the TestReporter domain
after tests have been discovered (e.g., using `--inspect` instead of
`--inspect-wait`), the `TestReporter.found`, `TestReporter.start`, and
`TestReporter.end` events would not fire. This is because tests
discovered without an enabled debugger have `test_id_for_debugger = 0`,
and the event emission code checks for non-zero IDs.
The fix retroactively assigns test IDs and reports discovered tests when
`TestReporter.enable` is called:
1. Check if there's an active test file in collection or execution phase
2. Iterate through the test tree (DescribeScopes and test entries)
3. Assign unique `test_id_for_debugger` values to each test/describe
4. Send `TestReporter.found` events for each discovered test
## Test plan
- [ ] Verify IDE integrations can now receive test telemetry when
connecting after test discovery
- [ ] Ensure existing `--inspect-wait` behavior continues to work
(debugger enabled before discovery)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
- Implements the `-l` (long listing) flag functionality for the shell
`ls` builtin
- The flag was being parsed but never used - output was identical to
short format
- Now displays proper long listing format: file type, permissions, hard
link count, UID, GID, size, modification time, and filename
## Test plan
- [x] Added regression test in `test/regression/issue/25831.test.ts`
- [x] Test passes with debug build: `bun bd test
test/regression/issue/25831.test.ts`
- [x] Test fails with system bun (confirming the bug exists):
`USE_SYSTEM_BUN=1 bun test test/regression/issue/25831.test.ts`
Example output with fix:
```
$ bun -e 'import { $ } from "bun"; console.log(await $`ls -l`.text())'
drwxr-xr-x 2 1000 1000 4096 Jan 12 15:30 subdir
-rw-r--r-- 1 1000 1000 11 Jan 12 15:30 file.txt
```
Fixes#25831🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
Fixes https://github.com/oven-sh/bun/issues/26082
- Fixes a bug where standalone executables compiled with
`--compile-exec-argv` would intercept `--version`, `-v`, `--help`, and
`-h` flags before user code could handle them
- CLI applications using libraries like `commander` can now properly
implement their own version and help commands
## Root Cause
When `--compile-exec-argv` is used, `Command.init` was being called with
`.AutoCommand`, which parses ALL arguments (including user arguments).
The `Arguments.parse` function intercepts `--version`/`--help` flags for
`AutoCommand`, preventing them from reaching user code.
## Fix
Temporarily set `bun.argv` to only include the executable name +
embedded exec argv options when calling `Command.init`. This ensures:
1. Bun's embedded options (like `--smol`, `--use-system-ca`) are
properly parsed
2. User arguments (including `--version`/`--help`) are NOT intercepted
by Bun's parser
3. User arguments are properly passed through to user code
## Test plan
- [x] Added tests for `--version`, `-v`, `--help`, and `-h` flags in
`compile-argv.test.ts`
- [x] Verified tests fail with `USE_SYSTEM_BUN=1` (proving the bug
exists)
- [x] Verified tests pass with debug build
- [x] Verified existing compile-argv tests still pass
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
- Fix a hang in sequential MySQL transactions where an INSERT is awaited
followed by a SELECT returned in an array
- The issue occurred because `handleResultSetOK`'s defer block only
called `queue.advance()` without flushing, causing queries added during
the JS callback to not be properly sent
- Changed to call `flushQueue()` instead of just `advance()` to ensure
data is actually sent to the server
Fixes#26030
## Test plan
- Added regression test `test/regression/issue/26030.test.ts` with three
test cases:
- `Sequential transactions with INSERT and returned SELECT should not
hang` - reproduces the exact pattern from the bug report
- `Sequential transactions with returned array of multiple queries` -
tests returning multiple queries in array
- `Many sequential transactions with awaited INSERT and returned SELECT`
- stress tests with 5 sequential transactions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
- Fixed a bug where named function expressions were not renamed when
their name shadowed an outer symbol that's referenced inside the
function body
- This caused infinite recursion at runtime when namespace imports were
inlined
- Particularly affected Svelte 5 apps in dev mode
## Test plan
- [x] Added regression test that reproduces the issue
- [x] Verified test fails with system bun and passes with fix
- [x] Ran bundler tests (bundler_regressions, bundler_naming,
bundler_edgecase, bundler_minify) - all pass
## Root cause
The bundler was skipping `function_args` scopes when renaming symbols.
This meant named function expression names (which are declared in the
function_args scope) were never considered for renaming when they
collided with outer symbols.
For example, this code:
```javascript
import * as $ from './lib';
$.doSomething(function get() {
return $.get(123); // Should call outer get
});
```
Would be bundled as:
```javascript
function get(x) { return x * 2; } // from lib
doSomething(function get() {
return get(123); // Calls itself - infinite recursion!
});
```
Instead of:
```javascript
function get(x) { return x * 2; }
doSomething(function get2() { // Renamed to avoid collision
return get(123); // Correctly calls outer get
});
```
Fixes#25648🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
## Summary
- Fixed MySQL VARCHAR/CHAR/TEXT columns with binary collations (like
`utf8mb4_bin`) being incorrectly returned as `Buffer` instead of
`string`
- The fix checks for `character_set == 63` (binary collation) in
addition to the BINARY flag to properly distinguish true binary types
Fixes#26063
## Root Cause
PR #26011 introduced a fix for binary column handling that checked
`column.flags.BINARY` to determine if data should be returned as
`Buffer`. However, MySQL sets the BINARY flag on VARCHAR/CHAR/TEXT
columns with binary collations (like `utf8mb4_bin`) even though they
should return strings.
The proper way to detect true binary types (BINARY, VARBINARY, BLOB) is
to check if `character_set == 63` (the "binary" collation), not just the
BINARY flag.
## Changes
1. **Text Protocol** (`ResultSet.zig:143-148`): Updated binary check to
`column.flags.BINARY and column.character_set == 63`
2. **Binary Protocol** (`DecodeBinaryValue.zig:154-156`): Added
`character_set` parameter and updated binary check
## Test plan
- [ ] Added regression test `test/regression/issue/26063.test.ts` that
tests VARCHAR, CHAR, and TEXT columns with `utf8mb4_bin` collation
return strings
- [ ] Test verifies that true BINARY/VARBINARY/BLOB columns still return
Buffers
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
## Summary
- Fixed `bun install --frozen-lockfile` to use scope-specific registry
for scoped packages when the lockfile has an empty registry URL
When parsing a `bun.lock` file with an empty registry URL for a scoped
package (like `@example/test-package`), bun was unconditionally using
the default npm registry (`https://registry.npmjs.org/`) instead of
looking up the scope-specific registry from `bunfig.toml`.
For example, with this configuration in `bunfig.toml`:
```toml
[install.scopes]
example = { url = "https://npm.pkg.github.com" }
```
And this lockfile entry with an empty registry URL:
```json
"@example/test-package": ["@example/test-package@1.0.0", "", {}, "sha512-AAAA"]
```
bun would try to fetch from
`https://registry.npmjs.org/@example/test-package/-/...` instead of
`https://npm.pkg.github.com/@example/test-package/-/...`.
The fix uses `manager.scopeForPackageName()` (the same pattern used in
`pnpm.zig`) to look up the correct scope-specific registry URL.
## Test plan
- [x] Added regression test `test/regression/issue/026039.test.ts` that
verifies:
- Scoped packages use the scope-specific registry from `bunfig.toml`
- Non-scoped packages continue to use the default registry
- [x] Verified test fails with system bun (without fix) and passes with
debug build (with fix)
Fixes#26039🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
### What does this PR do?
### How did you verify your code works?
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
### What does this PR do?
Previously, reactFastRefresh was silently ignored when target was not
'browser', even when explicitly enabled. This was confusing as there was
no warning or error.
This change removes the `target == .browser` check, trusting explicit
user intent. If users enable reactFastRefresh with a non-browser target,
the transform will now be applied. If `$RefreshReg$` is not defined at
runtime, it will fail fast with a clear error rather than silently doing
nothing.
Use case: Terminal UIs (like [termcast](https://termcast.app)) need
React Fast Refresh with target: 'bun' for hot reloading in non-browser
environments.
### How did you verify your code works?
Updated existing test removing target browser
## Summary
- Fixes `bun init --minimal` creating Cursor rules files and CLAUDE.md
when it shouldn't
- Adds regression test to verify `--minimal` only creates package.json
and tsconfig.json
## Test plan
- [x] Verify test fails with system bun (unfixed): `USE_SYSTEM_BUN=1 bun
test test/cli/init/init.test.ts -t "bun init --minimal"`
- [x] Verify test passes with debug build: `bun bd test
test/cli/init/init.test.ts -t "bun init --minimal"`
- [x] All existing init tests pass: `bun bd test
test/cli/init/init.test.ts`
Fixes#26050🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
- Add `_idleStart` property (getter/setter) to the Timeout object
returned by `setTimeout()` and `setInterval()`
- The property returns a monotonic timestamp (in milliseconds)
representing when the timer was created
- This mimics Node.js's behavior where `_idleStart` is the libuv
timestamp at timer creation time
## Test plan
- [x] Verified test fails with `USE_SYSTEM_BUN=1 bun test
test/regression/issue/25639.test.ts`
- [x] Verified test passes with `bun bd test
test/regression/issue/25639.test.ts`
- [x] Manual verification:
```bash
# Bun with fix - _idleStart exists
./build/debug/bun-debug -e "const t = setTimeout(() => {}, 0);
console.log('_idleStart' in t, typeof t._idleStart); clearTimeout(t)"
# Output: true number
# Node.js reference - same behavior
node -e "const t = setTimeout(() => {}, 0); console.log('_idleStart' in
t, typeof t._idleStart); clearTimeout(t)"
# Output: true number
```
Closes#25639🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
- Fixes handler context not being restored after minifying nested CSS
rules
- Adds regression test for the issue
## Test plan
- [x] Test fails with `USE_SYSTEM_BUN=1 bun test
test/regression/issue/25794.test.ts`
- [x] Test passes with `bun bd test test/regression/issue/25794.test.ts`
Fixes#25794🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
Fix a memory leak in `RequestContext.doRenderWithBody()` where
`Strong.Impl` memory was leaked when proxying streaming responses
through Bun's HTTP server.
## Problem
When a streaming response (e.g., from a proxied fetch request) was
forwarded through Bun's server:
1. `response_body_readable_stream_ref` was initialized at line 1836
(from `lock.readable`) or line 1841 (via `Strong.init()`)
2. For `.Bytes` streams with `has_received_last_chunk=false`, a **new**
Strong reference was created at line 1902
3. The old Strong reference was **never deinit'd**, causing
`Strong.Impl` memory to leak
This leak accumulated over time with every streaming response proxied
through the server.
## Solution
Add `this.response_body_readable_stream_ref.deinit()` before creating
the new Strong reference. This is safe because:
- `stream` exists as a stack-local variable
- JSC's conservative GC tracks stack-local JSValues
- No GC can occur between consecutive synchronous Zig statements
- Therefore, `stream` won't be collected between `deinit()` and
`Strong.init()`
## Test
Added `test/js/web/fetch/server-response-stream-leak.test.ts` which:
- Creates a backend server that returns delayed streaming responses
- Creates a proxy server that forwards the streaming responses
- Makes 200 requests and checks that ReadableStream objects don't
accumulate
- Fails on system Bun v1.3.5 (202 leaked), passes with the fix
## Related
Similar to the Strong reference leak fixes in:
- #23313 (fetch memory leak)
- #25846 (fetch cyclic reference leak)
When running `bun --print 'require("doesnotexist")'` or `bun -e 'require("doesnotexist")'`,
the error was being silently swallowed and `undefined` was printed with exit code 0.
The root cause was that `JSC::evaluate()` returns exceptions via an optional
`NakedPtr<Exception>` parameter rather than putting them on the throw scope.
The inline convenience version that doesn't take this parameter was being used,
which discarded the exception into an unused variable.
The fix passes a `NakedPtr<Exception>` to capture the exception and then
properly throws it onto the scope so it propagates through the module loader.
Also added exception checking in `EvalGlobalObject::moduleLoaderEvaluate` to
prevent storing results when exceptions occur in the ESM evaluation path.
Closes#25653
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
## What does this PR do?
Currently binary columns are returned as strings which means they get
corrupted when encoded in UTF8. This PR returns binary columns as
Buffers which is what user's actually expect and is also consistent with
PostgreSQL and SQLite.
### How did you verify your code works?
I added tests to verify the correct behavior. Before there were no tests
for binary columns at all.
This fixes#23991
Fixes#25862
### What does this PR do?
When a client sends pipelined data immediately after CONNECT request
headers in the same TCP segment, Bun now properly delivers this data to
the `head` parameter of the 'connect' event handler, matching Node.js
behavior.
This enables compatibility with Cap'n Proto's KJ HTTP library used by
Cloudflare's workerd runtime, which pipelines RPC data after CONNECT.
### How did you verify your code works?
<img width="694" height="612" alt="CleanShot 2026-01-09 at 15 30 22@2x"
src="https://github.com/user-attachments/assets/3ffe840e-1792-429c-8303-d98ac3e6912a"
/>
Tests
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
## Summary
- Add comprehensive TypeScript type definitions for `Bun.Archive` in
`bun.d.ts`
- `ArchiveInput` and `ArchiveCompression` types
- Full JSDoc documentation with examples for all methods (`from`,
`write`, `extract`, `blob`, `bytes`, `files`)
- Add documentation page at `docs/runtime/archive.mdx`
- Quickstart examples
- Creating and extracting archives
- `files()` method with glob filtering
- Compression support
- Full API reference section
- Add Archive to docs sidebar under "Data & Storage"
- Add `files()` benchmark comparing `Bun.Archive.files()` vs node-tar
- Shows ~7x speedup for reading archive contents into memory (59µs vs
434µs)
## Test plan
- [x] TypeScript types compile correctly
- [x] Documentation renders properly in Mintlify format
- [x] Benchmark runs successfully and shows performance comparison
- [x] Verified `files()` method works correctly with both Bun.Archive
and node-tar
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
## Summary
- Fixes a path traversal vulnerability via symlink when installing
GitHub packages
- Validates symlink targets before creation to ensure they stay within
the extraction directory
- Rejects absolute symlinks and relative paths that would escape the
extraction directory
## Details
When extracting GitHub tarballs, Bun did not validate symlink targets. A
malicious tarball could:
1. Create a symlink pointing outside the extraction directory (e.g.,
`../../../../../../../tmp`)
2. Include a file entry through that symlink path (e.g.,
`symlink-to-tmp/pwned.txt`)
When extracted, the symlink would be created first, then the file would
be written through it, ending up outside the intended package directory
(e.g., `/tmp/pwned.txt`).
### The Fix
Added `isSymlinkTargetSafe()` function that:
1. Rejects absolute symlink targets (starting with `/`)
2. Normalizes the combined path (symlink location + target) and rejects
if the result starts with `..` (would escape)
## Test plan
- [x] Added regression test
`test/cli/install/symlink-path-traversal.test.ts`
- [x] Tests verify relative path traversal symlinks are blocked
- [x] Tests verify absolute symlink targets are blocked
- [x] Tests verify safe relative symlinks within the package still work
- [x] Verified test fails with system bun (vulnerable) and passes with
debug build (fixed)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
## Summary
Adds a new CLI flag `--compile-executable-path` that allows specifying a
custom Bun executable path for cross-compilation instead of downloading
from the npm registry.
## Usage
```bash
bun build --compile --target=bun-linux-x64 \
--compile-executable-path=/path/to/bun-linux-x64 app.ts
```
## Motivation
The `executablePath` option was already available in the JavaScript
`Bun.build()` API. This exposes the same functionality from the CLI.
## Changes
- Added `--compile-executable-path <STR>` CLI parameter in
`src/cli/Arguments.zig`
- Added `compile_executable_path` field to `BundlerOptions` in
`src/cli.zig`
- Wired the option through to `StandaloneModuleGraph.toExecutable()` in
`src/cli/build_command.zig`
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
### What does this PR do?
remove agent in global WebSocket (in node.js it uses dispatcher not
agent) add agent support in ws module (this actually uses agent)
### How did you verify your code works?
Tests
## Summary
Fixes#25869
Two fixes to enable `jest.useFakeTimers()` to work with
`@testing-library/react` and `@testing-library/user-event`:
- Set `setTimeout.clock = true` when fake timers are enabled.
testing-library/react's `jestFakeTimersAreEnabled()` checks for this
property to determine if `jest.advanceTimersByTime()` should be called
when draining the microtask queue. Without this, testing-library never
advances timers.
- Make `advanceTimersByTime(0)` fire `setTimeout(fn, 0)` timers.
`setTimeout(fn, 0)` is internally scheduled with a 1ms delay per HTML
spec. Jest/testing-library expect `advanceTimersByTime(0)` to fire such
"immediate" timers, but we were advancing by 0ms so they never fired.
## Test plan
- [x] All 30 existing fake timer tests pass
- [x] New regression test validates both fixes
- [x] Original user-event reproduction now works (test completes instead
of hanging)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
## Summary
- **libarchive.zig:110**: Fix self-assignment bug where `this.pos` was
assigned to itself instead of `new_pos`
- **s3/credentials.zig:165,176,199**: Fix impossible range checks -
`and` should be `or` for pageSize, partSize, and retry validation (a
value cannot be both less than MIN and greater than MAX simultaneously)
- **postgres.zig:14**: Fix copy-paste error where createConnection
function was internally named "createQuery"
## Test plan
- [ ] Verify S3 credential validation now properly rejects out-of-range
values for pageSize, partSize, and retry
- [ ] Verify libarchive seek operations work correctly
- [ ] Verify postgres createConnection function has correct internal
name
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: Claude Bot <claude-bot@bun.sh>
## Summary
- Fixes#25903 - `Bun.write()` mode option ignored when copying from
`Bun.file()`
- The destination file now correctly uses the specified `mode` option
instead of default permissions
- Works on Linux (via open flags), macOS (chmod after clonefile), and
Windows (chmod after copyfile)
## Test plan
- [x] Added regression test in `test/regression/issue/25903.test.ts`
- [x] Test passes with `bun bd test test/regression/issue/25903.test.ts`
- [x] Test fails with `USE_SYSTEM_BUN=1 bun test
test/regression/issue/25903.test.ts` (verifies the bug exists)
## Changes
- `src/bun.js/webcore/Blob.zig`: Add `mode` field to `WriteFileOptions`
and parse from options
- `src/bun.js/webcore/blob/copy_file.zig`: Use `destination_mode` in
`CopyFile` struct and `doOpenFile`
- `packages/bun-types/bun.d.ts`: Add `mode` option to BunFile copy
overloads
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
Add support for in-memory entrypoints and files in `Bun.build` via the
`files` option:
```ts
await Bun.build({
entrypoints: ["/app/index.ts"],
files: {
"/app/index.ts": `
import { greet } from "./greet.ts";
console.log(greet("World"));
`,
"/app/greet.ts": `
export function greet(name: string) {
return "Hello, " + name + "!";
}
`,
},
});
```
### Features
- **Bundle entirely from memory**: No files on disk needed
- **Override files on disk**: In-memory files take priority over disk
files
- **Mix disk and virtual files**: Real files can import virtual files
and vice versa
- **Multiple content types**: Supports `string`, `Blob`, `TypedArray`,
and `ArrayBuffer`
### Use Cases
- Code generation at build time
- Injecting build-time constants
- Testing with mock modules
- Bundling dynamically generated code
- Overriding configuration files for different environments
### Implementation Details
- Added `FileMap` struct in `JSBundler.zig` with `resolve`, `get`,
`contains`, `fromJS`, and `deinit` methods
- Uses `"memory"` namespace to avoid `pathWithPrettyInitialized`
allocation issues during linking phase
- FileMap checks added in:
- `runResolver` (entry point resolution)
- `runResolutionForParseTask` (import resolution)
- `enqueueEntryPoints` (entry point handling)
- `getCodeForParseTaskWithoutPlugins` (file content reading)
- Root directory defaults to cwd when all entrypoints are in the FileMap
- Added TypeScript types with JSDoc documentation
- Added bundler documentation with examples
## Test plan
- [x] Basic in-memory file bundling
- [x] In-memory files with absolute imports
- [x] In-memory files with relative imports (same dir, subdirs, parent
dirs)
- [x] Nested/chained imports between in-memory files
- [x] TypeScript and JSX support
- [x] Blob, Uint8Array, and ArrayBuffer content types
- [x] Re-exports and default exports
- [x] In-memory file overrides real file on disk
- [x] Real file on disk imports in-memory file via relative path
- [x] Mixed disk and memory files with complex import graphs
Run tests with: `bun bd test test/bundler/bundler_files.test.ts`
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
## Summary
This PR implements a new `Bun.JSONC.parse()` API that allows parsing
JSONC (JSON with Comments) files. It addresses the feature request from
issue #16257 by providing a native API for parsing JSON with comments
and trailing commas.
The implementation follows the same pattern as `Bun.YAML` and
`Bun.TOML`, leveraging the existing `TSConfigParser` which already
handles JSONC parsing internally.
## Features
- **Parse JSON with comments**: Supports both `//` single-line and `/*
*/` block comments
- **Handle trailing commas**: Works with trailing commas in objects and
arrays
- **Full JavaScript object conversion**: Returns native JavaScript
objects/arrays
- **Error handling**: Proper error throwing for invalid JSON
- **TypeScript compatibility**: Works with TypeScript config files and
other JSONC formats
## Usage Example
```javascript
const result = Bun.JSONC.parse(`{
// This is a comment
"name": "my-app",
"version": "1.0.0", // trailing comma is allowed
"dependencies": {
"react": "^18.0.0",
},
}`);
// Returns native JavaScript object
```
## Implementation Details
- Created `JSONCObject.zig` following the same pattern as
`YAMLObject.zig` and `TOMLObject.zig`
- Uses the existing `TSConfigParser` from `json.zig` which already
handles comments and trailing commas
- Added proper C++ bindings and exports following Bun's established
patterns
- Comprehensive test suite covering various JSONC features
## Test Plan
- [x] Basic JSON parsing works
- [x] Single-line comments (`//`) are handled correctly
- [x] Block comments (`/* */`) are handled correctly
- [x] Trailing commas in objects and arrays work
- [x] Complex nested structures parse correctly
- [x] Error handling for invalid JSON
- [x] Empty objects and arrays work
- [x] Boolean and null values work correctly
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: Jarred-Sumner <709451+Jarred-Sumner@users.noreply.github.com>
### What does this PR do?
Fix bytecode CJS pragma detection when source file contains a shebang.
When bundling with `--bytecode` and the source file has a shebang, the
output silently fails to execute (exits 0, no output).
Reproduction:
[github.com/kjanat/bun-bytecode-banner-bug](https://github.com/kjanat/bun-bytecode-banner-bug)
```js
// Bundled output:
#!/usr/bin/env bun // shebang preserved
// @bun @bytecode @bun-cjs // pragma on line 2
(function(exports, require, module, __filename, __dirname) { ... })
```
The pragma parser in `hasBunPragma()` correctly skips the shebang line,
but uses `self.lexer.end` instead of `contents.len` when scanning for
`@bun-cjs`/`@bytecode` tokens. This causes the pragma to not be
recognized.
**Fix:**
```zig
// Before
while (cursor < self.lexer.end) : (cursor += 1) {
// After
while (cursor < end) : (cursor += 1) {
```
Where `end` is already defined as `contents.len` at the top of the
function.
### How did you verify your code works?
- Added bundler test `banner/SourceHashbangWithBytecodeAndCJSTargetBun`
in `test/bundler/bundler_banner.test.ts`
- Added regression tests in
`test/regression/issue/bun-bytecode-shebang.test.ts` that verify:
- CJS wrapper executes when source has shebang
- CJS wrapper executes when source has shebang + bytecode pragma
- End-to-end: bundled bytecode output with source shebang runs correctly
- Ran the tests in the
[kjanat/bun-bytecode-banner-bug](https://github.com/kjanat/bun-bytecode-banner-bug)
repo to verify the issue is fixed
---------
Signed-off-by: Kaj Kowalski <info@kajkowalski.nl>
Co-authored-by: Dylan Conway <dylan.conway567@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
## Summary
Fixes `ASSERTION FAILED: isUInt32AsAnyInt()` errors that occurred
intermittently, particularly in inspector-related tests.
## Problem
The code was directly manipulating JSPromise internal fields using
`asUInt32AsAnyInt()`:
```cpp
promise->internalField(JSC::JSPromise::Field::Flags).get().asUInt32AsAnyInt()
```
This caused assertion failures when the internal field state was not a
valid uint32.
## Solution
Use WebKit's official JSPromise helper methods instead:
| Before | After |
|--------|-------|
| Direct `internalField` manipulation for rejected promise |
`promise->rejectAsHandled(vm, globalObject, value)` |
| Direct `internalField` manipulation for resolved promise |
`promise->fulfill(vm, globalObject, value)` |
| Direct `internalField` manipulation for handled flag |
`promise->markAsHandled()` |
## Files Changed
- `src/bun.js/bindings/ZigGlobalObject.cpp`
- `src/bun.js/bindings/ModuleLoader.cpp`
- `src/bake/BakeGlobalObject.cpp`
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## Summary
- Disable HTTP keep-alive when a proxy returns a 407 (Proxy
Authentication Required) status code
- This prevents subsequent requests from trying to reuse a connection
that the proxy server has closed
- Refactored proxy tests to use `describe.concurrent` and async
`Bun.spawn` patterns
## Test plan
- [x] Added test `simultaneous proxy auth failures should not hang` that
verifies multiple concurrent requests with invalid proxy credentials
complete without hanging
- [x] Existing proxy tests pass
🤖 Generated with [Claude Code](https://claude.ai/code)
## Summary
- **SQLClient.cpp**: Fix bug where `RETURN_IF_EXCEPTION` after
`JSONParse` would never trigger on JSON parse failure since `JSONParse`
doesn't throw
- **BunString.cpp**: Simplify by using `JSONParseWithException` instead
of manually checking for empty result and throwing
## Details
`JSC::JSONParse` returns an empty `JSValue` on failure **without
throwing an exception**. This means that `RETURN_IF_EXCEPTION(scope,
{})` will never catch JSON parsing errors when used after `JSONParse`.
Before this fix in `SQLClient.cpp`:
```cpp
JSC::JSValue json = JSC::JSONParse(globalObject, str);
RETURN_IF_EXCEPTION(scope, {}); // This never triggers on parse failure!
return json; // Returns empty JSValue
```
This could cause issues when parsing invalid JSON data from SQL
databases (e.g., PostgreSQL's JSON/JSONB columns).
`JSONParseWithException` properly throws a `SyntaxError` exception that
`RETURN_IF_EXCEPTION` can catch.
## Test plan
- [x] Build succeeds with `bun bd`
- The changes follow the same pattern used in `ModuleLoader.cpp` and
`BunObject.cpp`
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
- Aligns Bun's temp directory resolution with Node.js's `os.tmpdir()`
behavior
- Checks `TMPDIR`, `TMP`, and `TEMP` environment variables in order
(matching Node.js)
- Uses `bun.once` for lazy initialization instead of mutable static
state
- Removes `setTempdir` function and simplifies the API to use
`RealFS.tmpdirPath()` directly
## Test plan
- [ ] Verify temp directory resolution matches Node.js behavior
- [ ] Test with various environment variable configurations
- [ ] Ensure existing tests pass with `bun bd test`
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude <noreply@anthropic.com>
## Summary
Fixes#20821
When `bun build --compile` was used with 8 or more embedded files, the
compiled binary would silently fail to execute any code (exit code 0, no
output).
**Root cause:** Chunks were sorted alphabetically by their `entry_bits`
key bytes. For entry point 0, the key starts with bit 0 set (byte
pattern `0x01`), but for entry point 8, the key has bit 8 set in the
byte (pattern `0x00, 0x01`). Alphabetically, `0x00 < 0x01`, so entry
point 8's chunk sorted before entry point 0.
This caused the wrong entry point to be identified as the main entry,
resulting in asset wrapper code being executed instead of the user's
code.
**Fix:** Custom sort that ensures `entry_point_id=0` (the main entry
point) always sorts first, with remaining chunks sorted alphabetically
for determinism.
## Test plan
- Added regression test `compile/ManyEmbeddedFiles` that embeds 8 files
and verifies the main entry point runs correctly
- Verified manually with reproduction case from issue
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
### What does this PR do?
It is standard practice to send HTTP2 window resize frames once half the
window is used up:
- [nghttp2](https://en.wikipedia.org/wiki/Nghttp2#HTTP/2_implementation)
- [Go](https://github.com/golang/net/blob/master/http2/flow.go#L31)
- [Rust
h2](https://github.com/hyperium/h2/blob/master/src/proto/streams/flow_control.rs#L17)
The current behaviour of Bun is to send a window update once the client
has sent 65535 bytes exactly. This leads to an interruption in
throughput while the window update is received.
This is not just a performance concern however, I think some clients
will not handle this well, as it means that if you stop sending data
even 1 byte before 65535, you have a deadlock. The reason I came across
this issue is that it appears that the Rust `hyper` crate always
reserves an additional 1 byte from the connection for each http2 stream
(https://github.com/hyperium/hyper/blob/master/src/proto/h2/mod.rs#L122).
This means that when you have two concurrent requests, the client treats
it like the window is exhausted when it actually has a byte remaining,
leading to a sequential dependency between the requests that can create
deadlocks if they depend on running concurrently. I accept this is not a
problem with bun, but its a happy accident that we can resolve such
off-by-one issues by increasing the window size once it is 50% utilized
### How did you verify your code works?
Using wireshark, bun debug logging, and client logging I can observe
that the window updates are now sent after 32767 bytes. This also
resolves the h2 crate client issue.
### What does this PR do?
- I was trying to understand how the SEA bundling worked in Bun and
noticed the size of the `Offsets` struct is hard-coded here to 32. It
should use the computed size to be future proof to changes in the
schema.
### How did you verify your code works?
- I didn't. Can add tests if this is not covered by existing tests.
ChatGPT agreed with me though. =)