chore: introduce manual promise helper (#8533)
This commit is contained in:
parent
d3a8c38b7e
commit
dd31f3bd43
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { assert } from '../utils/utils';
|
import { assert, ManualPromise } from '../utils/utils';
|
||||||
import { SdkObject } from './instrumentation';
|
import { SdkObject } from './instrumentation';
|
||||||
|
|
||||||
type SaveCallback = (localPath: string, error?: string) => Promise<void>;
|
type SaveCallback = (localPath: string, error?: string) => Promise<void>;
|
||||||
|
|
@ -25,8 +25,7 @@ export class Artifact extends SdkObject {
|
||||||
private _localPath: string;
|
private _localPath: string;
|
||||||
private _unaccessibleErrorMessage: string | undefined;
|
private _unaccessibleErrorMessage: string | undefined;
|
||||||
private _cancelCallback: CancelCallback | undefined;
|
private _cancelCallback: CancelCallback | undefined;
|
||||||
private _finishedCallback: () => void;
|
private _finishedPromise = new ManualPromise<void>();
|
||||||
private _finishedPromise: Promise<void>;
|
|
||||||
private _saveCallbacks: SaveCallback[] = [];
|
private _saveCallbacks: SaveCallback[] = [];
|
||||||
private _finished: boolean = false;
|
private _finished: boolean = false;
|
||||||
private _deleted = false;
|
private _deleted = false;
|
||||||
|
|
@ -37,8 +36,6 @@ export class Artifact extends SdkObject {
|
||||||
this._localPath = localPath;
|
this._localPath = localPath;
|
||||||
this._unaccessibleErrorMessage = unaccessibleErrorMessage;
|
this._unaccessibleErrorMessage = unaccessibleErrorMessage;
|
||||||
this._cancelCallback = cancelCallback;
|
this._cancelCallback = cancelCallback;
|
||||||
this._finishedCallback = () => {};
|
|
||||||
this._finishedPromise = new Promise(f => this._finishedCallback = f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
finishedPromise() {
|
finishedPromise() {
|
||||||
|
|
@ -122,6 +119,6 @@ export class Artifact extends SdkObject {
|
||||||
}
|
}
|
||||||
this._saveCallbacks = [];
|
this._saveCallbacks = [];
|
||||||
|
|
||||||
this._finishedCallback();
|
this._finishedPromise.resolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import * as dialog from '../dialog';
|
||||||
import * as dom from '../dom';
|
import * as dom from '../dom';
|
||||||
import * as frames from '../frames';
|
import * as frames from '../frames';
|
||||||
import { eventsHelper, RegisteredListener } from '../../utils/eventsHelper';
|
import { eventsHelper, RegisteredListener } from '../../utils/eventsHelper';
|
||||||
import { assert } from '../../utils/utils';
|
import { assert, ManualPromise } from '../../utils/utils';
|
||||||
import { Page, PageBinding, PageDelegate, Worker } from '../page';
|
import { Page, PageBinding, PageDelegate, Worker } from '../page';
|
||||||
import * as types from '../types';
|
import * as types from '../types';
|
||||||
import { getAccessibilityTree } from './ffAccessibility';
|
import { getAccessibilityTree } from './ffAccessibility';
|
||||||
|
|
@ -44,8 +44,7 @@ export class FFPage implements PageDelegate {
|
||||||
readonly _page: Page;
|
readonly _page: Page;
|
||||||
readonly _networkManager: FFNetworkManager;
|
readonly _networkManager: FFNetworkManager;
|
||||||
readonly _browserContext: FFBrowserContext;
|
readonly _browserContext: FFBrowserContext;
|
||||||
private _pagePromise: Promise<Page | Error>;
|
private _pagePromise = new ManualPromise<Page | Error>();
|
||||||
private _pageCallback: (pageOrError: Page | Error) => void = () => {};
|
|
||||||
_initializedPage: Page | null = null;
|
_initializedPage: Page | null = null;
|
||||||
private _initializationFailed = false;
|
private _initializationFailed = false;
|
||||||
readonly _opener: FFPage | null;
|
readonly _opener: FFPage | null;
|
||||||
|
|
@ -95,7 +94,6 @@ export class FFPage implements PageDelegate {
|
||||||
eventsHelper.addEventListener(this._session, 'Page.screencastFrame', this._onScreencastFrame.bind(this)),
|
eventsHelper.addEventListener(this._session, 'Page.screencastFrame', this._onScreencastFrame.bind(this)),
|
||||||
|
|
||||||
];
|
];
|
||||||
this._pagePromise = new Promise(f => this._pageCallback = f);
|
|
||||||
session.once(FFSessionEvents.Disconnected, () => {
|
session.once(FFSessionEvents.Disconnected, () => {
|
||||||
this._markAsError(new Error('Page closed'));
|
this._markAsError(new Error('Page closed'));
|
||||||
this._page._didDisconnect();
|
this._page._didDisconnect();
|
||||||
|
|
@ -108,7 +106,7 @@ export class FFPage implements PageDelegate {
|
||||||
// so that anyone who awaits pageOrError got a ready and reported page.
|
// so that anyone who awaits pageOrError got a ready and reported page.
|
||||||
this._initializedPage = this._page;
|
this._initializedPage = this._page;
|
||||||
this._page.reportAsNew();
|
this._page.reportAsNew();
|
||||||
this._pageCallback(this._page);
|
this._pagePromise.resolve(this._page);
|
||||||
});
|
});
|
||||||
// Ideally, we somehow ensure that utility world is created before Page.ready arrives, but currently it is racy.
|
// Ideally, we somehow ensure that utility world is created before Page.ready arrives, but currently it is racy.
|
||||||
// Therefore, we can end up with an initialized page without utility world, although very unlikely.
|
// Therefore, we can end up with an initialized page without utility world, although very unlikely.
|
||||||
|
|
@ -124,7 +122,7 @@ export class FFPage implements PageDelegate {
|
||||||
if (!this._initializedPage) {
|
if (!this._initializedPage) {
|
||||||
await this._page.initOpener(this._opener);
|
await this._page.initOpener(this._opener);
|
||||||
this._page.reportAsNew(error);
|
this._page.reportAsNew(error);
|
||||||
this._pageCallback(error);
|
this._pagePromise.resolve(error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import { Page } from './page';
|
||||||
import * as types from './types';
|
import * as types from './types';
|
||||||
import { BrowserContext } from './browserContext';
|
import { BrowserContext } from './browserContext';
|
||||||
import { Progress, ProgressController } from './progress';
|
import { Progress, ProgressController } from './progress';
|
||||||
import { assert, constructURLBasedOnBaseURL, makeWaitForNextTask } from '../utils/utils';
|
import { assert, constructURLBasedOnBaseURL, makeWaitForNextTask, ManualPromise } from '../utils/utils';
|
||||||
import { debugLogger } from '../utils/debugLogger';
|
import { debugLogger } from '../utils/debugLogger';
|
||||||
import { CallMetadata, internalCallMetadata, SdkObject } from './instrumentation';
|
import { CallMetadata, internalCallMetadata, SdkObject } from './instrumentation';
|
||||||
import { ElementStateWithoutStable } from './injected/injectedScript';
|
import { ElementStateWithoutStable } from './injected/injectedScript';
|
||||||
|
|
@ -1364,16 +1364,14 @@ class RerunnableTask {
|
||||||
class SignalBarrier {
|
class SignalBarrier {
|
||||||
private _progress: Progress | null;
|
private _progress: Progress | null;
|
||||||
private _protectCount = 0;
|
private _protectCount = 0;
|
||||||
private _promise: Promise<void>;
|
private _promise = new ManualPromise<void>();
|
||||||
private _promiseCallback = () => {};
|
|
||||||
|
|
||||||
constructor(progress: Progress | null) {
|
constructor(progress: Progress | null) {
|
||||||
this._progress = progress;
|
this._progress = progress;
|
||||||
this._promise = new Promise(f => this._promiseCallback = f);
|
|
||||||
this.retain();
|
this.retain();
|
||||||
}
|
}
|
||||||
|
|
||||||
waitFor(): Promise<void> {
|
waitFor(): PromiseLike<void> {
|
||||||
this.release();
|
this.release();
|
||||||
return this._promise;
|
return this._promise;
|
||||||
}
|
}
|
||||||
|
|
@ -1405,7 +1403,7 @@ class SignalBarrier {
|
||||||
release() {
|
release() {
|
||||||
--this._protectCount;
|
--this._protectCount;
|
||||||
if (!this._protectCount)
|
if (!this._protectCount)
|
||||||
this._promiseCallback();
|
this._promise.resolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
import * as frames from './frames';
|
import * as frames from './frames';
|
||||||
import * as types from './types';
|
import * as types from './types';
|
||||||
import { assert } from '../utils/utils';
|
import { assert, ManualPromise } from '../utils/utils';
|
||||||
import { SdkObject } from './instrumentation';
|
import { SdkObject } from './instrumentation';
|
||||||
|
|
||||||
export function filterCookies(cookies: types.NetworkCookie[], urls: string[]): types.NetworkCookie[] {
|
export function filterCookies(cookies: types.NetworkCookie[], urls: string[]): types.NetworkCookie[] {
|
||||||
|
|
@ -97,8 +97,7 @@ export class Request extends SdkObject {
|
||||||
private _headers: types.HeadersArray;
|
private _headers: types.HeadersArray;
|
||||||
private _headersMap = new Map<string, string>();
|
private _headersMap = new Map<string, string>();
|
||||||
private _frame: frames.Frame;
|
private _frame: frames.Frame;
|
||||||
private _waitForResponsePromise: Promise<Response | null>;
|
private _waitForResponsePromise = new ManualPromise<Response | null>();
|
||||||
private _waitForResponsePromiseCallback: (value: Response | null) => void = () => {};
|
|
||||||
_responseEndTiming = -1;
|
_responseEndTiming = -1;
|
||||||
_sizes: RequestSizes = { responseBodySize: 0, transferSize: 0 };
|
_sizes: RequestSizes = { responseBodySize: 0, transferSize: 0 };
|
||||||
|
|
||||||
|
|
@ -118,13 +117,12 @@ export class Request extends SdkObject {
|
||||||
this._headers = headers;
|
this._headers = headers;
|
||||||
for (const { name, value } of this._headers)
|
for (const { name, value } of this._headers)
|
||||||
this._headersMap.set(name.toLowerCase(), value);
|
this._headersMap.set(name.toLowerCase(), value);
|
||||||
this._waitForResponsePromise = new Promise(f => this._waitForResponsePromiseCallback = f);
|
|
||||||
this._isFavicon = url.endsWith('/favicon.ico');
|
this._isFavicon = url.endsWith('/favicon.ico');
|
||||||
}
|
}
|
||||||
|
|
||||||
_setFailureText(failureText: string) {
|
_setFailureText(failureText: string) {
|
||||||
this._failureText = failureText;
|
this._failureText = failureText;
|
||||||
this._waitForResponsePromiseCallback(null);
|
this._waitForResponsePromise.resolve(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
url(): string {
|
url(): string {
|
||||||
|
|
@ -151,7 +149,7 @@ export class Request extends SdkObject {
|
||||||
return this._headersMap.get(name);
|
return this._headersMap.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
response(): Promise<Response | null> {
|
response(): PromiseLike<Response | null> {
|
||||||
return this._waitForResponsePromise;
|
return this._waitForResponsePromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -161,7 +159,7 @@ export class Request extends SdkObject {
|
||||||
|
|
||||||
_setResponse(response: Response) {
|
_setResponse(response: Response) {
|
||||||
this._response = response;
|
this._response = response;
|
||||||
this._waitForResponsePromiseCallback(response);
|
this._waitForResponsePromise.resolve(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
_finalRequest(): Request {
|
_finalRequest(): Request {
|
||||||
|
|
@ -321,8 +319,7 @@ export type SecurityDetails = {
|
||||||
export class Response extends SdkObject {
|
export class Response extends SdkObject {
|
||||||
private _request: Request;
|
private _request: Request;
|
||||||
private _contentPromise: Promise<Buffer> | null = null;
|
private _contentPromise: Promise<Buffer> | null = null;
|
||||||
_finishedPromise: Promise<{ error?: string }>;
|
_finishedPromise = new ManualPromise<{ error?: string }>();
|
||||||
private _finishedPromiseCallback: (arg: { error?: string }) => void = () => {};
|
|
||||||
private _status: number;
|
private _status: number;
|
||||||
private _statusText: string;
|
private _statusText: string;
|
||||||
private _url: string;
|
private _url: string;
|
||||||
|
|
@ -330,10 +327,8 @@ export class Response extends SdkObject {
|
||||||
private _headersMap = new Map<string, string>();
|
private _headersMap = new Map<string, string>();
|
||||||
private _getResponseBodyCallback: GetResponseBodyCallback;
|
private _getResponseBodyCallback: GetResponseBodyCallback;
|
||||||
private _timing: ResourceTiming;
|
private _timing: ResourceTiming;
|
||||||
private _serverAddrPromise: Promise<RemoteAddr|undefined>;
|
private _serverAddrPromise = new ManualPromise<RemoteAddr | undefined>();
|
||||||
private _serverAddrPromiseCallback: (arg?: RemoteAddr) => void = () => {};
|
private _securityDetailsPromise = new ManualPromise<SecurityDetails | undefined>();
|
||||||
private _securityDetailsPromise: Promise<SecurityDetails|undefined>;
|
|
||||||
private _securityDetailsPromiseCallback: (arg?: SecurityDetails) => void = () => {};
|
|
||||||
private _httpVersion: string | undefined;
|
private _httpVersion: string | undefined;
|
||||||
|
|
||||||
constructor(request: Request, status: number, statusText: string, headers: types.HeadersArray, timing: ResourceTiming, getResponseBodyCallback: GetResponseBodyCallback, httpVersion?: string) {
|
constructor(request: Request, status: number, statusText: string, headers: types.HeadersArray, timing: ResourceTiming, getResponseBodyCallback: GetResponseBodyCallback, httpVersion?: string) {
|
||||||
|
|
@ -347,30 +342,21 @@ export class Response extends SdkObject {
|
||||||
for (const { name, value } of this._headers)
|
for (const { name, value } of this._headers)
|
||||||
this._headersMap.set(name.toLowerCase(), value);
|
this._headersMap.set(name.toLowerCase(), value);
|
||||||
this._getResponseBodyCallback = getResponseBodyCallback;
|
this._getResponseBodyCallback = getResponseBodyCallback;
|
||||||
this._serverAddrPromise = new Promise(f => {
|
|
||||||
this._serverAddrPromiseCallback = f;
|
|
||||||
});
|
|
||||||
this._securityDetailsPromise = new Promise(f => {
|
|
||||||
this._securityDetailsPromiseCallback = f;
|
|
||||||
});
|
|
||||||
this._finishedPromise = new Promise(f => {
|
|
||||||
this._finishedPromiseCallback = f;
|
|
||||||
});
|
|
||||||
this._request._setResponse(this);
|
this._request._setResponse(this);
|
||||||
this._httpVersion = httpVersion;
|
this._httpVersion = httpVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
_serverAddrFinished(addr?: RemoteAddr) {
|
_serverAddrFinished(addr?: RemoteAddr) {
|
||||||
this._serverAddrPromiseCallback(addr);
|
this._serverAddrPromise.resolve(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
_securityDetailsFinished(securityDetails?: SecurityDetails) {
|
_securityDetailsFinished(securityDetails?: SecurityDetails) {
|
||||||
this._securityDetailsPromiseCallback(securityDetails);
|
this._securityDetailsPromise.resolve(securityDetails);
|
||||||
}
|
}
|
||||||
|
|
||||||
_requestFinished(responseEndTiming: number, error?: string) {
|
_requestFinished(responseEndTiming: number, error?: string) {
|
||||||
this._request._responseEndTiming = Math.max(responseEndTiming, this._timing.responseStart);
|
this._request._responseEndTiming = Math.max(responseEndTiming, this._timing.responseStart);
|
||||||
this._finishedPromiseCallback({ error });
|
this._finishedPromise.resolve({ error });
|
||||||
}
|
}
|
||||||
|
|
||||||
_setHttpVersion(httpVersion: string) {
|
_setHttpVersion(httpVersion: string) {
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ import { ConsoleMessage } from './console';
|
||||||
import * as accessibility from './accessibility';
|
import * as accessibility from './accessibility';
|
||||||
import { FileChooser } from './fileChooser';
|
import { FileChooser } from './fileChooser';
|
||||||
import { Progress, ProgressController } from './progress';
|
import { Progress, ProgressController } from './progress';
|
||||||
import { assert, isError } from '../utils/utils';
|
import { assert, isError, ManualPromise } from '../utils/utils';
|
||||||
import { debugLogger } from '../utils/debugLogger';
|
import { debugLogger } from '../utils/debugLogger';
|
||||||
import { SelectorInfo, Selectors } from './selectors';
|
import { SelectorInfo, Selectors } from './selectors';
|
||||||
import { CallMetadata, SdkObject } from './instrumentation';
|
import { CallMetadata, SdkObject } from './instrumentation';
|
||||||
|
|
@ -115,14 +115,11 @@ export class Page extends SdkObject {
|
||||||
};
|
};
|
||||||
|
|
||||||
private _closedState: 'open' | 'closing' | 'closed' = 'open';
|
private _closedState: 'open' | 'closing' | 'closed' = 'open';
|
||||||
private _closedCallback: () => void;
|
private _closedPromise = new ManualPromise<void>();
|
||||||
private _closedPromise: Promise<void>;
|
|
||||||
private _disconnected = false;
|
private _disconnected = false;
|
||||||
private _initialized = false;
|
private _initialized = false;
|
||||||
private _disconnectedCallback: (e: Error) => void;
|
readonly _disconnectedPromise = new ManualPromise<Error>();
|
||||||
readonly _disconnectedPromise: Promise<Error>;
|
readonly _crashedPromise = new ManualPromise<Error>();
|
||||||
private _crashedCallback: (e: Error) => void;
|
|
||||||
readonly _crashedPromise: Promise<Error>;
|
|
||||||
readonly _browserContext: BrowserContext;
|
readonly _browserContext: BrowserContext;
|
||||||
readonly keyboard: input.Keyboard;
|
readonly keyboard: input.Keyboard;
|
||||||
readonly mouse: input.Mouse;
|
readonly mouse: input.Mouse;
|
||||||
|
|
@ -150,12 +147,6 @@ export class Page extends SdkObject {
|
||||||
super(browserContext, 'page');
|
super(browserContext, 'page');
|
||||||
this.attribution.page = this;
|
this.attribution.page = this;
|
||||||
this._delegate = delegate;
|
this._delegate = delegate;
|
||||||
this._closedCallback = () => {};
|
|
||||||
this._closedPromise = new Promise(f => this._closedCallback = f);
|
|
||||||
this._disconnectedCallback = () => {};
|
|
||||||
this._disconnectedPromise = new Promise(f => this._disconnectedCallback = f);
|
|
||||||
this._crashedCallback = () => {};
|
|
||||||
this._crashedPromise = new Promise(f => this._crashedCallback = f);
|
|
||||||
this._browserContext = browserContext;
|
this._browserContext = browserContext;
|
||||||
this._state = {
|
this._state = {
|
||||||
emulatedSize: browserContext._options.viewport ? { viewport: browserContext._options.viewport, screen: browserContext._options.screen || browserContext._options.viewport } : null,
|
emulatedSize: browserContext._options.viewport ? { viewport: browserContext._options.viewport, screen: browserContext._options.screen || browserContext._options.viewport } : null,
|
||||||
|
|
@ -218,20 +209,20 @@ export class Page extends SdkObject {
|
||||||
assert(this._closedState !== 'closed', 'Page closed twice');
|
assert(this._closedState !== 'closed', 'Page closed twice');
|
||||||
this._closedState = 'closed';
|
this._closedState = 'closed';
|
||||||
this.emit(Page.Events.Close);
|
this.emit(Page.Events.Close);
|
||||||
this._closedCallback();
|
this._closedPromise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
_didCrash() {
|
_didCrash() {
|
||||||
this._frameManager.dispose();
|
this._frameManager.dispose();
|
||||||
this.emit(Page.Events.Crash);
|
this.emit(Page.Events.Crash);
|
||||||
this._crashedCallback(new Error('Page crashed'));
|
this._crashedPromise.resolve(new Error('Page crashed'));
|
||||||
}
|
}
|
||||||
|
|
||||||
_didDisconnect() {
|
_didDisconnect() {
|
||||||
this._frameManager.dispose();
|
this._frameManager.dispose();
|
||||||
assert(!this._disconnected, 'Page disconnected twice');
|
assert(!this._disconnected, 'Page disconnected twice');
|
||||||
this._disconnected = true;
|
this._disconnected = true;
|
||||||
this._disconnectedCallback(new Error('Page closed'));
|
this._disconnectedPromise.resolve(new Error('Page closed'));
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onFileChooserOpened(handle: dom.ElementHandle) {
|
async _onFileChooserOpened(handle: dom.ElementHandle) {
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import * as network from '../network';
|
||||||
import * as types from '../types';
|
import * as types from '../types';
|
||||||
import { Protocol } from './protocol';
|
import { Protocol } from './protocol';
|
||||||
import { WKSession } from './wkConnection';
|
import { WKSession } from './wkConnection';
|
||||||
import { assert, headersObjectToArray, headersArrayToObject } from '../../utils/utils';
|
import { assert, headersObjectToArray, headersArrayToObject, ManualPromise } from '../../utils/utils';
|
||||||
import { InterceptedResponse } from '../network';
|
import { InterceptedResponse } from '../network';
|
||||||
import { WKPage } from './wkPage';
|
import { WKPage } from './wkPage';
|
||||||
|
|
||||||
|
|
@ -95,17 +95,14 @@ export class WKInterceptableRequest {
|
||||||
export class WKRouteImpl implements network.RouteDelegate {
|
export class WKRouteImpl implements network.RouteDelegate {
|
||||||
private readonly _session: WKSession;
|
private readonly _session: WKSession;
|
||||||
private readonly _requestId: string;
|
private readonly _requestId: string;
|
||||||
_requestInterceptedCallback: () => void = () => {};
|
readonly _requestInterceptedPromise = new ManualPromise<void>();
|
||||||
private readonly _requestInterceptedPromise: Promise<unknown>;
|
_responseInterceptedPromise: ManualPromise<{ response?: Protocol.Network.Response, error?: Protocol.Network.loadingFailedPayload }> | undefined;
|
||||||
_responseInterceptedCallback: ((payload: { response?: Protocol.Network.Response, error?: Protocol.Network.loadingFailedPayload }) => void) | undefined;
|
|
||||||
private _responseInterceptedPromise: Promise<{ response?: Protocol.Network.Response, error?: Protocol.Network.loadingFailedPayload }> | undefined;
|
|
||||||
private readonly _page: WKPage;
|
private readonly _page: WKPage;
|
||||||
|
|
||||||
constructor(session: WKSession, page: WKPage, requestId: string) {
|
constructor(session: WKSession, page: WKPage, requestId: string) {
|
||||||
this._session = session;
|
this._session = session;
|
||||||
this._page = page;
|
this._page = page;
|
||||||
this._requestId = requestId;
|
this._requestId = requestId;
|
||||||
this._requestInterceptedPromise = new Promise<void>(f => this._requestInterceptedCallback = f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async responseBody(): Promise<Buffer> {
|
async responseBody(): Promise<Buffer> {
|
||||||
|
|
@ -151,7 +148,7 @@ export class WKRouteImpl implements network.RouteDelegate {
|
||||||
async continue(request: network.Request, overrides: types.NormalizedContinueOverrides): Promise<network.InterceptedResponse|null> {
|
async continue(request: network.Request, overrides: types.NormalizedContinueOverrides): Promise<network.InterceptedResponse|null> {
|
||||||
if (overrides.interceptResponse) {
|
if (overrides.interceptResponse) {
|
||||||
await this._page._ensureResponseInterceptionEnabled();
|
await this._page._ensureResponseInterceptionEnabled();
|
||||||
this._responseInterceptedPromise = new Promise(f => this._responseInterceptedCallback = f);
|
this._responseInterceptedPromise = new ManualPromise();
|
||||||
}
|
}
|
||||||
await this._requestInterceptedPromise;
|
await this._requestInterceptedPromise;
|
||||||
// In certain cases, protocol will return error if the request was already canceled
|
// In certain cases, protocol will return error if the request was already canceled
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import * as jpeg from 'jpeg-js';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import * as png from 'pngjs';
|
import * as png from 'pngjs';
|
||||||
import { splitErrorMessage } from '../../utils/stackTrace';
|
import { splitErrorMessage } from '../../utils/stackTrace';
|
||||||
import { assert, createGuid, debugAssert, headersArrayToObject, headersObjectToArray, hostPlatform } from '../../utils/utils';
|
import { assert, createGuid, debugAssert, headersArrayToObject, headersObjectToArray, hostPlatform, ManualPromise } from '../../utils/utils';
|
||||||
import * as accessibility from '../accessibility';
|
import * as accessibility from '../accessibility';
|
||||||
import * as dialog from '../dialog';
|
import * as dialog from '../dialog';
|
||||||
import * as dom from '../dom';
|
import * as dom from '../dom';
|
||||||
|
|
@ -52,8 +52,7 @@ export class WKPage implements PageDelegate {
|
||||||
_session: WKSession;
|
_session: WKSession;
|
||||||
private _provisionalPage: WKProvisionalPage | null = null;
|
private _provisionalPage: WKProvisionalPage | null = null;
|
||||||
readonly _page: Page;
|
readonly _page: Page;
|
||||||
private readonly _pagePromise: Promise<Page | Error>;
|
private readonly _pagePromise = new ManualPromise<Page | Error>();
|
||||||
private _pagePromiseCallback: (page: Page | Error) => void = () => {};
|
|
||||||
private readonly _pageProxySession: WKSession;
|
private readonly _pageProxySession: WKSession;
|
||||||
readonly _opener: WKPage | null;
|
readonly _opener: WKPage | null;
|
||||||
private readonly _requestIdToRequest = new Map<string, WKInterceptableRequest>();
|
private readonly _requestIdToRequest = new Map<string, WKInterceptableRequest>();
|
||||||
|
|
@ -96,7 +95,6 @@ export class WKPage implements PageDelegate {
|
||||||
eventsHelper.addEventListener(this._pageProxySession, 'Target.didCommitProvisionalTarget', this._onDidCommitProvisionalTarget.bind(this)),
|
eventsHelper.addEventListener(this._pageProxySession, 'Target.didCommitProvisionalTarget', this._onDidCommitProvisionalTarget.bind(this)),
|
||||||
eventsHelper.addEventListener(this._pageProxySession, 'Screencast.screencastFrame', this._onScreencastFrame.bind(this)),
|
eventsHelper.addEventListener(this._pageProxySession, 'Screencast.screencastFrame', this._onScreencastFrame.bind(this)),
|
||||||
];
|
];
|
||||||
this._pagePromise = new Promise(f => this._pagePromiseCallback = f);
|
|
||||||
this._firstNonInitialNavigationCommittedPromise = new Promise((f, r) => {
|
this._firstNonInitialNavigationCommittedPromise = new Promise((f, r) => {
|
||||||
this._firstNonInitialNavigationCommittedFulfill = f;
|
this._firstNonInitialNavigationCommittedFulfill = f;
|
||||||
this._firstNonInitialNavigationCommittedReject = r;
|
this._firstNonInitialNavigationCommittedReject = r;
|
||||||
|
|
@ -335,7 +333,7 @@ export class WKPage implements PageDelegate {
|
||||||
// so that anyone who awaits pageOrError got a ready and reported page.
|
// so that anyone who awaits pageOrError got a ready and reported page.
|
||||||
this._initializedPage = pageOrError instanceof Page ? pageOrError : null;
|
this._initializedPage = pageOrError instanceof Page ? pageOrError : null;
|
||||||
this._page.reportAsNew(pageOrError instanceof Page ? undefined : pageOrError);
|
this._page.reportAsNew(pageOrError instanceof Page ? undefined : pageOrError);
|
||||||
this._pagePromiseCallback(pageOrError);
|
this._pagePromise.resolve(pageOrError);
|
||||||
} else {
|
} else {
|
||||||
assert(targetInfo.isProvisional);
|
assert(targetInfo.isProvisional);
|
||||||
assert(!this._provisionalPage);
|
assert(!this._provisionalPage);
|
||||||
|
|
@ -997,18 +995,18 @@ export class WKPage implements PageDelegate {
|
||||||
// Just continue.
|
// Just continue.
|
||||||
session.sendMayFail('Network.interceptWithRequest', { requestId: request._requestId });
|
session.sendMayFail('Network.interceptWithRequest', { requestId: request._requestId });
|
||||||
} else {
|
} else {
|
||||||
request._route._requestInterceptedCallback();
|
request._route._requestInterceptedPromise.resolve();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onResponseIntercepted(session: WKSession, event: Protocol.Network.responseInterceptedPayload) {
|
_onResponseIntercepted(session: WKSession, event: Protocol.Network.responseInterceptedPayload) {
|
||||||
const request = this._requestIdToRequest.get(event.requestId);
|
const request = this._requestIdToRequest.get(event.requestId);
|
||||||
const route = request?._routeForRedirectChain();
|
const route = request?._routeForRedirectChain();
|
||||||
if (!route?._responseInterceptedCallback) {
|
if (!route?._responseInterceptedPromise) {
|
||||||
session.sendMayFail('Network.interceptContinue', { requestId: event.requestId, stage: 'response' });
|
session.sendMayFail('Network.interceptContinue', { requestId: event.requestId, stage: 'response' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
route._responseInterceptedCallback({ response: event.response });
|
route._responseInterceptedPromise.resolve({ response: event.response });
|
||||||
}
|
}
|
||||||
|
|
||||||
_onResponseReceived(event: Protocol.Network.responseReceivedPayload) {
|
_onResponseReceived(event: Protocol.Network.responseReceivedPayload) {
|
||||||
|
|
@ -1068,8 +1066,8 @@ export class WKPage implements PageDelegate {
|
||||||
if (!request)
|
if (!request)
|
||||||
return;
|
return;
|
||||||
const route = request._routeForRedirectChain();
|
const route = request._routeForRedirectChain();
|
||||||
if (route?._responseInterceptedCallback)
|
if (route?._responseInterceptedPromise)
|
||||||
route._responseInterceptedCallback({ error: event });
|
route._responseInterceptedPromise.resolve({ error: event });
|
||||||
const response = request.request._existingResponse();
|
const response = request.request._existingResponse();
|
||||||
if (response) {
|
if (response) {
|
||||||
response._serverAddrFinished();
|
response._serverAddrFinished();
|
||||||
|
|
|
||||||
|
|
@ -122,8 +122,8 @@ export class WorkerRunner extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
async run(runPayload: RunPayload) {
|
async run(runPayload: RunPayload) {
|
||||||
let runFinishedCalback = () => {};
|
let runFinishedCallback = () => {};
|
||||||
this._runFinished = new Promise(f => runFinishedCalback = f);
|
this._runFinished = new Promise(f => runFinishedCallback = f);
|
||||||
try {
|
try {
|
||||||
this._entries = new Map(runPayload.entries.map(e => [ e.testId, e ]));
|
this._entries = new Map(runPayload.entries.map(e => [ e.testId, e ]));
|
||||||
await this._loadIfNeeded();
|
await this._loadIfNeeded();
|
||||||
|
|
@ -146,7 +146,7 @@ export class WorkerRunner extends EventEmitter {
|
||||||
this.unhandledError(e);
|
this.unhandledError(e);
|
||||||
} finally {
|
} finally {
|
||||||
this._reportDone();
|
this._reportDone();
|
||||||
runFinishedCalback();
|
runFinishedCallback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -392,3 +392,35 @@ export function wrapInASCIIBox(text: string, padding = 0): string {
|
||||||
'╚' + '═'.repeat(maxLength + padding * 2) + '╝',
|
'╚' + '═'.repeat(maxLength + padding * 2) + '╝',
|
||||||
].join('\n');
|
].join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ManualPromise<T> extends Promise<T> {
|
||||||
|
private _resolve!: (t: T) => void;
|
||||||
|
private _reject!: (e: Error) => void;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
let resolve: (t: T) => void;
|
||||||
|
let reject: (e: Error) => void;
|
||||||
|
super((f, r) => {
|
||||||
|
resolve = f;
|
||||||
|
reject = r;
|
||||||
|
});
|
||||||
|
this._resolve = resolve!;
|
||||||
|
this._reject = reject!;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve(t: T) {
|
||||||
|
this._resolve(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
reject(e: Error) {
|
||||||
|
this._reject(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
static override get [Symbol.species]() {
|
||||||
|
return Promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
override get [Symbol.toStringTag]() {
|
||||||
|
return 'ManualPromise';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue