From c08da50bb39b4a5d01689e97102afb8c51300a48 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Fri, 5 Jun 2020 07:50:26 -0700 Subject: [PATCH] chore: introduce session.sendMayFail to ease error logging (#2480) --- src/chromium/crBrowser.ts | 5 ++-- src/chromium/crConnection.ts | 11 ++++++-- src/chromium/crCoverage.ts | 32 ++++++++--------------- src/chromium/crNetworkManager.ts | 39 ++++++++++++---------------- src/chromium/crPage.ts | 35 ++++++++++++------------- src/firefox/ffConnection.ts | 10 +++++-- src/firefox/ffNetworkManager.ts | 13 +++++----- src/firefox/ffPage.ts | 7 +++-- src/network.ts | 3 --- src/webkit/wkConnection.ts | 11 +++++--- src/webkit/wkInterceptableRequest.ts | 25 +++++++----------- src/webkit/wkPage.ts | 18 ++++++------- 12 files changed, 98 insertions(+), 111 deletions(-) diff --git a/src/chromium/crBrowser.ts b/src/chromium/crBrowser.ts index a83967f8af..eb146aedec 100644 --- a/src/chromium/crBrowser.ts +++ b/src/chromium/crBrowser.ts @@ -29,7 +29,6 @@ import { readProtocolStream } from './crProtocolHelper'; import { Events } from './events'; import { Protocol } from './protocol'; import { CRExecutionContext } from './crExecutionContext'; -import { logError } from '../logger'; import { CRDevTools } from '../debug/crDevTools'; export class CRBrowser extends BrowserBase { @@ -133,8 +132,8 @@ export class CRBrowser extends BrowserBase { if (targetInfo.type === 'other' || !context) { if (waitingForDebugger) { // Ideally, detaching should resume any target, but there is a bug in the backend. - session.send('Runtime.runIfWaitingForDebugger').catch(logError(this)).then(() => { - this._session.send('Target.detachFromTarget', { sessionId }).catch(logError(this)); + session._sendMayFail('Runtime.runIfWaitingForDebugger').then(() => { + this._session._sendMayFail('Target.detachFromTarget', { sessionId }); }); } return; diff --git a/src/chromium/crConnection.ts b/src/chromium/crConnection.ts index 8116bb67f7..e0233601bd 100644 --- a/src/chromium/crConnection.ts +++ b/src/chromium/crConnection.ts @@ -19,7 +19,7 @@ import { assert } from '../helper'; import { ConnectionTransport, ProtocolRequest, ProtocolResponse, protocolLog } from '../transport'; import { Protocol } from './protocol'; import { EventEmitter } from 'events'; -import { InnerLogger } from '../logger'; +import { InnerLogger, errorLog } from '../logger'; import { rewriteErrorMessage } from '../debug/stackTrace'; export const ConnectionEvents = { @@ -36,7 +36,7 @@ export class CRConnection extends EventEmitter { private readonly _sessions = new Map(); readonly rootSession: CRSession; _closed = false; - private _logger: InnerLogger; + readonly _logger: InnerLogger; constructor(transport: ConnectionTransport, logger: InnerLogger) { super(); @@ -165,6 +165,13 @@ export class CRSession extends EventEmitter { }); } + _sendMayFail(method: T, params?: Protocol.CommandParameters[T]): Promise { + return this.send(method, params).catch(error => { + if (this._connection) + this._connection._logger._log(errorLog, error, []); + }); + } + _onMessage(object: ProtocolResponse) { if (object.id && this._callbacks.has(object.id)) { const callback = this._callbacks.get(object.id)!; diff --git a/src/chromium/crCoverage.ts b/src/chromium/crCoverage.ts index 6b9a90d02b..cd3110ac87 100644 --- a/src/chromium/crCoverage.ts +++ b/src/chromium/crCoverage.ts @@ -20,7 +20,6 @@ import { assert, helper, RegisteredListener } from '../helper'; import { Protocol } from './protocol'; import * as types from '../types'; import * as debugSupport from '../debug/debugSupport'; -import { logError, InnerLogger } from '../logger'; type JSRange = { startOffset: number, @@ -50,9 +49,9 @@ export class CRCoverage { private _jsCoverage: JSCoverage; private _cssCoverage: CSSCoverage; - constructor(client: CRSession, logger: InnerLogger) { - this._jsCoverage = new JSCoverage(client, logger); - this._cssCoverage = new CSSCoverage(client, logger); + constructor(client: CRSession) { + this._jsCoverage = new JSCoverage(client); + this._cssCoverage = new CSSCoverage(client); } async startJSCoverage(options?: types.JSCoverageOptions) { @@ -80,11 +79,9 @@ class JSCoverage { _eventListeners: RegisteredListener[]; _resetOnNavigation: boolean; _reportAnonymousScripts = false; - private _logger: InnerLogger; - constructor(client: CRSession, logger: InnerLogger) { + constructor(client: CRSession) { this._client = client; - this._logger = logger; this._enabled = false; this._scriptIds = new Set(); this._scriptSources = new Map(); @@ -131,13 +128,10 @@ class JSCoverage { // Ignore other anonymous scripts unless the reportAnonymousScripts option is true. if (!event.url && !this._reportAnonymousScripts) return; - try { - const response = await this._client.send('Debugger.getScriptSource', {scriptId: event.scriptId}); + // This might fail if the page has already navigated away. + const response = await this._client._sendMayFail('Debugger.getScriptSource', {scriptId: event.scriptId}); + if (response) this._scriptSources.set(event.scriptId, response.scriptSource); - } catch (e) { - // This might happen if the page has already navigated away. - logError(this._logger)(e); - } } async stop(): Promise { @@ -174,11 +168,9 @@ class CSSCoverage { _stylesheetSources: Map; _eventListeners: RegisteredListener[]; _resetOnNavigation: boolean; - private _logger: InnerLogger; - constructor(client: CRSession, logger: InnerLogger) { + constructor(client: CRSession) { this._client = client; - this._logger = logger; this._enabled = false; this._stylesheetURLs = new Map(); this._stylesheetSources = new Map(); @@ -216,13 +208,11 @@ class CSSCoverage { // Ignore anonymous scripts if (!header.sourceURL) return; - try { - const response = await this._client.send('CSS.getStyleSheetText', {styleSheetId: header.styleSheetId}); + // This might fail if the page has already navigated away. + const response = await this._client._sendMayFail('CSS.getStyleSheetText', {styleSheetId: header.styleSheetId}); + if (response) { this._stylesheetURLs.set(header.styleSheetId, header.sourceURL); this._stylesheetSources.set(header.styleSheetId, response.text); - } catch (e) { - // This might happen if the page has already navigated away. - logError(this._logger)(e); } } diff --git a/src/chromium/crNetworkManager.ts b/src/chromium/crNetworkManager.ts index e390348273..a815c10618 100644 --- a/src/chromium/crNetworkManager.ts +++ b/src/chromium/crNetworkManager.ts @@ -23,7 +23,6 @@ import * as network from '../network'; import * as frames from '../frames'; import { Credentials } from '../types'; import { CRPage } from './crPage'; -import { logError } from '../logger'; export class CRNetworkManager { private _client: CRSession; @@ -130,26 +129,26 @@ export class CRNetworkManager { this._attemptedAuthentications.add(event.requestId); } const {username, password} = this._credentials || {username: undefined, password: undefined}; - this._client.send('Fetch.continueWithAuth', { + this._client._sendMayFail('Fetch.continueWithAuth', { requestId: event.requestId, authChallengeResponse: { response, username, password }, - }).catch(logError(this._page)); + }); } _onRequestPaused(workerFrame: frames.Frame | undefined, event: Protocol.Fetch.requestPausedPayload) { if (!this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled) { - this._client.send('Fetch.continueRequest', { + this._client._sendMayFail('Fetch.continueRequest', { requestId: event.requestId - }).catch(logError(this._page)); + }); } if (!event.networkId) { // Fetch without networkId means that request was not recongnized by inspector, and // it will never receive Network.requestWillBeSent. Most likely, this is an internal request // that we can safely fail. - this._client.send('Fetch.failRequest', { + this._client._sendMayFail('Fetch.failRequest', { requestId: event.requestId, errorReason: 'Aborted', - }).catch(logError(this._page)); + }); return; } if (event.request.url.startsWith('data:')) @@ -189,7 +188,7 @@ export class CRNetworkManager { if (!frame) { if (requestPausedEvent) - this._client.send('Fetch.continueRequest', { requestId: requestPausedEvent.requestId }).catch(logError(this._page)); + this._client._sendMayFail('Fetch.continueRequest', { requestId: requestPausedEvent.requestId }); return; } const isNavigationRequest = requestWillBeSentEvent.requestId === requestWillBeSentEvent.loaderId && requestWillBeSentEvent.type === 'Document'; @@ -325,15 +324,13 @@ class InterceptableRequest implements network.RouteDelegate { } async continue(overrides: { method?: string; headers?: network.Headers; postData?: string } = {}) { - await this._client.send('Fetch.continueRequest', { + // In certain cases, protocol will return error if the request was already canceled + // or the page was closed. We should tolerate these errors. + await this._client._sendMayFail('Fetch.continueRequest', { requestId: this._interceptionId!, headers: overrides.headers ? headersArray(overrides.headers) : undefined, method: overrides.method, postData: overrides.postData - }).catch(error => { - // In certain cases, protocol will return error if the request was already canceled - // or the page was closed. We should tolerate these errors. - logError(this.request._page)(error); }); } @@ -350,29 +347,25 @@ class InterceptableRequest implements network.RouteDelegate { if (responseBody && !('content-length' in responseHeaders)) responseHeaders['content-length'] = String(Buffer.byteLength(responseBody)); - await this._client.send('Fetch.fulfillRequest', { + // In certain cases, protocol will return error if the request was already canceled + // or the page was closed. We should tolerate these errors. + await this._client._sendMayFail('Fetch.fulfillRequest', { requestId: this._interceptionId!, responseCode: response.status || 200, responsePhrase: network.STATUS_TEXTS[String(response.status || 200)], responseHeaders: headersArray(responseHeaders), body: responseBody ? responseBody.toString('base64') : undefined, - }).catch(error => { - // In certain cases, protocol will return error if the request was already canceled - // or the page was closed. We should tolerate these errors. - logError(this.request._page)(error); }); } async abort(errorCode: string = 'failed') { const errorReason = errorReasons[errorCode]; assert(errorReason, 'Unknown error code: ' + errorCode); - await this._client.send('Fetch.failRequest', { + // In certain cases, protocol will return error if the request was already canceled + // or the page was closed. We should tolerate these errors. + await this._client._sendMayFail('Fetch.failRequest', { requestId: this._interceptionId!, errorReason - }).catch(error => { - // In certain cases, protocol will return error if the request was already canceled - // or the page was closed. We should tolerate these errors. - logError(this.request._page)(error); }); } } diff --git a/src/chromium/crPage.ts b/src/chromium/crPage.ts index 10d26583ef..07c50a06d1 100644 --- a/src/chromium/crPage.ts +++ b/src/chromium/crPage.ts @@ -36,7 +36,6 @@ import { CRBrowserContext } from './crBrowser'; import * as types from '../types'; import { ConsoleMessage } from '../console'; import { NotConnectedError } from '../errors'; -import { logError } from '../logger'; import * as debugSupport from '../debug/debugSupport'; import { rewriteErrorMessage } from '../debug/stackTrace'; @@ -70,7 +69,7 @@ export class CRPage implements PageDelegate { this.rawKeyboard = new RawKeyboardImpl(client); this.rawMouse = new RawMouseImpl(client); this._pdf = new CRPDF(client); - this._coverage = new CRCoverage(client, browserContext); + this._coverage = new CRCoverage(client); this._browserContext = browserContext; this._page = new Page(this, browserContext); this._mainFrameSession = new FrameSession(this, client, targetId, null); @@ -121,7 +120,7 @@ export class CRPage implements PageDelegate { async exposeBinding(binding: PageBinding) { await this._forAllFrameSessions(frame => frame._initBinding(binding)); - await Promise.all(this._page.frames().map(frame => frame.evaluate(binding.source).catch(logError(this._page)))); + await Promise.all(this._page.frames().map(frame => frame.evaluate(binding.source).catch(e => {}))); } async updateExtraHTTPHeaders(): Promise { @@ -384,13 +383,13 @@ class FrameSession { const localFrames = this._isMainFrame() ? this._page.frames() : [ this._page._frameManager.frame(this._targetId)! ]; for (const frame of localFrames) { // Note: frames might be removed before we send these. - this._client.send('Page.createIsolatedWorld', { + this._client._sendMayFail('Page.createIsolatedWorld', { frameId: frame._id, grantUniveralAccess: true, worldName: UTILITY_WORLD_NAME, - }).catch(logError(this._page)); + }); for (const binding of this._crPage._browserContext._pageBindings.values()) - frame.evaluate(binding.source).catch(logError(this._page)); + frame.evaluate(binding.source).catch(e => {}); } const isInitialEmptyPage = this._isMainFrame() && this._page.mainFrame().url() === ':'; if (isInitialEmptyPage) { @@ -560,8 +559,8 @@ class FrameSession { if (event.targetInfo.type !== 'worker') { // Ideally, detaching should resume any target, but there is a bug in the backend. - session.send('Runtime.runIfWaitingForDebugger').catch(logError(this._page)).then(() => { - this._client.send('Target.detachFromTarget', { sessionId: event.sessionId }).catch(logError(this._page)); + session._sendMayFail('Runtime.runIfWaitingForDebugger').then(() => { + this._client._sendMayFail('Target.detachFromTarget', { sessionId: event.sessionId }); }); return; } @@ -573,10 +572,10 @@ class FrameSession { worker._createExecutionContext(new CRExecutionContext(session, event.context)); }); Promise.all([ - session.send('Runtime.enable'), - session.send('Network.enable'), - session.send('Runtime.runIfWaitingForDebugger'), - ]).catch(logError(this._page)); // This might fail if the target is closed before we initialize. + session._sendMayFail('Runtime.enable'), + session._sendMayFail('Network.enable'), + session._sendMayFail('Runtime.runIfWaitingForDebugger'), + ]); // This might fail if the target is closed before we initialize. session.on('Runtime.consoleAPICalled', event => { const args = event.args.map(o => worker._existingExecutionContext!.createHandle(o)); this._page._addConsoleMessage(event.type, args, toConsoleMessageLocation(event.stackTrace)); @@ -816,9 +815,9 @@ class FrameSession { } async _getBoundingBox(handle: dom.ElementHandle): Promise { - const result = await this._client.send('DOM.getBoxModel', { + const result = await this._client._sendMayFail('DOM.getBoxModel', { objectId: handle._objectId - }).catch(logError(this._page)); + }); if (!result) return null; const quad = result.model.border; @@ -843,9 +842,9 @@ class FrameSession { } async _getContentQuads(handle: dom.ElementHandle): Promise { - const result = await this._client.send('DOM.getContentQuads', { + const result = await this._client._sendMayFail('DOM.getContentQuads', { objectId: handle._objectId - }).catch(logError(this._page)); + }); if (!result) return null; return result.quads.map(quad => [ @@ -864,10 +863,10 @@ class FrameSession { } async _adoptBackendNodeId(backendNodeId: Protocol.DOM.BackendNodeId, to: dom.FrameExecutionContext): Promise { - const result = await this._client.send('DOM.resolveNode', { + const result = await this._client._sendMayFail('DOM.resolveNode', { backendNodeId, executionContextId: (to._delegate as CRExecutionContext)._contextId, - }).catch(logError(this._page)); + }); if (!result || result.object.subtype === 'null') throw new Error('Unable to adopt element handle from a different document'); return to.createHandle(result.object).asElement()!; diff --git a/src/firefox/ffConnection.ts b/src/firefox/ffConnection.ts index 3e45b0ab04..35d98a7a7a 100644 --- a/src/firefox/ffConnection.ts +++ b/src/firefox/ffConnection.ts @@ -19,7 +19,7 @@ import { EventEmitter } from 'events'; import { assert } from '../helper'; import { ConnectionTransport, ProtocolRequest, ProtocolResponse, protocolLog } from '../transport'; import { Protocol } from './protocol'; -import { InnerLogger } from '../logger'; +import { InnerLogger, errorLog } from '../logger'; import { rewriteErrorMessage } from '../debug/stackTrace'; export const ConnectionEvents = { @@ -34,7 +34,7 @@ export class FFConnection extends EventEmitter { private _lastId: number; private _callbacks: Map; private _transport: ConnectionTransport; - private _logger: InnerLogger; + readonly _logger: InnerLogger; readonly _sessions: Map; _closed: boolean; @@ -185,6 +185,12 @@ export class FFSession extends EventEmitter { }); } + sendMayFail(method: T, params?: Protocol.CommandParameters[T]): Promise { + return this.send(method, params).catch(error => { + this._connection._logger._log(errorLog, error, []); + }); + } + dispatchMessage(object: ProtocolResponse) { if (object.id && this._callbacks.has(object.id)) { const callback = this._callbacks.get(object.id)!; diff --git a/src/firefox/ffNetworkManager.ts b/src/firefox/ffNetworkManager.ts index ce9c664559..205bc681df 100644 --- a/src/firefox/ffNetworkManager.ts +++ b/src/firefox/ffNetworkManager.ts @@ -21,7 +21,6 @@ import { Page } from '../page'; import * as network from '../network'; import * as frames from '../frames'; import { Protocol } from './protocol'; -import { logError } from '../logger'; export class FFNetworkManager { private _session: FFSession; @@ -164,12 +163,12 @@ class InterceptableRequest implements network.RouteDelegate { headers, postData } = overrides; - await this._session.send('Network.resumeInterceptedRequest', { + await this._session.sendMayFail('Network.resumeInterceptedRequest', { requestId: this._id, method, headers: headers ? headersArray(headers) : undefined, postData: postData ? Buffer.from(postData).toString('base64') : undefined - }).catch(logError(this.request._page)); + }); } async fulfill(response: network.FulfillResponse) { @@ -185,20 +184,20 @@ class InterceptableRequest implements network.RouteDelegate { if (responseBody && !('content-length' in responseHeaders)) responseHeaders['content-length'] = String(Buffer.byteLength(responseBody)); - await this._session.send('Network.fulfillInterceptedRequest', { + await this._session.sendMayFail('Network.fulfillInterceptedRequest', { requestId: this._id, status: response.status || 200, statusText: network.STATUS_TEXTS[String(response.status || 200)] || '', headers: headersArray(responseHeaders), base64body: responseBody ? responseBody.toString('base64') : undefined, - }).catch(logError(this.request._page)); + }); } async abort(errorCode: string) { - await this._session.send('Network.abortInterceptedRequest', { + await this._session.sendMayFail('Network.abortInterceptedRequest', { requestId: this._id, errorCode, - }).catch(logError(this.request._page)); + }); } } diff --git a/src/firefox/ffPage.ts b/src/firefox/ffPage.ts index 157e7fa994..f3105c6320 100644 --- a/src/firefox/ffPage.ts +++ b/src/firefox/ffPage.ts @@ -32,7 +32,6 @@ import { FFNetworkManager, headersArray } from './ffNetworkManager'; import { Protocol } from './protocol'; import { selectors } from '../selectors'; import { NotConnectedError } from '../errors'; -import { logError } from '../logger'; import { rewriteErrorMessage } from '../debug/stackTrace'; const UTILITY_WORLD_NAME = '__playwright_utility_world__'; @@ -193,7 +192,7 @@ export class FFPage implements PageDelegate { params.type, params.message, async (accept: boolean, promptText?: string) => { - await this._session.send('Page.handleDialog', { dialogId: params.dialogId, accept, promptText }).catch(logError(this._page)); + await this._session.sendMayFail('Page.handleDialog', { dialogId: params.dialogId, accept, promptText }); }, params.defaultValue)); } @@ -429,10 +428,10 @@ export class FFPage implements PageDelegate { } async getContentQuads(handle: dom.ElementHandle): Promise { - const result = await this._session.send('Page.getContentQuads', { + const result = await this._session.sendMayFail('Page.getContentQuads', { frameId: handle._context.frame._id, objectId: handle._objectId, - }).catch(logError(this._page)); + }); if (!result) return null; return result.quads.map(quad => [ quad.p1, quad.p2, quad.p3, quad.p4 ]); diff --git a/src/network.ts b/src/network.ts index 8216f49e6a..ec92e0a9f4 100644 --- a/src/network.ts +++ b/src/network.ts @@ -19,7 +19,6 @@ import * as mime from 'mime'; import * as util from 'util'; import * as frames from './frames'; import { assert, helper } from './helper'; -import { Page } from './page'; import { URLSearchParams } from 'url'; export type NetworkCookie = { @@ -112,14 +111,12 @@ export class Request { private _frame: frames.Frame; private _waitForResponsePromise: Promise; private _waitForResponsePromiseCallback: (value: Response | null) => void = () => {}; - readonly _page: Page; constructor(routeDelegate: RouteDelegate | null, frame: frames.Frame, redirectedFrom: Request | null, documentId: string | undefined, url: string, resourceType: string, method: string, postData: string | null, headers: Headers) { assert(!url.startsWith('data:'), 'Data urls should not fire requests'); this._routeDelegate = routeDelegate; this._frame = frame; - this._page = frame._page; this._redirectedFrom = redirectedFrom; if (redirectedFrom) redirectedFrom._redirectedTo = this; diff --git a/src/webkit/wkConnection.ts b/src/webkit/wkConnection.ts index 79b11c72b1..dab4086417 100644 --- a/src/webkit/wkConnection.ts +++ b/src/webkit/wkConnection.ts @@ -19,7 +19,7 @@ import { EventEmitter } from 'events'; import { assert } from '../helper'; import { ConnectionTransport, ProtocolRequest, ProtocolResponse, protocolLog } from '../transport'; import { Protocol } from './protocol'; -import { InnerLogger } from '../logger'; +import { InnerLogger, errorLog } from '../logger'; import { rewriteErrorMessage } from '../debug/stackTrace'; // WKPlaywright uses this special id to issue Browser.close command which we @@ -36,9 +36,8 @@ export class WKConnection { private readonly _onDisconnect: () => void; private _lastId = 0; private _closed = false; - readonly browserSession: WKSession; - private _logger: InnerLogger; + readonly _logger: InnerLogger; constructor(transport: ConnectionTransport, logger: InnerLogger, onDisconnect: () => void) { this._transport = transport; @@ -138,6 +137,12 @@ export class WKSession extends EventEmitter { }); } + sendMayFail(method: T, params?: Protocol.CommandParameters[T]): Promise { + return this.send(method, params).catch(error => { + this.connection._logger._log(errorLog, error, []); + }); + } + markAsCrashed() { this._crashed = true; } diff --git a/src/webkit/wkInterceptableRequest.ts b/src/webkit/wkInterceptableRequest.ts index bdde7fdd08..98e75984cc 100644 --- a/src/webkit/wkInterceptableRequest.ts +++ b/src/webkit/wkInterceptableRequest.ts @@ -20,7 +20,6 @@ import { assert, helper } from '../helper'; import * as network from '../network'; import { Protocol } from './protocol'; import { WKSession } from './wkConnection'; -import { logError } from '../logger'; const errorReasons: { [reason: string]: string } = { 'aborted': 'Cancellation', @@ -59,11 +58,9 @@ export class WKInterceptableRequest implements network.RouteDelegate { const reason = errorReasons[errorCode]; assert(reason, 'Unknown error code: ' + errorCode); await this._interceptedPromise; - await this._session.send('Network.interceptAsError', { requestId: this._requestId, reason }).catch(error => { - // In certain cases, protocol will return error if the request was already canceled - // or the page was closed. We should tolerate these errors. - logError(this.request._page); - }); + // In certain cases, protocol will return error if the request was already canceled + // or the page was closed. We should tolerate these errors. + await this._session.sendMayFail('Network.interceptAsError', { requestId: this._requestId, reason }); } async fulfill(response: network.FulfillResponse) { @@ -89,7 +86,9 @@ export class WKInterceptableRequest implements network.RouteDelegate { if (responseBody && !('content-length' in responseHeaders)) responseHeaders['content-length'] = String(Buffer.byteLength(responseBody)); - await this._session.send('Network.interceptWithResponse', { + // In certain cases, protocol will return error if the request was already canceled + // or the page was closed. We should tolerate these errors. + await this._session.sendMayFail('Network.interceptWithResponse', { requestId: this._requestId, status: response.status || 200, statusText: network.STATUS_TEXTS[String(response.status || 200)], @@ -97,24 +96,18 @@ export class WKInterceptableRequest implements network.RouteDelegate { headers: responseHeaders, base64Encoded, content: responseBody - }).catch(error => { - // In certain cases, protocol will return error if the request was already canceled - // or the page was closed. We should tolerate these errors. - logError(this.request._page); }); } async continue(overrides: { method?: string; headers?: network.Headers; postData?: string }) { await this._interceptedPromise; - await this._session.send('Network.interceptContinue', { + // In certain cases, protocol will return error if the request was already canceled + // or the page was closed. We should tolerate these errors. + await this._session.sendMayFail('Network.interceptContinue', { requestId: this._requestId, method: overrides.method, headers: overrides.headers, postData: overrides.postData ? Buffer.from(overrides.postData).toString('base64') : undefined - }).catch((error: Error) => { - // In certain cases, protocol will return error if the request was already canceled - // or the page was closed. We should tolerate these errors. - logError(this.request._page); }); } diff --git a/src/webkit/wkPage.ts b/src/webkit/wkPage.ts index a3700e160a..23580631f5 100644 --- a/src/webkit/wkPage.ts +++ b/src/webkit/wkPage.ts @@ -287,7 +287,7 @@ export class WKPage implements PageDelegate { pageOrError = e; } if (targetInfo.isPaused) - this._pageProxySession.send('Target.resume', { targetId: targetInfo.targetId }).catch(logError(this._page)); + this._pageProxySession.sendMayFail('Target.resume', { targetId: targetInfo.targetId }); if ((pageOrError instanceof Page) && this._page.mainFrame().url() === '') { try { // Initial empty page has an empty url. We should wait until the first real url has been loaded, @@ -309,7 +309,7 @@ export class WKPage implements PageDelegate { this._provisionalPage = new WKProvisionalPage(session, this); if (targetInfo.isPaused) { this._provisionalPage.initializationPromise.then(() => { - this._pageProxySession.send('Target.resume', { targetId: targetInfo.targetId }).catch(logError(this._page)); + this._pageProxySession.sendMayFail('Target.resume', { targetId: targetInfo.targetId }); }); } } @@ -652,7 +652,7 @@ export class WKPage implements PageDelegate { private async _evaluateBindingScript(binding: PageBinding): Promise { const script = this._bindingToScript(binding); - await Promise.all(this._page.frames().map(frame => frame.evaluate(script).catch(logError(this._page)))); + await Promise.all(this._page.frames().map(frame => frame.evaluate(script).catch(e => {}))); } async evaluateOnNewDocument(script: string): Promise { @@ -680,10 +680,10 @@ export class WKPage implements PageDelegate { } async closePage(runBeforeUnload: boolean): Promise { - this._pageProxySession.send('Target.close', { + this._pageProxySession.sendMayFail('Target.close', { targetId: this._session.sessionId, runBeforeUnload - }).catch(logError(this._page)); + }); } canScreenshotOutsideViewport(): boolean { @@ -767,9 +767,9 @@ export class WKPage implements PageDelegate { } async getContentQuads(handle: dom.ElementHandle): Promise { - const result = await this._session.send('DOM.getContentQuads', { + const result = await this._session.sendMayFail('DOM.getContentQuads', { objectId: handle._objectId - }).catch(logError(this._page)); + }); if (!result) return null; return result.quads.map(quad => [ @@ -790,10 +790,10 @@ export class WKPage implements PageDelegate { } async adoptElementHandle(handle: dom.ElementHandle, to: dom.FrameExecutionContext): Promise> { - const result = await this._session.send('DOM.resolveNode', { + const result = await this._session.sendMayFail('DOM.resolveNode', { objectId: handle._objectId, executionContextId: (to._delegate as WKExecutionContext)._contextId - }).catch(logError(this._page)); + }); if (!result || result.object.subtype === 'null') throw new Error('Unable to adopt element handle from a different document'); return to.createHandle(result.object) as dom.ElementHandle;