Skip to content

Commit 2ed7eed

Browse files
committed
fix(aws-cdk-lib): construct error stack trace hides namespaced package name
We take efforts to condense a construct library stack trace to make it more comprehensible. This fixes two issues: - Only the first part of a namespaced package name would be captured - The stack trace looks confusing if it's too short to contain user code. Old: ``` ...aws-cdk-lib, @aws-cdk... ``` New: ``` ...aws-cdk-lib, @aws-cdk/aws-lambda-python-alpha... (no user code in 10 frames, use --stack-trace-limit to capture more) ```
1 parent 09e3daf commit 2ed7eed

File tree

2 files changed

+83
-1
lines changed

2 files changed

+83
-1
lines changed

packages/aws-cdk-lib/core/lib/stack-trace.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,15 @@ export function parseErrorStack(stack: string): CallSite[] {
136136
* - If there is 'node:' in the file path, we assume it is NodeJS internals and we skip it.
137137
*/
138138
export function renderCallStackJustMyCode(stack: CallSite[], indent = true): string[] {
139-
const moduleRe = /(\/|\\)node_modules(\/|\\)([^/\\]+)/;
139+
// Look for `/node_modules/` followed by either
140+
// - An @ sign, and 2 path segments
141+
// - No @ sign, and 1 path segment
142+
const moduleRe = /(\/|\\)node_modules(\/|\\)(@[^/\\]+[/\\][^/\\]+|[^@][^/\\]*)/;
140143

141144
const lines = [];
142145
let skipped = new Array<{ functionName?: string; fileName: string }>();
143146

147+
let sawMyCode = false;
144148
let i = 0;
145149
while (i < stack.length) {
146150
const frame = stack[i++];
@@ -161,9 +165,15 @@ export function renderCallStackJustMyCode(stack: CallSite[], indent = true): str
161165
reportSkipped(true);
162166
const prefix = indent ? ' at ' : '';
163167
lines.push(`${prefix}${frame.functionName} (${frame.fileName}:${frame.sourceLocation})`);
168+
sawMyCode = true;
164169
}
165170
}
166171
reportSkipped(false);
172+
173+
if (!sawMyCode) {
174+
lines.push(`${indent ? ' ' : ''}(no user code in ${Error.stackTraceLimit} frames, use --stack-trace-limit to capture more)`);
175+
}
176+
167177
return lines;
168178

169179
function skip(what: typeof skipped[number]) {
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { renderCallStackJustMyCode } from '../lib';
2+
3+
describe('renderCallStackJustMyCode', () => {
4+
test('renders namespaced packages correctly', () => {
5+
const stack: Parameters<typeof renderCallStackJustMyCode>[0] = [
6+
{
7+
fileName: '/path/to/project/node_modules/aws-cdk-lib/core/lib/asset-staging.js',
8+
functionName: 'AssetStaging.bundle',
9+
sourceLocation: '2:512',
10+
},
11+
{
12+
fileName: '/path/to/project/node_modules/aws-cdk-lib/aws-lambda/lib/function.js',
13+
functionName: 'new Function2',
14+
sourceLocation: '1:16236',
15+
},
16+
{
17+
fileName: '/path/to/project/node_modules/aws-cdk-lib/core/lib/prop-injectable.js',
18+
functionName: 'new Function2',
19+
sourceLocation: '1:726',
20+
},
21+
{
22+
fileName:
23+
'/path/to/project/node_modules/@aws-cdk/aws-lambda-python-alpha/lib/function.ts',
24+
functionName: 'new PythonFunction',
25+
sourceLocation: '70:5',
26+
},
27+
{
28+
fileName:
29+
'/path/to/project/myfile.js',
30+
functionName: 'new PythonFunction',
31+
sourceLocation: '70:5',
32+
},
33+
];
34+
35+
expect(renderCallStackJustMyCode(stack, false)).toEqual([
36+
'...aws-cdk-lib, new PythonFunction in @aws-cdk/aws-lambda-python-alpha...',
37+
'new PythonFunction (/path/to/project/myfile.js:70:5)',
38+
]);
39+
});
40+
41+
test('adds a hint if there are not enough stack frames to see Just My Code', () => {
42+
const stack: Parameters<typeof renderCallStackJustMyCode>[0] = [
43+
{
44+
fileName: '/path/to/project/node_modules/aws-cdk-lib/core/lib/asset-staging.js',
45+
functionName: 'AssetStaging.bundle',
46+
sourceLocation: '2:512',
47+
},
48+
{
49+
fileName: '/path/to/project/node_modules/aws-cdk-lib/aws-lambda/lib/function.js',
50+
functionName: 'new Function2',
51+
sourceLocation: '1:16236',
52+
},
53+
{
54+
fileName: '/path/to/project/node_modules/aws-cdk-lib/core/lib/prop-injectable.js',
55+
functionName: 'new Function2',
56+
sourceLocation: '1:726',
57+
},
58+
{
59+
fileName:
60+
'/path/to/project/node_modules/@aws-cdk/aws-lambda-python-alpha/lib/function.ts',
61+
functionName: 'new PythonFunction',
62+
sourceLocation: '70:5',
63+
},
64+
];
65+
66+
expect(renderCallStackJustMyCode(stack, false)).toEqual([
67+
'...aws-cdk-lib, new PythonFunction in @aws-cdk/aws-lambda-python-alpha...',
68+
'new PythonFunction (/path/to/project/myfile.js:70:5)',
69+
expect.stringContaining('use --stack-trace-limit to capture more'),
70+
]);
71+
});
72+
});

0 commit comments

Comments
 (0)