豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

Commit 05b01ec

Browse files
authored
feat: include Error.cause chain for uncaught errors and logged Errors (#906)
1 parent 9b90564 commit 05b01ec

File tree

3 files changed

+140
-0
lines changed

3 files changed

+140
-0
lines changed

src/DevtoolsUtils.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,23 @@ export class SymbolizedError {
286286
let cause: SymbolizedError | undefined;
287287
if (opts.resolvedCauseForTesting) {
288288
cause = opts.resolvedCauseForTesting;
289+
} else if (opts.details.exception) {
290+
try {
291+
const causeRemoteObj = await SymbolizedError.#lookupCause(
292+
opts.devTools,
293+
opts.details.exception,
294+
opts.targetId,
295+
);
296+
if (causeRemoteObj) {
297+
cause = await SymbolizedError.fromError({
298+
devTools: opts.devTools,
299+
error: causeRemoteObj,
300+
targetId: opts.targetId,
301+
});
302+
}
303+
} catch {
304+
// Ignore
305+
}
289306
}
290307
return new SymbolizedError(message, stackTrace, cause);
291308
}
@@ -355,6 +372,30 @@ export class SymbolizedError {
355372
);
356373
}
357374

375+
static async #lookupCause(
376+
devTools: TargetUniverse | undefined,
377+
error: Protocol.Runtime.RemoteObject,
378+
targetId: string,
379+
): Promise<Protocol.Runtime.RemoteObject | null> {
380+
if (!devTools || (error.type !== 'object' && error.subtype !== 'error')) {
381+
return null;
382+
}
383+
384+
const targetManager = devTools.universe.context.get(DevTools.TargetManager);
385+
const target = targetId
386+
? targetManager.targetById(targetId) || devTools.target
387+
: devTools.target;
388+
389+
const properties = await target.runtimeAgent().invoke_getProperties({
390+
objectId: error.objectId as DevTools.Protocol.Runtime.RemoteObjectId,
391+
});
392+
if (properties.getError()) {
393+
return null;
394+
}
395+
396+
return properties.result.find(prop => prop.name === 'cause')?.value ?? null;
397+
}
398+
358399
static createForTesting(
359400
message: string,
360401
stackTrace?: DevTools.StackTrace.StackTrace.StackTrace,

tests/tools/console.test.js.snapshot

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,25 @@
1+
exports[`console > get_console_message > applies source maps to stack traces of Error object (with cause) console.log arguments 1`] = `
2+
# test response
3+
ID: 1
4+
Message: log> foo failed JSHandle@error
5+
### Arguments
6+
Arg #0: foo failed
7+
Arg #1: Error: bar failed
8+
at foo (main.js:10:11)
9+
at Iife (main.js:16:5)
10+
at <anonymous> (main.js:14:1)
11+
Caused by: Error: b00m!
12+
at bar (main.js:3:9)
13+
at foo (main.js:8:5)
14+
at Iife (main.js:16:5)
15+
at <anonymous> (main.js:14:1)
16+
Note: line and column numbers use 1-based indexing
17+
### Stack trace
18+
at Iife (main.js:18:13)
19+
at <anonymous> (main.js:14:1)
20+
Note: line and column numbers use 1-based indexing
21+
`;
22+
123
exports[`console > get_console_message > applies source maps to stack traces of Error object console.log arguments 1`] = `
224
# test response
325
ID: 1
@@ -42,6 +64,25 @@ at <anonymous> (main.js:10:1)
4264
Note: line and column numbers use 1-based indexing
4365
`;
4466

67+
exports[`console > get_console_message > applies source maps to stack traces of uncaught exceptions with cause 1`] = `
68+
# test response
69+
ID: 1
70+
Message: error> Uncaught Error: foo failed
71+
### Stack trace
72+
at Iife (main.js:18:11)
73+
at <anonymous> (main.js:14:1)
74+
Caused by: Error: bar failed
75+
at foo (main.js:10:11)
76+
at Iife (main.js:16:5)
77+
at <anonymous> (main.js:14:1)
78+
Caused by: Error: b00m!
79+
at bar (main.js:3:9)
80+
at foo (main.js:8:5)
81+
at Iife (main.js:16:5)
82+
at <anonymous> (main.js:14:1)
83+
Note: line and column numbers use 1-based indexing
84+
`;
85+
4586
exports[`console > get_console_message > issues type > gets issue details with node id parsing 1`] = `
4687
# test response
4788
ID: 1

tests/tools/console.test.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,5 +315,63 @@ describe('console', () => {
315315
t.assert.snapshot?.(rawText);
316316
});
317317
});
318+
319+
it('applies source maps to stack traces of uncaught exceptions with cause', async t => {
320+
server.addRoute('/main.min.js', (_req, res) => {
321+
res.setHeader('Content-Type', 'text/javascript');
322+
res.statusCode = 200;
323+
res.end(`function r(){throw new Error("b00m!")}function o(){try{r()}catch(r){throw new Error("bar failed",{cause:r})}}(function r(){try{o()}catch(r){throw new Error("foo failed",{cause:r})}})();
324+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJiYXIiLCJFcnJvciIsImZvbyIsImUiLCJjYXVzZSIsIklpZmUiXSwic291cmNlcyI6WyIuL21haW4uanMiXSwic291cmNlc0NvbnRlbnQiOlsiXG5mdW5jdGlvbiBiYXIoKSB7XG4gIHRocm93IG5ldyBFcnJvcignYjAwbSEnKTtcbn1cblxuZnVuY3Rpb24gZm9vKCkge1xuICB0cnkge1xuICAgIGJhcigpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdiYXIgZmFpbGVkJywgeyBjYXVzZTogZSB9KTtcbiAgfVxufVxuXG4oZnVuY3Rpb24gSWlmZSgpIHtcbiAgdHJ5IHtcbiAgICBmb28oKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignZm9vIGZhaWxlZCcsIHsgY2F1c2U6IGUgfSk7XG4gIH1cbn0pKCk7XG5cbiJdLCJtYXBwaW5ncyI6IkFBQ0EsU0FBU0EsSUFDUCxNQUFNLElBQUlDLE1BQU0sUUFDbEIsQ0FFQSxTQUFTQyxJQUNQLElBQ0VGLEdBQ0YsQ0FBRSxNQUFPRyxHQUNQLE1BQU0sSUFBSUYsTUFBTSxhQUFjLENBQUVHLE1BQU9ELEdBQ3pDLENBQ0YsRUFFQSxTQUFVRSxJQUNSLElBQ0VILEdBQ0YsQ0FBRSxNQUFPQyxHQUNQLE1BQU0sSUFBSUYsTUFBTSxhQUFjLENBQUVHLE1BQU9ELEdBQ3pDLENBQ0QsRUFORCIsImlnbm9yZUxpc3QiOltdfQ==
325+
`);
326+
});
327+
server.addHtmlRoute(
328+
'/index.html',
329+
`<script src="${server.getRoute('/main.min.js')}"></script>`,
330+
);
331+
332+
await withMcpContext(async (response, context) => {
333+
const page = await context.newPage();
334+
await page.goto(server.getRoute('/index.html'));
335+
336+
await getConsoleMessage.handler(
337+
{params: {msgid: 1}},
338+
response,
339+
context,
340+
);
341+
const formattedResponse = await response.handle('test', context);
342+
const rawText = getTextContent(formattedResponse.content[0]);
343+
344+
t.assert.snapshot?.(rawText);
345+
});
346+
});
347+
348+
it('applies source maps to stack traces of Error object (with cause) console.log arguments', async t => {
349+
server.addRoute('/main.min.js', (_req, res) => {
350+
res.setHeader('Content-Type', 'text/javascript');
351+
res.statusCode = 200;
352+
res.end(`function o(){throw new Error("b00m!")}function r(){try{o()}catch(o){throw new Error("bar failed",{cause:o})}}(function o(){try{r()}catch(o){console.log("foo failed",o)}})();
353+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJiYXIiLCJFcnJvciIsImZvbyIsImUiLCJjYXVzZSIsIklpZmUiLCJjb25zb2xlIiwibG9nIl0sInNvdXJjZXMiOlsiLi9tYWluLmpzIl0sInNvdXJjZXNDb250ZW50IjpbIlxuZnVuY3Rpb24gYmFyKCkge1xuICB0aHJvdyBuZXcgRXJyb3IoJ2IwMG0hJyk7XG59XG5cbmZ1bmN0aW9uIGZvbygpIHtcbiAgdHJ5IHtcbiAgICBiYXIoKTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRocm93IG5ldyBFcnJvcignYmFyIGZhaWxlZCcsIHsgY2F1c2U6IGUgfSk7XG4gIH1cbn1cblxuKGZ1bmN0aW9uIElpZmUoKSB7XG4gIHRyeSB7XG4gICAgZm9vKCk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBjb25zb2xlLmxvZygnZm9vIGZhaWxlZCcsIGUpO1xuICB9XG59KSgpO1xuXG4iXSwibWFwcGluZ3MiOiJBQUNBLFNBQVNBLElBQ1AsTUFBTSxJQUFJQyxNQUFNLFFBQ2xCLENBRUEsU0FBU0MsSUFDUCxJQUNFRixHQUNGLENBQUUsTUFBT0csR0FDUCxNQUFNLElBQUlGLE1BQU0sYUFBYyxDQUFFRyxNQUFPRCxHQUN6QyxDQUNGLEVBRUEsU0FBVUUsSUFDUixJQUNFSCxHQUNGLENBQUUsTUFBT0MsR0FDUEcsUUFBUUMsSUFBSSxhQUFjSixFQUM1QixDQUNELEVBTkQiLCJpZ25vcmVMaXN0IjpbXX0=
354+
`);
355+
});
356+
server.addHtmlRoute(
357+
'/index.html',
358+
`<script src="${server.getRoute('/main.min.js')}"></script>`,
359+
);
360+
361+
await withMcpContext(async (response, context) => {
362+
const page = await context.newPage();
363+
await page.goto(server.getRoute('/index.html'));
364+
365+
await getConsoleMessage.handler(
366+
{params: {msgid: 1}},
367+
response,
368+
context,
369+
);
370+
const formattedResponse = await response.handle('test', context);
371+
const rawText = getTextContent(formattedResponse.content[0]);
372+
373+
t.assert.snapshot?.(rawText);
374+
});
375+
});
318376
});
319377
});

0 commit comments

Comments
 (0)