fix: interrupt request.allHeaders()/response() on page.close() (#27695)

Reference https://github.com/microsoft/playwright/issues/27227
This commit is contained in:
Yury Semikhatsky 2023-10-23 12:45:35 -07:00 committed by GitHub
parent 5752a28f87
commit 5e51a734e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 3 deletions

View File

@ -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<HeadersArray> {
return this._overrides?.headers || this._rawRequestHeadersPromise;
return this._overrides?.headers || this._targetClosedScope().race(this._rawRequestHeadersPromise);
}
response(): PromiseLike<Response | null> {
return this._waitForResponsePromise;
return this._targetClosedScope().race(this._waitForResponsePromise);
}
_existingResponse(): Response | null {

View File

@ -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);
});