### 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?
We must use the right number of properties or we should set it to 0
### How did you verify your code works?
Read the code to check the amount of properties + CI
In the crash reporter, we currently use glibc's `backtrace()` function
on glibc Linux targets. However, this has resulted in poor stack traces
in many scenarios, particularly when a JSC signal handlers is involved,
in which case the stack trace tends to have only one frame—the signal
handler itself. Considering that JSC installs a signal handler for SEGV,
this is particularly bad.
Zig's `std.debug.captureStackTrace` generates considerably more complete
stack traces, but it has an issue where the top frame is missing when a
signal handler is involved. This is unfortunate, but it's still the
better option for now. Note that our stack traces on macOS also have
this missing frame issue.
In the future, we will investigate backporting the changes to stack
trace capturing that were recently made in Zig's `master` branch, since
that seems to have fixed the missing frame issue.
This PR still uses the stack trace provided by `backtrace()` if it
returns more frames than `captureStackTrace`. In particular, ARM may
need this behavior.
(For internal tracking: fixes ENG-21406)
### What does this PR do?
Fixes the crash handler failing to capture and display stack traces on
Linux ARM64 systems.
**Before:**
```
============================================================
panic(main thread): cast causes pointer to be null
```
No stack trace shown.
**After:**
```
============================================================
panic(main thread): cast causes pointer to be null
bun.js.api.FFIObject.Reader.u8
/workspace/bun/src/bun.js/api/FFIObject.zig:67:41
bun.js.jsc.host_fn.toJSHostCall__anon_2545765
/workspace/bun/src/bun.js/jsc/host_fn.zig:93:5
```
Full stack trace with source locations.
#### Root Cause
- Zig's `std.debug.captureStackTrace` uses `StackIterator.init()` which
falls back to frame pointer-based unwinding when no context is provided
- Frame pointer-based unwinding doesn't work reliably on ARM64, even
with `-fno-omit-frame-pointer` enabled
- This resulted in 0 frames being captured (`trace.index == 0`)
#### Changes
1. **Use glibc's backtrace() on Linux**: On Linux with glibc (not musl),
always use glibc's `backtrace()` function instead of Zig's
StackIterator. glibc's implementation properly uses DWARF unwinding
information from `.eh_frame` sections.
2. **Skip crash handler frames**: After capturing with `backtrace()`,
find the desired `begin_addr` in the trace (within 128 byte tolerance)
and filter out crash handler internal frames for cleaner output. If
`begin_addr` is not found, use the complete backtrace.
3. **Preserve existing behavior**:
- Non-debug builds: Use WTF printer (fast, no external deps)
- Debug builds: Fall through to llvm-symbolizer (detailed source info)
### How did you verify your code works?
Reproduced the crash:
```bash
bun-debug --print 'Bun.FFI.read.u8(0)'
```
Verified that:
- ✅ Stack traces now appear on Linux ARM64 with proper source locations
- ✅ Crash handler frames are properly filtered out
- ✅ llvm-symbolizer integration works for debug builds
- ✅ WTF printer is used for release builds
- ✅ When begin_addr is not found, complete backtrace is used
🤖 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
Increase the stack trace buffer size in the crash handler from 10 to 20
frames to ensure more useful frames are included in crash reports sent
to bun.report.
## Motivation
Currently, we capture up to 10 stack frames when generating crash
reports. However, many of these frames get filtered out when
`StackLine.fromAddress()` returns `null` for invalid/empty frames. This
results in only a small number of frames (sometimes as few as 5)
actually being sent to the server.
## Changes
- Increased `addr_buf` array size from `[10]usize` to `[20]usize` in
`src/crash_handler.zig:307`
## Impact
By capturing more frames initially, we ensure that after filtering we
still have a meaningful number of frames in the crash report. This will
help with debugging crashes by providing more context about the call
stack.
The encoding function `encodeTraceString()` has no hardcoded limits and
will encode all available frames, so this change directly translates to
more frames being sent to bun.report.
🤖 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>
Two issues:
* We were always spawning `llvm-symbolizer-19`, even if
`llvm-symbolizer` succeeded.
* We were calling both `.spawn()` and `.spawnAndWait()` on the child
process, instead of a single `.spawnAndWait()`.
(For internal tracking: fixes STAB-1125)
### What does this PR do?
- Instead of storing `len` in `BoundedArray` as a `usize`, store it as
either a `u8` or ` u16` depending on the `buffer_capacity`
- Copy-paste `BoundedArray` from the standard library into Bun's
codebase as it was removed in
https://github.com/ziglang/zig/pull/24699/files#diff-cbd8cbbc17583cb9ea5cc0f711ce0ad447b446e62ea5ddbe29274696dce89e4f
and we will probably continue using it
### How did you verify your code works?
Ran `bun run zig:check`
---------
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: taylor.fish <contact@taylor.fish>
### What does this PR do?
- for these kinds of aborts which we test in CI, introduce a feature
flag to suppress core dumps and crash reporting only from that abort,
and set the flag when running the test:
- libuv stub functions
- Node-API abort (used in particular when calling illegal functions
during finalizers)
- passing `process.kill` its own PID
- core dumps are suppressed with `setrlimit`, and crash reporting with
the new `suppress_reporting` field. these suppressions are only engaged
right before crashing, so we won't ignore new kinds of crashes that come
up in these tests.
- for the test bindings used to test the crash handler in
`run-crash-handler.test.ts`, disables core dumps but does not disable
crash reporting (because crashes get reported to a server that the test
is running to make sure they are reported)
- fixes a panic when printing source code around an error containing
`\n\r`
- updates the code where we clone vendor tests to checkout the right tag
- adds `vendor/elysia/test/path/plugin.test.ts` to
no-validate-exceptions
- this failure was exposed by starting to test the version of elysia we
have been intending to test. the crash trace suggests it may be fixed by
#21307.
- makes dumping core or uploading a crash report count as a failing test
- this ensures we don't realize a crash has occurred if it happened in a
subprocess and the main test doesn't adequately check the exit code. to
spawn a subprocess you expect to fail, prefer `expect(code).toBe(1)`
over `expect(code).not.toBe(0)`. if you really expect multiple possible
erroneous exit codes, you might try `expect(signal).toBeNull()` to still
disallow crashes.
### How did you verify your code works?
Running affected tests on a Linux machine with core dumps set up and
checking no new ones appear.
https://buildkite.com/bun/bun/builds/21465 has no core dumps.