diff --git a/packages/puppeteer-core/src/api/Page.ts b/packages/puppeteer-core/src/api/Page.ts index b49f2bed..a3052797 100644 --- a/packages/puppeteer-core/src/api/Page.ts +++ b/packages/puppeteer-core/src/api/Page.ts @@ -40,11 +40,10 @@ import type {BidiNetworkManager} from '../bidi/NetworkManager.js'; import type {Accessibility} from '../cdp/Accessibility.js'; import type {Coverage} from '../cdp/Coverage.js'; import type {DeviceRequestPrompt} from '../cdp/DeviceRequestPrompt.js'; -import { - NetworkManagerEvent, - type NetworkManager as CdpNetworkManager, - type Credentials, - type NetworkConditions, +import type { + NetworkManager as CdpNetworkManager, + Credentials, + NetworkConditions, } from '../cdp/NetworkManager.js'; import type {Tracing} from '../cdp/Tracing.js'; import type {WebWorker} from '../cdp/WebWorker.js'; @@ -58,12 +57,14 @@ import { type Handler, } from '../common/EventEmitter.js'; import type {FileChooser} from '../common/FileChooser.js'; +import {NetworkManagerEvent} from '../common/NetworkManagerEvents.js'; import { paperFormats, type LowerCasePaperFormat, type ParsedPDFOptions, type PDFOptions, } from '../common/PDFOptions.js'; +import {TimeoutSettings} from '../common/TimeoutSettings.js'; import type { Awaitable, EvaluateFunc, @@ -603,6 +604,10 @@ export abstract class Page extends EventEmitter { * @internal */ _isDragging = false; + /** + * @internal + */ + _timeoutSettings = new TimeoutSettings(); #requestHandlers = new WeakMap, Handler>(); diff --git a/packages/puppeteer-core/src/bidi/NetworkManager.ts b/packages/puppeteer-core/src/bidi/NetworkManager.ts index 47de4fc2..8f5103ad 100644 --- a/packages/puppeteer-core/src/bidi/NetworkManager.ts +++ b/packages/puppeteer-core/src/bidi/NetworkManager.ts @@ -16,12 +16,11 @@ import type * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js'; -import {NetworkManagerEvent} from '../cdp/NetworkManager.js'; +import {EventEmitter, EventSubscription} from '../common/EventEmitter.js'; import { - EventEmitter, - EventSubscription, - type EventType, -} from '../common/EventEmitter.js'; + NetworkManagerEvent, + type NetworkManagerEvents, +} from '../common/NetworkManagerEvents.js'; import {DisposableStack} from '../util/disposable.js'; import type {BidiConnection} from './Connection.js'; @@ -33,18 +32,7 @@ import type {BidiPage} from './Page.js'; /** * @internal */ -export interface BidiNetworkManagerEvents extends Record { - [NetworkManagerEvent.Request]: BidiHTTPRequest; - [NetworkManagerEvent.RequestServedFromCache]: BidiHTTPRequest; - [NetworkManagerEvent.Response]: BidiHTTPResponse; - [NetworkManagerEvent.RequestFailed]: BidiHTTPRequest; - [NetworkManagerEvent.RequestFinished]: BidiHTTPRequest; -} - -/** - * @internal - */ -export class BidiNetworkManager extends EventEmitter { +export class BidiNetworkManager extends EventEmitter { #connection: BidiConnection; #page: BidiPage; #subscriptions = new DisposableStack(); diff --git a/packages/puppeteer-core/src/bidi/Page.ts b/packages/puppeteer-core/src/bidi/Page.ts index d7154834..0f0f34f4 100644 --- a/packages/puppeteer-core/src/bidi/Page.ts +++ b/packages/puppeteer-core/src/bidi/Page.ts @@ -33,7 +33,6 @@ import {Accessibility} from '../cdp/Accessibility.js'; import {Coverage} from '../cdp/Coverage.js'; import {EmulationManager as CdpEmulationManager} from '../cdp/EmulationManager.js'; import {FrameTree} from '../cdp/FrameTree.js'; -import {NetworkManagerEvent} from '../cdp/NetworkManager.js'; import {Tracing} from '../cdp/Tracing.js'; import { ConsoleMessage, @@ -45,15 +44,14 @@ import { TimeoutError, } from '../common/Errors.js'; import type {Handler} from '../common/EventEmitter.js'; +import {NetworkManagerEvent} from '../common/NetworkManagerEvents.js'; import type {PDFOptions} from '../common/PDFOptions.js'; -import {TimeoutSettings} from '../common/TimeoutSettings.js'; import type {Awaitable} from '../common/types.js'; import { debugError, evaluationString, - isString, validateDialogType, - waitForEvent, + waitForHTTP, waitWithTimeout, } from '../common/util.js'; import type {Viewport} from '../common/Viewport.js'; @@ -87,7 +85,6 @@ import {BidiSerializer} from './Serializer.js'; */ export class BidiPage extends Page { #accessibility: Accessibility; - #timeoutSettings = new TimeoutSettings(); #connection: BidiConnection; #frameTree = new FrameTree(); #networkManager: BidiNetworkManager; @@ -184,7 +181,7 @@ export class BidiPage extends Page { const frame = new BidiFrame( this, this.#browsingContext, - this.#timeoutSettings, + this._timeoutSettings, this.#browsingContext.parent ); this.#frameTree.addFrame(frame); @@ -356,7 +353,7 @@ export class BidiPage extends Page { const frame = new BidiFrame( this, context, - this.#timeoutSettings, + this._timeoutSettings, context.parent ); this.#frameTree.addFrame(frame); @@ -490,7 +487,7 @@ export class BidiPage extends Page { ): Promise { const { waitUntil = 'load', - timeout = this.#timeoutSettings.navigationTimeout(), + timeout = this._timeoutSettings.navigationTimeout(), } = options; const readinessState = lifeCycleToReadinessState.get( @@ -519,15 +516,15 @@ export class BidiPage extends Page { } override setDefaultNavigationTimeout(timeout: number): void { - this.#timeoutSettings.setDefaultNavigationTimeout(timeout); + this._timeoutSettings.setDefaultNavigationTimeout(timeout); } override setDefaultTimeout(timeout: number): void { - this.#timeoutSettings.setDefaultTimeout(timeout); + this._timeoutSettings.setDefaultTimeout(timeout); } override getDefaultTimeout(): number { - return this.#timeoutSettings.timeout(); + return this._timeoutSettings.timeout(); } override isJavaScriptEnabled(): boolean { @@ -691,21 +688,13 @@ export class BidiPage extends Page { | ((req: BidiHTTPRequest) => boolean | Promise), options: {timeout?: number} = {} ): Promise { - const {timeout = this.#timeoutSettings.timeout()} = options; - return await waitForEvent( + const {timeout = this._timeoutSettings.timeout()} = options; + return await waitForHTTP( this.#networkManager, NetworkManagerEvent.Request, - async request => { - if (isString(urlOrPredicate)) { - return urlOrPredicate === request.url(); - } - if (typeof urlOrPredicate === 'function') { - return !!(await urlOrPredicate(request)); - } - return false; - }, + urlOrPredicate, timeout, - this.#closedDeferred.valueOrThrow() + this.#closedDeferred ); } @@ -715,28 +704,20 @@ export class BidiPage extends Page { | ((res: BidiHTTPResponse) => boolean | Promise), options: {timeout?: number} = {} ): Promise { - const {timeout = this.#timeoutSettings.timeout()} = options; - return await waitForEvent( + const {timeout = this._timeoutSettings.timeout()} = options; + return await waitForHTTP( this.#networkManager, NetworkManagerEvent.Response, - async response => { - if (isString(urlOrPredicate)) { - return urlOrPredicate === response.url(); - } - if (typeof urlOrPredicate === 'function') { - return !!(await urlOrPredicate(response)); - } - return false; - }, + urlOrPredicate, timeout, - this.#closedDeferred.valueOrThrow() + this.#closedDeferred ); } override async waitForNetworkIdle( options: {idleTime?: number; timeout?: number} = {} ): Promise { - const {idleTime = 500, timeout = this.#timeoutSettings.timeout()} = options; + const {idleTime = 500, timeout = this._timeoutSettings.timeout()} = options; await this._waitForNetworkIdle( this.#networkManager, diff --git a/packages/puppeteer-core/src/cdp/HTTPRequest.ts b/packages/puppeteer-core/src/cdp/HTTPRequest.ts index 82f3bcca..754df524 100644 --- a/packages/puppeteer-core/src/cdp/HTTPRequest.ts +++ b/packages/puppeteer-core/src/cdp/HTTPRequest.ts @@ -28,16 +28,18 @@ import { type ResponseForRequest, STATUS_TEXTS, } from '../api/HTTPRequest.js'; -import type {HTTPResponse} from '../api/HTTPResponse.js'; import type {ProtocolError} from '../common/Errors.js'; import {debugError, isString} from '../common/util.js'; import {assert} from '../util/assert.js'; +import type {CdpHTTPResponse} from './HTTPResponse.js'; + /** * @internal */ export class CdpHTTPRequest extends HTTPRequest { declare _redirectChain: CdpHTTPRequest[]; + declare _response: CdpHTTPResponse | null; #client: CDPSession; #isNavigationRequest: boolean; @@ -191,7 +193,7 @@ export class CdpHTTPRequest extends HTTPRequest { return this.#headers; } - override response(): HTTPResponse | null { + override response(): CdpHTTPResponse | null { return this._response; } diff --git a/packages/puppeteer-core/src/cdp/LifecycleWatcher.ts b/packages/puppeteer-core/src/cdp/LifecycleWatcher.ts index 2395a7d8..26b97f14 100644 --- a/packages/puppeteer-core/src/cdp/LifecycleWatcher.ts +++ b/packages/puppeteer-core/src/cdp/LifecycleWatcher.ts @@ -17,17 +17,18 @@ import type Protocol from 'devtools-protocol'; import {type Frame, FrameEvent} from '../api/Frame.js'; +import type {HTTPRequest} from '../api/HTTPRequest.js'; import type {HTTPResponse} from '../api/HTTPResponse.js'; import type {TimeoutError} from '../common/Errors.js'; import {EventSubscription} from '../common/EventEmitter.js'; +import {NetworkManagerEvent} from '../common/NetworkManagerEvents.js'; import {assert} from '../util/assert.js'; import {Deferred} from '../util/Deferred.js'; import {DisposableStack} from '../util/disposable.js'; import type {CdpFrame} from './Frame.js'; import {FrameManagerEvent} from './FrameManager.js'; -import type {CdpHTTPRequest} from './HTTPRequest.js'; -import {type NetworkManager, NetworkManagerEvent} from './NetworkManager.js'; +import type {NetworkManager} from './NetworkManager.js'; /** * @public @@ -78,7 +79,7 @@ export class LifecycleWatcher { #expectedLifecycle: ProtocolLifeCycleEvent[]; #frame: CdpFrame; #timeout: number; - #navigationRequest: CdpHTTPRequest | null = null; + #navigationRequest: HTTPRequest | null = null; #subscriptions = new DisposableStack(); #initialLoaderId: string; @@ -184,7 +185,7 @@ export class LifecycleWatcher { this.#checkLifecycleComplete(); } - #onRequest(request: CdpHTTPRequest): void { + #onRequest(request: HTTPRequest): void { if (request.frame() !== this.#frame || !request.isNavigationRequest()) { return; } @@ -199,7 +200,7 @@ export class LifecycleWatcher { } } - #onRequestFailed(request: CdpHTTPRequest): void { + #onRequestFailed(request: HTTPRequest): void { if (this.#navigationRequest?._requestId !== request._requestId) { return; } diff --git a/packages/puppeteer-core/src/cdp/NetworkManager.test.ts b/packages/puppeteer-core/src/cdp/NetworkManager.test.ts index 5b310abe..67cced58 100644 --- a/packages/puppeteer-core/src/cdp/NetworkManager.test.ts +++ b/packages/puppeteer-core/src/cdp/NetworkManager.test.ts @@ -22,9 +22,10 @@ import type {CDPSessionEvents} from '../api/CDPSession.js'; import type {HTTPRequest} from '../api/HTTPRequest.js'; import type {HTTPResponse} from '../api/HTTPResponse.js'; import {EventEmitter} from '../common/EventEmitter.js'; +import {NetworkManagerEvent} from '../common/NetworkManagerEvents.js'; import type {CdpFrame} from './Frame.js'; -import {NetworkManager, NetworkManagerEvent} from './NetworkManager.js'; +import {NetworkManager} from './NetworkManager.js'; // TODO: develop a helper to generate fake network events for attributes that // are not relevant for the network manager to make tests shorter. diff --git a/packages/puppeteer-core/src/cdp/NetworkManager.ts b/packages/puppeteer-core/src/cdp/NetworkManager.ts index 61e61017..499c260c 100644 --- a/packages/puppeteer-core/src/cdp/NetworkManager.ts +++ b/packages/puppeteer-core/src/cdp/NetworkManager.ts @@ -18,11 +18,11 @@ import type {Protocol} from 'devtools-protocol'; import {CDPSessionEvent, type CDPSession} from '../api/CDPSession.js'; import type {Frame} from '../api/Frame.js'; +import {EventEmitter, EventSubscription} from '../common/EventEmitter.js'; import { - EventEmitter, - EventSubscription, - type EventType, -} from '../common/EventEmitter.js'; + NetworkManagerEvent, + type NetworkManagerEvents, +} from '../common/NetworkManagerEvents.js'; import {debugError, isString} from '../common/util.js'; import {assert} from '../util/assert.js'; import {DisposableStack} from '../util/disposable.js'; @@ -61,34 +61,6 @@ export interface InternalNetworkConditions extends NetworkConditions { offline: boolean; } -/** - * We use symbols to prevent any external parties listening to these events. - * They are internal to Puppeteer. - * - * @internal - */ -// eslint-disable-next-line @typescript-eslint/no-namespace -export namespace NetworkManagerEvent { - export const Request = Symbol('NetworkManager.Request'); - export const RequestServedFromCache = Symbol( - 'NetworkManager.RequestServedFromCache' - ); - export const Response = Symbol('NetworkManager.Response'); - export const RequestFailed = Symbol('NetworkManager.RequestFailed'); - export const RequestFinished = Symbol('NetworkManager.RequestFinished'); -} - -/** - * @internal - */ -export interface CdpNetworkManagerEvents extends Record { - [NetworkManagerEvent.Request]: CdpHTTPRequest; - [NetworkManagerEvent.RequestServedFromCache]: CdpHTTPRequest | undefined; - [NetworkManagerEvent.Response]: CdpHTTPResponse; - [NetworkManagerEvent.RequestFailed]: CdpHTTPRequest; - [NetworkManagerEvent.RequestFinished]: CdpHTTPRequest; -} - /** * @internal */ @@ -99,7 +71,7 @@ export interface FrameProvider { /** * @internal */ -export class NetworkManager extends EventEmitter { +export class NetworkManager extends EventEmitter { #ignoreHTTPSErrors: boolean; #frameManager: FrameProvider; #networkEventManager = new NetworkEventManager(); diff --git a/packages/puppeteer-core/src/cdp/Page.ts b/packages/puppeteer-core/src/cdp/Page.ts index 069dcfb6..3b96f97a 100644 --- a/packages/puppeteer-core/src/cdp/Page.ts +++ b/packages/puppeteer-core/src/cdp/Page.ts @@ -43,8 +43,8 @@ import { } from '../common/ConsoleMessage.js'; import {TargetCloseError} from '../common/Errors.js'; import {FileChooser} from '../common/FileChooser.js'; +import {NetworkManagerEvent} from '../common/NetworkManagerEvents.js'; import type {PDFOptions} from '../common/PDFOptions.js'; -import {TimeoutSettings} from '../common/TimeoutSettings.js'; import type {BindingPayload, HandleFor} from '../common/types.js'; import { createClientError, @@ -52,11 +52,10 @@ import { evaluationString, getReadableAsBuffer, getReadableFromProtocolStream, - isString, pageBindingInitString, validateDialogType, valueFromRemoteObject, - waitForEvent, + waitForHTTP, waitWithTimeout, } from '../common/util.js'; import type {Viewport} from '../common/Viewport.js'; @@ -79,11 +78,7 @@ import type {CdpFrame} from './Frame.js'; import {FrameManager, FrameManagerEvent} from './FrameManager.js'; import {CdpKeyboard, CdpMouse, CdpTouchscreen} from './Input.js'; import {MAIN_WORLD} from './IsolatedWorlds.js'; -import { - NetworkManagerEvent, - type Credentials, - type NetworkConditions, -} from './NetworkManager.js'; +import type {Credentials, NetworkConditions} from './NetworkManager.js'; import type {CdpTarget} from './Target.js'; import {TargetManagerEvent} from './TargetManager.js'; import {Tracing} from './Tracing.js'; @@ -121,7 +116,6 @@ export class CdpPage extends Page { #target: CdpTarget; #keyboard: CdpKeyboard; #mouse: CdpMouse; - #timeoutSettings = new TimeoutSettings(); #touchscreen: CdpTouchscreen; #accessibility: Accessibility; #frameManager: FrameManager; @@ -239,7 +233,7 @@ export class CdpPage extends Page { client, this, ignoreHTTPSErrors, - this.#timeoutSettings + this._timeoutSettings ); this.#emulationManager = new EmulationManager(client); this.#tracing = new Tracing(client); @@ -402,7 +396,7 @@ export class CdpPage extends Page { options: WaitTimeoutOptions = {} ): Promise { const needsEnable = this.#fileChooserDeferreds.size === 0; - const {timeout = this.#timeoutSettings.timeout()} = options; + const {timeout = this._timeoutSettings.timeout()} = options; const deferred = Deferred.create({ message: `Waiting for \`FileChooser\` failed: ${timeout}ms exceeded`, timeout, @@ -522,15 +516,15 @@ export class CdpPage extends Page { } override setDefaultNavigationTimeout(timeout: number): void { - this.#timeoutSettings.setDefaultNavigationTimeout(timeout); + this._timeoutSettings.setDefaultNavigationTimeout(timeout); } override setDefaultTimeout(timeout: number): void { - this.#timeoutSettings.setDefaultTimeout(timeout); + this._timeoutSettings.setDefaultTimeout(timeout); } override getDefaultTimeout(): number { - return this.#timeoutSettings.timeout(); + return this._timeoutSettings.timeout(); } override async queryObjects( @@ -876,21 +870,13 @@ export class CdpPage extends Page { urlOrPredicate: string | ((req: HTTPRequest) => boolean | Promise), options: {timeout?: number} = {} ): Promise { - const {timeout = this.#timeoutSettings.timeout()} = options; - return await waitForEvent( + const {timeout = this._timeoutSettings.timeout()} = options; + return await waitForHTTP( this.#frameManager.networkManager, NetworkManagerEvent.Request, - async request => { - if (isString(urlOrPredicate)) { - return urlOrPredicate === request.url(); - } - if (typeof urlOrPredicate === 'function') { - return !!(await urlOrPredicate(request)); - } - return false; - }, + urlOrPredicate, timeout, - this.#sessionCloseDeferred.valueOrThrow() + this.#sessionCloseDeferred ); } @@ -900,28 +886,20 @@ export class CdpPage extends Page { | ((res: HTTPResponse) => boolean | Promise), options: {timeout?: number} = {} ): Promise { - const {timeout = this.#timeoutSettings.timeout()} = options; - return await waitForEvent( + const {timeout = this._timeoutSettings.timeout()} = options; + return await waitForHTTP( this.#frameManager.networkManager, NetworkManagerEvent.Response, - async response => { - if (isString(urlOrPredicate)) { - return urlOrPredicate === response.url(); - } - if (typeof urlOrPredicate === 'function') { - return !!(await urlOrPredicate(response)); - } - return false; - }, + urlOrPredicate, timeout, - this.#sessionCloseDeferred.valueOrThrow() + this.#sessionCloseDeferred ); } override async waitForNetworkIdle( options: {idleTime?: number; timeout?: number} = {} ): Promise { - const {idleTime = 500, timeout = this.#timeoutSettings.timeout()} = options; + const {idleTime = 500, timeout = this._timeoutSettings.timeout()} = options; await this._waitForNetworkIdle( this.#frameManager.networkManager, diff --git a/packages/puppeteer-core/src/common/NetworkManagerEvents.ts b/packages/puppeteer-core/src/common/NetworkManagerEvents.ts new file mode 100644 index 00000000..e98f0e96 --- /dev/null +++ b/packages/puppeteer-core/src/common/NetworkManagerEvents.ts @@ -0,0 +1,48 @@ +/** + * Copyright 2022 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type {HTTPRequest} from '../api/HTTPRequest.js'; +import type {HTTPResponse} from '../api/HTTPResponse.js'; + +import type {EventType} from './EventEmitter.js'; + +/** + * We use symbols to prevent any external parties listening to these events. + * They are internal to Puppeteer. + * + * @internal + */ +// eslint-disable-next-line @typescript-eslint/no-namespace +export namespace NetworkManagerEvent { + export const Request = Symbol('NetworkManager.Request'); + export const RequestServedFromCache = Symbol( + 'NetworkManager.RequestServedFromCache' + ); + export const Response = Symbol('NetworkManager.Response'); + export const RequestFailed = Symbol('NetworkManager.RequestFailed'); + export const RequestFinished = Symbol('NetworkManager.RequestFinished'); +} + +/** + * @internal + */ +export interface NetworkManagerEvents extends Record { + [NetworkManagerEvent.Request]: HTTPRequest; + [NetworkManagerEvent.RequestServedFromCache]: HTTPRequest | undefined; + [NetworkManagerEvent.Response]: HTTPResponse; + [NetworkManagerEvent.RequestFailed]: HTTPRequest; + [NetworkManagerEvent.RequestFinished]: HTTPRequest; +} diff --git a/packages/puppeteer-core/src/common/common.ts b/packages/puppeteer-core/src/common/common.ts index e6444bc4..e6cbc85a 100644 --- a/packages/puppeteer-core/src/common/common.ts +++ b/packages/puppeteer-core/src/common/common.ts @@ -15,6 +15,7 @@ */ export * from './BrowserWebSocketTransport.js'; +export * from './common.js'; export * from './Configuration.js'; export * from './ConnectionTransport.js'; export * from './ConsoleMessage.js'; @@ -23,13 +24,15 @@ export * from './Debug.js'; export * from './Device.js'; export * from './Errors.js'; export * from './EventEmitter.js'; +export * from './fetch.js'; export * from './FileChooser.js'; export * from './GetQueryHandler.js'; export * from './HandleIterator.js'; export * from './LazyArg.js'; +export * from './NetworkManagerEvents.js'; export * from './PDFOptions.js'; -export * from './PQueryHandler.js'; export * from './PierceQueryHandler.js'; +export * from './PQueryHandler.js'; export * from './Product.js'; export * from './QueryHandler.js'; export * from './ScriptInjector.js'; @@ -37,11 +40,9 @@ export * from './SecurityDetails.js'; export * from './TaskQueue.js'; export * from './TextQueryHandler.js'; export * from './TimeoutSettings.js'; +export * from './types.js'; export * from './USKeyboardLayout.js'; +export * from './util.js'; export * from './Viewport.js'; export * from './WaitTask.js'; export * from './XPathQueryHandler.js'; -export * from './common.js'; -export * from './fetch.js'; -export * from './types.js'; -export * from './util.js'; diff --git a/packages/puppeteer-core/src/common/util.ts b/packages/puppeteer-core/src/common/util.ts index 93b9e2a4..a85286af 100644 --- a/packages/puppeteer-core/src/common/util.ts +++ b/packages/puppeteer-core/src/common/util.ts @@ -24,6 +24,11 @@ import { NEVER, timer, type Observable, + firstValueFrom, + fromEvent, + filterAsync, + from, + raceWith, } from '../../third_party/rxjs/rxjs.js'; import type {CDPSession} from '../api/CDPSession.js'; import type {Page} from '../api/Page.js'; @@ -34,8 +39,8 @@ import {isErrorLike} from '../util/ErrorLike.js'; import {debug} from './Debug.js'; import {TimeoutError} from './Errors.js'; -import {EventSubscription} from './EventEmitter.js'; -import type {Awaitable} from './types.js'; +import type {EventEmitter, EventType} from './EventEmitter.js'; +import type {NetworkManagerEvents} from './NetworkManagerEvents.js'; /** * @internal @@ -326,39 +331,6 @@ export const isDate = (obj: unknown): obj is Date => { return typeof obj === 'object' && obj?.constructor === Date; }; -/** - * @internal - */ -export async function waitForEvent( - // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types - emitter: any, - eventName: string | symbol, - predicate: (event: T) => Awaitable, - timeout: number, - abortPromise: Promise | Deferred -): Promise { - const deferred = Deferred.create({ - message: `Timeout exceeded while waiting for event ${String(eventName)}`, - timeout, - }); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - using _ = new EventSubscription(emitter, eventName, async (event: any) => { - if (await predicate(event)) { - deferred.resolve(event); - } - }); - - try { - const response = await Deferred.race([deferred, abortPromise]); - if (isErrorLike(response)) { - throw response; - } - return response; - } catch (error) { - throw error; - } -} - /** * @internal */ @@ -632,3 +604,32 @@ export const SOURCE_URL_REGEX = /^[\040\t]*\/\/[@#] sourceURL=\s*(\S*?)\s*$/m; export function getSourceUrlComment(url: string): string { return `//# sourceURL=${url}`; } + +/** + * @internal + */ +export async function waitForHTTP( + networkManager: EventEmitter, + eventName: EventType, + urlOrPredicate: string | ((res: T) => boolean | Promise), + /** Time after the function will timeout */ + ms: number, + cancelation: Deferred +): Promise { + return await firstValueFrom( + ( + fromEvent(networkManager, eventName as unknown as string) as Observable + ).pipe( + filterAsync(async http => { + if (isString(urlOrPredicate)) { + return urlOrPredicate === http.url(); + } + if (typeof urlOrPredicate === 'function') { + return !!(await urlOrPredicate(http)); + } + return false; + }), + raceWith(timeout(ms), from(cancelation.valueOrThrow())) + ) + ); +}