mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
chore: inverse FrameTask callbacks/promises (#2478)
Alternative way to handle this indirection.
This commit is contained in:
parent
c08da50bb3
commit
87e0c96ef2
120
src/frames.ts
120
src/frames.ts
@ -940,7 +940,7 @@ class RerunnableTask<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class SignalBarrier {
|
class SignalBarrier {
|
||||||
private _progress: Progress | null;
|
private _progress: Progress | null;
|
||||||
private _protectCount = 0;
|
private _protectCount = 0;
|
||||||
private _promise: Promise<void>;
|
private _promise: Promise<void>;
|
||||||
@ -976,45 +976,28 @@ export class SignalBarrier {
|
|||||||
|
|
||||||
release() {
|
release() {
|
||||||
--this._protectCount;
|
--this._protectCount;
|
||||||
this._maybeResolve();
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _maybeResolve() {
|
|
||||||
if (!this._protectCount)
|
if (!this._protectCount)
|
||||||
this._promiseCallback();
|
this._promiseCallback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class FrameTask {
|
class FrameTask {
|
||||||
private _frame: Frame;
|
private readonly _frame: Frame;
|
||||||
private _requestMap = new Map<string, network.Request>();
|
private readonly _requestMap = new Map<string, network.Request>();
|
||||||
private readonly _progress: Progress | null = null;
|
private readonly _progress: Progress | null = null;
|
||||||
|
private _onSameDocument?: { url?: types.URLMatch, resolve: () => void };
|
||||||
onNewDocument: (documentId: string, error?: Error) => void;
|
private _onSpecificDocument?: { expectedDocumentId: string, resolve: () => void, reject: (error: Error) => void };
|
||||||
onSameDocument: (documentId?: string, error?: Error) => void;
|
private _onNewDocument?: { url?: types.URLMatch, resolve: (documentId: string) => void, reject: (error: Error) => void };
|
||||||
onLifecycle: (frame: Frame, lifecycleEvent?: types.LifecycleEvent) => void;
|
private _onLifecycle?: { waitUntil: types.LifecycleEvent, resolve: () => void };
|
||||||
|
|
||||||
constructor(frame: Frame, progress: Progress | null) {
|
constructor(frame: Frame, progress: Progress | null) {
|
||||||
this._frame = frame;
|
this._frame = frame;
|
||||||
frame._frameTasks.add(this);
|
frame._frameTasks.add(this);
|
||||||
this._progress = progress;
|
this._progress = progress;
|
||||||
this.onSameDocument = this._logUrl.bind(this);
|
|
||||||
this.onNewDocument = this._logUrl.bind(this);
|
|
||||||
this.onLifecycle = this._logLifecycle.bind(this);
|
|
||||||
if (progress)
|
if (progress)
|
||||||
progress.cleanupWhenAborted(() => this.done());
|
progress.cleanupWhenAborted(() => this.done());
|
||||||
}
|
}
|
||||||
|
|
||||||
private _logUrl(documentId?: string, error?: Error) {
|
|
||||||
if (this._progress && !error)
|
|
||||||
this._progress.log(apiLog, `navigated to "${this._frame._url}"`);
|
|
||||||
}
|
|
||||||
|
|
||||||
private _logLifecycle(frame: Frame, lifecycleEvent?: types.LifecycleEvent) {
|
|
||||||
if (this._progress && frame === this._frame && lifecycleEvent && frame._url !== 'about:blank')
|
|
||||||
this._progress.log(apiLog, `"${lifecycleEvent}" event fired`);
|
|
||||||
}
|
|
||||||
|
|
||||||
onRequest(request: network.Request) {
|
onRequest(request: network.Request) {
|
||||||
if (!request._documentId || request.redirectedFrom())
|
if (!request._documentId || request.redirectedFrom())
|
||||||
return;
|
return;
|
||||||
@ -1025,43 +1008,59 @@ export class FrameTask {
|
|||||||
return this._requestMap.get(documentId);
|
return this._requestMap.get(documentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onSameDocument() {
|
||||||
|
if (this._progress)
|
||||||
|
this._progress.log(apiLog, `navigated to "${this._frame._url}"`);
|
||||||
|
if (this._onSameDocument && helper.urlMatches(this._frame.url(), this._onSameDocument.url))
|
||||||
|
this._onSameDocument.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
onNewDocument(documentId: string, error?: Error) {
|
||||||
|
if (this._progress && !error)
|
||||||
|
this._progress.log(apiLog, `navigated to "${this._frame._url}"`);
|
||||||
|
if (this._onSpecificDocument) {
|
||||||
|
if (documentId === this._onSpecificDocument.expectedDocumentId) {
|
||||||
|
if (error)
|
||||||
|
this._onSpecificDocument.reject(error);
|
||||||
|
else
|
||||||
|
this._onSpecificDocument.resolve();
|
||||||
|
} else if (!error) {
|
||||||
|
this._onSpecificDocument.reject(new Error('Navigation interrupted by another one'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this._onNewDocument) {
|
||||||
|
if (error)
|
||||||
|
this._onNewDocument.reject(error);
|
||||||
|
else if (helper.urlMatches(this._frame.url(), this._onNewDocument.url))
|
||||||
|
this._onNewDocument.resolve(documentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onLifecycle(frame: Frame, lifecycleEvent: types.LifecycleEvent) {
|
||||||
|
if (this._progress && frame === this._frame && frame._url !== 'about:blank')
|
||||||
|
this._progress.log(apiLog, `"${lifecycleEvent}" event fired`);
|
||||||
|
if (this._onLifecycle && this._checkLifecycleRecursively(this._frame, this._onLifecycle.waitUntil))
|
||||||
|
this._onLifecycle.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
waitForSameDocumentNavigation(url?: types.URLMatch): Promise<void> {
|
waitForSameDocumentNavigation(url?: types.URLMatch): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise(resolve => {
|
||||||
this.onSameDocument = () => {
|
assert(!this._onSameDocument);
|
||||||
this._logUrl();
|
this._onSameDocument = { url, resolve };
|
||||||
if (helper.urlMatches(this._frame.url(), url))
|
|
||||||
resolve();
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForSpecificDocument(expectedDocumentId: string): Promise<void> {
|
waitForSpecificDocument(expectedDocumentId: string): Promise<void> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.onNewDocument = (documentId: string, error?: Error) => {
|
assert(!this._onSpecificDocument);
|
||||||
this._logUrl(documentId, error);
|
this._onSpecificDocument = { expectedDocumentId, resolve, reject };
|
||||||
if (documentId === expectedDocumentId) {
|
|
||||||
if (!error)
|
|
||||||
resolve();
|
|
||||||
else
|
|
||||||
reject(error);
|
|
||||||
} else if (!error) {
|
|
||||||
reject(new Error('Navigation interrupted by another one'));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
waitForNewDocument(url?: types.URLMatch): Promise<string> {
|
waitForNewDocument(url?: types.URLMatch): Promise<string> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
this.onNewDocument = (documentId: string, error?: Error) => {
|
assert(!this._onNewDocument);
|
||||||
this._logUrl(documentId, error);
|
this._onNewDocument = { url, resolve, reject };
|
||||||
if (!error && !helper.urlMatches(this._frame.url(), url))
|
|
||||||
return;
|
|
||||||
if (error)
|
|
||||||
reject(error);
|
|
||||||
else
|
|
||||||
resolve(documentId);
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1070,26 +1069,23 @@ export class FrameTask {
|
|||||||
waitUntil = 'networkidle';
|
waitUntil = 'networkidle';
|
||||||
if (!types.kLifecycleEvents.has(waitUntil))
|
if (!types.kLifecycleEvents.has(waitUntil))
|
||||||
throw new Error(`Unsupported waitUntil option ${String(waitUntil)}`);
|
throw new Error(`Unsupported waitUntil option ${String(waitUntil)}`);
|
||||||
return new Promise((resolve, reject) => {
|
if (this._checkLifecycleRecursively(this._frame, waitUntil))
|
||||||
this.onLifecycle = (frame: Frame, lifecycleEvent?: types.LifecycleEvent) => {
|
return Promise.resolve();
|
||||||
this._logLifecycle(frame, lifecycleEvent);
|
return new Promise(resolve => {
|
||||||
if (!checkLifecycleRecursively(this._frame))
|
assert(!this._onLifecycle);
|
||||||
return;
|
this._onLifecycle = { waitUntil, resolve };
|
||||||
resolve();
|
|
||||||
};
|
|
||||||
this.onLifecycle(this._frame);
|
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function checkLifecycleRecursively(frame: Frame): boolean {
|
private _checkLifecycleRecursively(frame: Frame, waitUntil: types.LifecycleEvent): boolean {
|
||||||
if (!frame._firedLifecycleEvents.has(waitUntil))
|
if (!frame._firedLifecycleEvents.has(waitUntil))
|
||||||
return false;
|
return false;
|
||||||
for (const child of frame.childFrames()) {
|
for (const child of frame.childFrames()) {
|
||||||
if (!checkLifecycleRecursively(child))
|
if (!this._checkLifecycleRecursively(child, waitUntil))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
done() {
|
done() {
|
||||||
this._frame._frameTasks.delete(this);
|
this._frame._frameTasks.delete(this);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user