fix(api): Response.finished() throws when target closes (#20453)

This commit is contained in:
Dmitry Gozman 2023-01-27 10:42:43 -08:00 committed by GitHub
parent faadbba63c
commit ead4989947
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 12 additions and 4 deletions

View file

@ -35,6 +35,7 @@ import { APIResponse } from './fetch';
import type { Serializable } from '../../types/structs'; import type { Serializable } from '../../types/structs';
import type { BrowserContext } from './browserContext'; import type { BrowserContext } from './browserContext';
import { HarRouter } from './harRouter'; import { HarRouter } from './harRouter';
import { kBrowserOrContextClosedError } from '../common/errors';
export type NetworkCookie = { export type NetworkCookie = {
name: string, name: string,
@ -271,6 +272,10 @@ export class Request extends ChannelOwner<channels.RequestChannel> implements ap
_fallbackOverridesForContinue() { _fallbackOverridesForContinue() {
return this._fallbackOverrides; return this._fallbackOverrides;
} }
_targetClosedPromise(): Promise<void> {
return this.serviceWorker()?._closedPromise || this.frame()._page?._closedOrCrashedPromise || new Promise(() => {});
}
} }
export class Route extends ChannelOwner<channels.RouteChannel> implements api.Route { export class Route extends ChannelOwner<channels.RouteChannel> implements api.Route {
@ -294,7 +299,7 @@ export class Route extends ChannelOwner<channels.RouteChannel> implements api.Ro
// does not have a Page initialized just yet. // does not have a Page initialized just yet.
return Promise.race([ return Promise.race([
promise, promise,
this.request().serviceWorker()?._closedPromise || this.request().frame()._page?._closedOrCrashedPromise || Promise.resolve(), this.request()._targetClosedPromise(),
]); ]);
} }
@ -520,7 +525,12 @@ export class Response extends ChannelOwner<channels.ResponseChannel> implements
} }
async finished(): Promise<null> { async finished(): Promise<null> {
return this._finishedPromise.then(() => null); return Promise.race([
this._finishedPromise.then(() => null),
this.request()._targetClosedPromise().then(() => {
throw new Error(kBrowserOrContextClosedError);
}),
]);
} }
async body(): Promise<Buffer> { async body(): Promise<Buffer> {

View file

@ -109,7 +109,6 @@ it('should wait until response completes', async ({ page, server }) => {
}); });
it('should reject response.finished if page closes', async ({ page, server }) => { it('should reject response.finished if page closes', async ({ page, server }) => {
it.fixme();
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
server.setRoute('/get', (req, res) => { server.setRoute('/get', (req, res) => {
// In Firefox, |fetch| will be hanging until it receives |Content-Type| header // In Firefox, |fetch| will be hanging until it receives |Content-Type| header
@ -130,7 +129,6 @@ it('should reject response.finished if page closes', async ({ page, server }) =>
}); });
it('should reject response.finished if context closes', async ({ page, server }) => { it('should reject response.finished if context closes', async ({ page, server }) => {
it.fixme();
await page.goto(server.EMPTY_PAGE); await page.goto(server.EMPTY_PAGE);
server.setRoute('/get', (req, res) => { server.setRoute('/get', (req, res) => {
// In Firefox, |fetch| will be hanging until it receives |Content-Type| header // In Firefox, |fetch| will be hanging until it receives |Content-Type| header