## Summary
- Fix Request.text() failure with "TypeError: undefined is not a
function" after many requests on certain platforms
- Set `#js_ref` in `Request.toJS()` for server-created requests,
matching the existing pattern in `Response.toJS()`
## Root Cause
When Request objects are created by the server (via `Request.init()`),
the `#js_ref` field was never initialized. This caused
`checkBodyStreamRef()` to fail silently when called in `toJS()` because
`#js_ref.tryGet()` returned null.
The bug manifested on macOS after ~4,500 requests when GC conditions
were triggered, causing the weak reference lookup to fail and resulting
in "TypeError: undefined is not a function" when calling `req.text()`.
## Fix
The fix mirrors the existing pattern in `Response.toJS()`:
1. Create the JS value first via `js.toJSUnchecked()`
2. Set `#js_ref` with the JS wrapper reference
3. Then call `checkBodyStreamRef()` which can now properly access the JS
value
## Test plan
- [x] Added regression test that exercises Request.text() with 6000
requests and periodic GC
- [x] Existing request tests pass
- [x] HTTP server tests pass
Fixes#26387🤖 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 `bun pm pack` not respecting changes to `package.json` made by
prepack/prepare scripts
- Tracks whether lifecycle scripts (prepublishOnly, prepack, prepare)
ran
- If scripts ran, invalidates the cached package.json and re-reads from
disk before creating the tarball
Closes#24314
## Test plan
- Added regression test `test/regression/issue/24314.test.ts` that
verifies package.json modifications from prepack/prepare scripts are
included in the tarball
- All existing pack tests pass (69 tests)
🤖 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 `controller.desiredSize` throwing `TypeError: null is not an
object` when the stream's internal `controlledReadableStream` has been
set to `null` during cleanup
- Added null check in `readableStreamDefaultControllerGetDesiredSize` to
return `null` when the stream reference is null, matching WHATWG Streams
spec behavior for detached/errored streams
## Root Cause
When piping streams (e.g., `fetch` with `ReadableStream` body), cleanup
code in `assignStreamIntoResumableSink` and `readStreamIntoSink` sets
`controlledReadableStream` to `null` for GC purposes. If the user's
`pull()` function is still running asynchronously when this happens,
accessing `controller.desiredSize` throws instead of returning `null`.
## Test plan
- [x] Added regression test `test/regression/issue/26377.test.ts`
- [x] Verified tests pass with `bun bd test
test/regression/issue/26377.test.ts`
Fixes#26377🤖 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 `BUN_OPTIONS` environment variable not being applied as runtime
options for standalone executables (`bun build --compile`). Previously,
args from `BUN_OPTIONS` were incorrectly passed through to
`process.argv` instead of being parsed as Bun runtime options
(`process.execArgv`).
- Removed `BUN_CPU_PROFILE`, `BUN_CPU_PROFILE_DIR`, and
`BUN_CPU_PROFILE_NAME` env vars since `BUN_OPTIONS="--cpu-prof
--cpu-prof-dir=... --cpu-prof-name=..."` now works correctly with
standalone executables.
- Made `cpu_prof.name` and `cpu_prof.dir` non-optional with empty string
defaults.
fixes#21496
## Test plan
- [x] Added tests for `BUN_OPTIONS` with standalone executables (no
`compile-exec-argv`)
- [x] Added tests for `BUN_OPTIONS` combined with `--compile-exec-argv`
- [x] Added tests for `BUN_OPTIONS` with user passthrough args
- [x] Verified existing `compile-argv` tests still pass
- [x] Verified existing `bun-options` tests still pass
🤖 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: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Claude Bot <claude-bot@bun.sh>
## Summary
- Fixes `ws.once()` only working on the first call for each event type
- The bug was in the `#onOrOnce` method which tracked native listeners
via a bitset but didn't account for `once` listeners auto-removing after
firing
- Now only persistent `on()` listeners set the bitset; `once()`
listeners always add new native handlers unless a persistent listener
already exists
## Test plan
- [x] Added regression test `test/regression/issue/26358.test.ts`
- [x] Test verifies `once('message')` works multiple times
- [x] Test verifies `once('pong')` works multiple times
- [x] Test verifies `on()` still works correctly
- [x] Test verifies mixing `on()` and `once()` works correctly
- [x] Verified test fails with `USE_SYSTEM_BUN=1` (bug exists)
- [x] Verified test passes with `bun bd test` (fix works)
Fixes#26358🤖 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
This PR fixes multiple HTTP/2 protocol compliance issues that were
causing stream errors with various HTTP/2 clients (Fauna, gRPC/Connect,
etc.).
fixes https://github.com/oven-sh/bun/issues/12544
fixes https://github.com/oven-sh/bun/issues/25589
### Key Fixes
**Window Size and Settings Handling**
- Fix initial stream window size to use `DEFAULT_WINDOW_SIZE` until
`SETTINGS_ACK` is received
- Per RFC 7540 Section 6.5.1: The sender can only rely on settings being
applied AFTER receiving `SETTINGS_ACK`
- Properly adjust existing stream windows when `INITIAL_WINDOW_SIZE`
setting changes (RFC 7540 Section 6.9.2)
**Header List Size Enforcement**
- Implement `maxHeaderListSize` checking per RFC 7540 Section 6.5.2
- Track cumulative header list size using HPACK entry overhead (32 bytes
per RFC 7541 Section 4.1)
- Reject streams with `ENHANCE_YOUR_CALM` when header list exceeds
configured limit
**Custom Settings Support**
- Add validation for `customSettings` option (up to 10 custom settings,
matching Node.js `MAX_ADDITIONAL_SETTINGS`)
- Validate setting IDs are in range `[0, 0xFFFF]` per RFC 7540
- Validate setting values are in range `[0, 2^32-1]`
**Settings Validation Improvements**
- Use float comparison for settings validation to handle large values
correctly (was using `toInt32()` which truncates)
- Use proper `HTTP2_INVALID_SETTING_VALUE_RangeError` error codes for
Node.js compatibility
**BufferFallbackAllocator** - New allocator that tries a provided buffer
first, falls back to heap:
- Similar to `std.heap.stackFallback` but accepts external buffer slice
- Used with `shared_request_buffer` (16KB threadlocal) for common cases
- Falls back to `bun.default_allocator` for large headers
## Test Plan
- [x] `bun bd` compiles successfully
- [x] Node.js HTTP/2 tests pass: `bun bd
test/js/node/test/parallel/test-http2-connect.js`
- [x] New regression tests for frame size issues: `bun bd test
test/regression/issue/25589.test.ts`
- [x] HTTP/2 continuation tests: `bun bd test
test/js/node/http2/node-http2-continuation.test.ts`
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
### What does this PR do?
Fixes#24007
Possibly fixes https://github.com/oven-sh/bun/issues/18902,
https://github.com/oven-sh/bun/issues/7412
Some filesystems (bind mounts, FUSE, NFS) don't provide `d_type` in
directory entries, returning `DT_UNKNOWN`. This caused glob and
recursive readdir to skip entries entirely.
## Problem
On Linux filesystems that don't populate `d_type` in directory entries
(bind mounts, FUSE, NFS, some ext4 configurations), `readdir()` returns
`DT_UNKNOWN` instead of the actual file type. This caused:
- `Bun.Glob` to skip files/directories entirely
- `fs.readdirSync(..., {recursive: true})` to not recurse into
subdirectories
- `fs.readdirSync(..., {withFileTypes: true})` to report incorrect types
## Solution
Implemented a **lazy `lstatat()` fallback** when `d_type == DT_UNKNOWN`:
- **`sys.zig`**: Added `lstatat()` function - same as `fstatat()` but
with `AT_SYMLINK_NOFOLLOW` flag to correctly identify symlinks
- **`GlobWalker.zig`**: When encountering `.unknown` entries, first
check if filename matches pattern, then call `lstatat()` only if needed
- **`node_fs.zig`**: Handle `.unknown` in both async and sync recursive
readdir paths; propagate resolved kind to Dirent objects
- **`dir_iterator.zig`**: Return `.unknown` for `DT_UNKNOWN` entries,
letting callers handle lazy stat
**Why `lstatat` instead of `fstatat`?** We use `AT_SYMLINK_NOFOLLOW` to
preserve consistent behavior with normal filesystems - symlinks should
be reported as symlinks, not as their target type. This matches [Node.js
behavior](https://github.com/nodejs/node/blob/main/lib/internal/fs/utils.js#L251-L269)
which uses `lstat()` for the DT_UNKNOWN fallback, and follows the lazy
stat pattern established in PR #18172.
### How did you verify your code works?
**Testing:**
- Regression test: `test/regression/issue/24007.test.ts`
- FUSE filesystem test: `test/cli/run/glob-on-fuse.test.ts` (reuses
`fuse-fs.py` from PR #18172, includes symlink verification)
- All existing glob/readdir tests pass
- **Verified in Docker bind-mount environment:**
- Official Bun: `0 files`
- Patched Bun: `3 files`
**Performance:** No impact on normal filesystems - the `.unknown` branch
is only hit when `d_type == DT_UNKNOWN`. The lazy stat pattern avoids
unnecessary syscalls by checking pattern match first.
---------
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
### What does this PR do?
Updates WebKit to
87c6cde57d
### How did you verify your code works?
---------
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
## Summary
- When `bun install` encounters a stale lockfile with a `file:`
dependency path that differs from the package.json, it now shows which
dependency caused the issue instead of the misleading "Bun could not
find a package.json file to install from" error.
## Test plan
- Added regression test in `test/regression/issue/26337.test.ts`
- Verified test fails with system bun (`USE_SYSTEM_BUN=1 bun test
test/regression/issue/26337.test.ts`)
- Verified test passes with debug build (`bun bd test
test/regression/issue/26337.test.ts`)
Fixes#26337🤖 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
- When a string exceeds `WTF::String::MaxLength` (~4GB),
`bun.String.createUninitialized()` returns a `.Dead` tag
- The C++ layer now properly throws `ERR_STRING_TOO_LONG` when this
happens
- Updated `String.toJS()` in Zig to return `bun.JSError!jsc.JSValue`
instead of just `jsc.JSValue`
- Updated ~40 Zig caller files to handle the error with `try`
- C++ callers updated with `RETURN_IF_EXCEPTION` checks
## Test plan
- [x] `bun bd test test/js/node/buffer.test.js` - 449 tests pass
- [x] `bun bd
test/js/node/test/parallel/test-buffer-tostring-rangeerror.js` - passes
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Adds environment variable support for enabling CPU profiling without CLI
flags:
- `BUN_CPU_PROFILE=1` — enables the CPU profiler
- `BUN_CPU_PROFILE_DIR=<path>` — sets the output directory for the
profile
- `BUN_CPU_PROFILE_NAME=<name>` — sets the profile file name
These are used as fallbacks when the corresponding `--cpu-prof` CLI
options are not provided. This is useful for profiling in contexts where
modifying the command line isn't practical (e.g. scripts invoked by
other tools).
## Summary
Fixes bytecode alignment in standalone executables to prevent crashes
when loading bytecode cache on Windows.
The bytecode offset needs to be aligned such that when loaded at
runtime, the bytecode pointer is 128-byte aligned. Previously, alignment
was based on arbitrary memory addresses during compilation, which didn't
account for the 8-byte section header prepended at runtime. This caused
the bytecode to be misaligned, leading to segfaults in
`JSC::CachedJSValue::decode` on Windows.
## Root Cause
At runtime, embedded data starts 8 bytes after the PE/Mach-O section
virtual address (which is page-aligned, hence 128-byte aligned). For
bytecode at offset `O` to be aligned:
```
(section_va + 8 + O) % 128 == 0
=> (8 + O) % 128 == 0
=> O % 128 == 120
```
The previous code used `std.mem.alignInSlice()` which found aligned
addresses based on the compilation buffer's arbitrary address, not
accounting for the 8-byte header offset at load time.
## Changes
- **`src/StandaloneModuleGraph.zig`**: Calculate bytecode offset to
satisfy `offset % 128 == 120` instead of using `alignInSlice`
- **`test/regression/issue/26298.test.ts`**: Added regression tests for
bytecode cache in standalone executables
## Test plan
- [x] Added regression test `test/regression/issue/26298.test.ts` with 3
test cases
- [x] Existing `HelloWorldBytecode` test passes
- [x] Build succeeds
Fixes#26298🤖 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>
### What does this PR do?
Remove NFKDC normalization and stripVTControlCharacters since
Bun.stringWidth does this now
### How did you verify your code works?
ci
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
## Summary
- Fixes the `setTimeout.clock` property not being properly deleted after
`jest.useRealTimers()` is called
- Previously, the property was set to `false` instead of deleted,
causing `hasOwnProperty` checks to return `true`
- This broke React Testing Library and other libraries that check for
fake timers using `Object.prototype.hasOwnProperty.call(setTimeout,
'clock')`
## Changes
- Added `JSValue.deleteProperty()` binding in Zig to call JSC's
`deleteProperty()` method
- Updated `setFakeTimerMarker()` in `FakeTimers.zig` to delete the
`clock` property when disabling fake timers
- Updated existing test in `test/regression/issue/25869.test.ts` to
verify correct behavior
- Added new regression test in `test/regression/issue/26284.test.ts`
## Test plan
- [x] Verified new test fails with system bun (before fix)
- [x] Verified new test passes with debug build (after fix)
- [x] Verified existing fake timer tests still pass
- [x] Verified test for issue #25869 passes with fix
Fixes#26284🤖 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 panic "integer does not fit in destination type" when
reading/writing large files on Windows
- Add chunking for iovec arrays that exceed `c_uint` max entries
- Add chunking for individual buffers that exceed 4GB (`u32` max)
The libuv functions `uv_fs_read` and `uv_fs_write` have two size
limitations:
1. `nbufs` parameter is `c_uint` (32-bit), limiting the number of iovec
entries
2. `uv_buf_t.len` is `ULONG` (u32 on Windows), limiting individual
buffer sizes to 4GB
This change processes large operations in chunks, accumulating results
and updating file positions between chunks.
## Test plan
- [x] Verified `bun run zig:check-all` passes on all platforms
- [x] Verified `bun bd` builds successfully
- [x] Verified basic file read/write operations work correctly
🤖 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>
### What does this PR do?
Fixes#5344Fixes#6356
### How did you verify your code works?
Some test coverage
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude Bot <claude-bot@bun.sh>
## Summary
Fixes native module export corruption when compiling multiple NAPI
modules with `bun build --compile` on Linux.
- When loading multiple `.node` files in a compiled binary, the second
module would incorrectly get the first module's exports
- Root cause: memfd file descriptors were closed after dlopen, allowing
fd reuse. Since dlopen caches by path (`/proc/self/fd/N`), it returned
the wrong cached handle
- This bug occurs when loading native modules in quick succession, as
the fd number is likely to be reused immediately after being closed
- Fix: Disable the memfd optimization and always use temp files with
unique paths
## Test plan
- [x] Added regression test in `test/regression/issue/26045/`
- [x] Test fails with production bun (v1.3.6)
- [x] Test passes with the fix
Fixes https://github.com/oven-sh/bun/issues/26045🤖 Generated with [Claude Code](https://claude.com/claude-code)
## Summary
- Fix typo in `setVerifyMode` where `reject_unauthorized` was
incorrectly reading from `request_cert_js` instead of
`reject_unauthorized_js`
## Test plan
- Existing TLS renegotiation tests pass
- Code inspection shows the fix is correct (simple variable name typo)
🤖 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
- The 'l' key in `bun update --interactive` now correctly selects the
package when toggling between Target and Latest versions
- Previously, pressing 'l' would toggle `use_latest` but not mark the
package as selected, causing the underline indicator to disappear and
the package not being included when confirming
## Test plan
- [x] Added regression test `test/regression/issue/24131.test.ts` that
verifies 'l' selects the package
- [x] Test fails with system bun (before fix) and passes with debug
build (after fix)
- [x] `bun bd test test/regression/issue/24131.test.ts` passes
Fixes#24131🤖 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 an index out-of-bounds panic that occurs during bundler code
splitting on Windows.
- The `bytes()` function in `DynamicBitSetUnmanaged` was accessing
`masks[0..numMasks(bit_length) + 1]`, reading one element past the
allocated array
- When the bit set has exactly one mask (bit_length <= 64), this causes
a panic: "index out of bounds: index 1, len 1"
- The bug manifests when sorting chunk deduplication keys derived from
`AutoBitSet.bytes()`
The fix simply removes the erroneous `+ 1` from the slice bounds.
## Test plan
- [x] `bun bd test test/bundler/bundler_splitting.test.ts` - passes
- [x] `bun bd test test/bundler/esbuild/splitting.test.ts` - passes
- [x] `bun bd test test/bundler/bundler_regressions.test.ts` - passes
- [x] `bun bd test test/bundler/bundler_edgecase.test.ts` - passes
🤖 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 `Bun.Terminal` callbacks (data, exit, drain) not being invoked
when the terminal is created inside `AsyncLocalStorage.run()`
## Root Cause
The bug was a redundant `isCallable()` check when storing callbacks in
`initTerminal()`:
1. In `Options.parseFromJS()`, callbacks are validated with
`isCallable()`, then wrapped with `withAsyncContextIfNeeded()`
2. Inside `AsyncLocalStorage.run()`, `withAsyncContextIfNeeded()`
returns an `AsyncContextFrame` object that wraps the callback + async
context
3. An `AsyncContextFrame` is NOT callable - it's a wrapper object. So
the second `isCallable()` check fails
4. Because the check fails, the callback is never stored via
`js.gc.set()`
5. When `onReadChunk()` tries to get the callback, it returns `null` and
the callback is never invoked
## Fix
Removed the redundant `isCallable()` check in `initTerminal()`. The
check was already performed in `parseFromJS()` before wrapping. Other
similar patterns (socket Handlers, Timer) simply store the wrapped
callback without re-checking.
Fixes#26286
## Test plan
- [x] Added regression test in `test/regression/issue/26286.test.ts`
- [x] Verified test fails with system Bun (times out because callback
never invoked)
- [x] Verified test passes with debug build
🤖 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 TypeScript errors in the react-tailwind template's `build.ts`
when used with the template's strict `tsconfig.json`
## Test plan
- Added regression test `test/regression/issue/24364.test.ts` that
verifies TypeScript compilation passes
- Verified test fails with old template code and passes with fix
Closes#24364🤖 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
- Replaces empty placeholder executables with shell scripts that print
helpful error messages
- The scripts exit with code 1 instead of silently succeeding with code
0
- Helps users diagnose issues when installing with `--ignore-scripts` or
using pnpm
## Problem
When installing the `bun` npm package with `--ignore-scripts` or using
pnpm (which skips postinstall by default), the placeholder `bun.exe` and
`bunx.exe` files were empty, causing them to silently exit with code 0
and produce no output. This made it very difficult for users to
understand why bun wasn't working.
## Solution
The placeholder files are now shell scripts that:
1. Print a clear error message explaining the issue
2. Provide instructions on how to fix it (manually running postinstall
or reinstalling without `--ignore-scripts`)
3. Exit with code 1 to indicate failure
Example output when running the placeholder:
```
Error: Bun's postinstall script was not run.
This occurs when using --ignore-scripts during installation, or when using a
package manager like pnpm that does not run postinstall scripts by default.
To fix this, run the postinstall script manually:
cd node_modules/bun && node install.js
Or reinstall bun without the --ignore-scripts flag.
```
## Test plan
- [x] Added regression test that verifies the placeholder script
behavior
- [x] Test passes with `bun bd test test/regression/issue/24329.test.ts`
Fixes#24329🤖 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 `assert.partialDeepStrictEqual` to correctly handle Map subset
checking
- Previously, Map comparison used `Bun.deepEquals` which required exact
equality
- Now properly checks that all entries in the expected Map exist in the
actual Map with matching values
Fixes#24338
## Test plan
- Added comprehensive test suite in
`test/regression/issue/24338.test.ts` covering:
- Basic subset checking (key2 in Map with key1 and key2)
- Exact match cases
- Empty expected Map
- Multiple matching entries
- Nested objects as values
- Failure cases when expected has more keys
- Failure cases when key is missing in actual
- Failure cases when values differ
- Nested Map values
- Non-string keys
🤖 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
- Extracts credentials from WebSocket URL (`ws://user:pass@host`) and
sends them as Basic Authorization header
- User-provided `Authorization` header takes precedence over URL
credentials
- Credentials are properly URL-decoded before being Base64-encoded
Fixes#24388
## Test plan
- [x] Added regression test `test/regression/issue/24388.test.ts` with 5
test cases:
- Basic credentials in URL
- Empty password
- No credentials (no header sent)
- Custom Authorization header takes precedence
- Special characters (URL-encoded) in credentials
- [x] Tests pass with `bun bd test test/regression/issue/24388.test.ts`
- [x] Tests fail with `USE_SYSTEM_BUN=1 bun test` (confirming the bug
existed)
🤖 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 memory leak in socket reconnection path by freeing old resources
before reassignment
- Add regression test for socket connection/close operations
## Problem
When sockets are reused in `connectInner` (common with MongoDB driver
reconnection patterns), the old connection metadata was being
overwritten without being freed first. This caused memory leaks of:
- `connection` (hostname/path strings)
- `protos` (ALPN protocol strings)
- `server_name` (SNI hostname string)
- `socket_context` (SSL context)
## Solution
This fix ensures these resources are properly freed before reassignment
when a socket is reused for reconnection. This matches the cleanup
pattern already used in the socket's `deinit()` function.
## Test plan
- [x] Added regression test `test/regression/issue/24118.test.ts`
- [x] Verified build compiles successfully
- [x] Verified test passes with `bun bd test
test/regression/issue/24118.test.ts`
Fixes#24118🤖 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
- Fix `fs.Dirent.isFIFO()` incorrectly returning `true` for unknown file
types (e.g., on sshfs/NFS mounts)
- Remove the `EventPort` check from `isFIFO()` since `EventPort = 0 =
Unknown`
- Add regression test for the fix
Fixes#24129
## Root Cause
In `NodeDirent.cpp`, the `isFIFO()` method was checking:
```cpp
type == static_cast<int32_t>(DirEntType::NamedPipe) || type == static_cast<int32_t>(DirEntType::EventPort)
```
Since `EventPort = 0` and `Unknown = 0` (they share the same enum
value), any file with unknown type (returned by filesystems like sshfs,
NFS, etc. that don't populate `d_type`) would incorrectly trigger
`isFIFO() === true`.
## Test plan
- [x] Regression test: `bun bd test test/regression/issue/24129.test.ts`
- [x] Existing Dirent tests: `bun bd test test/js/node/fs/fs.test.ts -t
"Dirent"`
🤖 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 a double-free bug in the shell interpreter error handling path
## What Changed
When `interpreter.init()` succeeds but `globalThis.hasException()` is
true, the code was calling `shargs.deinit()` before
`interpreter.finalize()`. However, `interpreter.args` points to `shargs`
after `init()` succeeds, so calling `interpreter.finalize()` ->
`deinitFromFinalizer()` -> `this.args.deinit()` would then try to deinit
an already-freed `ShellArgs`, causing a double-free.
This is a related issue to #24368, which reported crashes during GC
finalization of ShellInterpreter objects. While the main fix for #24368
was added in v1.3.6 (commit 367eeb308e), this fixes an additional
double-free bug in the error handling path.
## Test plan
- [x] Added regression tests in `test/regression/issue/24368.test.ts`
- [x] Tests pass with `bun bd test test/regression/issue/24368.test.ts`
- [x] Basic shell functionality verified
Fixes#24368🤖 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 a panic in `bun add` when HTTP requests fail before receiving
response headers
- The panic "Assertion failure: Expected metadata to be set" now becomes
a graceful error message
## Root Cause
In `src/install/PackageManagerTask.zig`, the code assumed `metadata` is
always non-null and panicked when it wasn't. However, `metadata` can be
null when:
- HTTP request fails before receiving response headers
- Network connection is refused/lost
- Timeout occurs before response
- Firewall blocks/corrupts the response
## Fix
Replaced the panic with proper error handling, following the existing
pattern in `runTasks.zig`:
```zig
const metadata = manifest.network.response.metadata orelse {
// Handle the error gracefully instead of panicking
const err = manifest.network.response.fail orelse error.HTTPError;
// ... show user-friendly error message
};
```
## Test plan
- [x] Added regression test `test/regression/issue/26236.test.ts`
- [x] Test verifies Bun shows graceful error instead of panicking
- [x] `bun bd test test/regression/issue/26236.test.ts` passes
Fixes#26236🤖 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
- Make `bun:ffi`'s TinyCC compiler check standard C compiler environment
variables
- Add support for `C_INCLUDE_PATH` (include paths) and `LIBRARY_PATH`
(library paths)
- Fixes compilation on NixOS and other systems that don't use standard
FHS paths
## Test plan
- [x] Added regression test `test/regression/issue/26249.test.ts` that
verifies:
- Single path in `C_INCLUDE_PATH` works
- Multiple colon-separated paths in `C_INCLUDE_PATH` work
- [x] Verified test fails with system bun (without fix)
- [x] Verified test passes with debug build (with fix)
- [x] Verified existing `cc.test.ts` tests still pass
Closes#26249🤖 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
Optimize `Buffer.swap16()` and `Buffer.swap64()` by replacing
byte-by-byte swapping loops with `__builtin_bswap16/64` compiler
intrinsics.
## Problem
`Buffer.swap16` and `Buffer.swap64` were significantly slower than
Node.js due to inefficient byte-level operations:
- **swap16**: Swapped bytes one at a time in a loop
- **swap64**: Used a nested loop with 4 byte swaps per 8-byte element
## Solution
Replace the manual byte swapping with `__builtin_bswap16/64` intrinsics,
which compile to single CPU instructions (`BSWAP` on x86, `REV` on ARM).
Use `memcpy` for loading/storing values to handle potentially unaligned
buffers safely.
## Benchmark Results (64KB buffer, Apple M4 Max)
| Operation | Bun 1.3.6 | Node.js 24 | This PR | Improvement |
|-----------|-----------|------------|---------|-------------|
| swap16 | 1.00 µs | 0.57 µs | 0.56 µs | **1.79x faster** |
| swap32 | 0.55 µs | 0.77 µs | 0.54 µs | (no change, already fast) |
| swap64 | 2.02 µs | 0.58 µs | 0.56 µs | **3.6x faster** |
Bun now matches or exceeds Node.js performance for all swap operations.
## Notes
- `swap32` was not modified as the compiler already optimizes the 4-byte
swap pattern
- All existing tests pass
## Summary
- Remove unreachable dead code that checked for data URLs in
`fetchImpl()`
- Data URLs are already handled earlier in the function via the
`dispatch_request` block which processes `.data` scheme URLs
- This redundant check at lines 375-387 could never be reached
## Test plan
- [ ] Verify existing fetch tests pass with `bun bd test
test/js/web/fetch/`
- [ ] Confirm data URL fetching still works correctly (handled by
earlier code path)
## Changelog
<!-- CHANGELOG:START -->
<!-- No user-facing changes - internal code cleanup only -->
<!-- CHANGELOG:END -->
🤖 Generated with [Claude Code](https://claude.com/claude-code) (100%
12-shotted by claude-opus-4-5)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
## What does this PR do?
Updates the oven-sh/tinycc fork to the latest upstream TinyCC,
incorporating 30+ upstream commits while preserving all Bun-specific
patches.
### Upstream changes incorporated
- Build system improvements (c2str.exe handling, cross-compilation)
- macOS 15 compatibility fixes
- libtcc debugging support
- pic/pie support for i386
- arm64 alignment and symbol offset fixes
- RISC-V 64 improvements (pointer difference, assembly, Zicsr extension)
- Relocation updates
- Preprocessor improvements (integer literal overflow handling)
- x86-64 cvts*2si fix
- Various bug fixes
### Bun-specific patches preserved
- Fix crash on macOS x64 (libxcselect.dylib memory handling)
- Implement `-framework FrameworkName` on macOS (for framework header
parsing)
- Add missing #ifdef guards for TCC_IS_NATIVE
- Make `__attribute__(deprecated)` a no-op
- Fix `__has_include` with framework paths
- Support attributes after identifiers in enums
- Fix dlsym behavior on macOS (RTLD_SELF first, then RTLD_DEFAULT)
- Various tccmacho.c improvements
### Related PRs
- TinyCC fork CI is passing:
https://github.com/oven-sh/tinycc/actions/runs/21105489093
## How did you verify your code works?
- [x] TinyCC fork CI passes on all platforms (Linux
x86_64/arm64/armv7/riscv64, macOS x86_64/arm64, Windows i386/x86_64)
- [ ] Bun CI passes
🤖 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 assertion failure when using HTTP proxy with redirects and socket
closes during redirect processing
- Add `isClosedOrHasError()` checks before `releaseSocket` and
`closeSocket` in `doRedirect`
Fixes#26220
## Root Cause
In `doRedirect` (`src/http.zig:786-797`), the code called
`releaseSocket` or `closeSocket` without checking if the socket was
already closed. When `onClose` is triggered while `is_redirect_pending`
is true, it calls `doRedirect`, but the socket is already closed at that
point, causing the assertion in `HTTPContext.zig:168` to fail:
```zig
assert(!socket.isClosed()); // FAILS - socket IS closed
```
## Fix
Added `!socket.isClosedOrHasError()` checks before socket operations in
`doRedirect`, matching the pattern already used at line 1790 in the same
file.
## Test plan
- [x] All existing proxy redirect tests pass (`bun bd test
test/js/bun/http/proxy.test.ts`)
- [x] Build completes successfully (`bun bd`)
🤖 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 multipart uploads using form-data + node-fetch@2 +
fs.createReadStream() being truncated
- Convert old-style Node.js streams (that don't implement
`Symbol.asyncIterator`) to Web ReadableStreams before passing to native
fetch
## Test plan
- [x] New tests in `test/regression/issue/26225.test.ts` verify:
- Multipart uploads with form-data and createReadStream work correctly
- Async iterable bodies still work (regression test)
- Large file streams work correctly
- [x] Tests fail with `USE_SYSTEM_BUN=1` and pass with debug build
Fixes#26225🤖 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>