refactor: use RxJS for waitForHttp (#11133)
This commit is contained in:
parent
2c7d802d87
commit
8290dc9de9
@ -40,11 +40,10 @@ import type {BidiNetworkManager} from '../bidi/NetworkManager.js';
|
|||||||
import type {Accessibility} from '../cdp/Accessibility.js';
|
import type {Accessibility} from '../cdp/Accessibility.js';
|
||||||
import type {Coverage} from '../cdp/Coverage.js';
|
import type {Coverage} from '../cdp/Coverage.js';
|
||||||
import type {DeviceRequestPrompt} from '../cdp/DeviceRequestPrompt.js';
|
import type {DeviceRequestPrompt} from '../cdp/DeviceRequestPrompt.js';
|
||||||
import {
|
import type {
|
||||||
NetworkManagerEvent,
|
NetworkManager as CdpNetworkManager,
|
||||||
type NetworkManager as CdpNetworkManager,
|
Credentials,
|
||||||
type Credentials,
|
NetworkConditions,
|
||||||
type NetworkConditions,
|
|
||||||
} from '../cdp/NetworkManager.js';
|
} from '../cdp/NetworkManager.js';
|
||||||
import type {Tracing} from '../cdp/Tracing.js';
|
import type {Tracing} from '../cdp/Tracing.js';
|
||||||
import type {WebWorker} from '../cdp/WebWorker.js';
|
import type {WebWorker} from '../cdp/WebWorker.js';
|
||||||
@ -58,12 +57,14 @@ import {
|
|||||||
type Handler,
|
type Handler,
|
||||||
} from '../common/EventEmitter.js';
|
} from '../common/EventEmitter.js';
|
||||||
import type {FileChooser} from '../common/FileChooser.js';
|
import type {FileChooser} from '../common/FileChooser.js';
|
||||||
|
import {NetworkManagerEvent} from '../common/NetworkManagerEvents.js';
|
||||||
import {
|
import {
|
||||||
paperFormats,
|
paperFormats,
|
||||||
type LowerCasePaperFormat,
|
type LowerCasePaperFormat,
|
||||||
type ParsedPDFOptions,
|
type ParsedPDFOptions,
|
||||||
type PDFOptions,
|
type PDFOptions,
|
||||||
} from '../common/PDFOptions.js';
|
} from '../common/PDFOptions.js';
|
||||||
|
import {TimeoutSettings} from '../common/TimeoutSettings.js';
|
||||||
import type {
|
import type {
|
||||||
Awaitable,
|
Awaitable,
|
||||||
EvaluateFunc,
|
EvaluateFunc,
|
||||||
@ -603,6 +604,10 @@ export abstract class Page extends EventEmitter<PageEvents> {
|
|||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
_isDragging = false;
|
_isDragging = false;
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
_timeoutSettings = new TimeoutSettings();
|
||||||
|
|
||||||
#requestHandlers = new WeakMap<Handler<HTTPRequest>, Handler<HTTPRequest>>();
|
#requestHandlers = new WeakMap<Handler<HTTPRequest>, Handler<HTTPRequest>>();
|
||||||
|
|
||||||
|
@ -16,12 +16,11 @@
|
|||||||
|
|
||||||
import type * as Bidi from 'chromium-bidi/lib/cjs/protocol/protocol.js';
|
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 {
|
import {
|
||||||
EventEmitter,
|
NetworkManagerEvent,
|
||||||
EventSubscription,
|
type NetworkManagerEvents,
|
||||||
type EventType,
|
} from '../common/NetworkManagerEvents.js';
|
||||||
} from '../common/EventEmitter.js';
|
|
||||||
import {DisposableStack} from '../util/disposable.js';
|
import {DisposableStack} from '../util/disposable.js';
|
||||||
|
|
||||||
import type {BidiConnection} from './Connection.js';
|
import type {BidiConnection} from './Connection.js';
|
||||||
@ -33,18 +32,7 @@ import type {BidiPage} from './Page.js';
|
|||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
export interface BidiNetworkManagerEvents extends Record<EventType, unknown> {
|
export class BidiNetworkManager extends EventEmitter<NetworkManagerEvents> {
|
||||||
[NetworkManagerEvent.Request]: BidiHTTPRequest;
|
|
||||||
[NetworkManagerEvent.RequestServedFromCache]: BidiHTTPRequest;
|
|
||||||
[NetworkManagerEvent.Response]: BidiHTTPResponse;
|
|
||||||
[NetworkManagerEvent.RequestFailed]: BidiHTTPRequest;
|
|
||||||
[NetworkManagerEvent.RequestFinished]: BidiHTTPRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
export class BidiNetworkManager extends EventEmitter<BidiNetworkManagerEvents> {
|
|
||||||
#connection: BidiConnection;
|
#connection: BidiConnection;
|
||||||
#page: BidiPage;
|
#page: BidiPage;
|
||||||
#subscriptions = new DisposableStack();
|
#subscriptions = new DisposableStack();
|
||||||
|
@ -33,7 +33,6 @@ import {Accessibility} from '../cdp/Accessibility.js';
|
|||||||
import {Coverage} from '../cdp/Coverage.js';
|
import {Coverage} from '../cdp/Coverage.js';
|
||||||
import {EmulationManager as CdpEmulationManager} from '../cdp/EmulationManager.js';
|
import {EmulationManager as CdpEmulationManager} from '../cdp/EmulationManager.js';
|
||||||
import {FrameTree} from '../cdp/FrameTree.js';
|
import {FrameTree} from '../cdp/FrameTree.js';
|
||||||
import {NetworkManagerEvent} from '../cdp/NetworkManager.js';
|
|
||||||
import {Tracing} from '../cdp/Tracing.js';
|
import {Tracing} from '../cdp/Tracing.js';
|
||||||
import {
|
import {
|
||||||
ConsoleMessage,
|
ConsoleMessage,
|
||||||
@ -45,15 +44,14 @@ import {
|
|||||||
TimeoutError,
|
TimeoutError,
|
||||||
} from '../common/Errors.js';
|
} from '../common/Errors.js';
|
||||||
import type {Handler} from '../common/EventEmitter.js';
|
import type {Handler} from '../common/EventEmitter.js';
|
||||||
|
import {NetworkManagerEvent} from '../common/NetworkManagerEvents.js';
|
||||||
import type {PDFOptions} from '../common/PDFOptions.js';
|
import type {PDFOptions} from '../common/PDFOptions.js';
|
||||||
import {TimeoutSettings} from '../common/TimeoutSettings.js';
|
|
||||||
import type {Awaitable} from '../common/types.js';
|
import type {Awaitable} from '../common/types.js';
|
||||||
import {
|
import {
|
||||||
debugError,
|
debugError,
|
||||||
evaluationString,
|
evaluationString,
|
||||||
isString,
|
|
||||||
validateDialogType,
|
validateDialogType,
|
||||||
waitForEvent,
|
waitForHTTP,
|
||||||
waitWithTimeout,
|
waitWithTimeout,
|
||||||
} from '../common/util.js';
|
} from '../common/util.js';
|
||||||
import type {Viewport} from '../common/Viewport.js';
|
import type {Viewport} from '../common/Viewport.js';
|
||||||
@ -87,7 +85,6 @@ import {BidiSerializer} from './Serializer.js';
|
|||||||
*/
|
*/
|
||||||
export class BidiPage extends Page {
|
export class BidiPage extends Page {
|
||||||
#accessibility: Accessibility;
|
#accessibility: Accessibility;
|
||||||
#timeoutSettings = new TimeoutSettings();
|
|
||||||
#connection: BidiConnection;
|
#connection: BidiConnection;
|
||||||
#frameTree = new FrameTree<BidiFrame>();
|
#frameTree = new FrameTree<BidiFrame>();
|
||||||
#networkManager: BidiNetworkManager;
|
#networkManager: BidiNetworkManager;
|
||||||
@ -184,7 +181,7 @@ export class BidiPage extends Page {
|
|||||||
const frame = new BidiFrame(
|
const frame = new BidiFrame(
|
||||||
this,
|
this,
|
||||||
this.#browsingContext,
|
this.#browsingContext,
|
||||||
this.#timeoutSettings,
|
this._timeoutSettings,
|
||||||
this.#browsingContext.parent
|
this.#browsingContext.parent
|
||||||
);
|
);
|
||||||
this.#frameTree.addFrame(frame);
|
this.#frameTree.addFrame(frame);
|
||||||
@ -356,7 +353,7 @@ export class BidiPage extends Page {
|
|||||||
const frame = new BidiFrame(
|
const frame = new BidiFrame(
|
||||||
this,
|
this,
|
||||||
context,
|
context,
|
||||||
this.#timeoutSettings,
|
this._timeoutSettings,
|
||||||
context.parent
|
context.parent
|
||||||
);
|
);
|
||||||
this.#frameTree.addFrame(frame);
|
this.#frameTree.addFrame(frame);
|
||||||
@ -490,7 +487,7 @@ export class BidiPage extends Page {
|
|||||||
): Promise<BidiHTTPResponse | null> {
|
): Promise<BidiHTTPResponse | null> {
|
||||||
const {
|
const {
|
||||||
waitUntil = 'load',
|
waitUntil = 'load',
|
||||||
timeout = this.#timeoutSettings.navigationTimeout(),
|
timeout = this._timeoutSettings.navigationTimeout(),
|
||||||
} = options;
|
} = options;
|
||||||
|
|
||||||
const readinessState = lifeCycleToReadinessState.get(
|
const readinessState = lifeCycleToReadinessState.get(
|
||||||
@ -519,15 +516,15 @@ export class BidiPage extends Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override setDefaultNavigationTimeout(timeout: number): void {
|
override setDefaultNavigationTimeout(timeout: number): void {
|
||||||
this.#timeoutSettings.setDefaultNavigationTimeout(timeout);
|
this._timeoutSettings.setDefaultNavigationTimeout(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
override setDefaultTimeout(timeout: number): void {
|
override setDefaultTimeout(timeout: number): void {
|
||||||
this.#timeoutSettings.setDefaultTimeout(timeout);
|
this._timeoutSettings.setDefaultTimeout(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
override getDefaultTimeout(): number {
|
override getDefaultTimeout(): number {
|
||||||
return this.#timeoutSettings.timeout();
|
return this._timeoutSettings.timeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
override isJavaScriptEnabled(): boolean {
|
override isJavaScriptEnabled(): boolean {
|
||||||
@ -691,21 +688,13 @@ export class BidiPage extends Page {
|
|||||||
| ((req: BidiHTTPRequest) => boolean | Promise<boolean>),
|
| ((req: BidiHTTPRequest) => boolean | Promise<boolean>),
|
||||||
options: {timeout?: number} = {}
|
options: {timeout?: number} = {}
|
||||||
): Promise<BidiHTTPRequest> {
|
): Promise<BidiHTTPRequest> {
|
||||||
const {timeout = this.#timeoutSettings.timeout()} = options;
|
const {timeout = this._timeoutSettings.timeout()} = options;
|
||||||
return await waitForEvent(
|
return await waitForHTTP(
|
||||||
this.#networkManager,
|
this.#networkManager,
|
||||||
NetworkManagerEvent.Request,
|
NetworkManagerEvent.Request,
|
||||||
async request => {
|
urlOrPredicate,
|
||||||
if (isString(urlOrPredicate)) {
|
|
||||||
return urlOrPredicate === request.url();
|
|
||||||
}
|
|
||||||
if (typeof urlOrPredicate === 'function') {
|
|
||||||
return !!(await urlOrPredicate(request));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
timeout,
|
timeout,
|
||||||
this.#closedDeferred.valueOrThrow()
|
this.#closedDeferred
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -715,28 +704,20 @@ export class BidiPage extends Page {
|
|||||||
| ((res: BidiHTTPResponse) => boolean | Promise<boolean>),
|
| ((res: BidiHTTPResponse) => boolean | Promise<boolean>),
|
||||||
options: {timeout?: number} = {}
|
options: {timeout?: number} = {}
|
||||||
): Promise<BidiHTTPResponse> {
|
): Promise<BidiHTTPResponse> {
|
||||||
const {timeout = this.#timeoutSettings.timeout()} = options;
|
const {timeout = this._timeoutSettings.timeout()} = options;
|
||||||
return await waitForEvent(
|
return await waitForHTTP(
|
||||||
this.#networkManager,
|
this.#networkManager,
|
||||||
NetworkManagerEvent.Response,
|
NetworkManagerEvent.Response,
|
||||||
async response => {
|
urlOrPredicate,
|
||||||
if (isString(urlOrPredicate)) {
|
|
||||||
return urlOrPredicate === response.url();
|
|
||||||
}
|
|
||||||
if (typeof urlOrPredicate === 'function') {
|
|
||||||
return !!(await urlOrPredicate(response));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
timeout,
|
timeout,
|
||||||
this.#closedDeferred.valueOrThrow()
|
this.#closedDeferred
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
override async waitForNetworkIdle(
|
override async waitForNetworkIdle(
|
||||||
options: {idleTime?: number; timeout?: number} = {}
|
options: {idleTime?: number; timeout?: number} = {}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const {idleTime = 500, timeout = this.#timeoutSettings.timeout()} = options;
|
const {idleTime = 500, timeout = this._timeoutSettings.timeout()} = options;
|
||||||
|
|
||||||
await this._waitForNetworkIdle(
|
await this._waitForNetworkIdle(
|
||||||
this.#networkManager,
|
this.#networkManager,
|
||||||
|
@ -28,16 +28,18 @@ import {
|
|||||||
type ResponseForRequest,
|
type ResponseForRequest,
|
||||||
STATUS_TEXTS,
|
STATUS_TEXTS,
|
||||||
} from '../api/HTTPRequest.js';
|
} from '../api/HTTPRequest.js';
|
||||||
import type {HTTPResponse} from '../api/HTTPResponse.js';
|
|
||||||
import type {ProtocolError} from '../common/Errors.js';
|
import type {ProtocolError} from '../common/Errors.js';
|
||||||
import {debugError, isString} from '../common/util.js';
|
import {debugError, isString} from '../common/util.js';
|
||||||
import {assert} from '../util/assert.js';
|
import {assert} from '../util/assert.js';
|
||||||
|
|
||||||
|
import type {CdpHTTPResponse} from './HTTPResponse.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
export class CdpHTTPRequest extends HTTPRequest {
|
export class CdpHTTPRequest extends HTTPRequest {
|
||||||
declare _redirectChain: CdpHTTPRequest[];
|
declare _redirectChain: CdpHTTPRequest[];
|
||||||
|
declare _response: CdpHTTPResponse | null;
|
||||||
|
|
||||||
#client: CDPSession;
|
#client: CDPSession;
|
||||||
#isNavigationRequest: boolean;
|
#isNavigationRequest: boolean;
|
||||||
@ -191,7 +193,7 @@ export class CdpHTTPRequest extends HTTPRequest {
|
|||||||
return this.#headers;
|
return this.#headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
override response(): HTTPResponse | null {
|
override response(): CdpHTTPResponse | null {
|
||||||
return this._response;
|
return this._response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,17 +17,18 @@
|
|||||||
import type Protocol from 'devtools-protocol';
|
import type Protocol from 'devtools-protocol';
|
||||||
|
|
||||||
import {type Frame, FrameEvent} from '../api/Frame.js';
|
import {type Frame, FrameEvent} from '../api/Frame.js';
|
||||||
|
import type {HTTPRequest} from '../api/HTTPRequest.js';
|
||||||
import type {HTTPResponse} from '../api/HTTPResponse.js';
|
import type {HTTPResponse} from '../api/HTTPResponse.js';
|
||||||
import type {TimeoutError} from '../common/Errors.js';
|
import type {TimeoutError} from '../common/Errors.js';
|
||||||
import {EventSubscription} from '../common/EventEmitter.js';
|
import {EventSubscription} from '../common/EventEmitter.js';
|
||||||
|
import {NetworkManagerEvent} from '../common/NetworkManagerEvents.js';
|
||||||
import {assert} from '../util/assert.js';
|
import {assert} from '../util/assert.js';
|
||||||
import {Deferred} from '../util/Deferred.js';
|
import {Deferred} from '../util/Deferred.js';
|
||||||
import {DisposableStack} from '../util/disposable.js';
|
import {DisposableStack} from '../util/disposable.js';
|
||||||
|
|
||||||
import type {CdpFrame} from './Frame.js';
|
import type {CdpFrame} from './Frame.js';
|
||||||
import {FrameManagerEvent} from './FrameManager.js';
|
import {FrameManagerEvent} from './FrameManager.js';
|
||||||
import type {CdpHTTPRequest} from './HTTPRequest.js';
|
import type {NetworkManager} from './NetworkManager.js';
|
||||||
import {type NetworkManager, NetworkManagerEvent} from './NetworkManager.js';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
@ -78,7 +79,7 @@ export class LifecycleWatcher {
|
|||||||
#expectedLifecycle: ProtocolLifeCycleEvent[];
|
#expectedLifecycle: ProtocolLifeCycleEvent[];
|
||||||
#frame: CdpFrame;
|
#frame: CdpFrame;
|
||||||
#timeout: number;
|
#timeout: number;
|
||||||
#navigationRequest: CdpHTTPRequest | null = null;
|
#navigationRequest: HTTPRequest | null = null;
|
||||||
#subscriptions = new DisposableStack();
|
#subscriptions = new DisposableStack();
|
||||||
#initialLoaderId: string;
|
#initialLoaderId: string;
|
||||||
|
|
||||||
@ -184,7 +185,7 @@ export class LifecycleWatcher {
|
|||||||
this.#checkLifecycleComplete();
|
this.#checkLifecycleComplete();
|
||||||
}
|
}
|
||||||
|
|
||||||
#onRequest(request: CdpHTTPRequest): void {
|
#onRequest(request: HTTPRequest): void {
|
||||||
if (request.frame() !== this.#frame || !request.isNavigationRequest()) {
|
if (request.frame() !== this.#frame || !request.isNavigationRequest()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -199,7 +200,7 @@ export class LifecycleWatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#onRequestFailed(request: CdpHTTPRequest): void {
|
#onRequestFailed(request: HTTPRequest): void {
|
||||||
if (this.#navigationRequest?._requestId !== request._requestId) {
|
if (this.#navigationRequest?._requestId !== request._requestId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,10 @@ import type {CDPSessionEvents} from '../api/CDPSession.js';
|
|||||||
import type {HTTPRequest} from '../api/HTTPRequest.js';
|
import type {HTTPRequest} from '../api/HTTPRequest.js';
|
||||||
import type {HTTPResponse} from '../api/HTTPResponse.js';
|
import type {HTTPResponse} from '../api/HTTPResponse.js';
|
||||||
import {EventEmitter} from '../common/EventEmitter.js';
|
import {EventEmitter} from '../common/EventEmitter.js';
|
||||||
|
import {NetworkManagerEvent} from '../common/NetworkManagerEvents.js';
|
||||||
|
|
||||||
import type {CdpFrame} from './Frame.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
|
// TODO: develop a helper to generate fake network events for attributes that
|
||||||
// are not relevant for the network manager to make tests shorter.
|
// are not relevant for the network manager to make tests shorter.
|
||||||
|
@ -18,11 +18,11 @@ import type {Protocol} from 'devtools-protocol';
|
|||||||
|
|
||||||
import {CDPSessionEvent, type CDPSession} from '../api/CDPSession.js';
|
import {CDPSessionEvent, type CDPSession} from '../api/CDPSession.js';
|
||||||
import type {Frame} from '../api/Frame.js';
|
import type {Frame} from '../api/Frame.js';
|
||||||
|
import {EventEmitter, EventSubscription} from '../common/EventEmitter.js';
|
||||||
import {
|
import {
|
||||||
EventEmitter,
|
NetworkManagerEvent,
|
||||||
EventSubscription,
|
type NetworkManagerEvents,
|
||||||
type EventType,
|
} from '../common/NetworkManagerEvents.js';
|
||||||
} from '../common/EventEmitter.js';
|
|
||||||
import {debugError, isString} from '../common/util.js';
|
import {debugError, isString} from '../common/util.js';
|
||||||
import {assert} from '../util/assert.js';
|
import {assert} from '../util/assert.js';
|
||||||
import {DisposableStack} from '../util/disposable.js';
|
import {DisposableStack} from '../util/disposable.js';
|
||||||
@ -61,34 +61,6 @@ export interface InternalNetworkConditions extends NetworkConditions {
|
|||||||
offline: boolean;
|
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<EventType, unknown> {
|
|
||||||
[NetworkManagerEvent.Request]: CdpHTTPRequest;
|
|
||||||
[NetworkManagerEvent.RequestServedFromCache]: CdpHTTPRequest | undefined;
|
|
||||||
[NetworkManagerEvent.Response]: CdpHTTPResponse;
|
|
||||||
[NetworkManagerEvent.RequestFailed]: CdpHTTPRequest;
|
|
||||||
[NetworkManagerEvent.RequestFinished]: CdpHTTPRequest;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
@ -99,7 +71,7 @@ export interface FrameProvider {
|
|||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
export class NetworkManager extends EventEmitter<CdpNetworkManagerEvents> {
|
export class NetworkManager extends EventEmitter<NetworkManagerEvents> {
|
||||||
#ignoreHTTPSErrors: boolean;
|
#ignoreHTTPSErrors: boolean;
|
||||||
#frameManager: FrameProvider;
|
#frameManager: FrameProvider;
|
||||||
#networkEventManager = new NetworkEventManager();
|
#networkEventManager = new NetworkEventManager();
|
||||||
|
@ -43,8 +43,8 @@ import {
|
|||||||
} from '../common/ConsoleMessage.js';
|
} from '../common/ConsoleMessage.js';
|
||||||
import {TargetCloseError} from '../common/Errors.js';
|
import {TargetCloseError} from '../common/Errors.js';
|
||||||
import {FileChooser} from '../common/FileChooser.js';
|
import {FileChooser} from '../common/FileChooser.js';
|
||||||
|
import {NetworkManagerEvent} from '../common/NetworkManagerEvents.js';
|
||||||
import type {PDFOptions} from '../common/PDFOptions.js';
|
import type {PDFOptions} from '../common/PDFOptions.js';
|
||||||
import {TimeoutSettings} from '../common/TimeoutSettings.js';
|
|
||||||
import type {BindingPayload, HandleFor} from '../common/types.js';
|
import type {BindingPayload, HandleFor} from '../common/types.js';
|
||||||
import {
|
import {
|
||||||
createClientError,
|
createClientError,
|
||||||
@ -52,11 +52,10 @@ import {
|
|||||||
evaluationString,
|
evaluationString,
|
||||||
getReadableAsBuffer,
|
getReadableAsBuffer,
|
||||||
getReadableFromProtocolStream,
|
getReadableFromProtocolStream,
|
||||||
isString,
|
|
||||||
pageBindingInitString,
|
pageBindingInitString,
|
||||||
validateDialogType,
|
validateDialogType,
|
||||||
valueFromRemoteObject,
|
valueFromRemoteObject,
|
||||||
waitForEvent,
|
waitForHTTP,
|
||||||
waitWithTimeout,
|
waitWithTimeout,
|
||||||
} from '../common/util.js';
|
} from '../common/util.js';
|
||||||
import type {Viewport} from '../common/Viewport.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 {FrameManager, FrameManagerEvent} from './FrameManager.js';
|
||||||
import {CdpKeyboard, CdpMouse, CdpTouchscreen} from './Input.js';
|
import {CdpKeyboard, CdpMouse, CdpTouchscreen} from './Input.js';
|
||||||
import {MAIN_WORLD} from './IsolatedWorlds.js';
|
import {MAIN_WORLD} from './IsolatedWorlds.js';
|
||||||
import {
|
import type {Credentials, NetworkConditions} from './NetworkManager.js';
|
||||||
NetworkManagerEvent,
|
|
||||||
type Credentials,
|
|
||||||
type NetworkConditions,
|
|
||||||
} from './NetworkManager.js';
|
|
||||||
import type {CdpTarget} from './Target.js';
|
import type {CdpTarget} from './Target.js';
|
||||||
import {TargetManagerEvent} from './TargetManager.js';
|
import {TargetManagerEvent} from './TargetManager.js';
|
||||||
import {Tracing} from './Tracing.js';
|
import {Tracing} from './Tracing.js';
|
||||||
@ -121,7 +116,6 @@ export class CdpPage extends Page {
|
|||||||
#target: CdpTarget;
|
#target: CdpTarget;
|
||||||
#keyboard: CdpKeyboard;
|
#keyboard: CdpKeyboard;
|
||||||
#mouse: CdpMouse;
|
#mouse: CdpMouse;
|
||||||
#timeoutSettings = new TimeoutSettings();
|
|
||||||
#touchscreen: CdpTouchscreen;
|
#touchscreen: CdpTouchscreen;
|
||||||
#accessibility: Accessibility;
|
#accessibility: Accessibility;
|
||||||
#frameManager: FrameManager;
|
#frameManager: FrameManager;
|
||||||
@ -239,7 +233,7 @@ export class CdpPage extends Page {
|
|||||||
client,
|
client,
|
||||||
this,
|
this,
|
||||||
ignoreHTTPSErrors,
|
ignoreHTTPSErrors,
|
||||||
this.#timeoutSettings
|
this._timeoutSettings
|
||||||
);
|
);
|
||||||
this.#emulationManager = new EmulationManager(client);
|
this.#emulationManager = new EmulationManager(client);
|
||||||
this.#tracing = new Tracing(client);
|
this.#tracing = new Tracing(client);
|
||||||
@ -402,7 +396,7 @@ export class CdpPage extends Page {
|
|||||||
options: WaitTimeoutOptions = {}
|
options: WaitTimeoutOptions = {}
|
||||||
): Promise<FileChooser> {
|
): Promise<FileChooser> {
|
||||||
const needsEnable = this.#fileChooserDeferreds.size === 0;
|
const needsEnable = this.#fileChooserDeferreds.size === 0;
|
||||||
const {timeout = this.#timeoutSettings.timeout()} = options;
|
const {timeout = this._timeoutSettings.timeout()} = options;
|
||||||
const deferred = Deferred.create<FileChooser>({
|
const deferred = Deferred.create<FileChooser>({
|
||||||
message: `Waiting for \`FileChooser\` failed: ${timeout}ms exceeded`,
|
message: `Waiting for \`FileChooser\` failed: ${timeout}ms exceeded`,
|
||||||
timeout,
|
timeout,
|
||||||
@ -522,15 +516,15 @@ export class CdpPage extends Page {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override setDefaultNavigationTimeout(timeout: number): void {
|
override setDefaultNavigationTimeout(timeout: number): void {
|
||||||
this.#timeoutSettings.setDefaultNavigationTimeout(timeout);
|
this._timeoutSettings.setDefaultNavigationTimeout(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
override setDefaultTimeout(timeout: number): void {
|
override setDefaultTimeout(timeout: number): void {
|
||||||
this.#timeoutSettings.setDefaultTimeout(timeout);
|
this._timeoutSettings.setDefaultTimeout(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
override getDefaultTimeout(): number {
|
override getDefaultTimeout(): number {
|
||||||
return this.#timeoutSettings.timeout();
|
return this._timeoutSettings.timeout();
|
||||||
}
|
}
|
||||||
|
|
||||||
override async queryObjects<Prototype>(
|
override async queryObjects<Prototype>(
|
||||||
@ -876,21 +870,13 @@ export class CdpPage extends Page {
|
|||||||
urlOrPredicate: string | ((req: HTTPRequest) => boolean | Promise<boolean>),
|
urlOrPredicate: string | ((req: HTTPRequest) => boolean | Promise<boolean>),
|
||||||
options: {timeout?: number} = {}
|
options: {timeout?: number} = {}
|
||||||
): Promise<HTTPRequest> {
|
): Promise<HTTPRequest> {
|
||||||
const {timeout = this.#timeoutSettings.timeout()} = options;
|
const {timeout = this._timeoutSettings.timeout()} = options;
|
||||||
return await waitForEvent(
|
return await waitForHTTP(
|
||||||
this.#frameManager.networkManager,
|
this.#frameManager.networkManager,
|
||||||
NetworkManagerEvent.Request,
|
NetworkManagerEvent.Request,
|
||||||
async request => {
|
urlOrPredicate,
|
||||||
if (isString(urlOrPredicate)) {
|
|
||||||
return urlOrPredicate === request.url();
|
|
||||||
}
|
|
||||||
if (typeof urlOrPredicate === 'function') {
|
|
||||||
return !!(await urlOrPredicate(request));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
timeout,
|
timeout,
|
||||||
this.#sessionCloseDeferred.valueOrThrow()
|
this.#sessionCloseDeferred
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -900,28 +886,20 @@ export class CdpPage extends Page {
|
|||||||
| ((res: HTTPResponse) => boolean | Promise<boolean>),
|
| ((res: HTTPResponse) => boolean | Promise<boolean>),
|
||||||
options: {timeout?: number} = {}
|
options: {timeout?: number} = {}
|
||||||
): Promise<HTTPResponse> {
|
): Promise<HTTPResponse> {
|
||||||
const {timeout = this.#timeoutSettings.timeout()} = options;
|
const {timeout = this._timeoutSettings.timeout()} = options;
|
||||||
return await waitForEvent(
|
return await waitForHTTP(
|
||||||
this.#frameManager.networkManager,
|
this.#frameManager.networkManager,
|
||||||
NetworkManagerEvent.Response,
|
NetworkManagerEvent.Response,
|
||||||
async response => {
|
urlOrPredicate,
|
||||||
if (isString(urlOrPredicate)) {
|
|
||||||
return urlOrPredicate === response.url();
|
|
||||||
}
|
|
||||||
if (typeof urlOrPredicate === 'function') {
|
|
||||||
return !!(await urlOrPredicate(response));
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
timeout,
|
timeout,
|
||||||
this.#sessionCloseDeferred.valueOrThrow()
|
this.#sessionCloseDeferred
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
override async waitForNetworkIdle(
|
override async waitForNetworkIdle(
|
||||||
options: {idleTime?: number; timeout?: number} = {}
|
options: {idleTime?: number; timeout?: number} = {}
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const {idleTime = 500, timeout = this.#timeoutSettings.timeout()} = options;
|
const {idleTime = 500, timeout = this._timeoutSettings.timeout()} = options;
|
||||||
|
|
||||||
await this._waitForNetworkIdle(
|
await this._waitForNetworkIdle(
|
||||||
this.#frameManager.networkManager,
|
this.#frameManager.networkManager,
|
||||||
|
48
packages/puppeteer-core/src/common/NetworkManagerEvents.ts
Normal file
48
packages/puppeteer-core/src/common/NetworkManagerEvents.ts
Normal file
@ -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<EventType, unknown> {
|
||||||
|
[NetworkManagerEvent.Request]: HTTPRequest;
|
||||||
|
[NetworkManagerEvent.RequestServedFromCache]: HTTPRequest | undefined;
|
||||||
|
[NetworkManagerEvent.Response]: HTTPResponse;
|
||||||
|
[NetworkManagerEvent.RequestFailed]: HTTPRequest;
|
||||||
|
[NetworkManagerEvent.RequestFinished]: HTTPRequest;
|
||||||
|
}
|
@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
export * from './BrowserWebSocketTransport.js';
|
export * from './BrowserWebSocketTransport.js';
|
||||||
|
export * from './common.js';
|
||||||
export * from './Configuration.js';
|
export * from './Configuration.js';
|
||||||
export * from './ConnectionTransport.js';
|
export * from './ConnectionTransport.js';
|
||||||
export * from './ConsoleMessage.js';
|
export * from './ConsoleMessage.js';
|
||||||
@ -23,13 +24,15 @@ export * from './Debug.js';
|
|||||||
export * from './Device.js';
|
export * from './Device.js';
|
||||||
export * from './Errors.js';
|
export * from './Errors.js';
|
||||||
export * from './EventEmitter.js';
|
export * from './EventEmitter.js';
|
||||||
|
export * from './fetch.js';
|
||||||
export * from './FileChooser.js';
|
export * from './FileChooser.js';
|
||||||
export * from './GetQueryHandler.js';
|
export * from './GetQueryHandler.js';
|
||||||
export * from './HandleIterator.js';
|
export * from './HandleIterator.js';
|
||||||
export * from './LazyArg.js';
|
export * from './LazyArg.js';
|
||||||
|
export * from './NetworkManagerEvents.js';
|
||||||
export * from './PDFOptions.js';
|
export * from './PDFOptions.js';
|
||||||
export * from './PQueryHandler.js';
|
|
||||||
export * from './PierceQueryHandler.js';
|
export * from './PierceQueryHandler.js';
|
||||||
|
export * from './PQueryHandler.js';
|
||||||
export * from './Product.js';
|
export * from './Product.js';
|
||||||
export * from './QueryHandler.js';
|
export * from './QueryHandler.js';
|
||||||
export * from './ScriptInjector.js';
|
export * from './ScriptInjector.js';
|
||||||
@ -37,11 +40,9 @@ export * from './SecurityDetails.js';
|
|||||||
export * from './TaskQueue.js';
|
export * from './TaskQueue.js';
|
||||||
export * from './TextQueryHandler.js';
|
export * from './TextQueryHandler.js';
|
||||||
export * from './TimeoutSettings.js';
|
export * from './TimeoutSettings.js';
|
||||||
|
export * from './types.js';
|
||||||
export * from './USKeyboardLayout.js';
|
export * from './USKeyboardLayout.js';
|
||||||
|
export * from './util.js';
|
||||||
export * from './Viewport.js';
|
export * from './Viewport.js';
|
||||||
export * from './WaitTask.js';
|
export * from './WaitTask.js';
|
||||||
export * from './XPathQueryHandler.js';
|
export * from './XPathQueryHandler.js';
|
||||||
export * from './common.js';
|
|
||||||
export * from './fetch.js';
|
|
||||||
export * from './types.js';
|
|
||||||
export * from './util.js';
|
|
||||||
|
@ -24,6 +24,11 @@ import {
|
|||||||
NEVER,
|
NEVER,
|
||||||
timer,
|
timer,
|
||||||
type Observable,
|
type Observable,
|
||||||
|
firstValueFrom,
|
||||||
|
fromEvent,
|
||||||
|
filterAsync,
|
||||||
|
from,
|
||||||
|
raceWith,
|
||||||
} from '../../third_party/rxjs/rxjs.js';
|
} from '../../third_party/rxjs/rxjs.js';
|
||||||
import type {CDPSession} from '../api/CDPSession.js';
|
import type {CDPSession} from '../api/CDPSession.js';
|
||||||
import type {Page} from '../api/Page.js';
|
import type {Page} from '../api/Page.js';
|
||||||
@ -34,8 +39,8 @@ import {isErrorLike} from '../util/ErrorLike.js';
|
|||||||
|
|
||||||
import {debug} from './Debug.js';
|
import {debug} from './Debug.js';
|
||||||
import {TimeoutError} from './Errors.js';
|
import {TimeoutError} from './Errors.js';
|
||||||
import {EventSubscription} from './EventEmitter.js';
|
import type {EventEmitter, EventType} from './EventEmitter.js';
|
||||||
import type {Awaitable} from './types.js';
|
import type {NetworkManagerEvents} from './NetworkManagerEvents.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
@ -326,39 +331,6 @@ export const isDate = (obj: unknown): obj is Date => {
|
|||||||
return typeof obj === 'object' && obj?.constructor === Date;
|
return typeof obj === 'object' && obj?.constructor === Date;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
export async function waitForEvent<T>(
|
|
||||||
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
||||||
emitter: any,
|
|
||||||
eventName: string | symbol,
|
|
||||||
predicate: (event: T) => Awaitable<boolean>,
|
|
||||||
timeout: number,
|
|
||||||
abortPromise: Promise<Error> | Deferred<Error>
|
|
||||||
): Promise<T> {
|
|
||||||
const deferred = Deferred.create<T>({
|
|
||||||
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<T | Error>([deferred, abortPromise]);
|
|
||||||
if (isErrorLike(response)) {
|
|
||||||
throw response;
|
|
||||||
}
|
|
||||||
return response;
|
|
||||||
} catch (error) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
@ -632,3 +604,32 @@ export const SOURCE_URL_REGEX = /^[\040\t]*\/\/[@#] sourceURL=\s*(\S*?)\s*$/m;
|
|||||||
export function getSourceUrlComment(url: string): string {
|
export function getSourceUrlComment(url: string): string {
|
||||||
return `//# sourceURL=${url}`;
|
return `//# sourceURL=${url}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export async function waitForHTTP<T extends {url(): string}>(
|
||||||
|
networkManager: EventEmitter<NetworkManagerEvents>,
|
||||||
|
eventName: EventType,
|
||||||
|
urlOrPredicate: string | ((res: T) => boolean | Promise<boolean>),
|
||||||
|
/** Time after the function will timeout */
|
||||||
|
ms: number,
|
||||||
|
cancelation: Deferred<never>
|
||||||
|
): Promise<T> {
|
||||||
|
return await firstValueFrom(
|
||||||
|
(
|
||||||
|
fromEvent(networkManager, eventName as unknown as string) as Observable<T>
|
||||||
|
).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()))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user