Skip to content

Commit

Permalink
fix: supress init errors if the target is closed
Browse files Browse the repository at this point in the history
With #8520 Puppeteer is now aware of all targets it connects
to. In order to have a not flaky init, Puppeteer waits for
all existing targets to be configured during the connection process.
This does not work well in case of concurrent connections because
while one connection might initializing a target the other one
might be closed it. In general, that is expected because we
can only be eventually consistent about the target state but we
also should not crash the init if some targets have been closed.
This PR implements checks to see if the errors are caused by the
target or session closures and supresses them if it's the case.
  • Loading branch information
OrKoN committed Sep 13, 2022
1 parent c23c00a commit d15e8c3
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 10 deletions.
1 change: 0 additions & 1 deletion src/common/BrowserConnector.ts
Expand Up @@ -131,7 +131,6 @@ export async function _connectToBrowser(
targetFilter,
isPageTarget
);
await browser.pages();
return browser;
}

Expand Down
10 changes: 10 additions & 0 deletions src/common/Connection.ts
Expand Up @@ -445,3 +445,13 @@ function rewriteError(
error.originalMessage = originalMessage ?? error.originalMessage;
return error;
}

/**
* @internal
*/
export function isTargetClosedError(err: Error): boolean {
return (
err.message.includes('Target closed') ||
err.message.includes('Session closed')
);
}
8 changes: 2 additions & 6 deletions src/common/FrameManager.ts
Expand Up @@ -19,7 +19,7 @@ import {assert} from '../util/assert.js';
import {createDebuggableDeferredPromise} from '../util/DebuggableDeferredPromise.js';
import {DeferredPromise} from '../util/DeferredPromise.js';
import {isErrorLike} from '../util/ErrorLike.js';
import {CDPSession} from './Connection.js';
import {CDPSession, isTargetClosedError} from './Connection.js';
import {EventEmitter} from './EventEmitter.js';
import {EVALUATION_SCRIPT_URL, ExecutionContext} from './ExecutionContext.js';
import {Frame} from './Frame.js';
Expand Down Expand Up @@ -172,11 +172,7 @@ export class FrameManager extends EventEmitter {
]);
} catch (error) {
// The target might have been closed before the initialization finished.
if (
isErrorLike(error) &&
(error.message.includes('Target closed') ||
error.message.includes('Session closed'))
) {
if (isErrorLike(error) && isTargetClosedError(error)) {
return;
}

Expand Down
24 changes: 21 additions & 3 deletions src/common/Page.ts
Expand Up @@ -24,7 +24,11 @@ import {
import {isErrorLike} from '../util/ErrorLike.js';
import {Accessibility} from './Accessibility.js';
import {Browser, BrowserContext} from './Browser.js';
import {CDPSession, CDPSessionEmittedEvents} from './Connection.js';
import {
CDPSession,
CDPSessionEmittedEvents,
isTargetClosedError,
} from './Connection.js';
import {ConsoleMessage, ConsoleMessageType} from './ConsoleMessage.js';
import {Coverage} from './Coverage.js';
import {Dialog} from './Dialog.js';
Expand Down Expand Up @@ -402,6 +406,20 @@ export interface PageEventObject {
workerdestroyed: WebWorker;
}

/**
* Supresses the error if it's caused by the target being closed. It usually happens
* if there are concurrent Puppeteer connections to the target and the target is closed by
* the concurrent connection.
* @internal
*/
function debugErrorIfTargetClosed(err: Error): void {
if (isTargetClosedError(err)) {
debugError(err);
return;
}
throw err;
}

/**
* Page provides methods to interact with a single tab or
* {@link https://developer.chrome.com/extensions/background_pages | extension background page}
Expand Down Expand Up @@ -470,7 +488,7 @@ export class Page extends EventEmitter {
);
await page.#initialize();
if (defaultViewport) {
await page.setViewport(defaultViewport);
await page.setViewport(defaultViewport).catch(debugErrorIfTargetClosed);
}
return page;
}
Expand Down Expand Up @@ -649,7 +667,7 @@ export class Page extends EventEmitter {
this.#frameManager.initialize(this.#target._targetId),
this.#client.send('Performance.enable'),
this.#client.send('Log.enable'),
]);
]).catch(debugErrorIfTargetClosed);
}

async #onFileChooser(
Expand Down

0 comments on commit d15e8c3

Please sign in to comment.