Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
*.un~
/node_modules

.DS_Store
4 changes: 2 additions & 2 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ certain properties can be retrieved with it as noted in the API docs below.
When parsing an `err.stack` that has crossed the event loop boundary, a
`CallSite` object is created whose `getFileName()` returns the full dashed
separator line from the stack, including any leading whitespace such as
indentation. All other methods of the event loop boundary call site return
`null`.
indentation. The other getter-style methods of the event loop boundary call site
return `null`.

Historically this behavior was often observed together with
[long-stack-traces](https://github.com/tlrobinson/long-stack-traces), but that package is unmaintained. This module does not depend on it and still supports parsing dashed event-loop boundary markers when
Expand Down
32 changes: 31 additions & 1 deletion __tests__/get-test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { get } from "../index.js";
import { get, parse } from "../index.js";

describe("get", () => {
it("basic", () => {
Expand Down Expand Up @@ -48,4 +48,34 @@ describe("get", () => {
})();
})();
});

// Verification for https://github.com/felixge/node-stack-trace/issues/25
// V8 async stack traces (enabled by default since Node 12) ensure async/await
// callers appear in the captured stack.
it("async/await stack traces include caller frames", async () => {
// Verify issue #25: parse() handles async/await stack frames. We throw across
// an actual async suspension point (await Promise.resolve()) so the stack
// genuinely requires V8 async-stack-trace reconstruction.
async function innerAsync() {
await Promise.resolve(); // cross a real async boundary before throwing
throw new Error('async trace');
}
async function outerAsync() {
await innerAsync();
}
Comment thread
niemyjski marked this conversation as resolved.

let trace = [];
try {
await outerAsync();
} catch (err) {
trace = parse(err);
}

const hasInner = trace.some(t => t.getFunctionName() === 'innerAsync');
// V8 async frames are prefixed with 'async ' in the stack string, so the
// parsed function name is "async outerAsync" — match both forms.
const hasOuter = trace.some(t => (t.getFunctionName() || '').includes('outerAsync'));
assert.strictEqual(hasInner, true, 'should include innerAsync frame');
assert.strictEqual(hasOuter, true, 'should include outerAsync frame');
});
});
7 changes: 7 additions & 0 deletions __tests__/long-stack-trace-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,12 @@ describe("long stack trace", () => {

assert.notStrictEqual(boundary, undefined);
assert.match(boundary.getFileName(), /-----/);
assert.strictEqual(boundary.getFunctionName(), null);
assert.strictEqual(boundary.getMethodName(), null);
assert.strictEqual(boundary.getTypeName(), null);
assert.strictEqual(boundary.getLineNumber(), null);
assert.strictEqual(boundary.getColumnNumber(), null);
assert.strictEqual(boundary.getEvalOrigin(), null);
assert.strictEqual(boundary.isNative(), null);
});
});
Loading