Page.Events.Error should throw an proper error

This patch:
- renames Page.Events.Exception in Page.Events.Error
- dispatches an error which has a page stack as its message
This commit is contained in:
Andrey Lushnikov 2017-06-16 11:21:44 -07:00
parent 2066da9ec7
commit 632b90efae
3 changed files with 45 additions and 25 deletions

View File

@ -213,11 +213,12 @@ class Page extends EventEmitter {
return this._userAgent;
}
_handleException(exceptionDetails) {
var stack = [];
if (exceptionDetails.stackTrace)
stack = exceptionDetails.stackTrace.callFrames.map(cf => cf.url);
this.emit(Page.Events.Exception, exceptionDetails.exception.description, stack);
/**
* @param {!Object} exceptionDetails
*/
async _handleException(exceptionDetails) {
var message = await this._getExceptionMessage(exceptionDetails);
this.emit(Page.Events.Error, new Error(message));
}
_onConsoleAPI(event) {
@ -330,8 +331,8 @@ class Page extends EventEmitter {
expression: code
});
if (response.exceptionDetails) {
await throwException(this._client, response.exceptionDetails);
return;
var message = await this._getExceptionMessage(response.exceptionDetails);
throw new Error('Evaluation failed: ' + message);
}
var remoteObject = response.result;
@ -348,29 +349,38 @@ class Page extends EventEmitter {
objectId: remoteObject.objectId
});
if (response.exceptionDetails) {
await throwException(this._client, response.exceptionDetails);
return;
var message = await this._getExceptionMessage(response.exceptionDetails);
throw new Error('Evaluation failed with ' + message);
}
return response.result.value;
}
/**
* @param {!Object} exceptionDetails
* @return {!Promise}
*/
async function throwException(client, exceptionDetails) {
var exception = exceptionDetails.exception;
if (!exception) {
throw new Error('Evaluation failed with ' + exceptionDetails.text);
return;
}
var response = await client.send('Runtime.callFunctionOn', {
/**
* @param {!Object} exceptionDetails
* @return {string}
*/
async _getExceptionMessage(exceptionDetails) {
var message = '';
var exception = exceptionDetails.exception;
if (exception) {
var response = await this._client.send('Runtime.callFunctionOn', {
objectId: exception.objectId,
functionDeclaration: 'function() { return this.toString(); }',
functionDeclaration: 'function() { return this.message; }',
returnByValue: true,
});
throw new Error('Evaluation failed with ' + response.result.value);
message = response.result.value;
} else {
message = exceptionDetails.text;
}
if (exceptionDetails.stackTrace) {
for (var callframe of exceptionDetails.stackTrace.callFrames) {
var location = callframe.url + ':' + callframe.lineNumber + ':' + callframe.columnNumber;
var functionName = callframe.functionName || '<anonymous>';
message += `\n at ${functionName} (${location})`;
}
}
return message;
}
/**
@ -583,7 +593,7 @@ function convertPrintParameterToInches(parameter) {
Page.Events = {
ConsoleMessage: 'consolemessage',
Dialog: 'dialog',
Exception: 'exception',
Error: 'error',
ResourceLoadingFailed: 'resourceloadingfailed',
ResponseReceived: 'responsereceived',
};

View File

@ -64,7 +64,7 @@ class WebPage {
this._pageEvents.on(PageEvents.Confirm, message => this._onConfirm(message));
this._pageEvents.on(PageEvents.Alert, message => this._onAlert(message));
this._pageEvents.on(PageEvents.Dialog, dialog => this._onDialog(dialog));
this._pageEvents.on(PageEvents.Exception, (exception, stack) => (this._onError || noop).call(null, exception, stack));
this._pageEvents.on(PageEvents.Error, error => (this._onError || noop).call(null, error.message, error.stack));
}
/**

View File

@ -72,7 +72,7 @@ describe('Puppeteer', function() {
error = e;
}
expect(error).toBeTruthy();
expect(error.message).toContain('ReferenceError');
expect(error.message).toContain('not is not defined');
}));
});
@ -186,6 +186,16 @@ describe('Puppeteer', function() {
expect(result).toBe('answer!');
}));
});
describe('Page.Events.Error', function() {
it('should fire', function(done) {
page.on('error', error => {
expect(error.message).toContain('Fancy');
done();
});
page.navigate(STATIC_PREFIX + '/error.html');
});
});
});
// Since Jasmine doesn't like async functions, they should be wrapped