Skip to content

Commit 09ff7ea

Browse files
authored
chore: throw on context.close() if it was closed externally (#21347)
1 parent 57624bc commit 09ff7ea

File tree

3 files changed

+23
-49
lines changed

3 files changed

+23
-49
lines changed

packages/playwright-core/src/client/browserContext.ts

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import { Waiter } from './waiter';
3030
import type { URLMatch, Headers, WaitForEventOptions, BrowserContextOptions, StorageState, LaunchOptions } from './types';
3131
import { headersObjectToArray, isRegExp, isString } from '../utils';
3232
import { mkdirIfNeeded } from '../utils/fileUtils';
33-
import { isSafeCloseError } from '../common/errors';
3433
import type * as api from '../../types/types';
3534
import type * as structs from '../../types/structs';
3635
import { CDPSession } from './cdpSession';
@@ -59,6 +58,7 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
5958
readonly _serviceWorkers = new Set<Worker>();
6059
readonly _isChromium: boolean;
6160
private _harRecorders = new Map<string, { path: string, content: 'embed' | 'attach' | 'omit' | undefined }>();
61+
private _closeWasCalled = false;
6262

6363
static from(context: channels.BrowserContextChannel): BrowserContext {
6464
return (context as any)._object;
@@ -344,31 +344,28 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
344344
}
345345

346346
async close(): Promise<void> {
347-
try {
348-
await this._wrapApiCall(async () => {
349-
await this._browserType?._onWillCloseContext?.(this);
350-
for (const [harId, harParams] of this._harRecorders) {
351-
const har = await this._channel.harExport({ harId });
352-
const artifact = Artifact.from(har.artifact);
353-
// Server side will compress artifact if content is attach or if file is .zip.
354-
const isCompressed = harParams.content === 'attach' || harParams.path.endsWith('.zip');
355-
const needCompressed = harParams.path.endsWith('.zip');
356-
if (isCompressed && !needCompressed) {
357-
await artifact.saveAs(harParams.path + '.tmp');
358-
await this._connection.localUtils()._channel.harUnzip({ zipFile: harParams.path + '.tmp', harFile: harParams.path });
359-
} else {
360-
await artifact.saveAs(harParams.path);
361-
}
362-
await artifact.delete();
347+
if (this._closeWasCalled)
348+
return;
349+
this._closeWasCalled = true;
350+
await this._wrapApiCall(async () => {
351+
await this._browserType?._onWillCloseContext?.(this);
352+
for (const [harId, harParams] of this._harRecorders) {
353+
const har = await this._channel.harExport({ harId });
354+
const artifact = Artifact.from(har.artifact);
355+
// Server side will compress artifact if content is attach or if file is .zip.
356+
const isCompressed = harParams.content === 'attach' || harParams.path.endsWith('.zip');
357+
const needCompressed = harParams.path.endsWith('.zip');
358+
if (isCompressed && !needCompressed) {
359+
await artifact.saveAs(harParams.path + '.tmp');
360+
await this._connection.localUtils()._channel.harUnzip({ zipFile: harParams.path + '.tmp', harFile: harParams.path });
361+
} else {
362+
await artifact.saveAs(harParams.path);
363363
}
364-
}, true);
365-
await this._channel.close();
366-
await this._closedPromise;
367-
} catch (e) {
368-
if (isSafeCloseError(e))
369-
return;
370-
throw e;
371-
}
364+
await artifact.delete();
365+
}
366+
}, true);
367+
await this._channel.close();
368+
await this._closedPromise;
372369
}
373370

374371
async _enableRecorder(params: {

packages/playwright-core/src/client/page.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -532,7 +532,7 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
532532
else
533533
await this._channel.close(options);
534534
} catch (e) {
535-
if (isSafeCloseError(e))
535+
if (isSafeCloseError(e) && !options.runBeforeUnload)
536536
return;
537537
throw e;
538538
}

tests/library/browsertype-connect.spec.ts

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -426,29 +426,6 @@ for (const kind of ['launchServer', 'run-server'] as const) {
426426
await browser.close();
427427
});
428428

429-
test('should not throw on context.close after disconnect', async ({ connect, startRemoteServer }) => {
430-
const remoteServer = await startRemoteServer(kind);
431-
const browser = await connect(remoteServer.wsEndpoint());
432-
const context = await browser.newContext();
433-
await context.newPage();
434-
await Promise.all([
435-
new Promise(f => browser.on('disconnected', f)),
436-
remoteServer.close()
437-
]);
438-
await context.close();
439-
});
440-
441-
test('should not throw on page.close after disconnect', async ({ connect, startRemoteServer }) => {
442-
const remoteServer = await startRemoteServer(kind);
443-
const browser = await connect(remoteServer.wsEndpoint());
444-
const page = await browser.newPage();
445-
await Promise.all([
446-
new Promise(f => browser.on('disconnected', f)),
447-
remoteServer.close()
448-
]);
449-
await page.close();
450-
});
451-
452429
test('should saveAs videos from remote browser', async ({ connect, startRemoteServer }, testInfo) => {
453430
const remoteServer = await startRemoteServer(kind);
454431
const browser = await connect(remoteServer.wsEndpoint());

0 commit comments

Comments
 (0)