## Summary
- Fixes silent 401 Unauthorized errors when using proxies with long
passwords (e.g., JWT tokens > 4096 chars)
- Bun was silently dropping proxy passwords exceeding 4095 characters,
falling through to code that only encoded the username
## Changes
- Added `PercentEncoding.decodeWithFallback` which uses a 4KB stack
buffer for the common case and falls back to heap allocation only for
larger inputs
- Updated proxy auth encoding in `AsyncHTTP.zig` to use the new fallback
method
## Test plan
- [x] Added test case that verifies passwords > 4096 chars are handled
correctly
- [x] Test fails with system bun (v1.3.3), passes with this fix
- [x] All 29 proxy tests pass
🤖 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>
### What does this PR do?
Fixes a bug where idle WebSocket connections would cause 100% CPU usage
on macOS and other BSD systems using kqueue.
**Root cause:** The kqueue event filter comparison was using bitwise AND
(`&`) instead of equality (`==`) when checking the filter type. Combined
with missing `EV_ONESHOT` flags on writable events, this caused the
event loop to continuously spin even when no actual I/O was pending.
**Changes:**
1. **Fixed filter comparison** in `epoll_kqueue.c`: Changed `filter &
EVFILT_READ` to `filter == EVFILT_READ` (same for `EVFILT_WRITE`). The
filter field is a value, not a bitmask.
2. **Added `EV_ONESHOT` flag** to writable events: kqueue writable
events now use one-shot mode to prevent continuous triggering.
3. **Re-arm writable events when needed**: After a one-shot writable
event fires, the code now properly updates the poll state and re-arms
the writable event if another write is still pending.
### How did you verify your code works?
Added a test that:
1. Creates a TLS WebSocket server and client
2. Sends messages then lets the connection sit idle
3. Measures CPU usage over 3 seconds
4. Fails if CPU usage exceeds 2% (expected is ~0.XX% when idle)
This PR significantly improves `Bun.stringWidth` to handle a wider
variety of Unicode characters and escape sequences correctly.
## Zero-width character handling
Added support for many previously unhandled zero-width characters:
- Soft hyphen (U+00AD)
- Word joiner and invisible operators (U+2060-U+2064)
- Lone surrogates (U+D800-U+DFFF)
- Arabic formatting characters (U+0600-U+0605, U+06DD, U+070F, U+08E2)
- Indic script combining marks (Devanagari through Malayalam)
- Thai and Lao combining marks
- Combining Diacritical Marks Extended and Supplement
- Tag characters (U+E0000-U+E007F)
## ANSI escape sequence handling
### CSI sequences
- Now properly handles ALL CSI final bytes (0x40-0x7E), not just `m`
- This means cursor movement (A/B/C/D), erase (J/K), scroll (S/T), and
other CSI commands are now correctly excluded from width calculation
### OSC sequences
- Added support for OSC sequences (ESC ] ... BEL/ST)
- OSC 8 hyperlinks are now properly handled
- Supports both BEL (0x07) and ST (ESC \) terminators
### ESC ESC fix
- Fixed state machine bug where `ESC ESC` would incorrectly reset state
- Now correctly handles consecutive ESC characters
## Emoji handling
Added proper grapheme-aware emoji width calculation:
- Flag emoji (regional indicator pairs) → width 2
- Skin tone modifiers → width 2
- ZWJ sequences (family, professions, etc.) → width 2
- Keycap sequences → width 2
- Variation selectors (VS15 for text, VS16 for emoji presentation)
- Uses ICU's `UCHAR_EMOJI` property for accurate emoji detection
## Test coverage
Added comprehensive test suite with **94 tests** covering:
- All zero-width character categories
- All CSI final bytes
- OSC sequences with various terminators
- Emoji edge cases (flags, skin tones, ZWJ, keycaps, variation
selectors)
- East Asian width (CJK, fullwidth, halfwidth katakana)
- Indic and Thai script combining marks
- Fuzzer-like stress tests for robustness
## Breaking changes
This is a behavior change - `stringWidth` will return different values
for some inputs. However, the new values are more accurate
representations of terminal display width:
| Input | Old | New | Why |
|-------|-----|-----|-----|
| Flag emoji 🇺🇸 | 1 | 2 | Flags display as 2 cells |
| Skin tone 👋🏽 | 4 | 2 | Emoji + modifier = 1 grapheme |
| ZWJ family 👨👩👧 | 8 | 2 | ZWJ sequence = 1 grapheme |
| Word joiner U+2060 | 1 | 0 | Invisible character |
| OSC 8 hyperlinks | counted URL | just visible text | URLs are
invisible |
| Cursor movement ESC[5A | counted | 0 | Control sequence |
🤖 Generated with [Claude Code](https://claude.ai/code)
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Claude Bot <claude-bot@bun.sh>
## Summary
- Fixes strings ending with colons (e.g., `"tin:"`) not being quoted in
YAML.stringify output
- This caused YAML.parse to fail with "Unexpected token" when parsing
the output back
## Test plan
- Added regression tests in `test/regression/issue/25439.test.ts`
- Verified round-trip works for various strings ending with colons
- Ran existing YAML tests to ensure no regressions
Fixes#25439🤖 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
- When a URL object is passed as the proxy option, or when a proxy
object lacks a "url" property, ignore it instead of throwing an error
- This fixes a regression introduced in 1.3.4 where libraries like taze
that pass URL objects as proxy values would fail
## Test plan
- Added test: "proxy as URL object should be ignored (no url property)"
- passes a URL object directly as proxy
- Updated test: "proxy object without url is ignored (regression
#25413)" - proxy object with headers but no url
- Updated test: "proxy object with null url is ignored (regression
#25413)" - proxy object where url is null
- All 29 proxy tests pass
Fixes#25413🤖 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>
### What does this PR do?
- Add `contentDisposition` option to S3 file uploads to control the
`Content-Disposition` HTTP header
- Support passing `contentDisposition` through all S3 upload paths
(simple uploads, multipart uploads, and streaming uploads)
- Add TypeScript types for the new option
Fixes https://github.com/oven-sh/bun/issues/25362
### How did you verify your code works?
Test
Fixes ENG-21288
TODO: Test with `@testing-library/react` `waitFor`
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
### What does this PR do?
Ensures `ptr` is either a number or heap big int before converting to a
number.
also fixes ENG-24039
### How did you verify your code works?
Added a test
## Summary
- Adds stricter validation for chunk boundaries in the HTTP chunked
transfer encoding parser
- Ensures conformance with RFC 9112 requirements for chunk formatting
- Adds additional test coverage for chunked encoding edge cases
## Test plan
- Added new tests in `test/js/bun/http/request-smuggling.test.ts`
- All existing HTTP tests pass
- `bun bd test test/js/bun/http/request-smuggling.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 <noreply@anthropic.com>
## Summary
- Extends `fetch()` proxy option to accept an object format: `proxy: {
url: string, headers?: Headers }`
- Allows sending custom headers to the proxy server (useful for proxy
authentication, custom routing headers, etc.)
- Headers are sent in CONNECT requests (for HTTPS targets) and direct
proxy requests (for HTTP targets)
- User-provided `Proxy-Authorization` header overrides auto-generated
credentials from URL
## Usage
```typescript
// Old format (still works)
fetch(url, { proxy: "http://proxy.example.com:8080" });
// New object format with headers
fetch(url, {
proxy: {
url: "http://proxy.example.com:8080",
headers: {
"Proxy-Authorization": "Bearer token",
"X-Custom-Proxy-Header": "value"
}
}
});
```
## Test plan
- [x] Test proxy object with url string works same as string proxy
- [x] Test proxy object with headers sends headers to proxy (HTTP
target)
- [x] Test proxy object with headers sends headers in CONNECT request
(HTTPS target)
- [x] Test proxy object with Headers instance
- [x] Test proxy object with empty headers
- [x] Test proxy object with undefined headers
- [x] Test user-provided Proxy-Authorization overrides URL credentials
- [x] All existing proxy tests pass (25 total)
🤖 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
- Fix assertion failure in `Bun.mmap` when `offset` or `size` options
are non-numeric values
- Add validation to reject negative `offset`/`size` with clear error
messages
Minimal reproduction: `Bun.mmap("", { offset: null });`
## Root Cause
`Bun.mmap` was calling `toInt64()` directly on the `offset` and `size`
options without validating they are numbers first. `toInt64()` has an
assertion that the value must be a number or BigInt, which fails when
non-numeric values like `null` or functions are passed.
## Test plan
- [x] Added tests for negative offset/size rejection
- [x] Added tests for non-number inputs (null, undefined)
- [x] `bun bd test test/js/bun/util/mmap.test.js` passes
Closes ENG-22413
🤖 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
- Fix `spyOn` crash when using indexed property keys (e.g., `spyOn(arr,
0)`)
## Test plan
- [x] Added tests for `spyOn` with numeric indexed properties
- [x] Added tests for `spyOn` with string indexed properties (e.g.,
`"0"`)
- [x] All existing `spyOn` tests pass
- [x] Full `mock-fn.test.js` test suite passes
Fixes ENG-21973
🤖 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
- Fix assertion failure when `Bun.indexOfLine` is called with a
non-number offset argument
- Changed from `.to(u32)` to `.coerce(i32, globalThis)` for proper
JavaScript type coercion
## Test plan
- [x] Added regression test in `test/js/bun/util/index-of-line.test.ts`
- [x] `bun bd test test/js/bun/util/index-of-line.test.ts` passes
Closes ENG-21997
🤖 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
- Fixed a typo in `makeComponent` that incorrectly identified
2-character patterns starting with `.` (like `.*`) as `..` (DotBack)
patterns
- The condition checked `pattern[component.start] == '.'` twice instead
of checking both characters at positions 0 and 1
- This caused patterns like `.*/*` to be parsed as `../` + `*`, making
the glob walker traverse into parent directories
Fixes#24936
## Test plan
- [x] Added tests in `test/js/bun/glob/scan.test.ts` that verify
patterns like `.*/*` and `.*/**/*.ts` don't escape the cwd boundary
- [x] Tests fail with system bun (bug reproduced) and pass with the fix
- [x] All existing glob tests pass (169 tests)
🤖 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>
### What does this PR do?
This was creating `Zig::FFIFunction` when we could instead use a plain
`JSC::JSFunction`
### How did you verify your code works?
Added a test
### What does this PR do?
Fixes ENG-21490
### How did you verify your code works?
Added a test that would previously fail due to timeout. It also confirms
the parsed result is correct.
---------
Co-authored-by: taylor.fish <contact@taylor.fish>
### What does this PR do?
Ensures strings that would parse as a number with leading zeroes aren't
emitted without quotes.
fixes#23691
### How did you verify your code works?
Added a test
pulled out of https://github.com/oven-sh/bun/pull/21809
- brings the ASAN behavior on linux closer in sync with macos
- fixes some tests to also pass in node
---------
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
### What does this PR do?
Adds `"configVersion"` to bun.lock(b). The version will be used to keep
default settings the same if they would be breaking across bun versions.
fixes ENG-21389
fixes ENG-21388
### How did you verify your code works?
TODO:
- [ ] new project
- [ ] existing project without configVersion
- [ ] existing project with configVersion
- [ ] same as above but with bun.lockb
- [ ] configVersion@0 defaults to hoisted linker
- [ ] new projects use isolated linker
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>
## Summary
Adds a `subscriptions` getter to `ServerWebSocket` that returns an array
of all topics the WebSocket is currently subscribed to.
## Implementation
- Added `getTopicsCount()` and `iterateTopics()` helpers to uWS
WebSocket
- Implemented C++ function `uws_ws_get_topics_as_js_array` that:
- Uses `JSC::MarkedArgumentBuffer` to protect values from GC
- Constructs JSArray directly in C++ for efficiency
- Uses template pattern for SSL/TCP variants
- Properly handles iterator locks with explicit scopes
- Exposed as `subscriptions` getter property on ServerWebSocket
- Returns empty array when WebSocket is closed (not null)
## API
```typescript
const server = Bun.serve({
websocket: {
open(ws) {
ws.subscribe("chat");
ws.subscribe("notifications");
console.log(ws.subscriptions); // ["chat", "notifications"]
ws.unsubscribe("chat");
console.log(ws.subscriptions); // ["notifications"]
}
}
});
```
## Test Coverage
Added 5 comprehensive test cases covering:
- Basic subscription/unsubscription flow
- All subscriptions removed
- Behavior after WebSocket close
- Duplicate subscriptions (should only appear once)
- Multiple subscribe/unsubscribe cycles
All tests pass with 24 assertions.
🤖 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>
## Summary
This PR improves snapshot error messages when running tests in CI
environments to make debugging easier by showing exactly what snapshot
was being created and what value was attempted.
## Changes
### 1. Inline Snapshot Errors
**Before:**
```
Updating inline snapshots is disabled in CI environments unless --update-snapshots is used.
```
**After:**
```
Inline snapshot creation is not allowed in CI environments unless --update-snapshots is used.
If this is not a CI environment, set the environment variable CI=false to force allow.
Received: this is new
```
- Changed message to say "creation" instead of "updating" (more
accurate)
- Shows the received value that was attempted using Jest's pretty
printer
### 2. Snapshot File Errors
**Before:**
```
Snapshot creation is not allowed in CI environments unless --update-snapshots is used
If this is not a CI environment, set the environment variable CI=false to force allow.
Received: this is new
```
**After:**
```
Snapshot creation is not allowed in CI environments unless --update-snapshots is used
If this is not a CI environment, set the environment variable CI=false to force allow.
Snapshot name: "new snapshot 1"
Received: this is new
```
- Now shows the snapshot name that was being looked for
- Shows the received value using Jest's pretty printer
## Implementation Details
- Added `last_error_snapshot_name` field to `Snapshots` struct to pass
snapshot name from `getOrPut()` to error handler
- Removed unreachable code path for inline snapshot updates (mismatches
error earlier with diff)
- Updated test expectations in `ci-restrictions.test.ts`
## Test Plan
```bash
# Test inline snapshot creation in CI
cd /tmp/snapshot-test
echo 'import { test, expect } from "bun:test";
test("new inline snapshot", () => {
expect("this is new").toMatchInlineSnapshot();
});' > test.js
GITHUB_ACTIONS=1 bun test test.js
# Test snapshot file creation in CI
echo 'import { test, expect } from "bun:test";
test("new snapshot", () => {
expect("this is new").toMatchSnapshot();
});' > test2.js
GITHUB_ACTIONS=1 bun test test2.js
```
Both should show improved error messages with the received values and
snapshot name.
---------
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: pfg <pfg@pfg.pw>
## Summary
Fixes#20689
Previously, `@layer` blocks were not being processed through the CSS
minifier, which meant that `color-scheme` properties inside `@layer`
blocks would not get the required `--buncss-light`/`--buncss-dark`
variable injections needed for browsers that don't support the
`light-dark()` function.
## Changes
- Implemented proper minification for `LayerBlockRule` in
`src/css/rules/rules.zig:218-221`
- Added recursive call to `minify()` on nested rules, matching the
behavior of other at-rules like `@media` and `@supports`
- Added comprehensive tests for `color-scheme` inside `@layer` blocks
## Test Plan
Added three new test cases in `test/js/bun/css/css.test.ts`:
1. Simple `@layer` with `color-scheme: dark`
2. Named layers (`@layer shm.colors`) with multiple rules
3. Anonymous `@layer` with `color-scheme: light dark` (generates media
query)
All tests pass:
```bash
bun bd test test/js/bun/css/css.test.ts -t "color-scheme"
```
## Before
```css
/* Input */
@layer shm.colors {
body.theme-dark {
color-scheme: dark;
}
}
/* Output (broken - no variables) */
@layer shm.colors {
body.theme-dark {
color-scheme: dark;
}
}
```
## After
```css
/* Input */
@layer shm.colors {
body.theme-dark {
color-scheme: dark;
}
}
/* Output (fixed - variables injected) */
@layer shm.colors {
body.theme-dark {
--buncss-light: ;
--buncss-dark: initial;
color-scheme: dark;
}
}
```
🤖 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>
## Summary
Implements `onTestFinished()` for `bun:test`, which runs after all
`afterEach` hooks have completed.
## Implementation
- Added `onTestFinished` export to the test module in `jest.zig`
- Modified `genericHook` in `bun_test.zig` to handle `onTestFinished` as
a special case that:
- Can only be called inside a test (not in describe blocks or preload)
- Appends hooks at the very end of the execution sequence
- Added comprehensive tests covering basic ordering, multiple callbacks,
async callbacks, and interaction with other hooks
## Execution Order
When called inside a test:
1. Test body executes
2. `afterAll` hooks (if added inside the test)
3. `afterEach` hooks
4. `onTestFinished` hooks ✨
## Test Plan
- ✅ All new tests pass with `bun bd test`
- ✅ Tests correctly fail with `USE_SYSTEM_BUN=1` (feature not in
released version)
- ✅ Verifies correct ordering with `afterEach`, `afterAll`, and multiple
`onTestFinished` calls
- ✅ Tests async `onTestFinished` callbacks
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
---------
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: pfg <pfg@pfg.pw>
### What does this PR do?
Adds missing null checking for `Bun.CookieMap#delete`.
### How did you verify your code works?
Tests
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
fixes: oven-sh/bun#23717
### What does this PR do?
- Align ProxyTunnel.onClose with
[HTTPClient.onClose](https://github.com/oven-sh/bun/blob/bun-v1.3.0/src/http.zig#L223-L241):
when a tunneled HTTPS response is in-progress and either
- parsing chunked trailers (trailer-line states), or
- transfer-encoding is identity with content_length == null while in
.body,
treat EOF as end-of-message and complete the request, rather than
ECONNRESET.
- Schedule proxy deref instead of deref inside callbacks to avoid
lifetime hazards.
### How did you verify your code works?
- `test/js/bun/http/proxy.test.ts`: raw TLS origin returns
close-delimited 200 OK; verified no ECONNRESET and body delivered.
- Test suite passes under bun bd test.
## Risk/compat
- Only affects CONNECT/TLS path. Direct HTTP/HTTPS unchanged. Behavior
mirrors existing
[HTTPClient.onClose](https://github.com/oven-sh/bun/blob/bun-v1.3.0/src/http.zig#L223-L241).
## Repro (minimal)
See issue; core condition is no Content-Length and no Transfer-Encoding
(close-delimited).
Co-authored-by: Ciro Spaciari <ciro.spaciari@gmail.com>
### What does this PR do?
Adds support for `publicHoistPattern` in `bunfig.toml` and
`public-hoist-pattern` from `.npmrc`. This setting allows you to select
transitive packages to hoist to the root node_modules making them
available for all workspace packages.
```toml
[install]
# can be a string
publicHoistPattern = "@types*"
# or an array
publicHoistPattern = [ "@types*", "*eslint*" ]
```
`publicHoistPattern` only affects the isolated linker.
---
Adds `hoistPattern`. `hoistPattern` is the same as `publicHoistPattern`,
but applies to the `node_modules/.bun/node_modules` directory instead of
the root node_modules. Also the default value of `hoistPattern` is `*`
(everything is hoisted to `node_modules/.bun/node_modules` by default).
---
Fixes a determinism issue constructing the
`node_modules/.bun/node_modules` directory.
---
closes#23481closes#6160closes#23548
### How did you verify your code works?
Added tests for
- [x] only include patterns
- [x] only exclude patterns
- [x] mix of include and exclude
- [x] errors for unexpected expression types
- [x] excluding direct dependency (should still include)
- [x] match all with `*`
- [x] string and array expression types
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
### What does this PR do?
`short` is signed in C++ by default and not unsigned. Switched to
`uint16_t` so it's unambiguous.
### How did you verify your code works?
There is a test
---------
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
### What does this PR do?
Fixes#23489
The YAML parser was incorrectly treating `...` inside double-quoted
strings as document end markers, causing parse errors for strings
containing ellipsis, particularly affecting internationalized text.
### Example of the bug:
```yaml
balance: "👛 لا تمتلك محفظة... !"
```
This would fail with: `error: Unexpected document end`
### Root cause:
The bug was introduced in commit fcbd57ac48 which attempted to optimize
document marker detection by using `self.line_indent == .none` instead
of tracking newlines with a local flag. However, this check was
incomplete - it didn't track whether we had just processed a newline
character.
### The fix:
Restored the `nl` (newline) flag pattern from the single-quoted scanner
and combined it with the `line_indent` check. Document markers `...` and
`---` are now only recognized when **all** of these conditions are met:
1. We're after a newline (`nl == true`)
2. We're at column 0 (`self.line_indent == .none`)
3. Followed by whitespace or EOF
This allows `...` to appear freely in double-quoted strings while still
correctly recognizing actual document end markers at the start of lines.
### How did you verify your code works?
1. Reproduced the original issue from #23489
2. Applied the fix and verified all test cases pass:
- Original Arabic text with emoji: `"👛 لا تمتلك محفظة... !"`
- Various `...` positions: start, middle, end
- Both single and double quotes
- Multiline strings with indented `...` (issue #22392)
3. Created regression test in `test/regression/issue/23489.test.ts`
4. Verified existing YAML tests still pass (514 pass, up from 513)
cc @dylan-conway for review
---------
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 `--only-failures` flag to `bun test` that only displays test
failures, similar to `--dots` but without printing dots for each test.
## Motivation
When running large test suites or in CI environments, users often only
care about test failures. The existing `--dots` reporter reduces
verbosity by showing dots, but still requires visual scanning to find
failures. The `--only-failures` flag provides a cleaner output by
completely suppressing passing tests.
## Changes
- Added `--only-failures` CLI flag in `Arguments.zig`
- Added `only_failures` boolean to the test reporters struct in
`cli.zig`
- Updated test output logic in `test_command.zig` to skip non-failures
when flag is set
- Updated `jest.zig` and `bun_test.zig` to handle the new flag
- Added comprehensive tests in `only-failures.test.ts`
## Usage
```bash
bun test --only-failures
```
Example output (only shows failures):
```
test/example.test.ts:
(fail) failing test
error: expect(received).toBe(expected)
Expected: 3
Received: 2
5 pass
1 skip
2 fail
Ran 8 tests across 1 file.
```
## Test Plan
- Verified `--only-failures` flag only shows failing tests
- Verified normal test output still works without the flag
- Verified `--dots` reporter still works correctly
- Added regression tests with snapshot comparisons
🤖 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: pfg <pfg@pfg.pw>
## Summary
Fixes two critical bugs in Bun Shell:
1. **Memory leaks & incorrect GC reporting**: Shell objects weren't
reporting their memory usage to JavaScriptCore's garbage collector,
causing memory to accumulate unchecked. Also fixes a leak where
`ShellArgs` wasn't being freed in `Interpreter.finalize()`.
2. **Blocking I/O on macOS**: Fixes a bug where writing large amounts of
data (>1MB) to pipes would block the main thread on macOS. The issue:
`sendto()` with `MSG_NOWAIT` flag blocks on macOS despite the flag, so
we now avoid the socket fast path unless the socket is already
non-blocking.
## Changes
- Adds `memoryCost()` and `estimatedSize()` implementations across shell
AST nodes, interpreter, and I/O structures
- Reports estimated memory size to JavaScriptCore GC via
`vm.heap.reportExtraMemoryAllocated()`
- Fixes missing `this.args.deinit()` call in interpreter finalization
- Fixes `BabyList.memoryCost()` to return bytes, not element count
- Conditionally uses socket fast path in IOWriter based on platform and
socket state
## Test plan
- [x] New test: `shell-leak-args.test.ts` - validates memory doesn't
leak during parsing/execution
- [x] New test: `shell-blocking-pipe.test.ts` - validates large pipe
writes don't block the main thread
- [x] Existing shell tests pass
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
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 a panic that occurred when formatting deeply nested objects with
many properties in test output.
## Problem
The `writeIndent()` function in `pretty_format.zig:648` performed
`written * 2` which triggered integer overflow checking in debug builds
when formatting complex nested structures.
**Original crash:**
```
panic: integer overflow
writeIndent at bun.js/test/pretty_format.zig:648
```
**Platform:** Windows x86_64_baseline, Bun v1.3.0
## Solution
Changed from:
```zig
try writer.writeAll(buf[0 .. written * 2]);
```
To:
```zig
const byte_count = @min(buf.len, written *% 2);
try writer.writeAll(buf[0..byte_count]);
```
- Used wrapping multiplication (`*%`) to prevent overflow panic
- Added bounds checking with `@min(buf.len, ...)` for safety
- Maintains correct behavior while preventing crashes
## Test
Added regression test at
`test/js/bun/test/pretty-format-overflow.test.ts` that:
- Creates deeply nested objects (500 levels with 50 properties each)
- Verifies no panic/overflow/crash occurs when formatting
- Uses exact configuration that triggered the original crash
## Verification
- ✅ Test passes with the fix
- ✅ Test would crash without the fix (in debug builds)
- ✅ No changes to behavior, only safety improvement
Co-authored-by: Claude Bot <claude-bot@bun.sh>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Jarred Sumner <jarred@jarredsumner.com>