From 5e51a734e749eb84a589ec819e4cc14063a95982 Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Mon, 23 Oct 2023 12:45:35 -0700 Subject: [PATCH] fix: interrupt request.allHeaders()/response() on page.close() (#27695) Reference https://github.com/microsoft/playwright/issues/27227 --- .../playwright-core/src/server/network.ts | 10 ++++++--- tests/page/page-event-network.spec.ts | 21 +++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/packages/playwright-core/src/server/network.ts b/packages/playwright-core/src/server/network.ts index fdf0573ac3..6f4d09d76c 100644 --- a/packages/playwright-core/src/server/network.ts +++ b/packages/playwright-core/src/server/network.ts @@ -20,7 +20,7 @@ import type * as frames from './frames'; import type * as types from './types'; import type * as channels from '@protocol/channels'; import { assert } from '../utils'; -import { ManualPromise } from '../utils/manualPromise'; +import { LongStandingScope, ManualPromise } from '../utils/manualPromise'; import { SdkObject } from './instrumentation'; import type { HeadersArray, NameValue } from '../common/types'; import { APIRequestContext } from './fetch'; @@ -129,6 +129,10 @@ export class Request extends SdkObject { this._isFavicon = url.endsWith('/favicon.ico') || !!redirectedFrom?._isFavicon; } + private _targetClosedScope(): LongStandingScope { + return this._serviceWorker?.openScope || this._frame?._page.openScope || new LongStandingScope(); + } + _setFailureText(failureText: string) { this._failureText = failureText; this._waitForResponsePromise.resolve(null); @@ -179,11 +183,11 @@ export class Request extends SdkObject { } async rawRequestHeaders(): Promise { - return this._overrides?.headers || this._rawRequestHeadersPromise; + return this._overrides?.headers || this._targetClosedScope().race(this._rawRequestHeadersPromise); } response(): PromiseLike { - return this._waitForResponsePromise; + return this._targetClosedScope().race(this._waitForResponsePromise); } _existingResponse(): Response | null { diff --git a/tests/page/page-event-network.spec.ts b/tests/page/page-event-network.spec.ts index e7004f576a..8aa1462d5a 100644 --- a/tests/page/page-event-network.spec.ts +++ b/tests/page/page-event-network.spec.ts @@ -17,6 +17,7 @@ import type { ServerResponse } from 'http'; import { test as it, expect } from './pageTest'; +import { kTargetClosedErrorMessage } from '../config/errors'; it('Page.Events.Request @smoke', async ({ page, server }) => { const requests = []; @@ -137,3 +138,23 @@ it('should resolve responses after a navigation', async ({ page, server, browser // the response should resolve to null, because the page navigated. expect(await responsePromise).toBe(null); }); + +it('interrupt request.response() and request.allHeaders() on page.close', async ({ page, server, browserName }) => { + it.info().annotations.push({ type: 'issue', description: 'https://github.com/microsoft/playwright/issues/27227' }); + server.setRoute('/one-style.css', (req, res) => { + res.setHeader('Content-Type', 'text/css'); + }); + const reqPromise = page.waitForRequest('**/one-style.css'); + await page.goto(server.PREFIX + '/one-style.html', { waitUntil: 'domcontentloaded' }); + const req = await reqPromise; + const respPromise = req.response().catch(e => e); + const headersPromise = req.allHeaders().catch(e => e); + await page.close(); + expect((await respPromise).message).toContain(kTargetClosedErrorMessage); + // All headers are the same as "provisional" headers in Firefox. + if (browserName === 'firefox') + expect((await headersPromise)['user-agent']).toBeTruthy(); + else + expect((await headersPromise).message).toContain(kTargetClosedErrorMessage); + +});