fix(pageerror): report correct error message and stack (#1862)
The error stack matches the browser format.
This commit is contained in:
parent
4d8c057d9c
commit
649f37f885
|
|
@ -91,9 +91,21 @@ export function toConsoleMessageLocation(stackTrace: Protocol.Runtime.StackTrace
|
||||||
}
|
}
|
||||||
|
|
||||||
export function exceptionToError(exceptionDetails: Protocol.Runtime.ExceptionDetails): Error {
|
export function exceptionToError(exceptionDetails: Protocol.Runtime.ExceptionDetails): Error {
|
||||||
const message = getExceptionMessage(exceptionDetails);
|
const messageWithStack = getExceptionMessage(exceptionDetails);
|
||||||
|
const lines = messageWithStack.split('\n');
|
||||||
|
const firstStackTraceLine = lines.findIndex(line => line.startsWith(' at'));
|
||||||
|
let message = '';
|
||||||
|
let stack = '';
|
||||||
|
if (firstStackTraceLine === -1) {
|
||||||
|
message = messageWithStack;
|
||||||
|
} else {
|
||||||
|
message = lines.slice(0, firstStackTraceLine).join('\n');
|
||||||
|
stack = messageWithStack;
|
||||||
|
}
|
||||||
|
const match = message.match(/^[a-zA-Z0-0_]*Error: (.*)$/);
|
||||||
|
if (match)
|
||||||
|
message = match[1];
|
||||||
const err = new Error(message);
|
const err = new Error(message);
|
||||||
// Don't report clientside error with a node stack attached
|
err.stack = stack;
|
||||||
err.stack = 'Error: ' + err.message; // Stack is supposed to contain error message as the first line.
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,8 @@ export class FFPage implements PageDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
_onUncaughtError(params: Protocol.Page.uncaughtErrorPayload) {
|
_onUncaughtError(params: Protocol.Page.uncaughtErrorPayload) {
|
||||||
const error = new Error(params.message);
|
const message = params.message.startsWith('Error: ') ? params.message.substring(7) : params.message;
|
||||||
|
const error = new Error(message);
|
||||||
error.stack = params.stack;
|
error.stack = params.stack;
|
||||||
this._page.emit(Events.Page.PageError, error);
|
this._page.emit(Events.Page.PageError, error);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -149,16 +149,13 @@ class Helper {
|
||||||
Helper.removeEventListeners([listener]);
|
Helper.removeEventListeners([listener]);
|
||||||
clearTimeout(eventTimeout);
|
clearTimeout(eventTimeout);
|
||||||
}
|
}
|
||||||
const result = await Promise.race([promise, abortPromise]).then(r => {
|
return await Promise.race([promise, abortPromise]).then(r => {
|
||||||
cleanup();
|
cleanup();
|
||||||
return r;
|
return r;
|
||||||
}, e => {
|
}, e => {
|
||||||
cleanup();
|
cleanup();
|
||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
if (result instanceof Error)
|
|
||||||
throw result;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static async waitWithTimeout<T>(promise: Promise<T>, taskName: string, timeout: number): Promise<T> {
|
static async waitWithTimeout<T>(promise: Promise<T>, taskName: string, timeout: number): Promise<T> {
|
||||||
|
|
|
||||||
|
|
@ -454,8 +454,15 @@ export class WKPage implements PageDelegate {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (level === 'error' && source === 'javascript') {
|
if (level === 'error' && source === 'javascript') {
|
||||||
const error = new Error(text);
|
const message = text.startsWith('Error: ') ? text.substring(7) : text;
|
||||||
error.stack = 'Error: ' + error.message; // Nullify stack. Stack is supposed to contain error message as the first line.
|
const error = new Error(message);
|
||||||
|
if (event.message.stackTrace) {
|
||||||
|
error.stack = event.message.stackTrace.map(callFrame => {
|
||||||
|
return `${callFrame.functionName}@${callFrame.url}:${callFrame.lineNumber}:${callFrame.columnNumber}`;
|
||||||
|
}).join('\n');
|
||||||
|
} else {
|
||||||
|
error.stack = '';
|
||||||
|
}
|
||||||
this._page.emit(Events.Page.PageError, error);
|
this._page.emit(Events.Page.PageError, error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,8 @@ function b() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function c() {
|
function c() {
|
||||||
throw new Error('Fancy error!');
|
window.e = new Error('Fancy error!');
|
||||||
|
throw window.e;
|
||||||
}
|
}
|
||||||
|
//# sourceURL=myscript.js
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -493,13 +493,18 @@ describe('Page.exposeFunction', function() {
|
||||||
|
|
||||||
describe('Page.Events.PageError', function() {
|
describe('Page.Events.PageError', function() {
|
||||||
it('should fire', async({page, server}) => {
|
it('should fire', async({page, server}) => {
|
||||||
let error = null;
|
const [error] = await Promise.all([
|
||||||
page.once('pageerror', e => error = e);
|
page.waitForEvent('pageerror'),
|
||||||
await Promise.all([
|
|
||||||
page.goto(server.PREFIX + '/error.html'),
|
page.goto(server.PREFIX + '/error.html'),
|
||||||
new Promise(f => page.on('pageerror', f))
|
|
||||||
]);
|
]);
|
||||||
expect(error.message).toContain('Fancy');
|
expect(error.name).toBe('Error');
|
||||||
|
expect(error.message).toBe('Fancy error!');
|
||||||
|
let stack = await page.evaluate(() => window.e.stack);
|
||||||
|
// Note that WebKit does not use sourceURL for some reason and reports the stack of the 'throw' statement
|
||||||
|
// instead of the Error constructor call.
|
||||||
|
if (WEBKIT)
|
||||||
|
stack = stack.replace('14:25', '15:19');
|
||||||
|
expect(error.stack).toBe(stack);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue