Skip to content

Commit

Permalink
chore: refactor waitForNetworkIdle + waitForEvent (#10277)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lightning00Blade committed May 31, 2023
1 parent 54d6192 commit e61d9cb
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 44 deletions.
21 changes: 10 additions & 11 deletions packages/puppeteer-core/src/api/Page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1641,31 +1641,28 @@ export class Page extends EventEmitter {
const idleDeferred = createDeferred<void>();
const abortDeferred = createDeferred<Error>();

let idleTimer: NodeJS.Timeout;
let idleTimer: NodeJS.Timeout | undefined;
const cleanup = () => {
idleTimer && clearTimeout(idleTimer);
clearTimeout(idleTimer);
abortDeferred.reject(new Error('abort'));
};

const evaluate = () => {
idleTimer && clearTimeout(idleTimer);
clearTimeout(idleTimer);

if (networkManager.inFlightRequestsCount() === 0) {
idleTimer = setTimeout(idleDeferred.resolve, idleTime);
}
};

evaluate();

const eventHandler = () => {
evaluate();
return false;
};

const listenToEvent = (event: symbol) => {
return waitForEvent(
networkManager,
event,
eventHandler,
() => {
evaluate();
return false;
},
timeout,
abortDeferred.valueOrThrow()
);
Expand All @@ -1677,6 +1674,8 @@ export class Page extends EventEmitter {
listenToEvent(NetworkManagerEmittedEvents.RequestFailed),
];

evaluate();

await Promise.race([
idleDeferred.valueOrThrow(),
...eventPromises,
Expand Down
8 changes: 4 additions & 4 deletions packages/puppeteer-core/src/common/NetworkEventManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,13 @@ export class NetworkEventManager {
}

inFlightRequestsCount(): number {
let inProgressRequestCounter = 0;
for (const [, request] of this.#httpRequestsMap) {
let inFlightRequestCounter = 0;
for (const request of this.#httpRequestsMap.values()) {
if (!request.response()) {
inProgressRequestCounter++;
inFlightRequestCounter++;
}
}
return inProgressRequestCounter;
return inFlightRequestCounter;
}

storeRequestWillBeSent(
Expand Down
2 changes: 1 addition & 1 deletion packages/puppeteer-core/src/common/bidi/NetworkManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export class NetworkManager extends EventEmitter {

inFlightRequestsCount(): number {
let inFlightRequestCounter = 0;
for (const [, request] of this.#requestMap) {
for (const request of this.#requestMap.values()) {
if (!request.response() || request._failureText) {
inFlightRequestCounter++;
}
Expand Down
40 changes: 12 additions & 28 deletions packages/puppeteer-core/src/common/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import type {ElementHandle} from '../api/ElementHandle.js';
import type {JSHandle} from '../api/JSHandle.js';
import {Page} from '../api/Page.js';
import {isNode} from '../environment.js';
import {createDeferred} from '../puppeteer-core.js';
import {assert} from '../util/assert.js';
import {isErrorLike} from '../util/ErrorLike.js';

Expand Down Expand Up @@ -382,45 +383,28 @@ export async function waitForEvent<T>(
timeout: number,
abortPromise: Promise<Error>
): Promise<T> {
let eventTimeout: NodeJS.Timeout;
let resolveCallback: (value: T | PromiseLike<T>) => void;
let rejectCallback: (value: Error) => void;
const promise = new Promise<T>((resolve, reject) => {
resolveCallback = resolve;
rejectCallback = reject;
const deferred = createDeferred<T>({
message: `Timeout exceeded while waiting for event ${String(eventName)}`,
timeout,
});
const listener = addEventListener(emitter, eventName, async event => {
if (!(await predicate(event))) {
return;
if (await predicate(event)) {
deferred.resolve(event);
}
resolveCallback(event);
});
if (timeout) {
eventTimeout = setTimeout(() => {
rejectCallback(
new TimeoutError('Timeout exceeded while waiting for event')
);
}, timeout);
}
function cleanup(): void {
removeEventListeners([listener]);
clearTimeout(eventTimeout);
}
const result = await Promise.race([promise, abortPromise]).then(
return Promise.race([deferred.valueOrThrow(), abortPromise]).then(
r => {
cleanup();
removeEventListeners([listener]);
if (isErrorLike(r)) {
throw r;
}
return r;
},
error => {
cleanup();
removeEventListeners([listener]);
throw error;
}
);
if (isErrorLike(result)) {
throw result;
}

return result;
}

/**
Expand Down
6 changes: 6 additions & 0 deletions test/TestExpectations.json
Original file line number Diff line number Diff line change
Expand Up @@ -2099,6 +2099,12 @@
"parameters": ["chrome", "webDriverBiDi"],
"expectations": ["PASS"]
},
{
"testIdPattern": "[page.spec] Page Page.waitForNetworkIdle should work",
"platforms": ["darwin", "linux", "win32"],
"parameters": ["firefox", "webDriverBiDi"],
"expectations": ["FAIL"]
},
{
"testIdPattern": "[page.spec] Page Page.waitForNetworkIdle should work with aborted requests",
"platforms": ["linux"],
Expand Down

0 comments on commit e61d9cb

Please sign in to comment.