fix: leaking route handlers when times is used in Page.route (#9234)

This commit is contained in:
Max Schmitt 2021-09-30 12:37:05 +02:00 committed by GitHub
parent cf12a1a97e
commit 7c89bc162a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 22 additions and 8 deletions

View file

@ -141,14 +141,20 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel,
} }
_onRoute(route: network.Route, request: network.Request) { _onRoute(route: network.Route, request: network.Request) {
let handled = false;
for (const routeHandler of this._routes) { for (const routeHandler of this._routes) {
if (routeHandler.matches(request.url())) { if (routeHandler.matches(request.url())) {
routeHandler.handle(route, request); routeHandler.handle(route, request);
return; handled = true;
break;
} }
} }
// it can race with BrowserContext.close() which then throws since its closed if (!handled) {
route.continue().catch(() => {}); // it can race with BrowserContext.close() which then throws since its closed
route.continue().catch(() => {});
} else {
this._routes = this._routes.filter(route => !route.expired());
}
} }
async _onBinding(bindingCall: BindingCall) { async _onBinding(bindingCall: BindingCall) {

View file

@ -626,15 +626,18 @@ export class RouteHandler {
this.handler = handler; this.handler = handler;
} }
public expired(): boolean {
return !!this._times && this.handledCount >= this._times;
}
public matches(requestURL: string): boolean { public matches(requestURL: string): boolean {
if (this._times && this.handledCount >= this._times)
return false;
return urlMatches(this._baseURL, requestURL, this.url); return urlMatches(this._baseURL, requestURL, this.url);
} }
public handle(route: Route, request: Request) { public handle(route: Route, request: Request) {
this.handler(route, request); this.handler(route, request);
this.handledCount++; if (this._times)
this.handledCount++;
} }
} }

View file

@ -169,13 +169,18 @@ export class Page extends ChannelOwner<channels.PageChannel, channels.PageInitia
} }
private _onRoute(route: Route, request: Request) { private _onRoute(route: Route, request: Request) {
let handled = false;
for (const routeHandler of this._routes) { for (const routeHandler of this._routes) {
if (routeHandler.matches(request.url())) { if (routeHandler.matches(request.url())) {
routeHandler.handle(route, request); routeHandler.handle(route, request);
return; handled = true;
break;
} }
} }
this._browserContext._onRoute(route, request); if (!handled)
this._browserContext._onRoute(route, request);
else
this._routes = this._routes.filter(route => !route.expired());
} }
async _onBinding(bindingCall: BindingCall) { async _onBinding(bindingCall: BindingCall) {