mirror of
https://github.com/oven-sh/bun
synced 2026-02-10 02:48:50 +00:00
## Summary - Fixes V8StackTraceIterator terminating early when encountering stack frames without parentheses (e.g., "at unknown") - Ensures complete stack traces are shown by `Bun.inspect()` even after `error.stack` property is accessed - Addresses the root cause that PR #23022 was working around ## Problem When the V8StackTraceIterator encountered a stack frame line without parentheses (like `at unknown`), it would: 1. Set `offset = stack.length()` 2. Return `false`, terminating the entire iteration 3. Only parse frames before the "unknown" frame This caused `Bun.inspect()` to show incomplete stack traces after the `error.stack` property was accessed, as documented in issue discussions around PR #23022. ## Solution Changed the parser to continue iterating through subsequent frames instead of terminating. Frames without parentheses are now treated as having a source URL but no function name or location info. ## Test plan - [x] Added regression test `test/regression/issue/23022-stack-trace-iterator.test.ts` - [x] Verified existing stack trace tests still pass - [x] Manually tested with Node.js stream errors that trigger this code path ### Before fix: ``` error: Socket is closed code: "ERR_SOCKET_CLOSED" at node:net:1322:32 ``` ### After fix: ``` error: Socket is closed code: "ERR_SOCKET_CLOSED" at unknown:1:1 at _write (node:net:1322:32) at writeOrBuffer (internal:streams/writable:381:18) at internal:streams/writable:334:16 at testStackTrace (/workspace/bun/test.js:8:10) ... ``` 🤖 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>
34 lines
1.3 KiB
TypeScript
34 lines
1.3 KiB
TypeScript
import { expect, test } from "bun:test";
|
|
import * as net from "node:net";
|
|
|
|
test("V8StackTraceIterator handles frames without parentheses (issue #23022)", async () => {
|
|
// This test verifies that the V8StackTraceIterator correctly parses stack traces
|
|
// that contain frames without parentheses, such as "at unknown"
|
|
|
|
const socket = new net.Socket();
|
|
const { promise, resolve } = Promise.withResolvers<Error>();
|
|
|
|
socket.on("error", resolve);
|
|
socket.write("hello"); // This will trigger an error since socket is not connected
|
|
|
|
const err = await promise;
|
|
|
|
// Get the formatted error string (which internally uses V8StackTraceIterator after stack access)
|
|
const inspected = Bun.inspect(err);
|
|
|
|
// Count the number of "at" frames in the formatted output
|
|
const frameCount = (inspected.match(/\n\s+at\s+/g) || []).length;
|
|
|
|
// Should have multiple stack frames, not just one
|
|
// Before the fix, only 1 frame would be shown after accessing error.stack
|
|
expect(frameCount).toBeGreaterThan(3);
|
|
|
|
// Verify the stack property itself is intact
|
|
const stackFrames = err.stack?.split("\n").filter(line => line.trim().startsWith("at"));
|
|
expect(stackFrames?.length).toBeGreaterThan(3);
|
|
|
|
// Ensure both "unknown" frames and regular frames are present
|
|
expect(inspected).toContain("at unknown");
|
|
expect(inspected).toContain("at _write");
|
|
});
|