chore: drop wrapApiCall (2) (#10445)

This commit is contained in:
Pavel Feldman 2021-11-19 16:28:11 -08:00 committed by GitHub
parent 4eaeb3b59c
commit a73e6bbd0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 384 additions and 666 deletions

View File

@ -48,10 +48,8 @@ export class Android extends ChannelOwner<channels.AndroidChannel> implements ap
}
async devices(): Promise<AndroidDevice[]> {
return this._wrapApiCall(async (channel: channels.AndroidChannel) => {
const { devices } = await channel.devices();
return devices.map(d => AndroidDevice.from(d));
});
const { devices } = await this._channel.devices();
return devices.map(d => AndroidDevice.from(d));
}
}
@ -114,15 +112,11 @@ export class AndroidDevice extends ChannelOwner<channels.AndroidDeviceChannel> i
}
async wait(selector: api.AndroidSelector, options?: { state?: 'gone' } & types.TimeoutOptions) {
await this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.wait({ selector: toSelectorChannel(selector), ...options });
});
await this._channel.wait({ selector: toSelectorChannel(selector), ...options });
}
async fill(selector: api.AndroidSelector, text: string, options?: types.TimeoutOptions) {
await this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.fill({ selector: toSelectorChannel(selector), text, ...options });
});
await this._channel.fill({ selector: toSelectorChannel(selector), text, ...options });
}
async press(selector: api.AndroidSelector, key: api.AndroidKey, options?: types.TimeoutOptions) {
@ -131,114 +125,82 @@ export class AndroidDevice extends ChannelOwner<channels.AndroidDeviceChannel> i
}
async tap(selector: api.AndroidSelector, options?: { duration?: number } & types.TimeoutOptions) {
await this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.tap({ selector: toSelectorChannel(selector), ...options });
});
await this._channel.tap({ selector: toSelectorChannel(selector), ...options });
}
async drag(selector: api.AndroidSelector, dest: types.Point, options?: SpeedOptions & types.TimeoutOptions) {
await this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.drag({ selector: toSelectorChannel(selector), dest, ...options });
});
await this._channel.drag({ selector: toSelectorChannel(selector), dest, ...options });
}
async fling(selector: api.AndroidSelector, direction: Direction, options?: SpeedOptions & types.TimeoutOptions) {
await this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.fling({ selector: toSelectorChannel(selector), direction, ...options });
});
await this._channel.fling({ selector: toSelectorChannel(selector), direction, ...options });
}
async longTap(selector: api.AndroidSelector, options?: types.TimeoutOptions) {
await this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.longTap({ selector: toSelectorChannel(selector), ...options });
});
await this._channel.longTap({ selector: toSelectorChannel(selector), ...options });
}
async pinchClose(selector: api.AndroidSelector, percent: number, options?: SpeedOptions & types.TimeoutOptions) {
await this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.pinchClose({ selector: toSelectorChannel(selector), percent, ...options });
});
await this._channel.pinchClose({ selector: toSelectorChannel(selector), percent, ...options });
}
async pinchOpen(selector: api.AndroidSelector, percent: number, options?: SpeedOptions & types.TimeoutOptions) {
await this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.pinchOpen({ selector: toSelectorChannel(selector), percent, ...options });
});
await this._channel.pinchOpen({ selector: toSelectorChannel(selector), percent, ...options });
}
async scroll(selector: api.AndroidSelector, direction: Direction, percent: number, options?: SpeedOptions & types.TimeoutOptions) {
await this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.scroll({ selector: toSelectorChannel(selector), direction, percent, ...options });
});
await this._channel.scroll({ selector: toSelectorChannel(selector), direction, percent, ...options });
}
async swipe(selector: api.AndroidSelector, direction: Direction, percent: number, options?: SpeedOptions & types.TimeoutOptions) {
await this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.swipe({ selector: toSelectorChannel(selector), direction, percent, ...options });
});
await this._channel.swipe({ selector: toSelectorChannel(selector), direction, percent, ...options });
}
async info(selector: api.AndroidSelector): Promise<api.AndroidElementInfo> {
return await this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
return (await channel.info({ selector: toSelectorChannel(selector) })).info;
});
return (await this._channel.info({ selector: toSelectorChannel(selector) })).info;
}
async screenshot(options: { path?: string } = {}): Promise<Buffer> {
return await this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
const { binary } = await channel.screenshot();
const buffer = Buffer.from(binary, 'base64');
if (options.path)
await fs.promises.writeFile(options.path, buffer);
return buffer;
});
const { binary } = await this._channel.screenshot();
const buffer = Buffer.from(binary, 'base64');
if (options.path)
await fs.promises.writeFile(options.path, buffer);
return buffer;
}
async close() {
return this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.close();
this.emit(Events.AndroidDevice.Close);
});
await this._channel.close();
this.emit(Events.AndroidDevice.Close);
}
async shell(command: string): Promise<Buffer> {
return this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
const { result } = await channel.shell({ command });
return Buffer.from(result, 'base64');
});
const { result } = await this._channel.shell({ command });
return Buffer.from(result, 'base64');
}
async open(command: string): Promise<AndroidSocket> {
return this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
return AndroidSocket.from((await channel.open({ command })).socket);
});
return AndroidSocket.from((await this._channel.open({ command })).socket);
}
async installApk(file: string | Buffer, options?: { args: string[] }): Promise<void> {
return this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.installApk({ file: await loadFile(file), args: options && options.args });
});
await this._channel.installApk({ file: await loadFile(file), args: options && options.args });
}
async push(file: string | Buffer, path: string, options?: { mode: number }): Promise<void> {
return this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.push({ file: await loadFile(file), path, mode: options ? options.mode : undefined });
});
await this._channel.push({ file: await loadFile(file), path, mode: options ? options.mode : undefined });
}
async launchBrowser(options: types.BrowserContextOptions & { pkg?: string } = {}): Promise<BrowserContext> {
return this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
const contextOptions = await prepareBrowserContextParams(options);
const { context } = await channel.launchBrowser(contextOptions);
return BrowserContext.from(context) as BrowserContext;
});
const contextOptions = await prepareBrowserContextParams(options);
const { context } = await this._channel.launchBrowser(contextOptions);
return BrowserContext.from(context) as BrowserContext;
}
async waitForEvent(event: string, optionsOrPredicate: types.WaitForEventOptions = {}): Promise<any> {
return this._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
return this._wrapApiCall(async () => {
const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate);
const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate;
const waiter = Waiter.createForEvent(channel, event);
const waiter = Waiter.createForEvent(this._channel, event);
waiter.rejectOnTimeout(timeout, `Timeout while waiting for event "${event}"`);
if (event !== Events.AndroidDevice.Close)
waiter.rejectOnEvent(this, Events.AndroidDevice.Close, new Error('Device closed'));
@ -261,15 +223,11 @@ export class AndroidSocket extends ChannelOwner<channels.AndroidSocketChannel> i
}
async write(data: Buffer): Promise<void> {
return this._wrapApiCall(async (channel: channels.AndroidSocketChannel) => {
await channel.write({ data: data.toString('base64') });
});
await this._channel.write({ data: data.toString('base64') });
}
async close(): Promise<void> {
return this._wrapApiCall(async (channel: channels.AndroidSocketChannel) => {
await channel.close();
});
await this._channel.close();
}
}
@ -287,33 +245,23 @@ export class AndroidInput implements api.AndroidInput {
}
async type(text: string) {
return this._device._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.inputType({ text });
});
await this._device._channel.inputType({ text });
}
async press(key: api.AndroidKey) {
return this._device._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.inputPress({ key });
});
await this._device._channel.inputPress({ key });
}
async tap(point: types.Point) {
return this._device._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.inputTap({ point });
});
await this._device._channel.inputTap({ point });
}
async swipe(from: types.Point, segments: types.Point[], steps: number) {
return this._device._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.inputSwipe({ segments, steps });
});
await this._device._channel.inputSwipe({ segments, steps });
}
async drag(from: types.Point, to: types.Point, steps: number) {
return this._device._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
await channel.inputDrag({ from, to, steps });
});
await this._device._channel.inputDrag({ from, to, steps });
}
}
@ -393,9 +341,7 @@ export class AndroidWebView extends EventEmitter implements api.AndroidWebView {
}
private async _fetchPage(): Promise<Page> {
return this._device._wrapApiCall(async (channel: channels.AndroidDeviceChannel) => {
const { context } = await channel.connectToWebView({ pid: this._data.pid });
return BrowserContext.from(context).pages()[0];
});
const { context } = await this._device._channel.connectToWebView({ pid: this._data.pid });
return BrowserContext.from(context).pages()[0];
}
}

View File

@ -29,54 +29,42 @@ export class Artifact extends ChannelOwner<channels.ArtifactChannel> {
async pathAfterFinished(): Promise<string | null> {
if (this._connection.isRemote())
throw new Error(`Path is not available when connecting remotely. Use saveAs() to save a local copy.`);
return this._wrapApiCall(async (channel: channels.ArtifactChannel) => {
return (await channel.pathAfterFinished()).value || null;
});
return (await this._channel.pathAfterFinished()).value || null;
}
async saveAs(path: string): Promise<void> {
return this._wrapApiCall(async (channel: channels.ArtifactChannel) => {
if (!this._connection.isRemote()) {
await channel.saveAs({ path });
return;
}
if (!this._connection.isRemote()) {
await this._channel.saveAs({ path });
return;
}
const result = await channel.saveAsStream();
const stream = Stream.from(result.stream);
await mkdirIfNeeded(path);
await new Promise((resolve, reject) => {
stream.stream().pipe(fs.createWriteStream(path))
.on('finish' as any, resolve)
.on('error' as any, reject);
});
const result = await this._channel.saveAsStream();
const stream = Stream.from(result.stream);
await mkdirIfNeeded(path);
await new Promise((resolve, reject) => {
stream.stream().pipe(fs.createWriteStream(path))
.on('finish' as any, resolve)
.on('error' as any, reject);
});
}
async failure(): Promise<string | null> {
return this._wrapApiCall(async (channel: channels.ArtifactChannel) => {
return (await channel.failure()).error || null;
});
return (await this._channel.failure()).error || null;
}
async createReadStream(): Promise<Readable | null> {
return this._wrapApiCall(async (channel: channels.ArtifactChannel) => {
const result = await channel.stream();
if (!result.stream)
return null;
const stream = Stream.from(result.stream);
return stream.stream();
});
const result = await this._channel.stream();
if (!result.stream)
return null;
const stream = Stream.from(result.stream);
return stream.stream();
}
async cancel(): Promise<void> {
return this._wrapApiCall(async (channel: channels.ArtifactChannel) => {
return channel.cancel();
});
return this._channel.cancel();
}
async delete(): Promise<void> {
return this._wrapApiCall(async (channel: channels.ArtifactChannel) => {
return channel.delete();
});
return this._channel.delete();
}
}

View File

@ -55,17 +55,15 @@ export class Browser extends ChannelOwner<channels.BrowserChannel> implements ap
}
async newContext(options: BrowserContextOptions = {}): Promise<BrowserContext> {
return this._wrapApiCall(async (channel: channels.BrowserChannel) => {
options = { ...this._browserType._defaultContextOptions, ...options };
const contextOptions = await prepareBrowserContextParams(options);
const context = BrowserContext.from((await channel.newContext(contextOptions)).context);
context._options = contextOptions;
this._contexts.add(context);
context._logger = options.logger || this._logger;
context._setBrowserType(this._browserType);
await this._browserType._onDidCreateContext?.(context);
return context;
});
options = { ...this._browserType._defaultContextOptions, ...options };
const contextOptions = await prepareBrowserContextParams(options);
const context = BrowserContext.from((await this._channel.newContext(contextOptions)).context);
context._options = contextOptions;
this._contexts.add(context);
context._logger = options.logger || this._logger;
context._setBrowserType(this._browserType);
await this._browserType._onDidCreateContext?.(context);
return context;
}
contexts(): BrowserContext[] {
@ -89,32 +87,24 @@ export class Browser extends ChannelOwner<channels.BrowserChannel> implements ap
}
async newBrowserCDPSession(): Promise<api.CDPSession> {
return this._wrapApiCall(async (channel: channels.BrowserChannel) => {
return CDPSession.from((await channel.newBrowserCDPSession()).session);
});
return CDPSession.from((await this._channel.newBrowserCDPSession()).session);
}
async startTracing(page?: Page, options: { path?: string; screenshots?: boolean; categories?: string[]; } = {}) {
return this._wrapApiCall(async (channel: channels.BrowserChannel) => {
await channel.startTracing({ ...options, page: page ? page._channel : undefined });
});
await this._channel.startTracing({ ...options, page: page ? page._channel : undefined });
}
async stopTracing(): Promise<Buffer> {
return this._wrapApiCall(async (channel: channels.BrowserChannel) => {
return Buffer.from((await channel.stopTracing()).binary, 'base64');
});
return Buffer.from((await this._channel.stopTracing()).binary, 'base64');
}
async close(): Promise<void> {
try {
await this._wrapApiCall(async (channel: channels.BrowserChannel) => {
if (this._shouldCloseConnectionOnClose)
this._connection.close(kBrowserClosedError);
else
await channel.close();
await this._closedPromise;
});
if (this._shouldCloseConnectionOnClose)
this._connection.close(kBrowserClosedError);
else
await this._channel.close();
await this._closedPromise;
} catch (e) {
if (isSafeCloseError(e))
return;

View File

@ -147,7 +147,7 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
if (routeHandler.handle(route, request)) {
this._routes.splice(this._routes.indexOf(routeHandler), 1);
if (!this._routes.length)
this._wrapApiCall(channel => this._disableInterception(channel), true).catch(() => {});
this._wrapApiCall(() => this._disableInterception(), true).catch(() => {});
}
return;
}
@ -182,11 +182,9 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
}
async newPage(): Promise<Page> {
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
if (this._ownerPage)
throw new Error('Please use browser.newContext()');
return Page.from((await channel.newPage()).page);
});
if (this._ownerPage)
throw new Error('Please use browser.newContext()');
return Page.from((await this._channel.newPage()).page);
}
async cookies(urls?: string | string[]): Promise<network.NetworkCookie[]> {
@ -194,109 +192,81 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
urls = [];
if (urls && typeof urls === 'string')
urls = [ urls ];
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
return (await channel.cookies({ urls: urls as string[] })).cookies;
});
return (await this._channel.cookies({ urls: urls as string[] })).cookies;
}
async addCookies(cookies: network.SetNetworkCookieParam[]): Promise<void> {
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
await channel.addCookies({ cookies });
});
await this._channel.addCookies({ cookies });
}
async clearCookies(): Promise<void> {
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
await channel.clearCookies();
});
await this._channel.clearCookies();
}
async grantPermissions(permissions: string[], options?: { origin?: string }): Promise<void> {
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
await channel.grantPermissions({ permissions, ...options });
});
await this._channel.grantPermissions({ permissions, ...options });
}
async clearPermissions(): Promise<void> {
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
await channel.clearPermissions();
});
await this._channel.clearPermissions();
}
async setGeolocation(geolocation: { longitude: number, latitude: number, accuracy?: number } | null): Promise<void> {
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
await channel.setGeolocation({ geolocation: geolocation || undefined });
});
await this._channel.setGeolocation({ geolocation: geolocation || undefined });
}
async setExtraHTTPHeaders(headers: Headers): Promise<void> {
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
network.validateHeaders(headers);
await channel.setExtraHTTPHeaders({ headers: headersObjectToArray(headers) });
});
network.validateHeaders(headers);
await this._channel.setExtraHTTPHeaders({ headers: headersObjectToArray(headers) });
}
async setOffline(offline: boolean): Promise<void> {
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
await channel.setOffline({ offline });
});
await this._channel.setOffline({ offline });
}
async setHTTPCredentials(httpCredentials: { username: string, password: string } | null): Promise<void> {
if (!isUnderTest())
deprecate(`context.setHTTPCredentials`, `warning: method |context.setHTTPCredentials()| is deprecated. Instead of changing credentials, create another browser context with new credentials.`);
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
await channel.setHTTPCredentials({ httpCredentials: httpCredentials || undefined });
});
await this._channel.setHTTPCredentials({ httpCredentials: httpCredentials || undefined });
}
async addInitScript(script: Function | string | { path?: string, content?: string }, arg?: any): Promise<void> {
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
const source = await evaluationScript(script, arg);
await channel.addInitScript({ source });
});
const source = await evaluationScript(script, arg);
await this._channel.addInitScript({ source });
}
async exposeBinding(name: string, callback: (source: structs.BindingSource, ...args: any[]) => any, options: { handle?: boolean } = {}): Promise<void> {
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
await channel.exposeBinding({ name, needsHandle: options.handle });
this._bindings.set(name, callback);
});
await this._channel.exposeBinding({ name, needsHandle: options.handle });
this._bindings.set(name, callback);
}
async exposeFunction(name: string, callback: Function): Promise<void> {
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
await channel.exposeBinding({ name });
const binding = (source: structs.BindingSource, ...args: any[]) => callback(...args);
this._bindings.set(name, binding);
});
await this._channel.exposeBinding({ name });
const binding = (source: structs.BindingSource, ...args: any[]) => callback(...args);
this._bindings.set(name, binding);
}
async route(url: URLMatch, handler: network.RouteHandlerCallback, options: { times?: number } = {}): Promise<void> {
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
this._routes.unshift(new network.RouteHandler(this._options.baseURL, url, handler, options.times));
if (this._routes.length === 1)
await channel.setNetworkInterceptionEnabled({ enabled: true });
});
this._routes.unshift(new network.RouteHandler(this._options.baseURL, url, handler, options.times));
if (this._routes.length === 1)
await this._channel.setNetworkInterceptionEnabled({ enabled: true });
}
async unroute(url: URLMatch, handler?: network.RouteHandlerCallback): Promise<void> {
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler));
if (!this._routes.length)
await this._disableInterception(channel);
});
this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler));
if (!this._routes.length)
await this._disableInterception();
}
private async _disableInterception(channel: channels.BrowserContextChannel) {
await channel.setNetworkInterceptionEnabled({ enabled: false });
private async _disableInterception() {
await this._channel.setNetworkInterceptionEnabled({ enabled: false });
}
async waitForEvent(event: string, optionsOrPredicate: WaitForEventOptions = {}): Promise<any> {
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
return this._wrapApiCall(async () => {
const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate);
const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate;
const waiter = Waiter.createForEvent(channel, event);
const waiter = Waiter.createForEvent(this._channel, event);
waiter.rejectOnTimeout(timeout, `Timeout while waiting for event "${event}"`);
if (event !== Events.BrowserContext.Close)
waiter.rejectOnEvent(this, Events.BrowserContext.Close, new Error('Context closed'));
@ -307,14 +277,12 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
}
async storageState(options: { path?: string } = {}): Promise<StorageState> {
return await this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
const state = await channel.storageState();
if (options.path) {
await mkdirIfNeeded(options.path);
await fs.promises.writeFile(options.path, JSON.stringify(state, undefined, 2), 'utf8');
}
return state;
});
const state = await this._channel.storageState();
if (options.path) {
await mkdirIfNeeded(options.path);
await fs.promises.writeFile(options.path, JSON.stringify(state, undefined, 2), 'utf8');
}
return state;
}
backgroundPages(): Page[] {
@ -329,10 +297,8 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
// channelOwner.ts's validation messages don't handle the pseudo-union type, so we're explicit here
if (!(page instanceof Page) && !(page instanceof Frame))
throw new Error('page: expected Page or Frame');
return this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
const result = await channel.newCDPSession(page instanceof Page ? { page: page._channel } : { frame: page._channel });
return CDPSession.from(result.session);
});
const result = await this._channel.newCDPSession(page instanceof Page ? { page: page._channel } : { frame: page._channel });
return CDPSession.from(result.session);
}
_onClose() {
@ -344,7 +310,7 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
async close(): Promise<void> {
try {
await this._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
await this._wrapApiCall(async () => {
await this._browserType?._onWillCloseContext?.(this);
if (this._options.recordHar) {
const har = await this._channel.harExport();
@ -352,7 +318,7 @@ export class BrowserContext extends ChannelOwner<channels.BrowserContextChannel>
await artifact.saveAs(this._options.recordHar.path);
await artifact.delete();
}
await channel.close();
await this._channel.close();
await this._closedPromise;
});
} catch (e) {

View File

@ -68,21 +68,19 @@ export class BrowserType extends ChannelOwner<channels.BrowserTypeChannel> imple
async launch(options: LaunchOptions = {}): Promise<Browser> {
const logger = options.logger || this._defaultLaunchOptions.logger;
return this._wrapApiCall(async (channel: channels.BrowserTypeChannel) => {
assert(!(options as any).userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
assert(!(options as any).port, 'Cannot specify a port without launching as a server.');
options = { ...this._defaultLaunchOptions, ...options };
const launchOptions: channels.BrowserTypeLaunchParams = {
...options,
ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : undefined,
ignoreAllDefaultArgs: !!options.ignoreDefaultArgs && !Array.isArray(options.ignoreDefaultArgs),
env: options.env ? envObjectToArray(options.env) : undefined,
};
const browser = Browser.from((await channel.launch(launchOptions)).browser);
browser._logger = logger;
browser._setBrowserType(this);
return browser;
});
assert(!(options as any).userDataDir, 'userDataDir option is not supported in `browserType.launch`. Use `browserType.launchPersistentContext` instead');
assert(!(options as any).port, 'Cannot specify a port without launching as a server.');
options = { ...this._defaultLaunchOptions, ...options };
const launchOptions: channels.BrowserTypeLaunchParams = {
...options,
ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : undefined,
ignoreAllDefaultArgs: !!options.ignoreDefaultArgs && !Array.isArray(options.ignoreDefaultArgs),
env: options.env ? envObjectToArray(options.env) : undefined,
};
const browser = Browser.from((await this._channel.launch(launchOptions)).browser);
browser._logger = logger;
browser._setBrowserType(this);
return browser;
}
async launchServer(options: LaunchServerOptions = {}): Promise<api.BrowserServer> {
@ -94,26 +92,24 @@ export class BrowserType extends ChannelOwner<channels.BrowserTypeChannel> imple
async launchPersistentContext(userDataDir: string, options: LaunchPersistentContextOptions = {}): Promise<BrowserContext> {
const logger = options.logger || this._defaultLaunchOptions.logger;
return this._wrapApiCall(async (channel: channels.BrowserTypeChannel) => {
assert(!(options as any).port, 'Cannot specify a port without launching as a server.');
options = { ...this._defaultLaunchOptions, ...this._defaultContextOptions, ...options };
const contextParams = await prepareBrowserContextParams(options);
const persistentParams: channels.BrowserTypeLaunchPersistentContextParams = {
...contextParams,
ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : undefined,
ignoreAllDefaultArgs: !!options.ignoreDefaultArgs && !Array.isArray(options.ignoreDefaultArgs),
env: options.env ? envObjectToArray(options.env) : undefined,
channel: options.channel,
userDataDir,
};
const result = await channel.launchPersistentContext(persistentParams);
const context = BrowserContext.from(result.context);
context._options = contextParams;
context._logger = logger;
context._setBrowserType(this);
await this._onDidCreateContext?.(context);
return context;
});
assert(!(options as any).port, 'Cannot specify a port without launching as a server.');
options = { ...this._defaultLaunchOptions, ...this._defaultContextOptions, ...options };
const contextParams = await prepareBrowserContextParams(options);
const persistentParams: channels.BrowserTypeLaunchPersistentContextParams = {
...contextParams,
ignoreDefaultArgs: Array.isArray(options.ignoreDefaultArgs) ? options.ignoreDefaultArgs : undefined,
ignoreAllDefaultArgs: !!options.ignoreDefaultArgs && !Array.isArray(options.ignoreDefaultArgs),
env: options.env ? envObjectToArray(options.env) : undefined,
channel: options.channel,
userDataDir,
};
const result = await this._channel.launchPersistentContext(persistentParams);
const context = BrowserContext.from(result.context);
context._options = contextParams;
context._logger = logger;
context._setBrowserType(this);
await this._onDidCreateContext?.(context);
return context;
}
connect(options: api.ConnectOptions & { wsEndpoint?: string }): Promise<api.Browser>;
@ -127,10 +123,10 @@ export class BrowserType extends ChannelOwner<channels.BrowserTypeChannel> imple
async _connect(wsEndpoint: string, params: Partial<ConnectOptions> = {}): Promise<Browser> {
const logger = params.logger;
return await this._wrapApiCall(async (channel: channels.BrowserTypeChannel) => {
return await this._wrapApiCall(async () => {
const deadline = params.timeout ? monotonicTime() + params.timeout : 0;
let browser: Browser;
const { pipe } = await channel.connect({ wsEndpoint, headers: params.headers, slowMo: params.slowMo, timeout: params.timeout });
const { pipe } = await this._channel.connect({ wsEndpoint, headers: params.headers, slowMo: params.slowMo, timeout: params.timeout });
const closePipe = () => pipe.close().catch(() => {});
const connection = new Connection();
connection.markAsRemote();
@ -207,21 +203,19 @@ export class BrowserType extends ChannelOwner<channels.BrowserTypeChannel> imple
if (this.name() !== 'chromium')
throw new Error('Connecting over CDP is only supported in Chromium.');
const logger = params.logger;
return this._wrapApiCall(async (channel: channels.BrowserTypeChannel) => {
const paramsHeaders = Object.assign({ 'User-Agent': getUserAgent() }, params.headers);
const headers = paramsHeaders ? headersObjectToArray(paramsHeaders) : undefined;
const result = await channel.connectOverCDP({
endpointURL,
headers,
slowMo: params.slowMo,
timeout: params.timeout
});
const browser = Browser.from(result.browser);
if (result.defaultContext)
browser._contexts.add(BrowserContext.from(result.defaultContext));
browser._logger = logger;
browser._setBrowserType(this);
return browser;
const paramsHeaders = Object.assign({ 'User-Agent': getUserAgent() }, params.headers);
const headers = paramsHeaders ? headersObjectToArray(paramsHeaders) : undefined;
const result = await this._channel.connectOverCDP({
endpointURL,
headers,
slowMo: params.slowMo,
timeout: params.timeout
});
const browser = Browser.from(result.browser);
if (result.defaultContext)
browser._contexts.add(BrowserContext.from(result.defaultContext));
browser._logger = logger;
browser._setBrowserType(this);
return browser;
}
}

View File

@ -42,15 +42,11 @@ export class CDPSession extends ChannelOwner<channels.CDPSessionChannel> impleme
method: T,
params?: Protocol.CommandParameters[T]
): Promise<Protocol.CommandReturnValues[T]> {
return this._wrapApiCall(async (channel: channels.CDPSessionChannel) => {
const result = await channel.send({ method, params });
return result.result as Protocol.CommandReturnValues[T];
});
const result = await this._channel.send({ method, params });
return result.result as Protocol.CommandReturnValues[T];
}
async detach() {
return this._wrapApiCall(async (channel: channels.CDPSessionChannel) => {
return channel.detach();
});
return this._channel.detach();
}
}

View File

@ -84,7 +84,7 @@ export abstract class ChannelOwner<T extends channels.Channel = channels.Channel
const validator = scheme[paramsName(this._type, prop)];
if (validator) {
return (params: any) => {
return this._wrapApiCall((channel, apiZone) => {
return this._wrapApiCall(apiZone => {
const { stackTrace, csi, callCookie } = apiZone.reported ? { csi: undefined, callCookie: undefined, stackTrace: null } : apiZone;
apiZone.reported = true;
if (csi && stackTrace && stackTrace.apiName)
@ -101,12 +101,12 @@ export abstract class ChannelOwner<T extends channels.Channel = channels.Channel
return channel;
}
async _wrapApiCall<R, C extends channels.Channel = T>(func: (channel: C, apiZone: ApiZone) => Promise<R>, isInternal = false): Promise<R> {
async _wrapApiCall<R>(func: (apiZone: ApiZone) => Promise<R>, isInternal = false): Promise<R> {
const logger = this._logger;
const stack = captureRawStack();
const apiZone = zones.zoneData<ApiZone>('apiZone', stack);
if (apiZone)
return func(this._channel as any, apiZone);
return func(apiZone);
const stackTrace = captureStackTrace(stack);
if (isInternal)
@ -120,7 +120,7 @@ export abstract class ChannelOwner<T extends channels.Channel = channels.Channel
logApiCall(logger, `=> ${apiName} started`, isInternal);
const apiZone = { stackTrace, isInternal, reported: false, csi, callCookie };
const result = await zones.run<ApiZone, R>('apiZone', apiZone, async () => {
return await func(this._channel as any, apiZone);
return await func(apiZone);
});
csi?.onApiCallEnd(callCookie);
logApiCall(logger, `<= ${apiName} succeeded`, isInternal);

View File

@ -40,14 +40,10 @@ export class Dialog extends ChannelOwner<channels.DialogChannel> implements api.
}
async accept(promptText: string | undefined) {
return this._wrapApiCall(async (channel: channels.DialogChannel) => {
await channel.accept({ promptText });
});
await this._channel.accept({ promptText });
}
async dismiss() {
return this._wrapApiCall(async (channel: channels.DialogChannel) => {
await channel.dismiss();
});
await this._channel.dismiss();
}
}

View File

@ -46,14 +46,12 @@ export class Electron extends ChannelOwner<channels.ElectronChannel> implements
}
async launch(options: ElectronOptions = {}): Promise<ElectronApplication> {
return this._wrapApiCall(async (channel: channels.ElectronChannel) => {
const params: channels.ElectronLaunchParams = {
...options,
extraHTTPHeaders: options.extraHTTPHeaders && headersObjectToArray(options.extraHTTPHeaders),
env: envObjectToArray(options.env ? options.env : process.env),
};
return ElectronApplication.from((await channel.launch(params)).electronApplication);
});
const params: channels.ElectronLaunchParams = {
...options,
extraHTTPHeaders: options.extraHTTPHeaders && headersObjectToArray(options.extraHTTPHeaders),
env: envObjectToArray(options.env ? options.env : process.env),
};
return ElectronApplication.from((await this._channel.launch(params)).electronApplication);
}
}
@ -87,11 +85,9 @@ export class ElectronApplication extends ChannelOwner<channels.ElectronApplicati
}
async firstWindow(): Promise<Page> {
return this._wrapApiCall(async (channel: channels.ElectronApplicationChannel) => {
if (this._windows.size)
return this._windows.values().next().value;
return this.waitForEvent('window');
});
if (this._windows.size)
return this._windows.values().next().value;
return this.waitForEvent('window');
}
context(): BrowserContext {
@ -99,16 +95,14 @@ export class ElectronApplication extends ChannelOwner<channels.ElectronApplicati
}
async close() {
return this._wrapApiCall(async (channel: channels.ElectronApplicationChannel) => {
await channel.close();
});
await this._channel.close();
}
async waitForEvent(event: string, optionsOrPredicate: WaitForEventOptions = {}): Promise<any> {
return this._wrapApiCall(async (channel: channels.ElectronApplicationChannel) => {
return this._wrapApiCall(async () => {
const timeout = this._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate);
const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate;
const waiter = Waiter.createForEvent(channel, event);
const waiter = Waiter.createForEvent(this._channel, event);
waiter.rejectOnTimeout(timeout, `Timeout while waiting for event "${event}"`);
if (event !== Events.ElectronApplication.Close)
waiter.rejectOnEvent(this, Events.ElectronApplication.Close, new Error('Electron application closed'));
@ -119,23 +113,17 @@ export class ElectronApplication extends ChannelOwner<channels.ElectronApplicati
}
async browserWindow(page: Page): Promise<JSHandle<BrowserWindow>> {
return this._wrapApiCall(async (channel: channels.ElectronApplicationChannel) => {
const result = await channel.browserWindow({ page: page._channel });
return JSHandle.from(result.handle);
});
const result = await this._channel.browserWindow({ page: page._channel });
return JSHandle.from(result.handle);
}
async evaluate<R, Arg>(pageFunction: structs.PageFunctionOn<ElectronAppType, Arg, R>, arg: Arg): Promise<R> {
return this._wrapApiCall(async (channel: channels.ElectronApplicationChannel) => {
const result = await channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
return parseResult(result.value);
});
const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
return parseResult(result.value);
}
async evaluateHandle<R, Arg>(pageFunction: structs.PageFunctionOn<ElectronAppType, Arg, R>, arg: Arg): Promise<structs.SmartHandle<R>> {
return this._wrapApiCall(async (channel: channels.ElectronApplicationChannel) => {
const result = await channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
return JSHandle.from(result.handle) as any as structs.SmartHandle<R>;
});
const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
return JSHandle.from(result.handle) as any as structs.SmartHandle<R>;
}
}

View File

@ -47,174 +47,118 @@ export class ElementHandle<T extends Node = Node> extends JSHandle<T> implements
}
async ownerFrame(): Promise<Frame | null> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return Frame.fromNullable((await channel.ownerFrame()).frame);
});
return Frame.fromNullable((await this._elementChannel.ownerFrame()).frame);
}
async contentFrame(): Promise<Frame | null> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return Frame.fromNullable((await channel.contentFrame()).frame);
});
return Frame.fromNullable((await this._elementChannel.contentFrame()).frame);
}
async getAttribute(name: string): Promise<string | null> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
const value = (await channel.getAttribute({ name })).value;
return value === undefined ? null : value;
});
const value = (await this._elementChannel.getAttribute({ name })).value;
return value === undefined ? null : value;
}
async inputValue(): Promise<string> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return (await channel.inputValue()).value;
});
return (await this._elementChannel.inputValue()).value;
}
async textContent(): Promise<string | null> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
const value = (await channel.textContent()).value;
return value === undefined ? null : value;
});
const value = (await this._elementChannel.textContent()).value;
return value === undefined ? null : value;
}
async innerText(): Promise<string> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return (await channel.innerText()).value;
});
return (await this._elementChannel.innerText()).value;
}
async innerHTML(): Promise<string> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return (await channel.innerHTML()).value;
});
return (await this._elementChannel.innerHTML()).value;
}
async isChecked(): Promise<boolean> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return (await channel.isChecked()).value;
});
return (await this._elementChannel.isChecked()).value;
}
async isDisabled(): Promise<boolean> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return (await channel.isDisabled()).value;
});
return (await this._elementChannel.isDisabled()).value;
}
async isEditable(): Promise<boolean> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return (await channel.isEditable()).value;
});
return (await this._elementChannel.isEditable()).value;
}
async isEnabled(): Promise<boolean> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return (await channel.isEnabled()).value;
});
return (await this._elementChannel.isEnabled()).value;
}
async isHidden(): Promise<boolean> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return (await channel.isHidden()).value;
});
return (await this._elementChannel.isHidden()).value;
}
async isVisible(): Promise<boolean> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return (await channel.isVisible()).value;
});
return (await this._elementChannel.isVisible()).value;
}
async dispatchEvent(type: string, eventInit: Object = {}) {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
await channel.dispatchEvent({ type, eventInit: serializeArgument(eventInit) });
});
await this._elementChannel.dispatchEvent({ type, eventInit: serializeArgument(eventInit) });
}
async scrollIntoViewIfNeeded(options: channels.ElementHandleScrollIntoViewIfNeededOptions = {}) {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
await channel.scrollIntoViewIfNeeded(options);
});
await this._elementChannel.scrollIntoViewIfNeeded(options);
}
async hover(options: channels.ElementHandleHoverOptions = {}): Promise<void> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
await channel.hover(options);
});
await this._elementChannel.hover(options);
}
async click(options: channels.ElementHandleClickOptions = {}): Promise<void> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return await channel.click(options);
});
return await this._elementChannel.click(options);
}
async dblclick(options: channels.ElementHandleDblclickOptions = {}): Promise<void> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return await channel.dblclick(options);
});
return await this._elementChannel.dblclick(options);
}
async tap(options: channels.ElementHandleTapOptions = {}): Promise<void> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return await channel.tap(options);
});
return await this._elementChannel.tap(options);
}
async selectOption(values: string | api.ElementHandle | SelectOption | string[] | api.ElementHandle[] | SelectOption[] | null, options: SelectOptionOptions = {}): Promise<string[]> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
const result = await channel.selectOption({ ...convertSelectOptionValues(values), ...options });
return result.values;
});
const result = await this._elementChannel.selectOption({ ...convertSelectOptionValues(values), ...options });
return result.values;
}
async fill(value: string, options: channels.ElementHandleFillOptions = {}): Promise<void> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return await channel.fill({ value, ...options });
});
return await this._elementChannel.fill({ value, ...options });
}
async selectText(options: channels.ElementHandleSelectTextOptions = {}): Promise<void> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
await channel.selectText(options);
});
await this._elementChannel.selectText(options);
}
async setInputFiles(files: string | FilePayload | string[] | FilePayload[], options: channels.ElementHandleSetInputFilesOptions = {}) {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
await channel.setInputFiles({ files: await convertInputFiles(files), ...options });
});
await this._elementChannel.setInputFiles({ files: await convertInputFiles(files), ...options });
}
async focus(): Promise<void> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
await channel.focus();
});
await this._elementChannel.focus();
}
async type(text: string, options: channels.ElementHandleTypeOptions = {}): Promise<void> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
await channel.type({ text, ...options });
});
await this._elementChannel.type({ text, ...options });
}
async press(key: string, options: channels.ElementHandlePressOptions = {}): Promise<void> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
await channel.press({ key, ...options });
});
await this._elementChannel.press({ key, ...options });
}
async check(options: channels.ElementHandleCheckOptions = {}) {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return await channel.check(options);
});
return await this._elementChannel.check(options);
}
async uncheck(options: channels.ElementHandleUncheckOptions = {}) {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return await channel.uncheck(options);
});
return await this._elementChannel.uncheck(options);
}
async setChecked(checked: boolean, options?: channels.ElementHandleCheckOptions) {
@ -225,67 +169,51 @@ export class ElementHandle<T extends Node = Node> extends JSHandle<T> implements
}
async boundingBox(): Promise<Rect | null> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
const value = (await channel.boundingBox()).value;
return value === undefined ? null : value;
});
const value = (await this._elementChannel.boundingBox()).value;
return value === undefined ? null : value;
}
async screenshot(options: channels.ElementHandleScreenshotOptions & { path?: string } = {}): Promise<Buffer> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
const copy = { ...options };
if (!copy.type)
copy.type = determineScreenshotType(options);
const result = await channel.screenshot(copy);
const buffer = Buffer.from(result.binary, 'base64');
if (options.path) {
await mkdirIfNeeded(options.path);
await fs.promises.writeFile(options.path, buffer);
}
return buffer;
});
const copy = { ...options };
if (!copy.type)
copy.type = determineScreenshotType(options);
const result = await this._elementChannel.screenshot(copy);
const buffer = Buffer.from(result.binary, 'base64');
if (options.path) {
await mkdirIfNeeded(options.path);
await fs.promises.writeFile(options.path, buffer);
}
return buffer;
}
async $(selector: string): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return ElementHandle.fromNullable((await channel.querySelector({ selector })).element) as ElementHandle<SVGElement | HTMLElement> | null;
});
return ElementHandle.fromNullable((await this._elementChannel.querySelector({ selector })).element) as ElementHandle<SVGElement | HTMLElement> | null;
}
async $$(selector: string): Promise<ElementHandle<SVGElement | HTMLElement>[]> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
const result = await channel.querySelectorAll({ selector });
return result.elements.map(h => ElementHandle.from(h) as ElementHandle<SVGElement | HTMLElement>);
});
const result = await this._elementChannel.querySelectorAll({ selector });
return result.elements.map(h => ElementHandle.from(h) as ElementHandle<SVGElement | HTMLElement>);
}
async $eval<R, Arg>(selector: string, pageFunction: structs.PageFunctionOn<Element, Arg, R>, arg?: Arg): Promise<R> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
const result = await channel.evalOnSelector({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
return parseResult(result.value);
});
const result = await this._elementChannel.evalOnSelector({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
return parseResult(result.value);
}
async $$eval<R, Arg>(selector: string, pageFunction: structs.PageFunctionOn<Element[], Arg, R>, arg?: Arg): Promise<R> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
const result = await channel.evalOnSelectorAll({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
return parseResult(result.value);
});
const result = await this._elementChannel.evalOnSelectorAll({ selector, expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
return parseResult(result.value);
}
async waitForElementState(state: 'visible' | 'hidden' | 'stable' | 'enabled' | 'disabled', options: channels.ElementHandleWaitForElementStateOptions = {}): Promise<void> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
return await channel.waitForElementState({ state, ...options });
});
return await this._elementChannel.waitForElementState({ state, ...options });
}
waitForSelector(selector: string, options: channels.ElementHandleWaitForSelectorOptions & { state: 'attached' | 'visible' }): Promise<ElementHandle<SVGElement | HTMLElement>>;
waitForSelector(selector: string, options?: channels.ElementHandleWaitForSelectorOptions): Promise<ElementHandle<SVGElement | HTMLElement> | null>;
async waitForSelector(selector: string, options: channels.ElementHandleWaitForSelectorOptions = {}): Promise<ElementHandle<SVGElement | HTMLElement> | null> {
return this._wrapApiCall(async (channel: channels.ElementHandleChannel) => {
const result = await channel.waitForSelector({ selector, ...options });
return ElementHandle.fromNullable(result.element) as ElementHandle<SVGElement | HTMLElement> | null;
});
const result = await this._elementChannel.waitForSelector({ selector, ...options });
return ElementHandle.fromNullable(result.element) as ElementHandle<SVGElement | HTMLElement> | null;
}
}

