diff --git a/lighthouse-core/gather/connections/connection.js b/lighthouse-core/gather/connections/connection.js index f5b86cc0f80c..022f87fabefb 100644 --- a/lighthouse-core/gather/connections/connection.js +++ b/lighthouse-core/gather/connections/connection.js @@ -95,14 +95,16 @@ class Connection { const callback = this._callbacks.get(object.id); this._callbacks.delete(object.id); - if (object.error) { - return this.handleRawError(object.error, callback); - } + // handleRawError returns or throws synchronously; wrap to put into promise chain. + return callback.resolve(Promise.resolve().then(_ => { + if (object.error) { + return this.handleRawError(object.error, callback.method); + } - log.formatProtocol('method <= browser OK', + log.formatProtocol('method <= browser OK', {method: callback.method, params: object.result}, 'verbose'); - callback.resolve(object.result); - return; + return object.result; + })); } log.formatProtocol('<= event', {method: object.method, params: object.params}, 'verbose'); @@ -110,19 +112,20 @@ class Connection { } /** + * Handles error responses from the protocol, absorbing errors we don't care + * about and throwing on the rest. * @param {{message: string}} error - * @param {{resolve: function(*), reject: function(*), method: string}} callback + * @param {string} method Protocol method that received the error response. * @protected */ - handleRawError(error, callback) { + handleRawError(error, method) { // We proactively disable the DOM domain. Ignore any errors. if (error.message && error.message.includes('DOM agent hasn\'t been enabled')) { - callback.resolve(); return; } - log.formatProtocol('method <= browser ERR', {method: callback.method}, 'error'); - callback.reject(new Error(`Protocol error (${callback.method}): ${error.message}`)); + log.formatProtocol('method <= browser ERR', {method}, 'error'); + throw new Error(`Protocol error (${method}): ${error.message}`); } /** diff --git a/lighthouse-core/gather/connections/extension.js b/lighthouse-core/gather/connections/extension.js index 8e80d049d27d..f4eebf99498b 100644 --- a/lighthouse-core/gather/connections/extension.js +++ b/lighthouse-core/gather/connections/extension.js @@ -112,6 +112,8 @@ class ExtensionConnection extends Connection { chrome.debugger.sendCommand({tabId: this._tabId}, command, params, result => { if (chrome.runtime.lastError) { + // The error from the extension has a `message` property that is the + // stringified version of the actual protocol error object. const message = chrome.runtime.lastError.message; let error; try { @@ -119,12 +121,12 @@ class ExtensionConnection extends Connection { } catch (e) {} error = error || {message: 'Unknown debugger protocol error.'}; - const callback = { - resolve, - reject, - method: command - }; - return this.handleRawError(error, callback); + // handleRawError returns or throws synchronously, so try/catch awkwardly. + try { + return resolve(this.handleRawError(error, command)); + } catch (err) { + return reject(err); + } } log.formatProtocol('method <= browser OK', {method: command, params: result}, 'verbose'); diff --git a/lighthouse-core/gather/driver.js b/lighthouse-core/gather/driver.js index 34bcc3601326..38d443d140b6 100644 --- a/lighthouse-core/gather/driver.js +++ b/lighthouse-core/gather/driver.js @@ -151,7 +151,10 @@ class Driver { }).then(result => { clearTimeout(asyncTimeout); resolve(result.result.value); - }).catch(reject); + }).catch(err => { + clearTimeout(asyncTimeout); + reject(err); + }); }); }