chore: add dispose to core/UserContext (#11727)

This commit is contained in:
jrandolf 2024-01-24 10:09:24 +01:00 committed by GitHub
parent 9df9ede0b7
commit bc7bd01d85
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 46 additions and 11 deletions

View File

@ -8,6 +8,8 @@ import type * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
import {EventEmitter} from '../../common/EventEmitter.js'; import {EventEmitter} from '../../common/EventEmitter.js';
import {assert} from '../../util/assert.js'; import {assert} from '../../util/assert.js';
import {throwIfDisposed} from '../../util/decorators.js';
import {DisposableStack, disposeSymbol} from '../../util/disposable.js';
import type {Browser} from './Browser.js'; import type {Browser} from './Browser.js';
import {BrowsingContext} from './BrowsingContext.js'; import {BrowsingContext} from './BrowsingContext.js';
@ -41,11 +43,13 @@ export class UserContext extends EventEmitter<{
} }
// keep-sorted start // keep-sorted start
#reason?: string;
// Note these are only top-level contexts. // Note these are only top-level contexts.
readonly #browsingContexts = new Map<string, BrowsingContext>(); readonly #browsingContexts = new Map<string, BrowsingContext>();
// @ts-expect-error -- TODO: This will be used once the WebDriver BiDi // @ts-expect-error -- TODO: This will be used once the WebDriver BiDi
// protocol supports it. // protocol supports it.
readonly #id: string; readonly #id: string;
readonly #disposables = new DisposableStack();
readonly browser: Browser; readonly browser: Browser;
// keep-sorted end // keep-sorted end
@ -59,11 +63,13 @@ export class UserContext extends EventEmitter<{
} }
#initialize() { #initialize() {
// /////////////////////// // ////////////////////
// Session listeners // // Session listeners //
// /////////////////////// // ////////////////////
const session = this.#session; const sessionEmitter = this.#disposables.use(
session.on('browsingContext.contextCreated', info => { new EventEmitter(this.#session)
);
sessionEmitter.on('browsingContext.contextCreated', info => {
if (info.parent) { if (info.parent) {
return; return;
} }
@ -74,12 +80,15 @@ export class UserContext extends EventEmitter<{
info.context, info.context,
info.url info.url
); );
browsingContext.on('destroyed', () => { this.#browsingContexts.set(browsingContext.id, browsingContext);
const browsingContextEmitter = this.#disposables.use(
new EventEmitter(browsingContext)
);
browsingContextEmitter.on('destroyed', () => {
this.#browsingContexts.delete(browsingContext.id); this.#browsingContexts.delete(browsingContext.id);
}); });
this.#browsingContexts.set(browsingContext.id, browsingContext);
this.emit('browsingcontext', {browsingContext}); this.emit('browsingcontext', {browsingContext});
}); });
} }
@ -91,8 +100,20 @@ export class UserContext extends EventEmitter<{
get browsingContexts(): Iterable<BrowsingContext> { get browsingContexts(): Iterable<BrowsingContext> {
return this.#browsingContexts.values(); return this.#browsingContexts.values();
} }
get disposed(): boolean {
return Boolean(this.#reason);
}
// keep-sorted end // keep-sorted end
dispose(reason?: string): void {
this.#reason = reason;
this[disposeSymbol]();
}
@throwIfDisposed<UserContext>(context => {
// SAFETY: Disposal implies this exists.
return context.#reason!;
})
async createBrowsingContext( async createBrowsingContext(
type: Bidi.BrowsingContext.CreateType, type: Bidi.BrowsingContext.CreateType,
options: CreateBrowsingContextOptions = {} options: CreateBrowsingContextOptions = {}
@ -121,5 +142,17 @@ export class UserContext extends EventEmitter<{
promises.push(browsingContext.close()); promises.push(browsingContext.close());
} }
await Promise.all(promises); await Promise.all(promises);
this.dispose('User context was closed.');
}
[disposeSymbol](): void {
super[disposeSymbol]();
if (this.#reason === undefined) {
this.#reason =
'User context was destroyed, probably because browser disconnected/closed.';
}
this.#disposables.dispose();
} }
} }

View File

@ -64,11 +64,13 @@ export class UserPrompt extends EventEmitter<{
} }
#initialize() { #initialize() {
// /////////////////////// // ////////////////////
// Session listeners // // Session listeners //
// /////////////////////// // ////////////////////
const session = this.#disposables.use(new EventEmitter(this.#session)); const sessionEmitter = this.#disposables.use(
session.on('browsingContext.userPromptClosed', parameters => { new EventEmitter(this.#session)
);
sessionEmitter.on('browsingContext.userPromptClosed', parameters => {
if (parameters.context !== this.browsingContext.id) { if (parameters.context !== this.browsingContext.id) {
return; return;
} }