View File

@ -56,16 +56,14 @@ export class APIRequest implements api.APIRequest {
}
async newContext(options: NewContextOptions = {}): Promise<APIRequestContext> {
return await this._playwright._wrapApiCall(async (channel: channels.PlaywrightChannel) => {
const storageState = typeof options.storageState === 'string' ?
JSON.parse(await fs.promises.readFile(options.storageState, 'utf8')) :
options.storageState;
return APIRequestContext.from((await channel.newRequest({
...options,
extraHTTPHeaders: options.extraHTTPHeaders ? headersObjectToArray(options.extraHTTPHeaders) : undefined,
storageState,
})).request);
});
const storageState = typeof options.storageState === 'string' ?
JSON.parse(await fs.promises.readFile(options.storageState, 'utf8')) :
options.storageState;
return APIRequestContext.from((await this._playwright._channel.newRequest({
...options,
extraHTTPHeaders: options.extraHTTPHeaders ? headersObjectToArray(options.extraHTTPHeaders) : undefined,
storageState,
})).request);
}
}
@ -78,10 +76,8 @@ export class APIRequestContext extends ChannelOwner<channels.APIRequestContextCh
super(parent, type, guid, initializer);
}
dispose(): Promise<void> {
return this._wrapApiCall(async (channel: channels.APIRequestContextChannel) => {
await channel.dispose();
});
async dispose(): Promise<void> {
await this._channel.dispose();
}
async delete(url: string, options?: RequestWithBodyOptions): Promise<APIResponse> {
@ -127,7 +123,7 @@ export class APIRequestContext extends ChannelOwner<channels.APIRequestContextCh
}
async fetch(urlOrRequest: string | api.Request, options: FetchOptions = {}): Promise<APIResponse> {
return this._wrapApiCall(async (channel: channels.APIRequestContextChannel) => {
return this._wrapApiCall(async () => {
const request: network.Request | undefined = (urlOrRequest instanceof network.Request) ? urlOrRequest as network.Request : undefined;
assert(request || typeof urlOrRequest === 'string', 'First argument must be either URL string or Request');
assert((options.data === undefined ? 0 : 1) + (options.form === undefined ? 0 : 1) + (options.multipart === undefined ? 0 : 1) <= 1, `Only one of 'data', 'form' or 'multipart' can be specified`);
@ -175,7 +171,7 @@ export class APIRequestContext extends ChannelOwner<channels.APIRequestContextCh
if (postDataBuffer === undefined && jsonData === undefined && formData === undefined && multipartData === undefined)
postDataBuffer = request?.postDataBuffer() || undefined;
const postData = (postDataBuffer ? postDataBuffer.toString('base64') : undefined);
const result = await channel.fetch({
const result = await this._channel.fetch({
url,
params,
method,
@ -195,14 +191,12 @@ export class APIRequestContext extends ChannelOwner<channels.APIRequestContextCh
}
async storageState(options: { path?: string } = {}): Promise<StorageState> {
return await this._wrapApiCall(async (channel: channels.APIRequestContextChannel) => {
const state = await channel.storageState();
if (options.path) {
await mkdirIfNeeded(options.path);
await fs.promises.writeFile(options.path, JSON.stringify(state, undefined, 2), 'utf8');
}
return state;
});
const state = await this._channel.storageState();
if (options.path) {
await mkdirIfNeeded(options.path);
await fs.promises.writeFile(options.path, JSON.stringify(state, undefined, 2), 'utf8');
}
return state;
}
}
@ -242,18 +236,16 @@ export class APIResponse implements api.APIResponse {
}
async body(): Promise<Buffer> {
return this._request._wrapApiCall(async (channel: channels.APIRequestContextChannel) => {
try {
const result = await channel.fetchResponseBody({ fetchUid: this._fetchUid() });
if (result.binary === undefined)
throw new Error('Response has been disposed');
return Buffer.from(result.binary!, 'base64');
} catch (e) {
if (e.message === kBrowserOrContextClosedError)
throw new Error('Response has been disposed');
throw e;
}
});
try {
const result = await this._request._channel.fetchResponseBody({ fetchUid: this._fetchUid() });
if (result.binary === undefined)
throw new Error('Response has been disposed');
return Buffer.from(result.binary!, 'base64');
} catch (e) {
if (e.message.includes(kBrowserOrContextClosedError))
throw new Error('Response has been disposed');
throw e;
}
}
async text(): Promise<string> {
@ -267,9 +259,7 @@ export class APIResponse implements api.APIResponse {
}
async dispose(): Promise<void> {
return this._request._wrapApiCall(async (channel: channels.APIRequestContextChannel) => {
await channel.disposeAPIResponse({ fetchUid: this._fetchUid() });
});
await this._request._channel.disposeAPIResponse({ fetchUid: this._fetchUid() });
}
[util.inspect.custom]() {

View File

@ -44,8 +44,6 @@ export class FileChooser implements api.FileChooser {
}
async setFiles(files: string | FilePayload | string[] | FilePayload[], options?: channels.ElementHandleSetInputFilesOptions) {
return this._page._wrapApiCall(async () => {
return this._elementHandle.setInputFiles(files, options);
});
return this._elementHandle.setInputFiles(files, options);
}
}

View File

@ -105,7 +105,7 @@ export class Frame extends ChannelOwner<channels.FrameChannel> implements api.Fr
}
async waitForNavigation(options: WaitForNavigationOptions = {}): Promise<network.Response | null> {
return this._page!._wrapApiCall(async (channel: channels.PageChannel) => {
return this._page!._wrapApiCall(async () => {
const waitUntil = verifyLoadState('waitUntil', options.waitUntil === undefined ? 'load' : options.waitUntil);
const waiter = this._setupNavigationWaiter(options);
@ -143,7 +143,7 @@ export class Frame extends ChannelOwner<channels.FrameChannel> implements api.Fr
state = verifyLoadState('state', state);
if (this._loadStates.has(state))
return;
return this._page!._wrapApiCall(async (channel: channels.PageChannel) => {
return this._page!._wrapApiCall(async () => {
const waiter = this._setupNavigationWaiter(options);
await waiter.waitForEvent<LifecycleEvent>(this._eventEmitter, 'loadstate', s => {
waiter.log(` "${s}" event fired`);

View File

@ -27,33 +27,23 @@ export class Keyboard implements api.Keyboard {
}
async down(key: string) {
await this._page._wrapApiCall(async channel => {
await channel.keyboardDown({ key });
});
await this._page._channel.keyboardDown({ key });
}
async up(key: string) {
await this._page._wrapApiCall(async channel => {
await channel.keyboardUp({ key });
});
await this._page._channel.keyboardUp({ key });
}
async insertText(text: string) {
await this._page._wrapApiCall(async channel => {
await channel.keyboardInsertText({ text });
});
await this._page._channel.keyboardInsertText({ text });
}
async type(text: string, options: channels.PageKeyboardTypeOptions = {}) {
await this._page._wrapApiCall(async channel => {
await channel.keyboardType({ text, ...options });
});
await this._page._channel.keyboardType({ text, ...options });
}
async press(key: string, options: channels.PageKeyboardPressOptions = {}) {
await this._page._wrapApiCall(async channel => {
await channel.keyboardPress({ key, ...options });
});
await this._page._channel.keyboardPress({ key, ...options });
}
}
@ -65,27 +55,19 @@ export class Mouse implements api.Mouse {
}
async move(x: number, y: number, options: { steps?: number } = {}) {
await this._page._wrapApiCall(async channel => {
await channel.mouseMove({ x, y, ...options });
});
await this._page._channel.mouseMove({ x, y, ...options });
}
async down(options: channels.PageMouseDownOptions = {}) {
await this._page._wrapApiCall(async channel => {
await channel.mouseDown({ ...options });
});
await this._page._channel.mouseDown({ ...options });
}
async up(options: channels.PageMouseUpOptions = {}) {
await this._page._wrapApiCall(async channel => {
await channel.mouseUp(options);
});
await this._page._channel.mouseUp(options);
}
async click(x: number, y: number, options: channels.PageMouseClickOptions = {}) {
await this._page._wrapApiCall(async channel => {
await channel.mouseClick({ x, y, ...options });
});
await this._page._channel.mouseClick({ x, y, ...options });
}
async dblclick(x: number, y: number, options: Omit<channels.PageMouseClickOptions, 'clickCount'> = {}) {
@ -93,9 +75,7 @@ export class Mouse implements api.Mouse {
}
async wheel(deltaX: number, deltaY: number) {
await this._page._wrapApiCall(async channel => {
await channel.mouseWheel({ deltaX, deltaY });
});
await this._page._channel.mouseWheel({ deltaX, deltaY });
}
}
@ -107,8 +87,6 @@ export class Touchscreen implements api.Touchscreen {
}
async tap(x: number, y: number) {
await this._page._wrapApiCall(async channel => {
await channel.touchscreenTap({ x, y });
});
await this._page._channel.touchscreenTap({ x, y });
}
}

View File

@ -34,39 +34,29 @@ export class JSHandle<T = any> extends ChannelOwner<channels.JSHandleChannel> im
}
async evaluate<R, Arg>(pageFunction: structs.PageFunctionOn<T, Arg, R>, arg?: Arg): Promise<R> {
return this._wrapApiCall(async (channel: channels.JSHandleChannel) => {
const result = await channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
return parseResult(result.value);
});
const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
return parseResult(result.value);
}
async evaluateHandle<R, Arg>(pageFunction: structs.PageFunctionOn<T, Arg, R>, arg?: Arg): Promise<structs.SmartHandle<R>> {
return this._wrapApiCall(async (channel: channels.JSHandleChannel) => {
const result = await channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
return JSHandle.from(result.handle) as any as structs.SmartHandle<R>;
});
const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
return JSHandle.from(result.handle) as any as structs.SmartHandle<R>;
}
async getProperty(propertyName: string): Promise<JSHandle> {
return this._wrapApiCall(async (channel: channels.JSHandleChannel) => {
const result = await channel.getProperty({ name: propertyName });
return JSHandle.from(result.handle);
});
const result = await this._channel.getProperty({ name: propertyName });
return JSHandle.from(result.handle);
}
async getProperties(): Promise<Map<string, JSHandle>> {
return this._wrapApiCall(async (channel: channels.JSHandleChannel) => {
const map = new Map<string, JSHandle>();
for (const { name, value } of (await channel.getPropertyList()).properties)
map.set(name, JSHandle.from(value));
return map;
});
const map = new Map<string, JSHandle>();
for (const { name, value } of (await this._channel.getPropertyList()).properties)
map.set(name, JSHandle.from(value));
return map;
}
async jsonValue(): Promise<T> {
return this._wrapApiCall(async (channel: channels.JSHandleChannel) => {
return parseResult((await channel.jsonValue()).value);
});
return parseResult((await this._channel.jsonValue()).value);
}
asElement(): T extends Node ? api.ElementHandle<T> : null {
@ -74,9 +64,7 @@ export class JSHandle<T = any> extends ChannelOwner<channels.JSHandleChannel> im
}
async dispose() {
return this._wrapApiCall(async (channel: channels.JSHandleChannel) => {
return await channel.dispose();
});
return await this._channel.dispose();
}
override toString(): string {

View File

@ -37,8 +37,8 @@ export class Locator implements api.Locator {
timeout = this._frame.page()._timeoutSettings.timeout({ timeout });
const deadline = timeout ? monotonicTime() + timeout : 0;
return this._frame._wrapApiCall<R>(async (channel: channels.FrameChannel) => {
const result = await channel.waitForSelector({ selector: this._selector, strict: true, state: 'attached', timeout });
return this._frame._wrapApiCall<R>(async () => {
const result = await this._frame._channel.waitForSelector({ selector: this._selector, strict: true, state: 'attached', timeout });
const handle = ElementHandle.fromNullable(result.element) as ElementHandle<SVGElement | HTMLElement> | null;
if (!handle)
throw new Error(`Could not resolve ${this._selector} to DOM Element`);
@ -224,21 +224,17 @@ export class Locator implements api.Locator {
waitFor(options: channels.FrameWaitForSelectorOptions & { state: 'attached' | 'visible' }): Promise<void>;
waitFor(options?: channels.FrameWaitForSelectorOptions): Promise<void>;
async waitFor(options?: channels.FrameWaitForSelectorOptions): Promise<void> {
return this._frame._wrapApiCall(async (channel: channels.FrameChannel) => {
await channel.waitForSelector({ selector: this._selector, strict: true, omitReturnValue: true, ...options });
});
await this._frame._channel.waitForSelector({ selector: this._selector, strict: true, omitReturnValue: true, ...options });
}
async _expect(expression: string, options: FrameExpectOptions): Promise<{ matches: boolean, received?: any, log?: string[] }> {
return this._frame._wrapApiCall(async (channel: channels.FrameChannel) => {
const params: channels.FrameExpectParams = { selector: this._selector, expression, ...options, isNot: !!options.isNot };
if (options.expectedValue)
params.expectedValue = serializeArgument(options.expectedValue);
const result = (await channel.expect(params));
if (result.received !== undefined)
result.received = parseResult(result.received);
return result;
});
const params: channels.FrameExpectParams = { selector: this._selector, expression, ...options, isNot: !!options.isNot };
if (options.expectedValue)
params.expectedValue = serializeArgument(options.expectedValue);
const result = (await this._frame._channel.expect(params));
if (result.received !== undefined)
result.received = parseResult(result.received);
return result;
}
[util.inspect.custom]() {

View File

@ -142,8 +142,8 @@ export class Request extends ChannelOwner<channels.RequestChannel> implements ap
_actualHeaders(): Promise<RawHeaders> {
if (!this._actualHeadersPromise) {
this._actualHeadersPromise = this._wrapApiCall(async (channel: channels.RequestChannel) => {
return new RawHeaders((await channel.rawRequestHeaders()).headers);
this._actualHeadersPromise = this._wrapApiCall(async () => {
return new RawHeaders((await this._channel.rawRequestHeaders()).headers);
});
}
return this._actualHeadersPromise;
@ -162,14 +162,12 @@ export class Request extends ChannelOwner<channels.RequestChannel> implements ap
}
async response(): Promise<Response | null> {
return this._wrapApiCall(async (channel: channels.RequestChannel) => {
return Response.fromNullable((await channel.response()).response);
});
return Response.fromNullable((await this._channel.response()).response);
}
async _internalResponse(): Promise<Response | null> {
return this._wrapApiCall(async (channel: channels.RequestChannel) => {
return Response.fromNullable((await channel.response()).response);
return this._wrapApiCall(async () => {
return Response.fromNullable((await this._channel.response()).response);
}, true);
}
@ -205,9 +203,7 @@ export class Request extends ChannelOwner<channels.RequestChannel> implements ap
const response = await this.response();
if (!response)
throw new Error('Unable to fetch sizes for failed request');
return response._wrapApiCall(async (channel: channels.ResponseChannel) => {
return (await channel.sizes()).sizes;
});
return (await response._channel.sizes()).sizes;
}
_finalRequest(): Request {
@ -240,56 +236,52 @@ export class Route extends ChannelOwner<channels.RouteChannel> implements api.Ro
}
async abort(errorCode?: string) {
return this._wrapApiCall(async (channel: channels.RouteChannel) => {
await this._raceWithPageClose(channel.abort({ errorCode }));
});
await this._raceWithPageClose(this._channel.abort({ errorCode }));
}
async fulfill(options: { response?: api.APIResponse, status?: number, headers?: Headers, contentType?: string, body?: string | Buffer, path?: string } = {}) {
return this._wrapApiCall(async (channel: channels.RouteChannel) => {
let fetchResponseUid;
let { status: statusOption, headers: headersOption, body } = options;
if (options.response) {
statusOption ||= options.response.status();
headersOption ||= options.response.headers();
if (options.body === undefined && options.path === undefined && options.response instanceof APIResponse)
fetchResponseUid = (options.response as APIResponse)._fetchUid();
}
let fetchResponseUid;
let { status: statusOption, headers: headersOption, body } = options;
if (options.response) {
statusOption ||= options.response.status();
headersOption ||= options.response.headers();
if (options.body === undefined && options.path === undefined && options.response instanceof APIResponse)
fetchResponseUid = (options.response as APIResponse)._fetchUid();
}
let isBase64 = false;
let length = 0;
if (options.path) {
const buffer = await fs.promises.readFile(options.path);
body = buffer.toString('base64');
isBase64 = true;
length = buffer.length;
} else if (isString(body)) {
isBase64 = false;
length = Buffer.byteLength(body);
} else if (body) {
length = body.length;
body = body.toString('base64');
isBase64 = true;
}
let isBase64 = false;
let length = 0;
if (options.path) {
const buffer = await fs.promises.readFile(options.path);
body = buffer.toString('base64');
isBase64 = true;
length = buffer.length;
} else if (isString(body)) {
isBase64 = false;
length = Buffer.byteLength(body);
} else if (body) {
length = body.length;
body = body.toString('base64');
isBase64 = true;
}
const headers: Headers = {};
for (const header of Object.keys(headersOption || {}))
headers[header.toLowerCase()] = String(headersOption![header]);
if (options.contentType)
headers['content-type'] = String(options.contentType);
else if (options.path)
headers['content-type'] = mime.getType(options.path) || 'application/octet-stream';
if (length && !('content-length' in headers))
headers['content-length'] = String(length);
const headers: Headers = {};
for (const header of Object.keys(headersOption || {}))
headers[header.toLowerCase()] = String(headersOption![header]);
if (options.contentType)
headers['content-type'] = String(options.contentType);
else if (options.path)
headers['content-type'] = mime.getType(options.path) || 'application/octet-stream';
if (length && !('content-length' in headers))
headers['content-length'] = String(length);
await this._raceWithPageClose(channel.fulfill({
status: statusOption || 200,
headers: headersObjectToArray(headers),
body,
isBase64,
fetchResponseUid
}));
});
await this._raceWithPageClose(this._channel.fulfill({
status: statusOption || 200,
headers: headersObjectToArray(headers),
body,
isBase64,
fetchResponseUid
}));
}
async continue(options: { url?: string, method?: string, headers?: Headers, postData?: string | Buffer } = {}) {
@ -301,9 +293,9 @@ export class Route extends ChannelOwner<channels.RouteChannel> implements api.Ro
}
private async _continue(options: { url?: string, method?: string, headers?: Headers, postData?: string | Buffer }, isInternal?: boolean) {
return await this._wrapApiCall(async (channel: channels.RouteChannel) => {
return await this._wrapApiCall(async () => {
const postDataBuffer = isString(options.postData) ? Buffer.from(options.postData, 'utf8') : options.postData;
await this._raceWithPageClose(channel.continue({
await this._raceWithPageClose(this._channel.continue({
url: options.url,
method: options.method,
headers: options.headers ? headersObjectToArray(options.headers) : undefined,
@ -381,9 +373,9 @@ export class Response extends ChannelOwner<channels.ResponseChannel> implements
async _actualHeaders(): Promise<RawHeaders> {
if (!this._actualHeadersPromise) {
this._actualHeadersPromise = this._wrapApiCall(async (channel: channels.ResponseChannel) => {
return new RawHeaders((await channel.rawResponseHeaders()).headers);
});
this._actualHeadersPromise = (async () => {
return new RawHeaders((await this._channel.rawResponseHeaders()).headers);
})();
}
return this._actualHeadersPromise;
}
@ -409,9 +401,7 @@ export class Response extends ChannelOwner<channels.ResponseChannel> implements
}
async body(): Promise<Buffer> {
return this._wrapApiCall(async (channel: channels.ResponseChannel) => {
return Buffer.from((await channel.body()).binary, 'base64');
});
return Buffer.from((await this._channel.body()).binary, 'base64');
}
async text(): Promise<string> {
@ -433,15 +423,11 @@ export class Response extends ChannelOwner<channels.ResponseChannel> implements
}
async serverAddr(): Promise<RemoteAddr|null> {
return this._wrapApiCall(async (channel: channels.ResponseChannel) => {
return (await channel.serverAddr()).value || null;
});
return (await this._channel.serverAddr()).value || null;
}
async securityDetails(): Promise<SecurityDetails|null> {
return this._wrapApiCall(async (channel: channels.ResponseChannel) => {
return (await channel.securityDetails()).value || null;
});
return (await this._channel.securityDetails()).value || null;
}
}
@ -485,10 +471,10 @@ export class WebSocket extends ChannelOwner<channels.WebSocketChannel> implement
}
async waitForEvent(event: string, optionsOrPredicate: WaitForEventOptions = {}): Promise<any> {
return this._wrapApiCall(async (channel: channels.WebSocketChannel) => {
return this._wrapApiCall(async () => {
const timeout = this._page._timeoutSettings.timeout(typeof optionsOrPredicate === 'function' ? {} : optionsOrPredicate);
const predicate = typeof optionsOrPredicate === 'function' ? optionsOrPredicate : optionsOrPredicate.predicate;
const waiter = Waiter.createForEvent(channel, event);
const waiter = Waiter.createForEvent(this._channel, event);
waiter.rejectOnTimeout(timeout, `Timeout while waiting for event "${event}"`);
if (event !== Events.WebSocket.Error)
waiter.rejectOnEvent(this, Events.WebSocket.Error, new Error('Socket error'));

View File

@ -173,7 +173,7 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
if (routeHandler.handle(route, request)) {
this._routes.splice(this._routes.indexOf(routeHandler), 1);
if (!this._routes.length)
this._wrapApiCall(channel => this._disableInterception(channel), true).catch(() => {});
this._wrapApiCall(() => this._disableInterception(), true).catch(() => {});
}
return;
}
@ -440,11 +440,11 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
async unroute(url: URLMatch, handler?: RouteHandlerCallback): Promise<void> {
this._routes = this._routes.filter(route => route.url !== url || (handler && route.handler !== handler));
if (!this._routes.length)
await this._disableInterception(this._channel);
await this._disableInterception();
}
private async _disableInterception(channel: channels.PageChannel) {
await channel.setNetworkInterceptionEnabled({ enabled: false });
private async _disableInterception() {
await this._channel.setNetworkInterceptionEnabled({ enabled: false });
}
async screenshot(options: channels.PageScreenshotOptions & { path?: string } = {}): Promise<Buffer> {
@ -470,12 +470,10 @@ export class Page extends ChannelOwner<channels.PageChannel> implements api.Page
async close(options: { runBeforeUnload?: boolean } = { runBeforeUnload: undefined }) {
try {
await this._wrapApiCall(async (channel: channels.PageChannel) => {
if (this._ownedContext)
await this._ownedContext.close();
else
await channel.close(options);
});
if (this._ownedContext)
await this._ownedContext.close();
else
await this._channel.close(options);
} catch (e) {
if (isSafeCloseError(e))
return;

View File

@ -46,29 +46,25 @@ export class Tracing implements api.Tracing {
async start(options: { name?: string, title?: string, snapshots?: boolean, screenshots?: boolean, sources?: boolean } = {}) {
if (options.sources)
this._context._instrumentation!.addListener(this._instrumentationListener);
await this._context._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
await channel.tracingStart(options);
await channel.tracingStartChunk({ title: options.title });
await this._context._wrapApiCall(async () => {
await this._context._channel.tracingStart(options);
await this._context._channel.tracingStartChunk({ title: options.title });
});
}
async startChunk(options: { title?: string } = {}) {
this._sources = new Set();
await this._context._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
await channel.tracingStartChunk(options);
});
await this._context._channel.tracingStartChunk(options);
}
async stopChunk(options: { path?: string } = {}) {
await this._context._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
await this._doStopChunk(channel, options.path);
});
await this._doStopChunk(this._context._channel, options.path);
}
async stop(options: { path?: string } = {}) {
await this._context._wrapApiCall(async (channel: channels.BrowserContextChannel) => {
await this._doStopChunk(channel, options.path);
await channel.tracingStop();
await this._context._wrapApiCall(async () => {
await this._doStopChunk(this._context._channel, options.path);
await this._context._channel.tracingStop();
});
}

View File

@ -48,17 +48,13 @@ export class Worker extends ChannelOwner<channels.WorkerChannel> implements api.
async evaluate<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg): Promise<R> {
assertMaxArguments(arguments.length, 2);
return this._wrapApiCall(async (channel: channels.WorkerChannel) => {
const result = await channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
return parseResult(result.value);
});
const result = await this._channel.evaluateExpression({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
return parseResult(result.value);
}
async evaluateHandle<R, Arg>(pageFunction: structs.PageFunction<Arg, R>, arg?: Arg): Promise<structs.SmartHandle<R>> {
assertMaxArguments(arguments.length, 2);
return this._wrapApiCall(async (channel: channels.WorkerChannel) => {
const result = await channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
return JSHandle.from(result.handle) as any as structs.SmartHandle<R>;
});
const result = await this._channel.evaluateExpressionHandle({ expression: String(pageFunction), isFunction: typeof pageFunction === 'function', arg: serializeArgument(arg) });
return JSHandle.from(result.handle) as any as structs.SmartHandle<R>;
}
}