Files
bun.sh/test/regression/issue/23022-stack-trace-iterator.test.ts
robobun 5a12175cb0 Fix V8StackTraceIterator to handle frames without parentheses (#23034)
## 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>
2025-09-27 00:55:54 -07:00

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");
});