chore: use channels types instead of a copy in server (#14874)

This is to avoid duplicating types for no reason.
This commit is contained in:
Dmitry Gozman 2022-06-14 22:02:15 -07:00 committed by GitHub
parent e00a26a11d
commit 06c8d8e31c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 135 additions and 347 deletions

View File

@ -16,13 +16,13 @@
*/
import type * as dom from './dom';
import type * as types from './types';
import type * as channels from '../protocol/channels';
export interface AXNode {
isInteresting(insideControl: boolean): boolean;
isLeafNode(): boolean;
isControl(): boolean;
serialize(): types.SerializedAXNode;
serialize(): channels.AXNode;
children(): Iterable<AXNode>;
}
@ -35,7 +35,7 @@ export class Accessibility {
async snapshot(options: {
interestingOnly?: boolean;
root?: dom.ElementHandle;
} = {}): Promise<types.SerializedAXNode | null> {
} = {}): Promise<channels.AXNode | null> {
const {
interestingOnly = true,
root = null,
@ -65,8 +65,8 @@ function collectInterestingNodes(collection: Set<AXNode>, node: AXNode, insideCo
collectInterestingNodes(collection, child, insideControl);
}
function serializeTree(node: AXNode, whitelistedNodes?: Set<AXNode>): types.SerializedAXNode[] {
const children: types.SerializedAXNode[] = [];
function serializeTree(node: AXNode, whitelistedNodes?: Set<AXNode>): channels.AXNode[] {
const children: channels.AXNode[] = [];
for (const child of node.children())
children.push(...serializeTree(child, whitelistedNodes));

View File

@ -15,7 +15,6 @@
*/
import { debug } from '../../utilsBundle';
import type * as types from '../types';
import { EventEmitter } from 'events';
import fs from 'fs';
import os from 'os';
@ -34,13 +33,13 @@ import { PipeTransport } from '../../protocol/transport';
import { RecentLogsCollector } from '../../common/debugLogger';
import { gracefullyCloseSet } from '../../utils/processLauncher';
import { TimeoutSettings } from '../../common/timeoutSettings';
import type { AndroidWebView } from '../../protocol/channels';
import type * as channels from '../../protocol/channels';
import { SdkObject, serverSideCallMetadata } from '../instrumentation';
const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');
export interface Backend {
devices(options: types.AndroidDeviceOptions): Promise<DeviceBackend[]>;
devices(options: channels.AndroidDevicesOptions): Promise<DeviceBackend[]>;
}
export interface DeviceBackend {
@ -75,7 +74,7 @@ export class Android extends SdkObject {
this._timeoutSettings.setDefaultTimeout(timeout);
}
async devices(options: types.AndroidDeviceOptions): Promise<AndroidDevice[]> {
async devices(options: channels.AndroidDevicesOptions): Promise<AndroidDevice[]> {
const devices = (await this._backend.devices(options)).filter(d => d.status === 'device');
const newSerials = new Set<string>();
for (const d of devices) {
@ -101,13 +100,13 @@ export class AndroidDevice extends SdkObject {
readonly _backend: DeviceBackend;
readonly model: string;
readonly serial: string;
private _options: types.AndroidDeviceOptions;
private _options: channels.AndroidDevicesOptions;
private _driverPromise: Promise<PipeTransport> | undefined;
private _lastId = 0;
private _callbacks = new Map<number, { fulfill: (result: any) => void, reject: (error: Error) => void }>();
private _pollingWebViews: NodeJS.Timeout | undefined;
readonly _timeoutSettings: TimeoutSettings;
private _webViews = new Map<string, AndroidWebView>();
private _webViews = new Map<string, channels.AndroidWebView>();
static Events = {
WebViewAdded: 'webViewAdded',
@ -119,7 +118,7 @@ export class AndroidDevice extends SdkObject {
private _android: Android;
private _isClosed = false;
constructor(android: Android, backend: DeviceBackend, model: string, options: types.AndroidDeviceOptions) {
constructor(android: Android, backend: DeviceBackend, model: string, options: channels.AndroidDevicesOptions) {
super(android, 'android-device');
this._android = android;
this._backend = backend;
@ -129,7 +128,7 @@ export class AndroidDevice extends SdkObject {
this._timeoutSettings = new TimeoutSettings(android._timeoutSettings);
}
static async create(android: Android, backend: DeviceBackend, options: types.AndroidDeviceOptions): Promise<AndroidDevice> {
static async create(android: Android, backend: DeviceBackend, options: channels.AndroidDevicesOptions): Promise<AndroidDevice> {
await backend.init();
const model = await backend.runCommand('shell:getprop ro.product.model');
const device = new AndroidDevice(android, backend, model.toString().trim(), options);
@ -244,7 +243,7 @@ export class AndroidDevice extends SdkObject {
this.emit(AndroidDevice.Events.Closed);
}
async launchBrowser(pkg: string = 'com.android.chrome', options: types.BrowserContextOptions): Promise<BrowserContext> {
async launchBrowser(pkg: string = 'com.android.chrome', options: channels.BrowserNewContextParams): Promise<BrowserContext> {
debug('pw:android')('Force-stopping', pkg);
await this._backend.runCommand(`shell:am force-stop ${pkg}`);
const socketName = isUnderTest() ? 'webview_devtools_remote_playwright_test' : ('playwright-' + createGuid());
@ -262,7 +261,7 @@ export class AndroidDevice extends SdkObject {
return await this._connectToBrowser(socketName);
}
private async _connectToBrowser(socketName: string, options: types.BrowserContextOptions = {}): Promise<BrowserContext> {
private async _connectToBrowser(socketName: string, options: channels.BrowserNewContextParams = {}): Promise<BrowserContext> {
const socket = await this._waitForLocalAbstract(socketName);
const androidBrowser = new AndroidBrowser(this, socket);
await androidBrowser._init();
@ -304,7 +303,7 @@ export class AndroidDevice extends SdkObject {
return defaultContext;
}
webViews(): AndroidWebView[] {
webViews(): channels.AndroidWebView[] {
return [...this._webViews.values()];
}

View File

@ -15,14 +15,14 @@
*/
import { debug } from '../../utilsBundle';
import type * as types from '../types';
import type * as channels from '../../protocol/channels';
import * as net from 'net';
import { EventEmitter } from 'events';
import type { Backend, DeviceBackend, SocketBackend } from './android';
import { assert, createGuid } from '../../utils';
export class AdbBackend implements Backend {
async devices(options: types.AndroidDeviceOptions = {}): Promise<DeviceBackend[]> {
async devices(options: channels.AndroidDevicesOptions = {}): Promise<DeviceBackend[]> {
const result = await runCommand('host:devices', options.host, options.port);
const lines = result.toString().trim().split('\n');
return lines.map(line => {

View File

@ -15,6 +15,7 @@
*/
import type * as types from './types';
import type * as channels from '../protocol/channels';
import { BrowserContext, validateBrowserContextOptions } from './browserContext';
import { Page } from './page';
import { Download } from './download';
@ -48,7 +49,7 @@ export type BrowserOptions = PlaywrightOptions & {
downloadsPath: string,
tracesDir: string,
headful?: boolean,
persistent?: types.BrowserContextOptions, // Undefined means no persistent context.
persistent?: channels.BrowserNewContextParams, // Undefined means no persistent context.
browserProcess: BrowserProcess,
customExecutablePath?: string;
proxy?: ProxySettings,
@ -75,13 +76,13 @@ export abstract class Browser extends SdkObject {
this.options = options;
}
abstract doCreateNewContext(options: types.BrowserContextOptions): Promise<BrowserContext>;
abstract doCreateNewContext(options: channels.BrowserNewContextParams): Promise<BrowserContext>;
abstract contexts(): BrowserContext[];
abstract isConnected(): boolean;
abstract version(): string;
abstract userAgent(): string;
async newContext(metadata: CallMetadata, options: types.BrowserContextOptions): Promise<BrowserContext> {
async newContext(metadata: CallMetadata, options: channels.BrowserNewContextParams): Promise<BrowserContext> {
validateBrowserContextOptions(options, this.options);
const context = await this.doCreateNewContext(options);
if (options.storageState)

View File

@ -29,6 +29,7 @@ import { Page, PageBinding } from './page';
import type { Progress } from './progress';
import type { Selectors } from './selectors';
import type * as types from './types';
import type * as channels from '../protocol/channels';
import path from 'path';
import fs from 'fs';
import type { CallMetadata } from './instrumentation';
@ -54,7 +55,7 @@ export abstract class BrowserContext extends SdkObject {
readonly _timeoutSettings = new TimeoutSettings();
readonly _pageBindings = new Map<string, PageBinding>();
readonly _options: types.BrowserContextOptions;
readonly _options: channels.BrowserNewContextParams;
_requestInterceptor?: network.RouteHandler;
private _isPersistentContext: boolean;
private _closedStatus: 'open' | 'closing' | 'closed' = 'open';
@ -74,7 +75,7 @@ export abstract class BrowserContext extends SdkObject {
private _settingStorageState = false;
readonly initScripts: string[] = [];
constructor(browser: Browser, options: types.BrowserContextOptions, browserContextId: string | undefined) {
constructor(browser: Browser, options: channels.BrowserNewContextParams, browserContextId: string | undefined) {
super(browser, 'browser-context');
this.attribution.context = this;
this._browser = browser;
@ -156,13 +157,13 @@ export abstract class BrowserContext extends SdkObject {
// BrowserContext methods.
abstract pages(): Page[];
abstract newPageDelegate(): Promise<PageDelegate>;
abstract addCookies(cookies: types.SetNetworkCookieParam[]): Promise<void>;
abstract addCookies(cookies: channels.SetNetworkCookie[]): Promise<void>;
abstract clearCookies(): Promise<void>;
abstract setGeolocation(geolocation?: types.Geolocation): Promise<void>;
abstract setExtraHTTPHeaders(headers: types.HeadersArray): Promise<void>;
abstract setOffline(offline: boolean): Promise<void>;
abstract cancelDownload(uuid: string): Promise<void>;
protected abstract doGetCookies(urls: string[]): Promise<types.NetworkCookie[]>;
protected abstract doGetCookies(urls: string[]): Promise<channels.NetworkCookie[]>;
protected abstract doGrantPermissions(origin: string, permissions: string[]): Promise<void>;
protected abstract doClearPermissions(): Promise<void>;
protected abstract doSetHTTPCredentials(httpCredentials?: types.Credentials): Promise<void>;
@ -174,7 +175,7 @@ export abstract class BrowserContext extends SdkObject {
protected abstract doClose(): Promise<void>;
protected abstract onClosePersistent(): void;
async cookies(urls: string | string[] | undefined = []): Promise<types.NetworkCookie[]> {
async cookies(urls: string | string[] | undefined = []): Promise<channels.NetworkCookie[]> {
if (urls && !Array.isArray(urls))
urls = [ urls ];
return await this.doGetCookies(urls as string[]);
@ -374,8 +375,8 @@ export abstract class BrowserContext extends SdkObject {
this._origins.add(origin);
}
async storageState(): Promise<types.StorageState> {
const result: types.StorageState = {
async storageState(): Promise<channels.BrowserContextStorageStateResult> {
const result: channels.BrowserContextStorageStateResult = {
cookies: await this.cookies(),
origins: []
};
@ -386,7 +387,7 @@ export abstract class BrowserContext extends SdkObject {
handler.fulfill({ body: '<html></html>' }).catch(() => {});
});
for (const origin of this._origins) {
const originStorage: types.OriginStorage = { origin, localStorage: [] };
const originStorage: channels.OriginStorage = { origin, localStorage: [] };
const frame = page.mainFrame();
await frame.goto(internalMetadata, origin);
const storage = await frame.evaluateExpression(`({
@ -405,7 +406,7 @@ export abstract class BrowserContext extends SdkObject {
return this._settingStorageState;
}
async setStorageState(metadata: CallMetadata, state: types.SetStorageState) {
async setStorageState(metadata: CallMetadata, state: NonNullable<channels.BrowserNewContextParams['storageState']>) {
this._settingStorageState = true;
try {
if (state.cookies)
@ -450,7 +451,7 @@ export function assertBrowserContextIsNotOwned(context: BrowserContext) {
}
}
export function validateBrowserContextOptions(options: types.BrowserContextOptions, browserOptions: BrowserOptions) {
export function validateBrowserContextOptions(options: channels.BrowserNewContextParams, browserOptions: BrowserOptions) {
if (options.noDefaultViewport && options.deviceScaleFactor !== undefined)
throw new Error(`"deviceScaleFactor" option is not supported with null "viewport"`);
if (options.noDefaultViewport && options.isMobile !== undefined)

View File

@ -30,6 +30,7 @@ import { PipeTransport } from './pipeTransport';
import type { Progress } from './progress';
import { ProgressController } from './progress';
import type * as types from './types';
import type * as channels from '../protocol/channels';
import { DEFAULT_TIMEOUT, TimeoutSettings } from '../common/timeoutSettings';
import { debugMode } from '../utils';
import { existsAsync } from '../utils/fileUtils';
@ -73,10 +74,10 @@ export abstract class BrowserType extends SdkObject {
return browser;
}
async launchPersistentContext(metadata: CallMetadata, userDataDir: string, options: types.LaunchPersistentOptions): Promise<BrowserContext> {
async launchPersistentContext(metadata: CallMetadata, userDataDir: string, options: channels.BrowserTypeLaunchPersistentContextOptions & { useWebSocket?: boolean }): Promise<BrowserContext> {
options = this._validateLaunchOptions(options);
const controller = new ProgressController(metadata, this);
const persistent: types.BrowserContextOptions = options;
const persistent: channels.BrowserNewContextParams = options;
controller.setLogName('browser');
const browser = await controller.run(progress => {
return this._innerLaunchWithRetries(progress, options, persistent, helper.debugProtocolLogger(), userDataDir).catch(e => { throw this._rewriteStartupError(e); });
@ -84,7 +85,7 @@ export abstract class BrowserType extends SdkObject {
return browser._defaultContext!;
}
async _innerLaunchWithRetries(progress: Progress, options: types.LaunchOptions, persistent: types.BrowserContextOptions | undefined, protocolLogger: types.ProtocolLogger, userDataDir?: string): Promise<Browser> {
async _innerLaunchWithRetries(progress: Progress, options: types.LaunchOptions, persistent: channels.BrowserNewContextParams | undefined, protocolLogger: types.ProtocolLogger, userDataDir?: string): Promise<Browser> {
try {
return await this._innerLaunch(progress, options, persistent, protocolLogger, userDataDir);
} catch (error) {
@ -98,7 +99,7 @@ export abstract class BrowserType extends SdkObject {
}
}
async _innerLaunch(progress: Progress, options: types.LaunchOptions, persistent: types.BrowserContextOptions | undefined, protocolLogger: types.ProtocolLogger, maybeUserDataDir?: string): Promise<Browser> {
async _innerLaunch(progress: Progress, options: types.LaunchOptions, persistent: channels.BrowserNewContextParams | undefined, protocolLogger: types.ProtocolLogger, maybeUserDataDir?: string): Promise<Browser> {
options.proxy = options.proxy ? normalizeProxySettings(options.proxy) : undefined;
const browserLogsCollector = new RecentLogsCollector();
const { browserProcess, userDataDir, artifactsDir, transport } = await this._launchProcess(progress, options, !!persistent, browserLogsCollector, maybeUserDataDir);

View File

@ -30,6 +30,7 @@ import { CRDevTools } from './crDevTools';
import type { BrowserOptions, BrowserProcess, PlaywrightOptions } from '../browser';
import { Browser } from '../browser';
import type * as types from '../types';
import type * as channels from '../../protocol/channels';
import type { HTTPRequestParams } from '../../common/netUtils';
import { fetchData } from '../../common/netUtils';
import { getUserAgent } from '../../common/userAgent';
@ -94,7 +95,7 @@ export class Chromium extends BrowserType {
await cleanedUp;
};
const browserProcess: BrowserProcess = { close: doClose, kill: doClose };
const persistent: types.BrowserContextOptions = { noDefaultViewport: true };
const persistent: channels.BrowserNewContextParams = { noDefaultViewport: true };
const browserOptions: BrowserOptions = {
...this._playwrightOptions,
slowMo: options.slowMo,

View File

@ -19,7 +19,7 @@ import type { CRSession } from './crConnection';
import type { Protocol } from './protocol';
import type * as dom from '../dom';
import type * as accessibility from '../accessibility';
import type * as types from '../types';
import type * as channels from '../../protocol/channels';
export async function getAccessibilityTree(client: CRSession, needle?: dom.ElementHandle): Promise<{tree: accessibility.AXNode, needle: accessibility.AXNode | null}> {
const { nodes } = await client.send('Accessibility.getFullAXTree');
@ -210,19 +210,19 @@ class CRAXNode implements accessibility.AXNode {
}
}
serialize(): types.SerializedAXNode {
serialize(): channels.AXNode {
const properties: Map<string, number | string | boolean> = new Map();
for (const property of this._payload.properties || [])
properties.set(property.name.toLowerCase(), property.value.value);
if (this._payload.description)
properties.set('description', this._payload.description.value);
const node: {[x in keyof types.SerializedAXNode]: any} = {
const node: {[x in keyof channels.AXNode]: any} = {
role: this.normalizedRole(),
name: this._payload.name ? (this._payload.name.value || '') : '',
};
const userStringProperties: Array<keyof types.SerializedAXNode> = [
const userStringProperties: Array<keyof channels.AXNode> = [
'description',
'keyshortcuts',
'roledescription',
@ -233,7 +233,7 @@ class CRAXNode implements accessibility.AXNode {
continue;
node[userStringProperty] = properties.get(userStringProperty);
}
const booleanProperties: Array<keyof types.SerializedAXNode> = [
const booleanProperties: Array<keyof channels.AXNode> = [
'disabled',
'expanded',
'focused',
@ -254,7 +254,7 @@ class CRAXNode implements accessibility.AXNode {
continue;
node[booleanProperty] = value;
}
const numericalProperties: Array<keyof types.SerializedAXNode> = [
const numericalProperties: Array<keyof channels.AXNode> = [
'level',
'valuemax',
'valuemin',
@ -264,7 +264,7 @@ class CRAXNode implements accessibility.AXNode {
continue;
node[numericalProperty] = properties.get(numericalProperty);
}
const tokenProperties: Array<keyof types.SerializedAXNode> = [
const tokenProperties: Array<keyof channels.AXNode> = [
'autocomplete',
'haspopup',
'invalid',
@ -277,7 +277,7 @@ class CRAXNode implements accessibility.AXNode {
node[tokenProperty] = value;
}
const axNode = node as types.SerializedAXNode;
const axNode = node as channels.AXNode;
if (this._payload.value) {
if (typeof this._payload.value.value === 'string')
axNode.valueString = this._payload.value.value;

View File

@ -26,6 +26,7 @@ import { Frame } from '../frames';
import type { Dialog } from '../dialog';
import type { ConnectionTransport } from '../transport';
import type * as types from '../types';
import type * as channels from '../../protocol/channels';
import type { CRSession } from './crConnection';
import { ConnectionEvents, CRConnection } from './crConnection';
import { CRPage } from './crPage';
@ -95,7 +96,7 @@ export class CRBrowser extends Browser {
this._session.on('Browser.downloadProgress', this._onDownloadProgress.bind(this));
}
async doCreateNewContext(options: types.BrowserContextOptions): Promise<BrowserContext> {
async doCreateNewContext(options: channels.BrowserNewContextParams): Promise<BrowserContext> {
let proxyBypassList = undefined;
if (options.proxy) {
if (process.env.PLAYWRIGHT_DISABLE_FORCED_CHROMIUM_PROXIED_LOOPBACK)
@ -327,7 +328,7 @@ export class CRBrowserContext extends BrowserContext {
declare readonly _browser: CRBrowser;
constructor(browser: CRBrowser, browserContextId: string | undefined, options: types.BrowserContextOptions) {
constructor(browser: CRBrowser, browserContextId: string | undefined, options: channels.BrowserNewContextParams) {
super(browser, options, browserContextId);
this._authenticateProxyViaCredentials();
}
@ -383,7 +384,7 @@ export class CRBrowserContext extends BrowserContext {
return this._browser._crPages.get(targetId)!;
}
async doGetCookies(urls: string[]): Promise<types.NetworkCookie[]> {
async doGetCookies(urls: string[]): Promise<channels.NetworkCookie[]> {
const { cookies } = await this._browser._session.send('Storage.getCookies', { browserContextId: this._browserContextId });
return network.filterCookies(cookies.map(c => {
const copy: any = { sameSite: 'Lax', ...c };
@ -393,11 +394,11 @@ export class CRBrowserContext extends BrowserContext {
delete copy.sameParty;
delete copy.sourceScheme;
delete copy.sourcePort;
return copy as types.NetworkCookie;
return copy as channels.NetworkCookie;
}), urls);
}
async addCookies(cookies: types.SetNetworkCookieParam[]) {
async addCookies(cookies: channels.SetNetworkCookie[]) {
await this._browser._session.send('Storage.setCookies', { cookies: network.rewriteCookies(cookies), browserContextId: this._browserContextId });
}

View File

@ -19,7 +19,7 @@ import type { CRSession } from './crConnection';
import type { RegisteredListener } from '../../utils/eventsHelper';
import { eventsHelper } from '../../utils/eventsHelper';
import type { Protocol } from './protocol';
import type * as types from '../types';
import type * as channels from '../../protocol/channels';
import { assert } from '../../utils';
export class CRCoverage {
@ -31,19 +31,19 @@ export class CRCoverage {
this._cssCoverage = new CSSCoverage(client);
}
async startJSCoverage(options?: types.JSCoverageOptions) {
async startJSCoverage(options: channels.PageStartJSCoverageParams) {
return await this._jsCoverage.start(options);
}
async stopJSCoverage(): Promise<types.JSCoverageEntry[]> {
async stopJSCoverage(): Promise<channels.PageStopJSCoverageResult> {
return await this._jsCoverage.stop();
}
async startCSSCoverage(options?: types.CSSCoverageOptions) {
async startCSSCoverage(options: channels.PageStartCSSCoverageParams) {
return await this._cssCoverage.start(options);
}
async stopCSSCoverage(): Promise<types.CSSCoverageEntry[]> {
async stopCSSCoverage(): Promise<channels.PageStopCSSCoverageResult> {
return await this._cssCoverage.stop();
}
}
@ -66,7 +66,7 @@ class JSCoverage {
this._resetOnNavigation = false;
}
async start(options: types.JSCoverageOptions = {}) {
async start(options: channels.PageStartJSCoverageParams) {
assert(!this._enabled, 'JSCoverage is already enabled');
const {
resetOnNavigation = true,
@ -112,7 +112,7 @@ class JSCoverage {
this._scriptSources.set(event.scriptId, response.scriptSource);
}
async stop(): Promise<types.JSCoverageEntry[]> {
async stop(): Promise<channels.PageStopJSCoverageResult> {
assert(this._enabled, 'JSCoverage is not enabled');
this._enabled = false;
const [profileResponse] = await Promise.all([
@ -123,7 +123,7 @@ class JSCoverage {
] as const);
eventsHelper.removeEventListeners(this._eventListeners);
const coverage: types.JSCoverageEntry[] = [];
const coverage: channels.PageStopJSCoverageResult = { entries: [] };
for (const entry of profileResponse.result) {
if (!this._scriptIds.has(entry.scriptId))
continue;
@ -131,9 +131,9 @@ class JSCoverage {
continue;
const source = this._scriptSources.get(entry.scriptId);
if (source)
coverage.push({ ...entry, source });
coverage.entries.push({ ...entry, source });
else
coverage.push(entry);
coverage.entries.push(entry);
}
return coverage;
}
@ -156,7 +156,7 @@ class CSSCoverage {
this._resetOnNavigation = false;
}
async start(options: types.CSSCoverageOptions = {}) {
async start(options: channels.PageStartCSSCoverageParams) {
assert(!this._enabled, 'CSSCoverage is already enabled');
const { resetOnNavigation = true } = options;
this._resetOnNavigation = resetOnNavigation;
@ -194,7 +194,7 @@ class CSSCoverage {
}
}
async stop(): Promise<types.CSSCoverageEntry[]> {
async stop(): Promise<channels.PageStopCSSCoverageResult> {
assert(this._enabled, 'CSSCoverage is not enabled');
this._enabled = false;
const ruleTrackingResponse = await this._client.send('CSS.stopRuleUsageTracking');
@ -219,12 +219,12 @@ class CSSCoverage {
});
}
const coverage: types.CSSCoverageEntry[] = [];
const coverage: channels.PageStopCSSCoverageResult = { entries: [] };
for (const styleSheetId of this._stylesheetURLs.keys()) {
const url = this._stylesheetURLs.get(styleSheetId)!;
const text = this._stylesheetSources.get(styleSheetId)!;
const ranges = convertToDisjointRanges(styleSheetIdToCoverage.get(styleSheetId) || []);
coverage.push({ url, ranges, text });
coverage.entries.push({ url, ranges, text });
}
return coverage;

View File

@ -30,6 +30,7 @@ import type { PageBinding, PageDelegate } from '../page';
import { Page, Worker } from '../page';
import type { Progress } from '../progress';
import type * as types from '../types';
import type * as channels from '../../protocol/channels';
import { getAccessibilityTree } from './crAccessibility';
import { CRBrowserContext } from './crBrowser';
import type { CRSession } from './crConnection';
@ -356,7 +357,7 @@ export class CRPage implements PageDelegate {
await this._mainFrameSession._client.send('Page.enable').catch(e => {});
}
async pdf(options?: types.PDFOptions): Promise<Buffer> {
async pdf(options: channels.PagePdfParams): Promise<Buffer> {
return this._pdf.generate(options);
}

View File

@ -16,7 +16,7 @@
*/
import { assert } from '../../utils';
import type * as types from '../types';
import type * as channels from '../../protocol/channels';
import type { CRSession } from './crConnection';
import { readProtocolStream } from './crProtocolHelper';
@ -67,7 +67,7 @@ export class CRPDF {
this._client = client;
}
async generate(options: types.PDFOptions = {}): Promise<Buffer> {
async generate(options: channels.PagePdfParams): Promise<Buffer> {
const {
scale = 1,
displayHeaderFooter = false,

View File

@ -14,11 +14,11 @@
* limitations under the License.
*/
import type * as types from './types';
import type * as channels from '../protocol/channels';
class Cookie {
private _raw: types.NetworkCookie;
constructor(data: types.NetworkCookie) {
private _raw: channels.NetworkCookie;
constructor(data: channels.NetworkCookie) {
this._raw = data;
}
@ -43,7 +43,7 @@ class Cookie {
this._raw.path === other._raw.path;
}
networkCookie(): types.NetworkCookie {
networkCookie(): channels.NetworkCookie {
return this._raw;
}
@ -61,12 +61,12 @@ class Cookie {
export class CookieStore {
private readonly _nameToCookies: Map<string, Set<Cookie>> = new Map();
addCookies(cookies: types.NetworkCookie[]) {
addCookies(cookies: channels.NetworkCookie[]) {
for (const cookie of cookies)
this._addCookie(new Cookie(cookie));
}
cookies(url: URL): types.NetworkCookie[] {
cookies(url: URL): channels.NetworkCookie[] {
const result = [];
for (const cookie of this._cookiesIterator()) {
if (cookie.matches(url))
@ -75,7 +75,7 @@ export class CookieStore {
return result;
}
allCookies(): types.NetworkCookie[] {
allCookies(): channels.NetworkCookie[] {
const result = [];
for (const cookie of this._cookiesIterator())
result.push(cookie.networkCookie());

View File

@ -274,7 +274,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel> imple
async stopJSCoverage(params: channels.PageStopJSCoverageParams, metadata: CallMetadata): Promise<channels.PageStopJSCoverageResult> {
const coverage = this._page.coverage as CRCoverage;
return { entries: await coverage.stopJSCoverage() };
return await coverage.stopJSCoverage();
}
async startCSSCoverage(params: channels.PageStartCSSCoverageParams, metadata: CallMetadata): Promise<void> {
@ -284,7 +284,7 @@ export class PageDispatcher extends Dispatcher<Page, channels.PageChannel> imple
async stopCSSCoverage(params: channels.PageStopCSSCoverageParams, metadata: CallMetadata): Promise<channels.PageStopCSSCoverageResult> {
const coverage = this._page.coverage as CRCoverage;
return { entries: await coverage.stopCSSCoverage() };
return await coverage.stopCSSCoverage();
}
_onFrameAttached(frame: Frame) {

View File

@ -41,7 +41,6 @@ import * as readline from 'readline';
import { RecentLogsCollector } from '../../common/debugLogger';
import { serverSideCallMetadata, SdkObject } from '../instrumentation';
import type * as channels from '../../protocol/channels';
import type { BrowserContextOptions } from '../types';
const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');
@ -211,7 +210,7 @@ export class Electron extends SdkObject {
close: gracefullyClose,
kill
};
const contextOptions: BrowserContextOptions = {
const contextOptions: channels.BrowserNewContextParams = {
...options,
noDefaultViewport: true,
};

View File

@ -52,7 +52,7 @@ export type APIRequestEvent = {
url: URL,
method: string,
headers: { [name: string]: string },
cookies: types.NameValueList,
cookies: channels.NameValue[],
postData?: Buffer
};
@ -60,7 +60,7 @@ export type APIRequestFinishedEvent = {
requestEvent: APIRequestEvent,
httpVersion: string;
headers: http.IncomingHttpHeaders;
cookies: types.NetworkCookie[];
cookies: channels.NetworkCookie[];
rawHeaders: string[];
statusCode: number;
statusMessage: string;
@ -110,8 +110,8 @@ export abstract class APIRequestContext extends SdkObject {
abstract dispose(): Promise<void>;
abstract _defaultOptions(): FetchRequestOptions;
abstract _addCookies(cookies: types.NetworkCookie[]): Promise<void>;
abstract _cookies(url: URL): Promise<types.NetworkCookie[]>;
abstract _addCookies(cookies: channels.NetworkCookie[]): Promise<void>;
abstract _cookies(url: URL): Promise<channels.NetworkCookie[]>;
abstract storageState(): Promise<channels.APIRequestContextStorageStateResult>;
private _storeResponseBody(body: Buffer): string {
@ -120,7 +120,7 @@ export abstract class APIRequestContext extends SdkObject {
return uid;
}
async fetch(params: channels.APIRequestContextFetchParams, metadata: CallMetadata): Promise<Omit<types.APIResponse, 'body'> & { fetchUid: string }> {
async fetch(params: channels.APIRequestContextFetchParams, metadata: CallMetadata): Promise<channels.APIResponse> {
const headers: { [name: string]: string } = {};
const defaults = this._defaultOptions();
headers['user-agent'] = defaults.userAgent;
@ -194,16 +194,16 @@ export abstract class APIRequestContext extends SdkObject {
return { ...fetchResponse, fetchUid };
}
private _parseSetCookieHeader(responseUrl: string, setCookie: string[] | undefined): types.NetworkCookie[] {
private _parseSetCookieHeader(responseUrl: string, setCookie: string[] | undefined): channels.NetworkCookie[] {
if (!setCookie)
return [];
const url = new URL(responseUrl);
// https://datatracker.ietf.org/doc/html/rfc6265#section-5.1.4
const defaultPath = '/' + url.pathname.substr(1).split('/').slice(0, -1).join('/');
const cookies: types.NetworkCookie[] = [];
const cookies: channels.NetworkCookie[] = [];
for (const header of setCookie) {
// Decode cookie value?
const cookie: types.NetworkCookie | null = parseCookie(header);
const cookie: channels.NetworkCookie | null = parseCookie(header);
if (!cookie)
continue;
// https://datatracker.ietf.org/doc/html/rfc6265#section-5.2.3
@ -231,7 +231,7 @@ export abstract class APIRequestContext extends SdkObject {
}
}
private async _sendRequest(progress: Progress, url: URL, options: https.RequestOptions & { maxRedirects: number, deadline: number }, postData?: Buffer): Promise<types.APIResponse>{
private async _sendRequest(progress: Progress, url: URL, options: https.RequestOptions & { maxRedirects: number, deadline: number }, postData?: Buffer): Promise<Omit<channels.APIResponse, 'fetchUid'> & { body: Buffer }>{
await this._updateRequestCookieHeader(url, options);
const requestCookies = (options.headers!['cookie'] as (string | undefined))?.split(';').map(p => {
@ -247,7 +247,7 @@ export abstract class APIRequestContext extends SdkObject {
};
this.emit(APIRequestContext.Events.Request, requestEvent);
return new Promise<types.APIResponse>((fulfill, reject) => {
return new Promise((fulfill, reject) => {
const requestConstructor: ((url: URL, options: http.RequestOptions, callback?: (res: http.IncomingMessage) => void) => http.ClientRequest)
= (url.protocol === 'https:' ? https : http).request;
const request = requestConstructor(url, options, async response => {
@ -455,11 +455,11 @@ export class BrowserContextAPIRequestContext extends APIRequestContext {
};
}
async _addCookies(cookies: types.NetworkCookie[]): Promise<void> {
async _addCookies(cookies: channels.NetworkCookie[]): Promise<void> {
await this._context.addCookies(cookies);
}
async _cookies(url: URL): Promise<types.NetworkCookie[]> {
async _cookies(url: URL): Promise<channels.NetworkCookie[]> {
return await this._context.cookies(url.toString());
}
@ -519,11 +519,11 @@ export class GlobalAPIRequestContext extends APIRequestContext {
return this._options;
}
async _addCookies(cookies: types.NetworkCookie[]): Promise<void> {
async _addCookies(cookies: channels.NetworkCookie[]): Promise<void> {
this._cookieStore.addCookies(cookies);
}
async _cookies(url: URL): Promise<types.NetworkCookie[]> {
async _cookies(url: URL): Promise<channels.NetworkCookie[]> {
return this._cookieStore.cookies(url);
}
@ -544,7 +544,7 @@ function toHeadersArray(rawHeaders: string[]): types.HeadersArray {
const redirectStatus = [301, 302, 303, 307, 308];
function parseCookie(header: string): types.NetworkCookie | null {
function parseCookie(header: string): channels.NetworkCookie | null {
const pairs = header.split(';').filter(s => s.trim().length > 0).map(p => {
let key = '';
let value = '';
@ -563,7 +563,7 @@ function parseCookie(header: string): types.NetworkCookie | null {
if (!pairs.length)
return null;
const [name, value] = pairs[0];
const cookie: types.NetworkCookie = {
const cookie: channels.NetworkCookie = {
name,
value,
domain: '',

View File

@ -19,7 +19,7 @@ import type * as accessibility from '../accessibility';
import type { FFSession } from './ffConnection';
import type { Protocol } from './protocol';
import type * as dom from '../dom';
import type * as types from '../types';
import type * as channels from '../../protocol/channels';
export async function getAccessibilityTree(session: FFSession, needle?: dom.ElementHandle): Promise<{tree: accessibility.AXNode, needle: accessibility.AXNode | null}> {
const objectId = needle ? needle._objectId : undefined;
@ -198,12 +198,12 @@ class FFAXNode implements accessibility.AXNode {
return this.isLeafNode() && !!this._name.trim();
}
serialize(): types.SerializedAXNode {
const node: {[x in keyof types.SerializedAXNode]: any} = {
serialize(): channels.AXNode {
const node: {[x in keyof channels.AXNode]: any} = {
role: FFRoleToARIARole.get(this._role) || this._role,
name: this._name || '',
};
const userStringProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Accessibility.AXTree> = [
const userStringProperties: Array<keyof channels.AXNode & keyof Protocol.Accessibility.AXTree> = [
'name',
'description',
'roledescription',
@ -215,7 +215,7 @@ class FFAXNode implements accessibility.AXNode {
continue;
node[userStringProperty] = this._payload[userStringProperty];
}
const booleanProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Accessibility.AXTree> = [
const booleanProperties: Array<keyof channels.AXNode & keyof Protocol.Accessibility.AXTree> = [
'disabled',
'expanded',
'focused',
@ -234,7 +234,7 @@ class FFAXNode implements accessibility.AXNode {
continue;
node[booleanProperty] = value;
}
const numericalProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Accessibility.AXTree> = [
const numericalProperties: Array<keyof channels.AXNode & keyof Protocol.Accessibility.AXTree> = [
'level'
];
for (const numericalProperty of numericalProperties) {
@ -242,7 +242,7 @@ class FFAXNode implements accessibility.AXNode {
continue;
node[numericalProperty] = this._payload[numericalProperty];
}
const tokenProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Accessibility.AXTree> = [
const tokenProperties: Array<keyof channels.AXNode & keyof Protocol.Accessibility.AXTree> = [
'autocomplete',
'haspopup',
'invalid',
@ -255,7 +255,7 @@ class FFAXNode implements accessibility.AXNode {
node[tokenProperty] = value;
}
const axNode = node as types.SerializedAXNode;
const axNode = node as channels.AXNode;
axNode.valueString = this._payload.value;
if ('checked' in this._payload)
axNode.checked = this._payload.checked === true ? 'checked' : this._payload.checked === 'mixed' ? 'mixed' : 'unchecked';

View File

@ -24,6 +24,7 @@ import * as network from '../network';
import type { Page, PageBinding, PageDelegate } from '../page';
import type { ConnectionTransport } from '../transport';
import type * as types from '../types';
import type * as channels from '../../protocol/channels';
import { ConnectionEvents, FFConnection } from './ffConnection';
import { FFPage } from './ffPage';
import type { Protocol } from './protocol';
@ -77,7 +78,7 @@ export class FFBrowser extends Browser {
return !this._connection._closed;
}
async doCreateNewContext(options: types.BrowserContextOptions): Promise<BrowserContext> {
async doCreateNewContext(options: channels.BrowserNewContextParams): Promise<BrowserContext> {
if (options.isMobile)
throw new Error('options.isMobile is not supported in Firefox');
const { browserContextId } = await this._connection.send('Browser.createBrowserContext', { removeOnDetach: true });
@ -155,7 +156,7 @@ export class FFBrowser extends Browser {
export class FFBrowserContext extends BrowserContext {
declare readonly _browser: FFBrowser;
constructor(browser: FFBrowser, browserContextId: string | undefined, options: types.BrowserContextOptions) {
constructor(browser: FFBrowser, browserContextId: string | undefined, options: channels.BrowserNewContextParams) {
super(browser, options, browserContextId);
}
@ -255,17 +256,17 @@ export class FFBrowserContext extends BrowserContext {
return this._browser._ffPages.get(targetId)!;
}
async doGetCookies(urls: string[]): Promise<types.NetworkCookie[]> {
async doGetCookies(urls: string[]): Promise<channels.NetworkCookie[]> {
const { cookies } = await this._browser._connection.send('Browser.getCookies', { browserContextId: this._browserContextId });
return network.filterCookies(cookies.map(c => {
const copy: any = { ... c };
delete copy.size;
delete copy.session;
return copy as types.NetworkCookie;
return copy as channels.NetworkCookie;
}), urls);
}
async addCookies(cookies: types.SetNetworkCookieParam[]) {
async addCookies(cookies: channels.SetNetworkCookie[]) {
const cc = network.rewriteCookies(cookies).map(c => ({
...c,
expires: c.expires && c.expires !== -1 ? c.expires : undefined,

View File

@ -20,16 +20,16 @@ import { Artifact } from '../artifact';
import type { BrowserContext } from '../browserContext';
import type * as har from './har';
import { HarTracer } from './harTracer';
import type { HarOptions } from '../types';
import type * as channels from '../../protocol/channels';
export class HarRecorder {
private _artifact: Artifact;
private _isFlushed: boolean = false;
private _options: HarOptions;
private _options: channels.RecordHarOptions;
private _tracer: HarTracer;
private _entries: har.Entry[] = [];
constructor(context: BrowserContext | APIRequestContext, options: HarOptions) {
constructor(context: BrowserContext | APIRequestContext, options: channels.RecordHarOptions) {
this._artifact = new Artifact(context, options.path);
this._options = options;
const urlFilterRe = options.urlRegexSource !== undefined && options.urlRegexFlags !== undefined ? new RegExp(options.urlRegexSource, options.urlRegexFlags) : undefined;

View File

@ -23,7 +23,7 @@ import { SdkObject } from './instrumentation';
import type { NameValue } from '../common/types';
import { APIRequestContext } from './fetch';
export function filterCookies(cookies: types.NetworkCookie[], urls: string[]): types.NetworkCookie[] {
export function filterCookies(cookies: channels.NetworkCookie[], urls: string[]): channels.NetworkCookie[] {
const parsedURLs = urls.map(s => new URL(s));
// Chromiums's cookies are missing sameSite when it is 'None'
return cookies.filter(c => {
@ -50,7 +50,7 @@ export function filterCookies(cookies: types.NetworkCookie[], urls: string[]): t
// 253402300800 == Sat, 1 Jan 1000 00:00:00 +0000 (UTC)
const kMaxCookieExpiresDateInSeconds = 253402300799;
export function rewriteCookies(cookies: types.SetNetworkCookieParam[]): types.SetNetworkCookieParam[] {
export function rewriteCookies(cookies: channels.SetNetworkCookie[]): channels.SetNetworkCookie[] {
return cookies.map(c => {
assert(c.url || (c.domain && c.path), 'Cookie should have a url or a domain/path pair');
assert(!(c.url && c.domain), 'Cookie should have either url or domain');

View File

@ -20,6 +20,7 @@ import * as frames from './frames';
import * as input from './input';
import * as js from './javascript';
import * as network from './network';
import type * as channels from '../protocol/channels';
import type { ScreenshotOptions } from './screenshotter';
import { Screenshotter, validateScreenshotOptions } from './screenshotter';
import { TimeoutSettings } from '../common/timeoutSettings';
@ -86,7 +87,7 @@ export interface PageDelegate {
setScreencastOptions(options: { width: number, height: number, quality: number } | null): Promise<void>;
getAccessibilityTree(needle?: dom.ElementHandle): Promise<{tree: accessibility.AXNode, needle: accessibility.AXNode | null}>;
pdf?: (options?: types.PDFOptions) => Promise<Buffer>;
pdf?: (options: channels.PagePdfParams) => Promise<Buffer>;
coverage?: () => any;
// Work around WebKit's raf issues on Windows.
@ -160,7 +161,7 @@ export class Page extends SdkObject {
readonly _frameManager: frames.FrameManager;
readonly accessibility: accessibility.Accessibility;
private _workers = new Map<string, Worker>();
readonly pdf: ((options?: types.PDFOptions) => Promise<Buffer>) | undefined;
readonly pdf: ((options: channels.PagePdfParams) => Promise<Buffer>) | undefined;
readonly coverage: any;
private _clientRequestInterceptor: network.RouteHandler | undefined;
private _serverRequestInterceptor: network.RouteHandler | undefined;

View File

@ -17,6 +17,7 @@
import type { Size, Point, TimeoutOptions } from '../common/types';
export type { Size, Point, Rect, Quad, URLMatch, TimeoutOptions } from '../common/types';
import type * as channels from '../protocol/channels';
export type StrictOptions = {
strict?: boolean,
@ -77,16 +78,12 @@ export type FilePayload = {
};
export type MediaType = 'screen' | 'print';
export const mediaTypes: Set<MediaType> = new Set(['screen', 'print']);
export type ColorScheme = 'dark' | 'light' | 'no-preference';
export const colorSchemes: Set<ColorScheme> = new Set(['dark', 'light', 'no-preference']);
export type ReducedMotion = 'no-preference' | 'reduce';
export const reducedMotions: Set<ReducedMotion> = new Set(['no-preference', 'reduce']);
export type ForcedColors = 'active' | 'none';
export const forcedColors: Set<ForcedColors> = new Set(['active', 'none']);
export type DeviceDescriptor = {
userAgent: string,
@ -98,56 +95,6 @@ export type DeviceDescriptor = {
};
export type Devices = { [name: string]: DeviceDescriptor };
export type PDFOptions = {
scale?: number,
displayHeaderFooter?: boolean,
headerTemplate?: string,
footerTemplate?: string,
printBackground?: boolean,
landscape?: boolean,
pageRanges?: string,
format?: string,
width?: string,
height?: string,
preferCSSPageSize?: boolean,
margin?: {top?: string, bottom?: string, left?: string, right?: string},
};
export type CSSCoverageOptions = {
resetOnNavigation?: boolean,
};
export type JSCoverageOptions = {
resetOnNavigation?: boolean,
reportAnonymousScripts?: boolean,
};
export type JSRange = {
startOffset: number,
endOffset: number,
count: number
};
export type CSSCoverageEntry = {
url: string,
text?: string,
ranges: {
start: number,
end: number
}[]
};
export type JSCoverageEntry = {
url: string,
scriptId: string,
source?: string,
functions: {
functionName: string,
isBlockCoverage: boolean,
ranges: JSRange[]
}[]
};
export type ProxySettings = {
server: string,
bypass?: string,
@ -202,180 +149,14 @@ export type NormalizedContinueOverrides = {
postData?: Buffer,
};
export type NetworkCookie = {
name: string,
value: string,
domain: string,
path: string,
expires: number,
httpOnly: boolean,
secure: boolean,
sameSite: 'Strict' | 'Lax' | 'None'
};
export type SetNetworkCookieParam = {
name: string,
value: string,
url?: string,
domain?: string,
path?: string,
expires?: number,
httpOnly?: boolean,
secure?: boolean,
sameSite?: 'Strict' | 'Lax' | 'None'
};
export type EmulatedSize = { viewport: Size, screen: Size };
export type HarOptions = {
omitContent?: boolean,
path: string,
urlGlob?: string,
urlRegexSource?: string,
urlRegexFlags?: string,
};
export type BrowserContextOptions = {
viewport?: Size,
screen?: Size,
noDefaultViewport?: boolean,
ignoreHTTPSErrors?: boolean,
javaScriptEnabled?: boolean,
bypassCSP?: boolean,
userAgent?: string,
locale?: string,
timezoneId?: string,
geolocation?: Geolocation,
permissions?: string[],
extraHTTPHeaders?: HeadersArray,
offline?: boolean,
httpCredentials?: Credentials,
deviceScaleFactor?: number,
isMobile?: boolean,
hasTouch?: boolean,
colorScheme?: ColorScheme,
reducedMotion?: ReducedMotion,
forcedColors?: ForcedColors,
acceptDownloads?: boolean,
recordVideo?: {
dir: string,
size?: Size,
},
recordHar?: HarOptions,
storageState?: SetStorageState,
strictSelectors?: boolean,
proxy?: ProxySettings,
baseURL?: string,
serviceWorkers?: 'allow' | 'block',
};
export type EnvArray = { name: string, value: string }[];
type LaunchOptionsBase = {
channel?: string,
executablePath?: string,
args?: string[],
ignoreDefaultArgs?: string[],
ignoreAllDefaultArgs?: boolean,
handleSIGINT?: boolean,
handleSIGTERM?: boolean,
handleSIGHUP?: boolean,
timeout?: number,
env?: EnvArray,
headless?: boolean,
devtools?: boolean,
proxy?: ProxySettings,
downloadsPath?: string,
chromiumSandbox?: boolean,
slowMo?: number,
useWebSocket?: boolean,
tracesDir?: string,
};
export type LaunchOptions = LaunchOptionsBase & {
firefoxUserPrefs?: { [key: string]: string | number | boolean },
};
export type LaunchPersistentOptions = LaunchOptionsBase & BrowserContextOptions;
export type LaunchOptions = channels.BrowserTypeLaunchOptions & { useWebSocket?: boolean };
export type ProtocolLogger = (direction: 'send' | 'receive', message: object) => void;
export type SerializedAXNode = {
role: string,
name: string,
valueString?: string,
valueNumber?: number,
description?: string,
keyshortcuts?: string,
roledescription?: string,
valuetext?: string,
disabled?: boolean,
expanded?: boolean,
focused?: boolean,
modal?: boolean,
multiline?: boolean,
multiselectable?: boolean,
readonly?: boolean,
required?: boolean,
selected?: boolean,
checked?: 'checked' | 'unchecked' | 'mixed',
pressed?: 'pressed' | 'released' | 'mixed',
level?: number,
valuemin?: number,
valuemax?: number,
autocomplete?: string,
haspopup?: string,
invalid?: string,
orientation?: string,
children?: SerializedAXNode[]
};
export type ConsoleMessageLocation = {
url: string,
lineNumber: number,
columnNumber: number,
};
export type Error = {
message: string,
name: string,
stack?: string,
};
export type NameValueList = {
name: string;
value: string;
}[];
export type OriginStorage = {
origin: string;
localStorage: NameValueList;
};
export type StorageState = {
cookies: NetworkCookie[],
origins: OriginStorage[]
};
export type SetStorageState = {
cookies?: SetNetworkCookieParam[],
origins?: OriginStorage[]
};
export type APIResponse = {
url: string,
status: number,
statusText: string,
headers: HeadersArray,
body: Buffer,
};
export type AndroidDeviceOptions = {
host?: string,
port?: number,
omitDriverInstall?: boolean,
};

View File

@ -17,7 +17,7 @@ import type * as accessibility from '../accessibility';
import type { WKSession } from './wkConnection';
import type { Protocol } from './protocol';
import type * as dom from '../dom';
import type * as types from '../types';
import type * as channels from '../../protocol/channels';
export async function getAccessibilityTree(session: WKSession, needle?: dom.ElementHandle) {
const objectId = needle ? needle._objectId : undefined;
@ -167,8 +167,8 @@ class WKAXNode implements accessibility.AXNode {
return false;
}
serialize(): types.SerializedAXNode {
const node: types.SerializedAXNode = {
serialize(): channels.AXNode {
const node: channels.AXNode = {
role: WKRoleToARIARole.get(this._payload.role) || this._payload.role,
name: this._name(),
};
@ -195,7 +195,7 @@ class WKAXNode implements accessibility.AXNode {
if ('pressed' in this._payload)
node.pressed = this._payload.pressed === 'true' ? 'pressed' : this._payload.pressed === 'false' ? 'released' : 'mixed';
const userStringProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Page.AXNode> = [
const userStringProperties: Array<keyof channels.AXNode & keyof Protocol.Page.AXNode> = [
'keyshortcuts',
'valuetext'
];
@ -205,7 +205,7 @@ class WKAXNode implements accessibility.AXNode {
(node as any)[userStringProperty] = this._payload[userStringProperty];
}
const booleanProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Page.AXNode> = [
const booleanProperties: Array<keyof channels.AXNode & keyof Protocol.Page.AXNode> = [
'disabled',
'expanded',
'focused',
@ -227,7 +227,7 @@ class WKAXNode implements accessibility.AXNode {
(node as any)[booleanProperty] = value;
}
const numericalProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Page.AXNode> = [
const numericalProperties: Array<keyof channels.AXNode & keyof Protocol.Page.AXNode> = [
'level',
'valuemax',
'valuemin',
@ -237,7 +237,7 @@ class WKAXNode implements accessibility.AXNode {
continue;
(node as any)[numericalProperty] = (this._payload as any)[numericalProperty];
}
const tokenProperties: Array<keyof types.SerializedAXNode & keyof Protocol.Page.AXNode> = [
const tokenProperties: Array<keyof channels.AXNode & keyof Protocol.Page.AXNode> = [
'autocomplete',
'haspopup',
'invalid',

View File

@ -25,6 +25,7 @@ import * as network from '../network';
import type { Page, PageBinding, PageDelegate } from '../page';
import type { ConnectionTransport } from '../transport';
import type * as types from '../types';
import type * as channels from '../../protocol/channels';
import type { Protocol } from './protocol';
import type { PageProxyMessageReceivedPayload } from './wkConnection';
import { kPageProxyMessageReceived, WKConnection, WKSession } from './wkConnection';
@ -82,7 +83,7 @@ export class WKBrowser extends Browser {
this._didClose();
}
async doCreateNewContext(options: types.BrowserContextOptions): Promise<BrowserContext> {
async doCreateNewContext(options: channels.BrowserNewContextParams): Promise<BrowserContext> {
const createOptions = options.proxy ? {
proxyServer: options.proxy.server,
proxyBypassList: options.proxy.bypass
@ -206,7 +207,7 @@ export class WKBrowser extends Browser {
export class WKBrowserContext extends BrowserContext {
declare readonly _browser: WKBrowser;
constructor(browser: WKBrowser, browserContextId: string | undefined, options: types.BrowserContextOptions) {
constructor(browser: WKBrowser, browserContextId: string | undefined, options: channels.BrowserNewContextParams) {
super(browser, options, browserContextId);
this._authenticateProxyViaHeader();
}
@ -249,17 +250,17 @@ export class WKBrowserContext extends BrowserContext {
return this._browser._wkPages.get(pageProxyId)!;
}
async doGetCookies(urls: string[]): Promise<types.NetworkCookie[]> {
async doGetCookies(urls: string[]): Promise<channels.NetworkCookie[]> {
const { cookies } = await this._browser._browserSession.send('Playwright.getAllCookies', { browserContextId: this._browserContextId });
return network.filterCookies(cookies.map((c: types.NetworkCookie) => {
return network.filterCookies(cookies.map((c: channels.NetworkCookie) => {
const copy: any = { ... c };
copy.expires = c.expires === -1 ? -1 : c.expires / 1000;
delete copy.session;
return copy as types.NetworkCookie;
return copy as channels.NetworkCookie;
}), urls);
}
async addCookies(cookies: types.SetNetworkCookieParam[]) {
async addCookies(cookies: channels.SetNetworkCookie[]) {
const cc = network.rewriteCookies(cookies).map(c => ({
...c,
session: c.expires === -1 || c.expires === undefined,