browser(firefox): report unhandled rejections for Firefox (#15391)

References #14165
This commit is contained in:
Andrey Lushnikov 2022-07-05 15:46:28 -07:00 коммит произвёл GitHub
Родитель cc45ac91f5
Коммит 530867e8ab
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
4 изменённых файлов: 45 добавлений и 25 удалений

Просмотреть файл

@ -1,2 +1,2 @@
1333
Changed: lushnikov@chromium.org Tue Jul 5 18:02:39 MSK 2022
1334
Changed: lushnikov@chromium.org Wed Jul 6 00:25:34 MSK 2022

Просмотреть файл

@ -101,7 +101,6 @@ class PageAgent {
helper.addObserver(this._filePickerShown.bind(this), 'juggler-file-picker-shown'),
helper.addEventListener(this._messageManager, 'DOMContentLoaded', this._onDOMContentLoaded.bind(this)),
helper.addObserver(this._onDocumentOpenLoad.bind(this), 'juggler-document-open-loaded'),
helper.addEventListener(this._messageManager, 'error', this._onError.bind(this)),
helper.on(this._frameTree, 'load', this._onLoad.bind(this)),
helper.on(this._frameTree, 'frameattached', this._onFrameAttached.bind(this)),
helper.on(this._frameTree, 'framedetached', this._onFrameDetached.bind(this)),
@ -129,6 +128,7 @@ class PageAgent {
});
}),
this._runtime.events.onConsoleMessage(msg => this._browserPage.emit('runtimeConsole', msg)),
this._runtime.events.onRuntimeError(this._onRuntimeError.bind(this)),
this._runtime.events.onExecutionContextCreated(this._onExecutionContextCreated.bind(this)),
this._runtime.events.onExecutionContextDestroyed(this._onExecutionContextDestroyed.bind(this)),
this._runtime.events.onBindingCalled(this._onBindingCalled.bind(this)),
@ -273,15 +273,11 @@ class PageAgent {
});
}
_onError(errorEvent) {
const docShell = errorEvent.target.ownerGlobal.docShell;
const frame = this._frameTree.frameForDocShell(docShell);
if (!frame)
return;
_onRuntimeError({ executionContext, message, stack }) {
this._browserPage.emit('pageUncaughtError', {
frameId: frame.id(),
message: errorEvent.message,
stack: errorEvent.error && typeof errorEvent.error.stack === 'string' ? errorEvent.error.stack : '',
frameId: executionContext.auxData().frameId,
message: message.toString(),
stack: stack.toString(),
});
}

Просмотреть файл

@ -71,6 +71,7 @@ class Runtime {
// Use plain callbacks instead.
this.events = {
onConsoleMessage: createEvent(),
onRuntimeError: createEvent(),
onErrorFromWorker: createEvent(),
onExecutionContextCreated: createEvent(),
onExecutionContextDestroyed: createEvent(),
@ -129,7 +130,7 @@ class Runtime {
observe: message => {
if (!(message instanceof Ci.nsIScriptError) || !message.outerWindowID ||
!message.category || disallowedMessageCategories.has(message.category) || message.hasException) {
!message.category || disallowedMessageCategories.has(message.category)) {
return;
}
const errorWindow = Services.wm.getOuterWindowWithId(message.outerWindowID);
@ -138,26 +139,35 @@ class Runtime {
return;
}
const executionContext = this._windowToExecutionContext.get(errorWindow);
if (!executionContext)
if (!executionContext) {
return;
}
const typeNames = {
[Ci.nsIConsoleMessage.debug]: 'debug',
[Ci.nsIConsoleMessage.info]: 'info',
[Ci.nsIConsoleMessage.warn]: 'warn',
[Ci.nsIConsoleMessage.error]: 'error',
};
emitEvent(this.events.onConsoleMessage, {
args: [{
value: message.message,
}],
type: typeNames[message.logLevel],
executionContextId: executionContext.id(),
location: {
lineNumber: message.lineNumber,
columnNumber: message.columnNumber,
url: message.sourceName,
},
});
if (!message.hasException) {
emitEvent(this.events.onConsoleMessage, {
args: [{
value: message.message,
}],
type: typeNames[message.logLevel],
executionContextId: executionContext.id(),
location: {
lineNumber: message.lineNumber,
columnNumber: message.columnNumber,
url: message.sourceName,
},
});
} else {
emitEvent(this.events.onRuntimeError, {
executionContext,
message: message.errorMessage,
stack: message.stack.toString(),
});
}
},
};
Services.console.registerListener(consoleServiceListener);

Просмотреть файл

@ -132,3 +132,17 @@ it('should handle window', async ({ page, browserName, isElectron }) => {
it('should remove a listener of a non-existing event handler', async ({ page }) => {
page.removeListener('pageerror', () => {});
});
it('should emit error from unhandled rejects', async ({ page, browserName }) => {
it.fixme(browserName === 'firefox', 'see https://github.com/microsoft/playwright/issues/14165');
it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/14165' });
const [error] = await Promise.all([
page.waitForEvent('pageerror'),
page.setContent(`
<script>
Promise.reject(new Error('sad :('));
</script>
`),
]);
expect(error.message).toBe('sad :(');
});