diff --git a/src/cli/cli.ts b/src/cli/cli.ts index 2476e1f35c..95e9b37e72 100755 --- a/src/cli/cli.ts +++ b/src/cli/cli.ts @@ -39,7 +39,7 @@ program commandWithOpenOptions('open [url]', 'open page in browser specified via -b, --browser', []) .action(function(url, command) { - open(command, url, language()); + open(command, url, language()).catch(logErrorAndExit); }) .on('--help', function() { console.log(''); @@ -54,7 +54,7 @@ commandWithOpenOptions('codegen [url]', 'open page and generate code for user ac ['-o, --output ', 'saves the generated script to a file'], ['--target ', `language to use, one of javascript, python, python-async, csharp`, language()], ]).action(function(url, command) { - codegen(command, url, command.target, command.output); + codegen(command, url, command.target, command.output).catch(logErrorAndExit); }).on('--help', function() { console.log(''); console.log('Examples:'); @@ -122,7 +122,7 @@ const browsers = [ for (const {alias, name, type} of browsers) { commandWithOpenOptions(`${alias} [url]`, `open page in ${name}`, []) .action(function(url, command) { - open({ ...command, browser: type }, url, command.target); + open({ ...command, browser: type }, url, command.target).catch(logErrorAndExit); }).on('--help', function() { console.log(''); console.log('Examples:'); @@ -137,7 +137,7 @@ commandWithOpenOptions('screenshot ', 'capture a page screenshot ['--wait-for-timeout ', 'wait for timeout in milliseconds before taking a screenshot'], ['--full-page', 'whether to take a full page screenshot (entire scrollable area)'], ]).action(function(url, filename, command) { - screenshot(command, command, url, filename); + screenshot(command, command, url, filename).catch(logErrorAndExit); }).on('--help', function() { console.log(''); console.log('Examples:'); @@ -150,7 +150,7 @@ commandWithOpenOptions('pdf ', 'save page as pdf', ['--wait-for-selector ', 'wait for given selector before saving as pdf'], ['--wait-for-timeout ', 'wait for given timeout in milliseconds before saving as pdf'], ]).action(function(url, filename, command) { - pdf(command, command, url, filename); + pdf(command, command, url, filename).catch(logErrorAndExit); }).on('--help', function() { console.log(''); console.log('Examples:'); @@ -164,7 +164,7 @@ if (process.env.PWTRACE) { .option('--resources ', 'load resources from shared folder') .description('Show trace viewer') .action(function(trace, command) { - showTraceViewer(trace, command.resources); + showTraceViewer(trace, command.resources).catch(logErrorAndExit); }).on('--help', function() { console.log(''); console.log('Examples:'); @@ -179,7 +179,7 @@ if (process.argv[2] === 'run-driver') else if (process.argv[2] === 'print-api-json') printApiJson(); else if (process.argv[2] === 'launch-server') - launchBrowserServer(process.argv[3], process.argv[4]); + launchBrowserServer(process.argv[3], process.argv[4]).catch(logErrorAndExit); else program.parse(process.argv); @@ -446,6 +446,11 @@ function validateOptions(options: Options) { } } +function logErrorAndExit(e: Error) { + console.error(e); + process.exit(1); +} + function language(): string { return process.env.PW_CLI_TARGET_LANG || 'javascript'; } diff --git a/src/client/browserContext.ts b/src/client/browserContext.ts index 3eb7ad96b5..e849f39182 100644 --- a/src/client/browserContext.ts +++ b/src/client/browserContext.ts @@ -87,7 +87,7 @@ export class BrowserContext extends ChannelOwner { - await this._object.close(); + this._object.close(); } } diff --git a/src/remote/playwrightServer.ts b/src/remote/playwrightServer.ts index f0b44c289b..14880cdb24 100644 --- a/src/remote/playwrightServer.ts +++ b/src/remote/playwrightServer.ts @@ -48,11 +48,11 @@ export class PlaywrightServer { ws.on('message', message => dispatcherConnection.dispatch(JSON.parse(message.toString()))); ws.on('close', () => { debugLog('Client closed'); - this._onDisconnect(); + this._onDisconnect().catch(debugLog); }); ws.on('error', error => { debugLog('Client error ' + error); - this._onDisconnect(); + this._onDisconnect().catch(debugLog); }); dispatcherConnection.onmessage = message => ws.send(JSON.stringify(message)); new PlaywrightDispatcher(dispatcherConnection.rootDispatcher(), createPlaywright()); diff --git a/src/server/android/android.ts b/src/server/android/android.ts index 3e98f84c7e..b477470ab7 100644 --- a/src/server/android/android.ts +++ b/src/server/android/android.ts @@ -43,7 +43,7 @@ export interface Backend { export interface DeviceBackend { serial: string; status: string; - close(): Promise; + close(): void; init(): Promise; runCommand(command: string): Promise; open(command: string): Promise; @@ -51,7 +51,7 @@ export interface DeviceBackend { export interface SocketBackend extends EventEmitter { write(data: Buffer): Promise; - close(): Promise; + close(): void; } export class Android extends SdkObject { @@ -176,7 +176,7 @@ export class AndroidDevice extends SdkObject { await this.installApk(await readFileAsync(require.resolve(`../../../bin/${file}`))); debug('pw:android')('Starting the new driver'); - this.shell('am instrument -w com.microsoft.playwright.androiddriver.test/androidx.test.runner.AndroidJUnitRunner'); + this.shell('am instrument -w com.microsoft.playwright.androiddriver.test/androidx.test.runner.AndroidJUnitRunner').catch(e => debug('pw:android')(e)); const socket = await this._waitForLocalAbstract('playwright_android_driver_socket'); const transport = new Transport(socket, socket, socket, 'be'); transport.onmessage = message => { @@ -301,7 +301,7 @@ export class AndroidDevice extends SdkObject { await installSocket.write(content); const success = await new Promise(f => installSocket.on('data', f)); debug('pw:android')('Written driver bytes: ' + success); - await installSocket.close(); + installSocket.close(); } async push(content: Buffer, path: string, mode = 0o644): Promise { @@ -325,7 +325,7 @@ export class AndroidDevice extends SdkObject { const code = result.slice(0, 4).toString(); if (code !== 'OKAY') throw new Error('Could not push: ' + code); - await socket.close(); + socket.close(); } private async _refreshWebViews() { @@ -420,7 +420,7 @@ Sec-WebSocket-Version: 13\r } async close() { - await this._socket!.close(); + this._socket!.close(); } } diff --git a/src/server/android/backendAdb.ts b/src/server/android/backendAdb.ts index 2ce9915af0..1927994b51 100644 --- a/src/server/android/backendAdb.ts +++ b/src/server/android/backendAdb.ts @@ -75,7 +75,7 @@ async function runCommand(command: string, serial?: string): Promise { } else { commandOutput = await socket.readAll(); } - await socket.close(); + socket.close(); return commandOutput; } @@ -138,7 +138,7 @@ class BufferedSocketWrapper extends EventEmitter implements SocketBackend { await new Promise(f => this._socket.write(data, f)); } - async close() { + close() { if (this._isClosed) return; debug('pw:adb')('Close ' + this._command); diff --git a/src/server/chromium/crDevTools.ts b/src/server/chromium/crDevTools.ts index cec6124160..6dae9754f2 100644 --- a/src/server/chromium/crDevTools.ts +++ b/src/server/chromium/crDevTools.ts @@ -33,7 +33,7 @@ export class CRDevTools { this._savePromise = Promise.resolve(); } - async install(session: CRSession) { + install(session: CRSession) { session.on('Runtime.bindingCalled', async event => { if (event.name !== kBindingName) return; @@ -66,7 +66,7 @@ export class CRDevTools { contextId: event.executionContextId }).catch(e => null); }); - await Promise.all([ + Promise.all([ session.send('Runtime.enable'), session.send('Runtime.addBinding', { name: kBindingName }), session.send('Page.enable'), diff --git a/src/server/chromium/crPage.ts b/src/server/chromium/crPage.ts index 3ea29466aa..d65e70633d 100644 --- a/src/server/chromium/crPage.ts +++ b/src/server/chromium/crPage.ts @@ -646,11 +646,10 @@ class FrameSession { session.once('Runtime.executionContextCreated', async event => { worker._createExecutionContext(new CRExecutionContext(session, event.context)); }); - Promise.all([ - session._sendMayFail('Runtime.enable'), - session._sendMayFail('Network.enable'), - session._sendMayFail('Runtime.runIfWaitingForDebugger'), - ]); // This might fail if the target is closed before we initialize. + // This might fail if the target is closed before we initialize. + session._sendMayFail('Runtime.enable'); + session._sendMayFail('Network.enable'); + session._sendMayFail('Runtime.runIfWaitingForDebugger'); session.on('Runtime.consoleAPICalled', event => { const args = event.args.map(o => worker._existingExecutionContext!.createHandle(o)); this._page._addConsoleMessage(event.type, args, toConsoleMessageLocation(event.stackTrace)); diff --git a/src/server/download.ts b/src/server/download.ts index 091fa9d454..86f7252d65 100644 --- a/src/server/download.ts +++ b/src/server/download.ts @@ -83,7 +83,7 @@ export class Download { throw new Error('Download not found on disk. Check download.failure() for details.'); if (this._finished) { - saveCallback(path.join(this._downloadsPath, this._uuid)); + saveCallback(path.join(this._downloadsPath, this._uuid)).catch(e => {}); return; } this._saveCallbacks.push(saveCallback); @@ -117,7 +117,7 @@ export class Download { const fileName = path.join(this._downloadsPath, this._uuid); await util.promisify(fs.unlink)(fileName).catch(e => {}); } - this._reportFinished('Download deleted upon browser context closure.'); + await this._reportFinished('Download deleted upon browser context closure.'); } async _reportFinished(error?: string) { @@ -128,7 +128,7 @@ export class Download { if (error) { for (const callback of this._saveCallbacks) - callback('', error); + await callback('', error); } else { const fullPath = path.join(this._downloadsPath, this._uuid); for (const callback of this._saveCallbacks) diff --git a/src/server/firefox/ffExecutionContext.ts b/src/server/firefox/ffExecutionContext.ts index 7af3563c31..293204ca4e 100644 --- a/src/server/firefox/ffExecutionContext.ts +++ b/src/server/firefox/ffExecutionContext.ts @@ -90,7 +90,7 @@ export class FFExecutionContext implements js.ExecutionContextDelegate { await this._session.send('Runtime.disposeObject', { executionContextId: this._executionContextId, objectId: handle._objectId, - }).catch(error => {}); + }); } } diff --git a/src/server/firefox/ffPage.ts b/src/server/firefox/ffPage.ts index 1889d32319..89469e940e 100644 --- a/src/server/firefox/ffPage.ts +++ b/src/server/firefox/ffPage.ts @@ -232,14 +232,14 @@ export class FFPage implements PageDelegate { const context = this._contextIdToContext.get(event.executionContextId)!; const pageOrError = await this.pageOrError(); if (!(pageOrError instanceof Error)) - this._page._onBindingCalled(event.payload, context); + await this._page._onBindingCalled(event.payload, context); } async _onFileChooserOpened(payload: Protocol.Page.fileChooserOpenedPayload) { const {executionContextId, element} = payload; const context = this._contextIdToContext.get(executionContextId)!; const handle = context.createHandle(element).asElement()!; - this._page._onFileChooserOpened(handle); + await this._page._onFileChooserOpened(handle); } async _onWorkerCreated(event: Protocol.Page.workerCreatedPayload) { @@ -267,7 +267,7 @@ export class FFPage implements PageDelegate { // Note: we receive worker exceptions directly from the page. } - async _onWorkerDestroyed(event: Protocol.Page.workerDestroyedPayload) { + _onWorkerDestroyed(event: Protocol.Page.workerDestroyedPayload) { const workerId = event.workerId; const worker = this._workers.get(workerId); if (!worker) diff --git a/src/server/javascript.ts b/src/server/javascript.ts index 2eac1a143a..bb4a3f201f 100644 --- a/src/server/javascript.ts +++ b/src/server/javascript.ts @@ -160,11 +160,11 @@ export class JSHandle extends SdkObject { return null; } - async dispose() { + dispose() { if (this._disposed) return; this._disposed = true; - await this._context._delegate.releaseHandle(this); + this._context._delegate.releaseHandle(this).catch(e => {}); } toString(): string { diff --git a/src/server/progress.ts b/src/server/progress.ts index cf146a597d..12ad76b1a7 100644 --- a/src/server/progress.ts +++ b/src/server/progress.ts @@ -106,7 +106,7 @@ export class ProgressController { return result; } catch (e) { this._state = 'aborted'; - await Promise.all(this._cleanups.splice(0).map(cleanup => runCleanup(cleanup))); + await Promise.all(this._cleanups.splice(0).map(runCleanup)); throw e; } finally { clearTimeout(timer); diff --git a/src/server/trace/recorder/tracer.ts b/src/server/trace/recorder/tracer.ts index 05c21524d3..a179f11c6c 100644 --- a/src/server/trace/recorder/tracer.ts +++ b/src/server/trace/recorder/tracer.ts @@ -209,7 +209,7 @@ class ContextTracer { async dispose() { this._disposed = true; helper.removeEventListeners(this._eventListeners); - this._snapshotter.dispose(); + await this._snapshotter.dispose(); const event: trace.ContextDestroyedTraceEvent = { timestamp: monotonicTime(), type: 'context-destroyed', @@ -219,7 +219,6 @@ class ContextTracer { // Ensure all writes are finished. await this._appendEventChain; - await this._snapshotter.dispose(); } private _appendTraceEvent(event: any) { diff --git a/src/server/webkit/wkExecutionContext.ts b/src/server/webkit/wkExecutionContext.ts index 4cabce197c..37b8186468 100644 --- a/src/server/webkit/wkExecutionContext.ts +++ b/src/server/webkit/wkExecutionContext.ts @@ -143,7 +143,7 @@ export class WKExecutionContext implements js.ExecutionContextDelegate { async releaseHandle(handle: js.JSHandle): Promise { if (!handle._objectId) return; - await this._session.send('Runtime.releaseObject', {objectId: handle._objectId}).catch(error => {}); + await this._session.send('Runtime.releaseObject', {objectId: handle._objectId}); } } diff --git a/src/server/webkit/wkPage.ts b/src/server/webkit/wkPage.ts index c3610a7a5d..18e2927ee6 100644 --- a/src/server/webkit/wkPage.ts +++ b/src/server/webkit/wkPage.ts @@ -113,7 +113,7 @@ export class WKPage implements PageDelegate { promises.push(this.updateHttpCredentials()); if (this._browserContext._permissions.size) { for (const [key, value] of this._browserContext._permissions) - this._grantPermissions(key, value); + promises.push(this._grantPermissions(key, value)); } if (this._browserContext._options.recordVideo) { const size = this._browserContext._options.recordVideo.size || this._browserContext._options.viewport || { width: 1280, height: 720 };