refactor: change target promises to be deferred (#10191)

This commit is contained in:
Alex Rudenko 2023-05-16 17:18:22 +02:00 committed by GitHub
parent 354ac3bfc8
commit 5a5e4d46a3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 37 additions and 41 deletions

View File

@ -39,7 +39,13 @@ import {ChromeTargetManager} from './ChromeTargetManager.js';
import {CDPSession, Connection, ConnectionEmittedEvents} from './Connection.js';
import {FirefoxTargetManager} from './FirefoxTargetManager.js';
import {Viewport} from './PuppeteerViewport.js';
import {OtherTarget, PageTarget, Target, WorkerTarget} from './Target.js';
import {
InitializationStatus,
OtherTarget,
PageTarget,
Target,
WorkerTarget,
} from './Target.js';
import {TargetManager, TargetManagerEmittedEvents} from './TargetManager.js';
import {TaskQueue} from './TaskQueue.js';
import {waitWithTimeout} from './util.js';
@ -364,8 +370,8 @@ export class CDPBrowser extends BrowserBase {
};
#onDetachedFromTarget = async (target: Target): Promise<void> => {
target._initializedCallback(false);
target._closedCallback();
target._initializedPromise.resolve(InitializationStatus.ABORTED);
target._isClosedPromise.resolve();
if (await target._initializedPromise) {
this.emit(BrowserEmittedEvents.TargetDestroyed, target);
target
@ -447,7 +453,7 @@ export class CDPBrowser extends BrowserBase {
return Array.from(
this.#targetManager.getAvailableTargets().values()
).filter(target => {
return target._isInitialized;
return target._initializedPromise.resolved();
});
}

View File

@ -22,7 +22,7 @@ import {createDeferredPromise} from '../util/DeferredPromise.js';
import {CDPSession, Connection} from './Connection.js';
import {EventEmitter} from './EventEmitter.js';
import {Target} from './Target.js';
import {InitializationStatus, Target} from './Target.js';
import {
TargetInterceptor,
TargetFactory,
@ -267,7 +267,8 @@ export class ChromeTargetManager extends EventEmitter implements TargetManager {
return;
}
const previousURL = target.url();
const wasInitialized = target._isInitialized;
const wasInitialized =
target._initializedPromise.value() === InitializationStatus.SUCCESS;
target._targetInfoChanged(event.targetInfo);

View File

@ -19,6 +19,7 @@ import {Protocol} from 'devtools-protocol';
import type {Browser} from '../api/Browser.js';
import type {BrowserContext} from '../api/BrowserContext.js';
import {Page, PageEmittedEvents} from '../api/Page.js';
import {createDeferredPromise} from '../util/DeferredPromise.js';
import {CDPSession} from './Connection.js';
import {CDPPage} from './Page.js';
@ -28,6 +29,14 @@ import {TaskQueue} from './TaskQueue.js';
import {debugError} from './util.js';
import {WebWorker} from './WebWorker.js';
/**
* @internal
*/
export enum InitializationStatus {
SUCCESS = 'success',
ABORTED = 'aborted',
}
/**
* Target represents a
* {@link https://chromedevtools.github.io/devtools-protocol/tot/Target/ | CDP target}.
@ -40,35 +49,22 @@ export class Target {
#browserContext: BrowserContext;
#session?: CDPSession;
#targetInfo: Protocol.Target.TargetInfo;
#targetManager: TargetManager;
#sessionFactory: (isAutoAttachEmulated: boolean) => Promise<CDPSession>;
/**
* @internal
*/
_initializedPromise: Promise<boolean>;
_initializedPromise = createDeferredPromise<InitializationStatus>();
/**
* @internal
*/
_initializedCallback!: (x: boolean) => void;
/**
* @internal
*/
_isClosedPromise: Promise<void>;
/**
* @internal
*/
_closedCallback!: () => void;
/**
* @internal
*/
_isInitialized = false;
_isClosedPromise = createDeferredPromise<void>();
/**
* @internal
*/
_targetId: string;
#targetManager: TargetManager;
/**
* @internal
*/
@ -85,12 +81,6 @@ export class Target {
this.#browserContext = browserContext;
this._targetId = targetInfo.targetId;
this.#sessionFactory = sessionFactory;
this._initializedPromise = new Promise<boolean>(fulfill => {
return (this._initializedCallback = fulfill);
});
this._isClosedPromise = new Promise<void>(fulfill => {
return (this._closedCallback = fulfill);
});
this._initialize();
}
@ -208,21 +198,15 @@ export class Target {
* @internal
*/
protected _initialize(): void {
// TODO: refactor to deferred promises.
this._isInitialized = true;
if (this._isInitialized) {
this._initializedCallback(true);
}
this._initializedPromise.resolve(InitializationStatus.SUCCESS);
}
/**
* @internal
*/
protected _checkIfInitialized(): void {
if (!this._isInitialized) {
this._isInitialized = true;
this._initializedCallback(true);
return;
if (!this._initializedPromise.resolved()) {
this._initializedPromise.resolve(InitializationStatus.SUCCESS);
}
}
@ -309,12 +293,11 @@ export class PageTarget extends Target {
}
override _checkIfInitialized(): void {
if (this._isInitialized) {
if (this._initializedPromise.resolved()) {
return;
}
this._isInitialized = this._getTargetInfo().url !== '';
if (this._isInitialized) {
this._initializedCallback(true);
if (this._getTargetInfo().url !== '') {
this._initializedPromise.resolve(InitializationStatus.SUCCESS);
}
}
}

View File

@ -8,6 +8,7 @@ export interface DeferredPromise<T> extends Promise<T> {
resolved: () => boolean;
resolve: (value: T) => void;
reject: (reason?: unknown) => void;
value: () => T | undefined;
}
/**
@ -32,6 +33,7 @@ export function createDeferredPromise<T>(
): DeferredPromise<T> {
let isResolved = false;
let isRejected = false;
let _value: T | undefined;
let resolver: (value: T) => void;
let rejector: (reason?: unknown) => void;
const taskPromise = new Promise<T>((resolve, reject) => {
@ -57,6 +59,7 @@ export function createDeferredPromise<T>(
clearTimeout(timeoutId);
}
isResolved = true;
_value = value;
resolver(value);
},
reject: (err?: unknown) => {
@ -64,5 +67,8 @@ export function createDeferredPromise<T>(
isRejected = true;
rejector(err);
},
value: () => {
return _value;
},
});
}