mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
refactor: Deferred to a class (#10282)
This commit is contained in:
parent
5fc136eec1
commit
39e9737232
@ -194,6 +194,12 @@ module.exports = {
|
|||||||
selector: "CallExpression[callee.name='require']",
|
selector: "CallExpression[callee.name='require']",
|
||||||
message: '`require` statements are not allowed. Use `import`.',
|
message: '`require` statements are not allowed. Use `import`.',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// We need this as NodeJS will run until all the timers have resolved
|
||||||
|
message: 'Use method `Deferred.race()` instead.',
|
||||||
|
selector:
|
||||||
|
'MemberExpression[object.name="Promise"][property.name="race"]',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
'@typescript-eslint/no-floating-promises': [
|
'@typescript-eslint/no-floating-promises': [
|
||||||
'error',
|
'error',
|
||||||
|
@ -61,7 +61,6 @@ import {
|
|||||||
import type {WebWorker} from '../common/WebWorker.js';
|
import type {WebWorker} from '../common/WebWorker.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 {createDeferred} from '../util/Deferred.js';
|
|
||||||
|
|
||||||
import type {Browser} from './Browser.js';
|
import type {Browser} from './Browser.js';
|
||||||
import type {BrowserContext} from './BrowserContext.js';
|
import type {BrowserContext} from './BrowserContext.js';
|
||||||
@ -1638,8 +1637,8 @@ export class Page extends EventEmitter {
|
|||||||
timeout: number,
|
timeout: number,
|
||||||
closedDeferred: Deferred<TargetCloseError>
|
closedDeferred: Deferred<TargetCloseError>
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
const idleDeferred = createDeferred<void>();
|
const idleDeferred = Deferred.create<void>();
|
||||||
const abortDeferred = createDeferred<Error>();
|
const abortDeferred = Deferred.create<Error>();
|
||||||
|
|
||||||
let idleTimer: NodeJS.Timeout | undefined;
|
let idleTimer: NodeJS.Timeout | undefined;
|
||||||
const cleanup = () => {
|
const cleanup = () => {
|
||||||
@ -1651,7 +1650,9 @@ export class Page extends EventEmitter {
|
|||||||
clearTimeout(idleTimer);
|
clearTimeout(idleTimer);
|
||||||
|
|
||||||
if (networkManager.inFlightRequestsCount() === 0) {
|
if (networkManager.inFlightRequestsCount() === 0) {
|
||||||
idleTimer = setTimeout(idleDeferred.resolve, idleTime);
|
idleTimer = setTimeout(() => {
|
||||||
|
return idleDeferred.resolve();
|
||||||
|
}, idleTime);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1676,11 +1677,7 @@ export class Page extends EventEmitter {
|
|||||||
|
|
||||||
evaluate();
|
evaluate();
|
||||||
|
|
||||||
await Promise.race([
|
await Deferred.race([idleDeferred, ...eventPromises, closedDeferred]).then(
|
||||||
idleDeferred.valueOrThrow(),
|
|
||||||
...eventPromises,
|
|
||||||
closedDeferred.valueOrThrow(),
|
|
||||||
]).then(
|
|
||||||
r => {
|
r => {
|
||||||
cleanup();
|
cleanup();
|
||||||
return r;
|
return r;
|
||||||
|
@ -33,7 +33,7 @@ import {
|
|||||||
import {BrowserContext} from '../api/BrowserContext.js';
|
import {BrowserContext} from '../api/BrowserContext.js';
|
||||||
import {Page} from '../api/Page.js';
|
import {Page} from '../api/Page.js';
|
||||||
import {assert} from '../util/assert.js';
|
import {assert} from '../util/assert.js';
|
||||||
import {createDeferred} from '../util/Deferred.js';
|
import {Deferred} from '../util/Deferred.js';
|
||||||
|
|
||||||
import {ChromeTargetManager} from './ChromeTargetManager.js';
|
import {ChromeTargetManager} from './ChromeTargetManager.js';
|
||||||
import {CDPSession, Connection, ConnectionEmittedEvents} from './Connection.js';
|
import {CDPSession, Connection, ConnectionEmittedEvents} from './Connection.js';
|
||||||
@ -501,7 +501,7 @@ export class CDPBrowser extends BrowserBase {
|
|||||||
options: WaitForTargetOptions = {}
|
options: WaitForTargetOptions = {}
|
||||||
): Promise<Target> {
|
): Promise<Target> {
|
||||||
const {timeout = 30000} = options;
|
const {timeout = 30000} = options;
|
||||||
const targetDeferred = createDeferred<Target | PromiseLike<Target>>();
|
const targetDeferred = Deferred.create<Target | PromiseLike<Target>>();
|
||||||
|
|
||||||
this.on(BrowserEmittedEvents.TargetCreated, check);
|
this.on(BrowserEmittedEvents.TargetCreated, check);
|
||||||
this.on(BrowserEmittedEvents.TargetChanged, check);
|
this.on(BrowserEmittedEvents.TargetChanged, check);
|
||||||
|
@ -18,7 +18,7 @@ import {Protocol} from 'devtools-protocol';
|
|||||||
|
|
||||||
import {TargetFilterCallback} from '../api/Browser.js';
|
import {TargetFilterCallback} from '../api/Browser.js';
|
||||||
import {assert} from '../util/assert.js';
|
import {assert} from '../util/assert.js';
|
||||||
import {createDeferred} from '../util/Deferred.js';
|
import {Deferred} from '../util/Deferred.js';
|
||||||
|
|
||||||
import {CDPSession, Connection} from './Connection.js';
|
import {CDPSession, Connection} from './Connection.js';
|
||||||
import {EventEmitter} from './EventEmitter.js';
|
import {EventEmitter} from './EventEmitter.js';
|
||||||
@ -81,7 +81,7 @@ export class ChromeTargetManager extends EventEmitter implements TargetManager {
|
|||||||
(event: Protocol.Target.DetachedFromTargetEvent) => void
|
(event: Protocol.Target.DetachedFromTargetEvent) => void
|
||||||
> = new WeakMap();
|
> = new WeakMap();
|
||||||
|
|
||||||
#initializeDeferred = createDeferred<void>();
|
#initializeDeferred = Deferred.create<void>();
|
||||||
#targetsIdsForInit: Set<string> = new Set();
|
#targetsIdsForInit: Set<string> = new Set();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -18,7 +18,7 @@ import {Protocol} from 'devtools-protocol';
|
|||||||
import {ProtocolMapping} from 'devtools-protocol/types/protocol-mapping.js';
|
import {ProtocolMapping} from 'devtools-protocol/types/protocol-mapping.js';
|
||||||
|
|
||||||
import {assert} from '../util/assert.js';
|
import {assert} from '../util/assert.js';
|
||||||
import {createDeferred, Deferred} from '../util/util.js';
|
import {Deferred} from '../util/util.js';
|
||||||
|
|
||||||
import {ConnectionTransport} from './ConnectionTransport.js';
|
import {ConnectionTransport} from './ConnectionTransport.js';
|
||||||
import {debug} from './Debug.js';
|
import {debug} from './Debug.js';
|
||||||
@ -64,7 +64,7 @@ function createIncrementalIdGenerator(): GetIdFn {
|
|||||||
export class Callback {
|
export class Callback {
|
||||||
#id: number;
|
#id: number;
|
||||||
#error = new ProtocolError();
|
#error = new ProtocolError();
|
||||||
#deferred = createDeferred<unknown>();
|
#deferred = Deferred.create<unknown>();
|
||||||
#timer?: ReturnType<typeof setTimeout>;
|
#timer?: ReturnType<typeof setTimeout>;
|
||||||
#label: string;
|
#label: string;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ import Protocol from 'devtools-protocol';
|
|||||||
|
|
||||||
import {WaitTimeoutOptions} from '../api/Page.js';
|
import {WaitTimeoutOptions} from '../api/Page.js';
|
||||||
import {assert} from '../util/assert.js';
|
import {assert} from '../util/assert.js';
|
||||||
import {createDeferred, Deferred} from '../util/Deferred.js';
|
import {Deferred} from '../util/Deferred.js';
|
||||||
|
|
||||||
import {CDPSession} from './Connection.js';
|
import {CDPSession} from './Connection.js';
|
||||||
import {TimeoutSettings} from './TimeoutSettings.js';
|
import {TimeoutSettings} from './TimeoutSettings.js';
|
||||||
@ -151,7 +151,7 @@ export class DeviceRequestPrompt {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const {timeout = this.#timeoutSettings.timeout()} = options;
|
const {timeout = this.#timeoutSettings.timeout()} = options;
|
||||||
const deferred = createDeferred<DeviceRequestPromptDevice>({
|
const deferred = Deferred.create<DeviceRequestPromptDevice>({
|
||||||
message: `Waiting for \`DeviceRequestPromptDevice\` failed: ${timeout}ms exceeded`,
|
message: `Waiting for \`DeviceRequestPromptDevice\` failed: ${timeout}ms exceeded`,
|
||||||
timeout,
|
timeout,
|
||||||
});
|
});
|
||||||
@ -250,7 +250,7 @@ export class DeviceRequestPromptManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const {timeout = this.#timeoutSettings.timeout()} = options;
|
const {timeout = this.#timeoutSettings.timeout()} = options;
|
||||||
const deferred = createDeferred<DeviceRequestPrompt>({
|
const deferred = Deferred.create<DeviceRequestPrompt>({
|
||||||
message: `Waiting for \`DeviceRequestPrompt\` failed: ${timeout}ms exceeded`,
|
message: `Waiting for \`DeviceRequestPrompt\` failed: ${timeout}ms exceeded`,
|
||||||
timeout,
|
timeout,
|
||||||
});
|
});
|
||||||
|
@ -18,7 +18,7 @@ import {Protocol} from 'devtools-protocol';
|
|||||||
|
|
||||||
import {TargetFilterCallback} from '../api/Browser.js';
|
import {TargetFilterCallback} from '../api/Browser.js';
|
||||||
import {assert} from '../util/assert.js';
|
import {assert} from '../util/assert.js';
|
||||||
import {createDeferred} from '../util/Deferred.js';
|
import {Deferred} from '../util/Deferred.js';
|
||||||
|
|
||||||
import {CDPSession, Connection} from './Connection.js';
|
import {CDPSession, Connection} from './Connection.js';
|
||||||
import {EventEmitter} from './EventEmitter.js';
|
import {EventEmitter} from './EventEmitter.js';
|
||||||
@ -88,7 +88,7 @@ export class FirefoxTargetManager
|
|||||||
(event: Protocol.Target.AttachedToTargetEvent) => Promise<void>
|
(event: Protocol.Target.AttachedToTargetEvent) => Promise<void>
|
||||||
> = new WeakMap();
|
> = new WeakMap();
|
||||||
|
|
||||||
#initializeDeferred = createDeferred<void>();
|
#initializeDeferred = Deferred.create<void>();
|
||||||
#targetsIdsForInit: Set<string> = new Set();
|
#targetsIdsForInit: Set<string> = new Set();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -26,6 +26,7 @@ import {
|
|||||||
import {HTTPResponse} from '../api/HTTPResponse.js';
|
import {HTTPResponse} from '../api/HTTPResponse.js';
|
||||||
import {Page, WaitTimeoutOptions} from '../api/Page.js';
|
import {Page, WaitTimeoutOptions} from '../api/Page.js';
|
||||||
import {assert} from '../util/assert.js';
|
import {assert} from '../util/assert.js';
|
||||||
|
import {Deferred} from '../util/Deferred.js';
|
||||||
import {isErrorLike} from '../util/ErrorLike.js';
|
import {isErrorLike} from '../util/ErrorLike.js';
|
||||||
|
|
||||||
import {CDPSession} from './Connection.js';
|
import {CDPSession} from './Connection.js';
|
||||||
@ -123,7 +124,7 @@ export class Frame extends BaseFrame {
|
|||||||
waitUntil,
|
waitUntil,
|
||||||
timeout
|
timeout
|
||||||
);
|
);
|
||||||
let error = await Promise.race([
|
let error = await Deferred.race([
|
||||||
navigate(
|
navigate(
|
||||||
this.#client,
|
this.#client,
|
||||||
url,
|
url,
|
||||||
@ -134,7 +135,7 @@ export class Frame extends BaseFrame {
|
|||||||
watcher.timeoutOrTerminationPromise(),
|
watcher.timeoutOrTerminationPromise(),
|
||||||
]);
|
]);
|
||||||
if (!error) {
|
if (!error) {
|
||||||
error = await Promise.race([
|
error = await Deferred.race([
|
||||||
watcher.timeoutOrTerminationPromise(),
|
watcher.timeoutOrTerminationPromise(),
|
||||||
ensureNewDocumentNavigation
|
ensureNewDocumentNavigation
|
||||||
? watcher.newDocumentNavigationPromise()
|
? watcher.newDocumentNavigationPromise()
|
||||||
@ -197,7 +198,7 @@ export class Frame extends BaseFrame {
|
|||||||
waitUntil,
|
waitUntil,
|
||||||
timeout
|
timeout
|
||||||
);
|
);
|
||||||
const error = await Promise.race([
|
const error = await Deferred.race([
|
||||||
watcher.timeoutOrTerminationPromise(),
|
watcher.timeoutOrTerminationPromise(),
|
||||||
watcher.sameDocumentNavigationPromise(),
|
watcher.sameDocumentNavigationPromise(),
|
||||||
watcher.newDocumentNavigationPromise(),
|
watcher.newDocumentNavigationPromise(),
|
||||||
@ -389,8 +390,8 @@ export class Frame extends BaseFrame {
|
|||||||
|
|
||||||
return this.worlds[MAIN_WORLD].transferHandle(
|
return this.worlds[MAIN_WORLD].transferHandle(
|
||||||
await this.worlds[PUPPETEER_WORLD].evaluateHandle(
|
await this.worlds[PUPPETEER_WORLD].evaluateHandle(
|
||||||
async ({createDeferred}, {url, id, type, content}) => {
|
async ({Deferred}, {url, id, type, content}) => {
|
||||||
const deferred = createDeferred<void>();
|
const deferred = Deferred.create<void>();
|
||||||
const script = document.createElement('script');
|
const script = document.createElement('script');
|
||||||
script.type = type;
|
script.type = type;
|
||||||
script.text = content;
|
script.text = content;
|
||||||
@ -457,8 +458,8 @@ export class Frame extends BaseFrame {
|
|||||||
|
|
||||||
return this.worlds[MAIN_WORLD].transferHandle(
|
return this.worlds[MAIN_WORLD].transferHandle(
|
||||||
await this.worlds[PUPPETEER_WORLD].evaluateHandle(
|
await this.worlds[PUPPETEER_WORLD].evaluateHandle(
|
||||||
async ({createDeferred}, {url, content}) => {
|
async ({Deferred}, {url, content}) => {
|
||||||
const deferred = createDeferred<void>();
|
const deferred = Deferred.create<void>();
|
||||||
let element: HTMLStyleElement | HTMLLinkElement;
|
let element: HTMLStyleElement | HTMLLinkElement;
|
||||||
if (!url) {
|
if (!url) {
|
||||||
element = document.createElement('style');
|
element = document.createElement('style');
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {Frame as BaseFrame} from '../api/Frame.js';
|
import {Frame as BaseFrame} from '../api/Frame.js';
|
||||||
import {createDeferred, Deferred} from '../util/Deferred.js';
|
import {Deferred} from '../util/Deferred.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keeps track of the page frame tree and it's is managed by
|
* Keeps track of the page frame tree and it's is managed by
|
||||||
@ -50,7 +50,7 @@ export class FrameTree<Frame extends BaseFrame> {
|
|||||||
if (frame) {
|
if (frame) {
|
||||||
return Promise.resolve(frame);
|
return Promise.resolve(frame);
|
||||||
}
|
}
|
||||||
const deferred = createDeferred<Frame>();
|
const deferred = Deferred.create<Frame>();
|
||||||
const callbacks =
|
const callbacks =
|
||||||
this.#waitRequests.get(frameId) || new Set<Deferred<Frame>>();
|
this.#waitRequests.get(frameId) || new Set<Deferred<Frame>>();
|
||||||
callbacks.add(deferred);
|
callbacks.add(deferred);
|
||||||
|
@ -20,7 +20,7 @@ import {
|
|||||||
HTTPResponse as BaseHTTPResponse,
|
HTTPResponse as BaseHTTPResponse,
|
||||||
RemoteAddress,
|
RemoteAddress,
|
||||||
} from '../api/HTTPResponse.js';
|
} from '../api/HTTPResponse.js';
|
||||||
import {createDeferred} from '../util/Deferred.js';
|
import {Deferred} from '../util/Deferred.js';
|
||||||
|
|
||||||
import {CDPSession} from './Connection.js';
|
import {CDPSession} from './Connection.js';
|
||||||
import {ProtocolError} from './Errors.js';
|
import {ProtocolError} from './Errors.js';
|
||||||
@ -34,7 +34,7 @@ export class HTTPResponse extends BaseHTTPResponse {
|
|||||||
#client: CDPSession;
|
#client: CDPSession;
|
||||||
#request: HTTPRequest;
|
#request: HTTPRequest;
|
||||||
#contentPromise: Promise<Buffer> | null = null;
|
#contentPromise: Promise<Buffer> | null = null;
|
||||||
#bodyLoadedDeferred = createDeferred<Error | void>();
|
#bodyLoadedDeferred = Deferred.create<Error | void>();
|
||||||
#remoteAddress: RemoteAddress;
|
#remoteAddress: RemoteAddress;
|
||||||
#status: number;
|
#status: number;
|
||||||
#statusText: string;
|
#statusText: string;
|
||||||
|
@ -19,7 +19,7 @@ import {Protocol} from 'devtools-protocol';
|
|||||||
import type {ClickOptions, ElementHandle} from '../api/ElementHandle.js';
|
import type {ClickOptions, ElementHandle} from '../api/ElementHandle.js';
|
||||||
import {JSHandle} from '../api/JSHandle.js';
|
import {JSHandle} from '../api/JSHandle.js';
|
||||||
import {assert} from '../util/assert.js';
|
import {assert} from '../util/assert.js';
|
||||||
import {createDeferred} from '../util/Deferred.js';
|
import {Deferred} from '../util/Deferred.js';
|
||||||
|
|
||||||
import {Binding} from './Binding.js';
|
import {Binding} from './Binding.js';
|
||||||
import {CDPSession} from './Connection.js';
|
import {CDPSession} from './Connection.js';
|
||||||
@ -101,7 +101,7 @@ export interface IsolatedWorldChart {
|
|||||||
export class IsolatedWorld {
|
export class IsolatedWorld {
|
||||||
#frame: Frame;
|
#frame: Frame;
|
||||||
#document?: ElementHandle<Document>;
|
#document?: ElementHandle<Document>;
|
||||||
#context = createDeferred<ExecutionContext>();
|
#context = Deferred.create<ExecutionContext>();
|
||||||
#detached = false;
|
#detached = false;
|
||||||
|
|
||||||
// Set of bindings that have been registered in the current context.
|
// Set of bindings that have been registered in the current context.
|
||||||
@ -144,7 +144,7 @@ export class IsolatedWorld {
|
|||||||
|
|
||||||
clearContext(): void {
|
clearContext(): void {
|
||||||
this.#document = undefined;
|
this.#document = undefined;
|
||||||
this.#context = createDeferred();
|
this.#context = Deferred.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
setContext(context: ExecutionContext): void {
|
setContext(context: ExecutionContext): void {
|
||||||
@ -304,7 +304,7 @@ export class IsolatedWorld {
|
|||||||
waitUntil,
|
waitUntil,
|
||||||
timeout
|
timeout
|
||||||
);
|
);
|
||||||
const error = await Promise.race([
|
const error = await Deferred.race<void | Error | undefined>([
|
||||||
watcher.timeoutOrTerminationPromise(),
|
watcher.timeoutOrTerminationPromise(),
|
||||||
watcher.lifecyclePromise(),
|
watcher.lifecyclePromise(),
|
||||||
]);
|
]);
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
import {HTTPResponse} from '../api/HTTPResponse.js';
|
import {HTTPResponse} from '../api/HTTPResponse.js';
|
||||||
import {assert} from '../util/assert.js';
|
import {assert} from '../util/assert.js';
|
||||||
import {Deferred, createDeferred} from '../util/Deferred.js';
|
import {Deferred} from '../util/Deferred.js';
|
||||||
|
|
||||||
import {CDPSessionEmittedEvents} from './Connection.js';
|
import {CDPSessionEmittedEvents} from './Connection.js';
|
||||||
import {TimeoutError} from './Errors.js';
|
import {TimeoutError} from './Errors.js';
|
||||||
@ -71,10 +71,10 @@ export class LifecycleWatcher {
|
|||||||
#eventListeners: PuppeteerEventListener[];
|
#eventListeners: PuppeteerEventListener[];
|
||||||
#initialLoaderId: string;
|
#initialLoaderId: string;
|
||||||
|
|
||||||
#sameDocumentNavigationDeferred = createDeferred<Error | undefined>();
|
#sameDocumentNavigationDeferred = Deferred.create<undefined>();
|
||||||
#lifecycleDeferred = createDeferred<void>();
|
#lifecycleDeferred = Deferred.create<void>();
|
||||||
#newDocumentNavigationDeferred = createDeferred<Error | undefined>();
|
#newDocumentNavigationDeferred = Deferred.create<undefined>();
|
||||||
#terminationDeferred = createDeferred<Error | undefined>();
|
#terminationDeferred = Deferred.create<Error>();
|
||||||
|
|
||||||
#timeoutPromise: Promise<TimeoutError | undefined>;
|
#timeoutPromise: Promise<TimeoutError | undefined>;
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ export class LifecycleWatcher {
|
|||||||
// navigation requests reported by the backend. This generally should not
|
// navigation requests reported by the backend. This generally should not
|
||||||
// happen by it looks like it's possible.
|
// happen by it looks like it's possible.
|
||||||
this.#navigationResponseReceived?.resolve();
|
this.#navigationResponseReceived?.resolve();
|
||||||
this.#navigationResponseReceived = createDeferred();
|
this.#navigationResponseReceived = Deferred.create();
|
||||||
if (request.response() !== null) {
|
if (request.response() !== null) {
|
||||||
this.#navigationResponseReceived?.resolve();
|
this.#navigationResponseReceived?.resolve();
|
||||||
}
|
}
|
||||||
@ -222,10 +222,7 @@ export class LifecycleWatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
timeoutOrTerminationPromise(): Promise<Error | TimeoutError | undefined> {
|
timeoutOrTerminationPromise(): Promise<Error | TimeoutError | undefined> {
|
||||||
return Promise.race([
|
return Deferred.race([this.#timeoutPromise, this.#terminationDeferred]);
|
||||||
this.#timeoutPromise,
|
|
||||||
this.#terminationDeferred.valueOrThrow(),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async #createTimeoutPromise(): Promise<TimeoutError | undefined> {
|
async #createTimeoutPromise(): Promise<TimeoutError | undefined> {
|
||||||
@ -299,6 +296,6 @@ export class LifecycleWatcher {
|
|||||||
|
|
||||||
dispose(): void {
|
dispose(): void {
|
||||||
removeEventListeners(this.#eventListeners);
|
removeEventListeners(this.#eventListeners);
|
||||||
this.#maximumTimer !== undefined && clearTimeout(this.#maximumTimer);
|
clearTimeout(this.#maximumTimer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ import {
|
|||||||
NewDocumentScriptEvaluation,
|
NewDocumentScriptEvaluation,
|
||||||
} from '../api/Page.js';
|
} from '../api/Page.js';
|
||||||
import {assert} from '../util/assert.js';
|
import {assert} from '../util/assert.js';
|
||||||
import {createDeferred, Deferred} from '../util/Deferred.js';
|
import {Deferred} from '../util/Deferred.js';
|
||||||
import {isErrorLike} from '../util/ErrorLike.js';
|
import {isErrorLike} from '../util/ErrorLike.js';
|
||||||
|
|
||||||
import {Accessibility} from './Accessibility.js';
|
import {Accessibility} from './Accessibility.js';
|
||||||
@ -153,7 +153,7 @@ export class CDPPage extends Page {
|
|||||||
#screenshotTaskQueue: TaskQueue;
|
#screenshotTaskQueue: TaskQueue;
|
||||||
#workers = new Map<string, WebWorker>();
|
#workers = new Map<string, WebWorker>();
|
||||||
#fileChooserDeferreds = new Set<Deferred<FileChooser>>();
|
#fileChooserDeferreds = new Set<Deferred<FileChooser>>();
|
||||||
#sessionCloseDeferred = createDeferred<TargetCloseError>();
|
#sessionCloseDeferred = Deferred.create<TargetCloseError>();
|
||||||
#serviceWorkerBypassed = false;
|
#serviceWorkerBypassed = false;
|
||||||
#userDragInterceptionEnabled = false;
|
#userDragInterceptionEnabled = false;
|
||||||
|
|
||||||
@ -374,7 +374,7 @@ export class CDPPage extends Page {
|
|||||||
): 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 = createDeferred<FileChooser>({
|
const deferred = Deferred.create<FileChooser>({
|
||||||
message: `Waiting for \`FileChooser\` failed: ${timeout}ms exceeded`,
|
message: `Waiting for \`FileChooser\` failed: ${timeout}ms exceeded`,
|
||||||
timeout,
|
timeout,
|
||||||
});
|
});
|
||||||
@ -1029,7 +1029,7 @@ export class CDPPage extends Page {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const eventRace: Promise<Frame> = Promise.race([
|
const eventRace: Promise<Frame> = Deferred.race([
|
||||||
waitForEvent(
|
waitForEvent(
|
||||||
this.#frameManager,
|
this.#frameManager,
|
||||||
FrameManagerEmittedEvents.FrameAttached,
|
FrameManagerEmittedEvents.FrameAttached,
|
||||||
|
@ -19,7 +19,7 @@ import {Protocol} from 'devtools-protocol';
|
|||||||
import type {Browser} from '../api/Browser.js';
|
import type {Browser} from '../api/Browser.js';
|
||||||
import type {BrowserContext} from '../api/BrowserContext.js';
|
import type {BrowserContext} from '../api/BrowserContext.js';
|
||||||
import {Page, PageEmittedEvents} from '../api/Page.js';
|
import {Page, PageEmittedEvents} from '../api/Page.js';
|
||||||
import {createDeferred} from '../util/Deferred.js';
|
import {Deferred} from '../util/Deferred.js';
|
||||||
|
|
||||||
import {CDPSession} from './Connection.js';
|
import {CDPSession} from './Connection.js';
|
||||||
import {CDPPage} from './Page.js';
|
import {CDPPage} from './Page.js';
|
||||||
@ -55,11 +55,11 @@ export class Target {
|
|||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
_initializedDeferred = createDeferred<InitializationStatus>();
|
_initializedDeferred = Deferred.create<InitializationStatus>();
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
_isClosedDeferred = createDeferred<void>();
|
_isClosedDeferred = Deferred.create<void>();
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import {ElementHandle} from '../api/ElementHandle.js';
|
import {ElementHandle} from '../api/ElementHandle.js';
|
||||||
import {JSHandle} from '../api/JSHandle.js';
|
import {JSHandle} from '../api/JSHandle.js';
|
||||||
import type {Poller} from '../injected/Poller.js';
|
import type {Poller} from '../injected/Poller.js';
|
||||||
import {createDeferred} from '../util/Deferred.js';
|
import {Deferred} from '../util/Deferred.js';
|
||||||
import {isErrorLike} from '../util/ErrorLike.js';
|
import {isErrorLike} from '../util/ErrorLike.js';
|
||||||
import {stringifyFunction} from '../util/Function.js';
|
import {stringifyFunction} from '../util/Function.js';
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ export class WaitTask<T = unknown> {
|
|||||||
|
|
||||||
#timeout?: NodeJS.Timeout;
|
#timeout?: NodeJS.Timeout;
|
||||||
|
|
||||||
#result = createDeferred<HandleFor<T>>();
|
#result = Deferred.create<HandleFor<T>>();
|
||||||
|
|
||||||
#poller?: JSHandle<Poller<T>>;
|
#poller?: JSHandle<Poller<T>>;
|
||||||
#signal?: AbortSignal;
|
#signal?: AbortSignal;
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
import {Protocol} from 'devtools-protocol';
|
import {Protocol} from 'devtools-protocol';
|
||||||
|
|
||||||
import {createDeferred} from '../util/Deferred.js';
|
import {Deferred} from '../util/Deferred.js';
|
||||||
|
|
||||||
import {CDPSession} from './Connection.js';
|
import {CDPSession} from './Connection.js';
|
||||||
import {ConsoleMessageType} from './ConsoleMessage.js';
|
import {ConsoleMessageType} from './ConsoleMessage.js';
|
||||||
@ -68,7 +68,7 @@ export type ExceptionThrownCallback = (
|
|||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export class WebWorker extends EventEmitter {
|
export class WebWorker extends EventEmitter {
|
||||||
#executionContext = createDeferred<ExecutionContext>();
|
#executionContext = Deferred.create<ExecutionContext>();
|
||||||
|
|
||||||
#client: CDPSession;
|
#client: CDPSession;
|
||||||
#url: string;
|
#url: string;
|
||||||
|
@ -25,7 +25,7 @@ import {
|
|||||||
WaitForOptions,
|
WaitForOptions,
|
||||||
} from '../../api/Page.js';
|
} from '../../api/Page.js';
|
||||||
import {assert} from '../../util/assert.js';
|
import {assert} from '../../util/assert.js';
|
||||||
import {createDeferred} from '../../util/Deferred.js';
|
import {Deferred} from '../../util/Deferred.js';
|
||||||
import {ConsoleMessage, ConsoleMessageLocation} from '../ConsoleMessage.js';
|
import {ConsoleMessage, ConsoleMessageLocation} from '../ConsoleMessage.js';
|
||||||
import {TargetCloseError} from '../Errors.js';
|
import {TargetCloseError} from '../Errors.js';
|
||||||
import {Handler} from '../EventEmitter.js';
|
import {Handler} from '../EventEmitter.js';
|
||||||
@ -61,7 +61,7 @@ export class Page extends PageBase {
|
|||||||
#frameTree = new FrameTree<Frame>();
|
#frameTree = new FrameTree<Frame>();
|
||||||
#networkManager: NetworkManager;
|
#networkManager: NetworkManager;
|
||||||
#viewport: Viewport | null = null;
|
#viewport: Viewport | null = null;
|
||||||
#closedDeferred = createDeferred<TargetCloseError>();
|
#closedDeferred = Deferred.create<TargetCloseError>();
|
||||||
#subscribedEvents = new Map<string, Handler<any>>([
|
#subscribedEvents = new Map<string, Handler<any>>([
|
||||||
['log.entryAdded', this.#onLogEntryAdded.bind(this)],
|
['log.entryAdded', this.#onLogEntryAdded.bind(this)],
|
||||||
[
|
[
|
||||||
|
@ -22,8 +22,8 @@ import type {ElementHandle} from '../api/ElementHandle.js';
|
|||||||
import type {JSHandle} from '../api/JSHandle.js';
|
import type {JSHandle} from '../api/JSHandle.js';
|
||||||
import {Page} from '../api/Page.js';
|
import {Page} from '../api/Page.js';
|
||||||
import {isNode} from '../environment.js';
|
import {isNode} from '../environment.js';
|
||||||
|
import {Deferred} from '../puppeteer-core.js';
|
||||||
import {assert} from '../util/assert.js';
|
import {assert} from '../util/assert.js';
|
||||||
import {createDeferred} from '../util/Deferred.js';
|
|
||||||
import {isErrorLike} from '../util/ErrorLike.js';
|
import {isErrorLike} from '../util/ErrorLike.js';
|
||||||
|
|
||||||
import type {CDPSession} from './Connection.js';
|
import type {CDPSession} from './Connection.js';
|
||||||
@ -382,7 +382,7 @@ export async function waitForEvent<T>(
|
|||||||
timeout: number,
|
timeout: number,
|
||||||
abortPromise: Promise<Error>
|
abortPromise: Promise<Error>
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
const deferred = createDeferred<T>({
|
const deferred = Deferred.create<T>({
|
||||||
message: `Timeout exceeded while waiting for event ${String(eventName)}`,
|
message: `Timeout exceeded while waiting for event ${String(eventName)}`,
|
||||||
timeout,
|
timeout,
|
||||||
});
|
});
|
||||||
@ -391,23 +391,19 @@ export async function waitForEvent<T>(
|
|||||||
deferred.resolve(event);
|
deferred.resolve(event);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return Promise.race([deferred.valueOrThrow(), abortPromise])
|
return Deferred.race<T | Error>([deferred, abortPromise]).then(
|
||||||
.then(
|
r => {
|
||||||
r => {
|
removeEventListeners([listener]);
|
||||||
removeEventListeners([listener]);
|
if (isErrorLike(r)) {
|
||||||
if (isErrorLike(r)) {
|
throw r;
|
||||||
throw r;
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
},
|
|
||||||
error => {
|
|
||||||
removeEventListeners([listener]);
|
|
||||||
throw error;
|
|
||||||
}
|
}
|
||||||
)
|
return r;
|
||||||
.finally(() => {
|
},
|
||||||
deferred.reject(new Error('Cleared'));
|
error => {
|
||||||
});
|
removeEventListeners([listener]);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -509,12 +505,12 @@ export async function waitWithTimeout<T>(
|
|||||||
taskName: string,
|
taskName: string,
|
||||||
timeout: number
|
timeout: number
|
||||||
): Promise<T> {
|
): Promise<T> {
|
||||||
const deferred = createDeferred<never>({
|
const deferred = Deferred.create<never>({
|
||||||
message: `waiting for ${taskName} failed: timeout ${timeout}ms exceeded`,
|
message: `waiting for ${taskName} failed: timeout ${timeout}ms exceeded`,
|
||||||
timeout,
|
timeout,
|
||||||
});
|
});
|
||||||
|
|
||||||
return await Promise.race([promise, deferred.valueOrThrow()]).finally(() => {
|
return await Deferred.race([promise, deferred.valueOrThrow()]).finally(() => {
|
||||||
deferred.reject(new Error('Cleared'));
|
deferred.reject(new Error('Cleared'));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {assert} from '../util/assert.js';
|
import {assert} from '../util/assert.js';
|
||||||
import {createDeferred, Deferred} from '../util/Deferred.js';
|
import {Deferred} from '../util/Deferred.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
@ -42,7 +42,7 @@ export class MutationPoller<T> implements Poller<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async start(): Promise<void> {
|
async start(): Promise<void> {
|
||||||
const deferred = (this.#deferred = createDeferred<T>());
|
const deferred = (this.#deferred = Deferred.create<T>());
|
||||||
const result = await this.#fn();
|
const result = await this.#fn();
|
||||||
if (result) {
|
if (result) {
|
||||||
deferred.resolve(result);
|
deferred.resolve(result);
|
||||||
@ -92,7 +92,7 @@ export class RAFPoller<T> implements Poller<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async start(): Promise<void> {
|
async start(): Promise<void> {
|
||||||
const deferred = (this.#deferred = createDeferred<T>());
|
const deferred = (this.#deferred = Deferred.create<T>());
|
||||||
const result = await this.#fn();
|
const result = await this.#fn();
|
||||||
if (result) {
|
if (result) {
|
||||||
deferred.resolve(result);
|
deferred.resolve(result);
|
||||||
@ -143,7 +143,7 @@ export class IntervalPoller<T> implements Poller<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async start(): Promise<void> {
|
async start(): Promise<void> {
|
||||||
const deferred = (this.#deferred = createDeferred<T>());
|
const deferred = (this.#deferred = Deferred.create<T>());
|
||||||
const result = await this.#fn();
|
const result = await this.#fn();
|
||||||
if (result) {
|
if (result) {
|
||||||
deferred.resolve(result);
|
deferred.resolve(result);
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {createDeferred} from '../util/Deferred.js';
|
import {Deferred} from '../util/Deferred.js';
|
||||||
import {createFunction} from '../util/Function.js';
|
import {createFunction} from '../util/Function.js';
|
||||||
|
|
||||||
import * as ARIAQuerySelector from './ARIAQuerySelector.js';
|
import * as ARIAQuerySelector from './ARIAQuerySelector.js';
|
||||||
@ -41,7 +41,7 @@ const PuppeteerUtil = Object.freeze({
|
|||||||
...TextQuerySelector,
|
...TextQuerySelector,
|
||||||
...util,
|
...util,
|
||||||
...XPathQuerySelector,
|
...XPathQuerySelector,
|
||||||
createDeferred,
|
Deferred,
|
||||||
createFunction,
|
createFunction,
|
||||||
createTextContent,
|
createTextContent,
|
||||||
IntervalPoller,
|
IntervalPoller,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import {DEFERRED_PROMISE_DEBUG_TIMEOUT} from '../environment.js';
|
import {DEFERRED_PROMISE_DEBUG_TIMEOUT} from '../environment.js';
|
||||||
|
|
||||||
import {Deferred, createDeferred} from './Deferred.js';
|
import {Deferred} from './Deferred.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and returns a deferred promise using DEFERRED_PROMISE_DEBUG_TIMEOUT
|
* Creates and returns a deferred promise using DEFERRED_PROMISE_DEBUG_TIMEOUT
|
||||||
@ -10,10 +10,10 @@ import {Deferred, createDeferred} from './Deferred.js';
|
|||||||
*/
|
*/
|
||||||
export function createDebuggableDeferred<T>(message: string): Deferred<T> {
|
export function createDebuggableDeferred<T>(message: string): Deferred<T> {
|
||||||
if (DEFERRED_PROMISE_DEBUG_TIMEOUT > 0) {
|
if (DEFERRED_PROMISE_DEBUG_TIMEOUT > 0) {
|
||||||
return createDeferred({
|
return Deferred.create({
|
||||||
message,
|
message,
|
||||||
timeout: DEFERRED_PROMISE_DEBUG_TIMEOUT,
|
timeout: DEFERRED_PROMISE_DEBUG_TIMEOUT,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return createDeferred();
|
return Deferred.create();
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,5 @@
|
|||||||
import {TimeoutError} from '../common/Errors.js';
|
import {TimeoutError} from '../common/Errors.js';
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
export interface Deferred<T> {
|
|
||||||
finished: () => boolean;
|
|
||||||
resolved: () => boolean;
|
|
||||||
resolve: (value: T) => void;
|
|
||||||
reject: (error: Error) => void;
|
|
||||||
value: () => T | Error | undefined;
|
|
||||||
valueOrThrow: () => Promise<T>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
@ -29,61 +17,94 @@ export interface DeferredOptions {
|
|||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
export function createDeferred<T>(opts?: DeferredOptions): Deferred<T> {
|
export class Deferred<T> {
|
||||||
let isResolved = false;
|
#isResolved = false;
|
||||||
let isRejected = false;
|
#isRejected = false;
|
||||||
let _value: T | Error | undefined;
|
#value: T | Error | undefined;
|
||||||
let resolver: (value: void) => void;
|
#resolver: (value: void) => void = () => {};
|
||||||
const taskPromise = new Promise<void>(resolve => {
|
#taskPromise = new Promise<void>(resolve => {
|
||||||
resolver = resolve;
|
this.#resolver = resolve;
|
||||||
});
|
});
|
||||||
const timeoutId =
|
#timeoutId: ReturnType<typeof setTimeout> | undefined;
|
||||||
opts && opts.timeout > 0
|
|
||||||
? setTimeout(() => {
|
|
||||||
reject(new TimeoutError(opts.message));
|
|
||||||
}, opts.timeout)
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
function finish(value: T | Error) {
|
constructor(opts?: DeferredOptions) {
|
||||||
clearTimeout(timeoutId);
|
this.#timeoutId =
|
||||||
_value = value;
|
opts && opts.timeout > 0
|
||||||
resolver();
|
? setTimeout(() => {
|
||||||
|
this.reject(new TimeoutError(opts.message));
|
||||||
|
}, opts.timeout)
|
||||||
|
: undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolve(value: T) {
|
#finish(value: T | Error) {
|
||||||
if (isRejected || isResolved) {
|
clearTimeout(this.#timeoutId);
|
||||||
|
this.#value = value;
|
||||||
|
this.#resolver();
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(value: T): void {
|
||||||
|
if (this.#isRejected || this.#isResolved) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
isResolved = true;
|
this.#isResolved = true;
|
||||||
finish(value);
|
this.#finish(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
function reject(error: Error) {
|
reject(error: Error): void {
|
||||||
if (isRejected || isResolved) {
|
if (this.#isRejected || this.#isResolved) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
isRejected = true;
|
this.#isRejected = true;
|
||||||
finish(error);
|
this.#finish(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
resolved(): boolean {
|
||||||
resolved: () => {
|
return this.#isResolved;
|
||||||
return isResolved;
|
}
|
||||||
},
|
|
||||||
finished: () => {
|
finished(): boolean {
|
||||||
return isResolved || isRejected;
|
return this.#isResolved || this.#isRejected;
|
||||||
},
|
}
|
||||||
resolve,
|
|
||||||
reject,
|
value(): T | Error | undefined {
|
||||||
value: () => {
|
return this.#value;
|
||||||
return _value;
|
}
|
||||||
},
|
|
||||||
async valueOrThrow() {
|
async valueOrThrow(): Promise<T> {
|
||||||
await taskPromise;
|
await this.#taskPromise;
|
||||||
if (isRejected) {
|
if (this.#isRejected) {
|
||||||
throw _value;
|
throw this.#value;
|
||||||
|
}
|
||||||
|
return this.#value as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
static create<R>(opts?: DeferredOptions): Deferred<R> {
|
||||||
|
return new Deferred<R>(opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async race<R>(
|
||||||
|
awaitables: Array<Promise<R> | Deferred<R>>
|
||||||
|
): Promise<R> {
|
||||||
|
const deferredWithTimeout: Set<Deferred<R>> = new Set();
|
||||||
|
try {
|
||||||
|
const promises = awaitables.map(value => {
|
||||||
|
if (value instanceof Deferred) {
|
||||||
|
deferredWithTimeout.add(value);
|
||||||
|
|
||||||
|
return value.valueOrThrow();
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
|
return await Promise.race(promises);
|
||||||
|
} finally {
|
||||||
|
for (const deferred of deferredWithTimeout) {
|
||||||
|
// We need to stop the timeout else
|
||||||
|
// Node.JS will keep running the event loop till the
|
||||||
|
// timer executes
|
||||||
|
deferred.reject(new Error('Timeout cleared'));
|
||||||
}
|
}
|
||||||
return _value as T;
|
}
|
||||||
},
|
}
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import expect from 'expect';
|
import expect from 'expect';
|
||||||
import {
|
import {Deferred} from 'puppeteer-core/internal/util/Deferred.js';
|
||||||
Deferred,
|
|
||||||
createDeferred,
|
|
||||||
} from 'puppeteer-core/internal/util/Deferred.js';
|
|
||||||
|
|
||||||
describe('DeferredPromise', function () {
|
describe('DeferredPromise', function () {
|
||||||
it('should catch errors', async () => {
|
it('should catch errors', async () => {
|
||||||
@ -30,7 +27,7 @@ describe('DeferredPromise', function () {
|
|||||||
}
|
}
|
||||||
// Async function that fails.
|
// Async function that fails.
|
||||||
function fails(): Deferred<void> {
|
function fails(): Deferred<void> {
|
||||||
const deferred = createDeferred<void>();
|
const deferred = Deferred.create<void>();
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
deferred.reject(new Error('test'));
|
deferred.reject(new Error('test'));
|
||||||
}, 25);
|
}, 25);
|
||||||
|
Loading…
Reference in New Issue
Block a user