chore: prepare library types for rpc (#2706)

This commit is contained in:
Pavel Feldman 2020-06-25 08:30:56 -07:00 коммит произвёл GitHub
Родитель 1865c5685a
Коммит bc3050776e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
21 изменённых файлов: 270 добавлений и 195 удалений

Просмотреть файл

@ -14,7 +14,8 @@
* limitations under the License.
*/
import { BrowserContext, BrowserContextOptions, BrowserContextBase, PersistentContextOptions } from './browserContext';
import * as types from './types';
import { BrowserContext, BrowserContextBase } from './browserContext';
import { Page } from './page';
import { EventEmitter } from 'events';
import { Download } from './download';
@ -22,17 +23,20 @@ import type { BrowserServer } from './server/browserServer';
import { Events } from './events';
import { Loggers } from './logger';
import { ProxySettings } from './types';
import { LoggerSink } from './loggerSink';
export type BrowserOptions = {
loggers: Loggers,
downloadsPath?: string,
headful?: boolean,
persistent?: PersistentContextOptions, // Undefined means no persistent context.
persistent?: types.BrowserContextOptions, // Undefined means no persistent context.
slowMo?: number,
ownedServer?: BrowserServer,
proxy?: ProxySettings,
};
export type BrowserContextOptions = types.BrowserContextOptions & { logger?: LoggerSink };
export interface Browser extends EventEmitter {
newContext(options?: BrowserContextOptions): Promise<BrowserContext>;
contexts(): BrowserContext[];

Просмотреть файл

@ -31,43 +31,18 @@ import { ProgressController } from './progress';
import { DebugController } from './debug/debugController';
import { LoggerSink } from './loggerSink';
type CommonContextOptions = {
viewport?: types.Size | null,
ignoreHTTPSErrors?: boolean,
javaScriptEnabled?: boolean,
bypassCSP?: boolean,
userAgent?: string,
locale?: string,
timezoneId?: string,
geolocation?: types.Geolocation,
permissions?: string[],
extraHTTPHeaders?: network.Headers,
offline?: boolean,
httpCredentials?: types.Credentials,
deviceScaleFactor?: number,
isMobile?: boolean,
hasTouch?: boolean,
colorScheme?: types.ColorScheme,
acceptDownloads?: boolean,
};
export type PersistentContextOptions = CommonContextOptions;
export type BrowserContextOptions = CommonContextOptions & {
logger?: LoggerSink,
};
export interface BrowserContext {
setDefaultNavigationTimeout(timeout: number): void;
setDefaultTimeout(timeout: number): void;
pages(): Page[];
newPage(): Promise<Page>;
cookies(urls?: string | string[]): Promise<network.NetworkCookie[]>;
addCookies(cookies: network.SetNetworkCookieParam[]): Promise<void>;
cookies(urls?: string | string[]): Promise<types.NetworkCookie[]>;
addCookies(cookies: types.SetNetworkCookieParam[]): Promise<void>;
clearCookies(): Promise<void>;
grantPermissions(permissions: string[], options?: { origin?: string }): Promise<void>;
clearPermissions(): Promise<void>;
setGeolocation(geolocation: types.Geolocation | null): Promise<void>;
setExtraHTTPHeaders(headers: network.Headers): Promise<void>;
setExtraHTTPHeaders(headers: types.Headers): Promise<void>;
setOffline(offline: boolean): Promise<void>;
setHTTPCredentials(httpCredentials: types.Credentials | null): Promise<void>;
addInitScript(script: Function | string | { path?: string, content?: string }, arg?: any): Promise<void>;
@ -79,6 +54,8 @@ export interface BrowserContext {
close(): Promise<void>;
}
type BrowserContextOptions = types.BrowserContextOptions & { logger?: LoggerSink };
export abstract class BrowserContextBase extends EventEmitter implements BrowserContext {
readonly _timeoutSettings = new TimeoutSettings();
readonly _pageBindings = new Map<string, PageBinding>();
@ -141,21 +118,27 @@ export abstract class BrowserContextBase extends EventEmitter implements Browser
// BrowserContext methods.
abstract pages(): Page[];
abstract newPage(): Promise<Page>;
abstract cookies(...urls: string[]): Promise<network.NetworkCookie[]>;
abstract addCookies(cookies: network.SetNetworkCookieParam[]): Promise<void>;
abstract _doCookies(urls: string[]): Promise<types.NetworkCookie[]>;
abstract addCookies(cookies: types.SetNetworkCookieParam[]): Promise<void>;
abstract clearCookies(): Promise<void>;
abstract _doGrantPermissions(origin: string, permissions: string[]): Promise<void>;
abstract _doClearPermissions(): Promise<void>;
abstract setGeolocation(geolocation: types.Geolocation | null): Promise<void>;
abstract setHTTPCredentials(httpCredentials: types.Credentials | null): Promise<void>;
abstract setExtraHTTPHeaders(headers: network.Headers): Promise<void>;
abstract setExtraHTTPHeaders(headers: types.Headers): Promise<void>;
abstract setOffline(offline: boolean): Promise<void>;
abstract addInitScript(script: string | Function | { path?: string | undefined; content?: string | undefined; }, arg?: any): Promise<void>;
abstract _doAddInitScript(expression: string): Promise<void>;
abstract _doExposeBinding(binding: PageBinding): Promise<void>;
abstract route(url: types.URLMatch, handler: network.RouteHandler): Promise<void>;
abstract unroute(url: types.URLMatch, handler?: network.RouteHandler): Promise<void>;
abstract close(): Promise<void>;
async cookies(urls: string | string[] | undefined = []): Promise<types.NetworkCookie[]> {
if (urls && !Array.isArray(urls))
urls = [ urls ];
return await this._doCookies(urls as string[]);
}
async exposeFunction(name: string, playwrightFunction: Function): Promise<void> {
await this.exposeBinding(name, (options, ...args: any) => playwrightFunction(...args));
}
@ -172,6 +155,11 @@ export abstract class BrowserContextBase extends EventEmitter implements Browser
this._doExposeBinding(binding);
}
async addInitScript(script: string | Function | { path?: string | undefined; content?: string | undefined; }, arg?: any): Promise<void> {
const source = await helper.evaluationScript(script, arg);
await this._doAddInitScript(source);
}
async grantPermissions(permissions: string[], options?: { origin?: string }) {
let origin = '*';
if (options && options.origin) {

Просмотреть файл

@ -15,10 +15,10 @@
* limitations under the License.
*/
import { BrowserBase, BrowserOptions } from '../browser';
import { assertBrowserContextIsNotOwned, BrowserContext, BrowserContextBase, BrowserContextOptions, validateBrowserContextOptions, verifyGeolocation } from '../browserContext';
import { BrowserBase, BrowserOptions, BrowserContextOptions } from '../browser';
import { assertBrowserContextIsNotOwned, BrowserContext, BrowserContextBase, validateBrowserContextOptions, verifyGeolocation } from '../browserContext';
import { Events as CommonEvents } from '../events';
import { assert, helper } from '../helper';
import { assert } from '../helper';
import * as network from '../network';
import { Page, PageBinding, Worker } from '../page';
import { ConnectionTransport, SlowMoTransport } from '../transport';
@ -280,7 +280,7 @@ export class CRBrowserContext extends BrowserContextBase {
readonly _browserContextId: string | null;
readonly _evaluateOnNewDocumentSources: string[];
constructor(browser: CRBrowser, browserContextId: string | null, options: BrowserContextOptions) {
constructor(browser: CRBrowser, browserContextId: string | null, options: types.BrowserContextOptions) {
super(browser, options);
this._browser = browser;
this._browserContextId = browserContextId;
@ -325,18 +325,18 @@ export class CRBrowserContext extends BrowserContextBase {
throw result;
}
async cookies(urls?: string | string[]): Promise<network.NetworkCookie[]> {
async _doCookies(urls: string[]): Promise<types.NetworkCookie[]> {
const { cookies } = await this._browser._session.send('Storage.getCookies', { browserContextId: this._browserContextId || undefined });
return network.filterCookies(cookies.map(c => {
const copy: any = { sameSite: 'None', ...c };
delete copy.size;
delete copy.priority;
delete copy.session;
return copy as network.NetworkCookie;
return copy as types.NetworkCookie;
}), urls);
}
async addCookies(cookies: network.SetNetworkCookieParam[]) {
async addCookies(cookies: types.SetNetworkCookieParam[]) {
await this._browser._session.send('Storage.setCookies', { cookies: network.rewriteCookies(cookies), browserContextId: this._browserContextId || undefined });
}
@ -384,7 +384,7 @@ export class CRBrowserContext extends BrowserContextBase {
await (page._delegate as CRPage).updateGeolocation();
}
async setExtraHTTPHeaders(headers: network.Headers): Promise<void> {
async setExtraHTTPHeaders(headers: types.Headers): Promise<void> {
this._options.extraHTTPHeaders = network.verifyHeaders(headers);
for (const page of this.pages())
await (page._delegate as CRPage).updateExtraHTTPHeaders();
@ -402,8 +402,7 @@ export class CRBrowserContext extends BrowserContextBase {
await (page._delegate as CRPage).updateHttpCredentials();
}
async addInitScript(script: Function | string | { path?: string, content?: string }, arg?: any) {
const source = await helper.evaluationScript(script, arg);
async _doAddInitScript(source: string) {
this._evaluateOnNewDocumentSources.push(source);
for (const page of this.pages())
await (page._delegate as CRPage).evaluateOnNewDocument(source);

Просмотреть файл

@ -21,7 +21,7 @@ import { assert, helper, RegisteredListener } from '../helper';
import { Protocol } from './protocol';
import * as network from '../network';
import * as frames from '../frames';
import { Credentials } from '../types';
import * as types from '../types';
import { CRPage } from './crPage';
export class CRNetworkManager {
@ -63,7 +63,7 @@ export class CRNetworkManager {
helper.removeEventListeners(this._eventListeners);
}
async authenticate(credentials: Credentials | null) {
async authenticate(credentials: types.Credentials | null) {
this._credentials = credentials;
await this._updateProtocolRequestInterception();
}
@ -350,7 +350,7 @@ class InterceptableRequest implements network.RouteDelegate {
this.request = new network.Request(allowInterception ? this : null, frame, redirectedFrom, documentId, url, type, method, postData, headersObject(headers));
}
async continue(overrides: { method?: string; headers?: network.Headers; postData?: string } = {}) {
async continue(overrides: { method?: string; headers?: types.Headers; postData?: string } = {}) {
// In certain cases, protocol will return error if the request was already canceled
// or the page was closed. We should tolerate these errors.
await this._client._sendMayFail('Fetch.continueRequest', {
@ -361,7 +361,7 @@ class InterceptableRequest implements network.RouteDelegate {
});
}
async fulfill(response: network.FulfillResponse) {
async fulfill(response: types.FulfillResponse) {
const responseBody = response.body && helper.isString(response.body) ? Buffer.from(response.body) : (response.body || null);
const responseHeaders: { [s: string]: string; } = {};
@ -423,8 +423,8 @@ function headersArray(headers: { [s: string]: string; }): { name: string; value:
return result;
}
function headersObject(headers: Protocol.Network.Headers): network.Headers {
const result: network.Headers = {};
function headersObject(headers: Protocol.Network.Headers): types.Headers {
const result: types.Headers = {};
for (const key of Object.keys(headers))
result[key.toLowerCase()] = headers[key];
return result;

Просмотреть файл

@ -20,10 +20,10 @@
import * as program from 'commander';
import { Playwright } from '../server/playwright';
import { BrowserType, LaunchOptions } from '../server/browserType';
import { BrowserType } from '../server/browserType';
import { DeviceDescriptors } from '../deviceDescriptors';
import { BrowserContextOptions } from '../browserContext';
import { helper } from '../helper';
import { LaunchOptions, BrowserContextOptions } from '../types';
const playwright = new Playwright(__dirname, require('../../browsers.json')['browsers']);

Просмотреть файл

@ -19,7 +19,7 @@ import * as mime from 'mime';
import * as path from 'path';
import * as util from 'util';
import * as frames from './frames';
import { assert, helper } from './helper';
import { assert, helper, assertMaxArguments } from './helper';
import InjectedScript from './injected/injectedScript';
import * as injectedScriptSource from './generated/injectedScriptSource';
import * as debugScriptSource from './generated/debugScriptSource';
@ -55,6 +55,12 @@ export class FrameExecutionContext extends js.ExecutionContext {
});
}
async evaluateExpressionInternal(expression: string, isFunction: boolean, ...args: any[]): Promise<any> {
return await this.frame._page._frameManager.waitForSignalsCreatedBy(null, false /* noWaitFor */, async () => {
return js.evaluateExpression(this, true /* returnByValue */, expression, isFunction, ...args);
});
}
async evaluateHandleInternal<R>(pageFunction: js.Func0<R>): Promise<js.SmartHandle<R>>;
async evaluateHandleInternal<Arg, R>(pageFunction: js.Func1<Arg, R>, arg: Arg): Promise<js.SmartHandle<R>>;
async evaluateHandleInternal(pageFunction: never, ...args: never[]): Promise<any> {
@ -63,6 +69,12 @@ export class FrameExecutionContext extends js.ExecutionContext {
});
}
async evaluateExpressionHandleInternal(expression: string, isFunction: boolean, ...args: any[]): Promise<any> {
return await this.frame._page._frameManager.waitForSignalsCreatedBy(null, false /* noWaitFor */, async () => {
return js.evaluateExpression(this, false /* returnByValue */, expression, isFunction, ...args);
});
}
createHandle(remoteObject: js.RemoteObject): js.JSHandle {
if (this.frame._page._delegate.isElementHandle(remoteObject))
return new ElementHandle(this, remoteObject.objectId!);
@ -618,10 +630,15 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
async $eval<R, Arg>(selector: string, pageFunction: js.FuncOn<Element, Arg, R>, arg: Arg): Promise<R>;
async $eval<R>(selector: string, pageFunction: js.FuncOn<Element, void, R>, arg?: any): Promise<R>;
async $eval<R, Arg>(selector: string, pageFunction: js.FuncOn<Element, Arg, R>, arg: Arg): Promise<R> {
assertMaxArguments(arguments.length, 3);
return this._$evalExpression(selector, String(pageFunction), typeof pageFunction === 'function', arg);
}
async _$evalExpression(selector: string, expression: string, isFunction: boolean, arg: any): Promise<any> {
const handle = await selectors._query(this._context.frame, selector, this);
if (!handle)
throw new Error(`Error: failed to find element matching selector "${selector}"`);
const result = await handle.evaluate(pageFunction, arg);
const result = await handle._evaluateExpression(expression, isFunction, true, arg);
handle.dispose();
return result;
}
@ -629,8 +646,13 @@ export class ElementHandle<T extends Node = Node> extends js.JSHandle<T> {
async $$eval<R, Arg>(selector: string, pageFunction: js.FuncOn<Element[], Arg, R>, arg: Arg): Promise<R>;
async $$eval<R>(selector: string, pageFunction: js.FuncOn<Element[], void, R>, arg?: any): Promise<R>;
async $$eval<R, Arg>(selector: string, pageFunction: js.FuncOn<Element[], Arg, R>, arg: Arg): Promise<R> {
assertMaxArguments(arguments.length, 3);
return this._$$evalExpression(selector, String(pageFunction), typeof pageFunction === 'function', arg);
}
async _$$evalExpression(selector: string, expression: string, isFunction: boolean, arg: any): Promise<any> {
const arrayHandle = await selectors._queryArray(this._context.frame, selector, this);
const result = await arrayHandle.evaluate(pageFunction, arg);
const result = await arrayHandle._evaluateExpression(expression, isFunction, true, arg);
arrayHandle.dispose();
return result;
}

Просмотреть файл

@ -15,8 +15,8 @@
* limitations under the License.
*/
import { BrowserBase, BrowserOptions } from '../browser';
import { assertBrowserContextIsNotOwned, BrowserContext, BrowserContextBase, BrowserContextOptions, validateBrowserContextOptions, verifyGeolocation } from '../browserContext';
import { BrowserBase, BrowserOptions, BrowserContextOptions } from '../browser';
import { assertBrowserContextIsNotOwned, BrowserContext, BrowserContextBase, validateBrowserContextOptions, verifyGeolocation } from '../browserContext';
import { Events } from '../events';
import { assert, helper, RegisteredListener } from '../helper';
import * as network from '../network';
@ -146,7 +146,7 @@ export class FFBrowserContext extends BrowserContextBase {
readonly _browser: FFBrowser;
readonly _browserContextId: string | null;
constructor(browser: FFBrowser, browserContextId: string | null, options: BrowserContextOptions) {
constructor(browser: FFBrowser, browserContextId: string | null, options: types.BrowserContextOptions) {
super(browser, options);
this._browser = browser;
this._browserContextId = browserContextId;
@ -237,17 +237,17 @@ export class FFBrowserContext extends BrowserContextBase {
throw pageOrError;
}
async cookies(urls?: string | string[]): Promise<network.NetworkCookie[]> {
async _doCookies(urls: string[]): Promise<types.NetworkCookie[]> {
const { cookies } = await this._browser._connection.send('Browser.getCookies', { browserContextId: this._browserContextId || undefined });
return network.filterCookies(cookies.map(c => {
const copy: any = { ... c };
delete copy.size;
delete copy.session;
return copy as network.NetworkCookie;
return copy as types.NetworkCookie;
}), urls);
}
async addCookies(cookies: network.SetNetworkCookieParam[]) {
async addCookies(cookies: types.SetNetworkCookieParam[]) {
await this._browser._connection.send('Browser.setCookies', { browserContextId: this._browserContextId || undefined, cookies: network.rewriteCookies(cookies) });
}
@ -282,7 +282,7 @@ export class FFBrowserContext extends BrowserContextBase {
await this._browser._connection.send('Browser.setGeolocationOverride', { browserContextId: this._browserContextId || undefined, geolocation });
}
async setExtraHTTPHeaders(headers: network.Headers): Promise<void> {
async setExtraHTTPHeaders(headers: types.Headers): Promise<void> {
this._options.extraHTTPHeaders = network.verifyHeaders(headers);
const allHeaders = { ...this._options.extraHTTPHeaders };
if (this._options.locale)
@ -300,8 +300,7 @@ export class FFBrowserContext extends BrowserContextBase {
await this._browser._connection.send('Browser.setHTTPCredentials', { browserContextId: this._browserContextId || undefined, credentials: httpCredentials });
}
async addInitScript(script: Function | string | { path?: string, content?: string }, arg?: any) {
const source = await helper.evaluationScript(script, arg);
async _doAddInitScript(source: string) {
await this._browser._connection.send('Browser.addScriptToEvaluateOnNewDocument', { browserContextId: this._browserContextId || undefined, script: source });
}

Просмотреть файл

@ -20,6 +20,7 @@ import { FFSession } from './ffConnection';
import { Page } from '../page';
import * as network from '../network';
import * as frames from '../frames';
import * as types from '../types';
import { Protocol } from './protocol';
export class FFNetworkManager {
@ -74,7 +75,7 @@ export class FFNetworkManager {
throw new Error(`Response body for ${request.request.method()} ${request.request.url()} was evicted!`);
return Buffer.from(response.base64body, 'base64');
};
const headers: network.Headers = {};
const headers: types.Headers = {};
for (const {name, value} of event.headers)
headers[name.toLowerCase()] = value;
const response = new network.Response(request.request, event.status, event.statusText, headers, getResponseBody);
@ -149,7 +150,7 @@ class InterceptableRequest implements network.RouteDelegate {
this._id = payload.requestId;
this._session = session;
const headers: network.Headers = {};
const headers: types.Headers = {};
for (const {name, value} of payload.headers)
headers[name.toLowerCase()] = value;
@ -157,7 +158,7 @@ class InterceptableRequest implements network.RouteDelegate {
payload.url, internalCauseToResourceType[payload.internalCause] || causeToResourceType[payload.cause] || 'other', payload.method, payload.postData || null, headers);
}
async continue(overrides: { method?: string; headers?: network.Headers; postData?: string }) {
async continue(overrides: { method?: string; headers?: types.Headers; postData?: string }) {
const {
method,
headers,
@ -171,7 +172,7 @@ class InterceptableRequest implements network.RouteDelegate {
});
}
async fulfill(response: network.FulfillResponse) {
async fulfill(response: types.FulfillResponse) {
const responseBody = response.body && helper.isString(response.body) ? Buffer.from(response.body) : (response.body || null);
const responseHeaders: { [s: string]: string; } = {};
@ -201,7 +202,7 @@ class InterceptableRequest implements network.RouteDelegate {
}
}
export function headersArray(headers: network.Headers): Protocol.Network.HTTPHeader[] {
export function headersArray(headers: types.Headers): Protocol.Network.HTTPHeader[] {
const result: Protocol.Network.HTTPHeader[] = [];
for (const name in headers) {
if (!Object.is(headers[name], undefined))

Просмотреть файл

@ -36,9 +36,6 @@ type ContextData = {
rerunnableTasks: Set<RerunnableTask<any>>;
};
export type GotoOptions = types.NavigateOptions & {
referer?: string,
};
export type GotoResult = {
newDocumentId?: string,
};
@ -347,7 +344,7 @@ export class Frame {
return `${subject}.${method}`;
}
async goto(url: string, options: GotoOptions = {}): Promise<network.Response | null> {
async goto(url: string, options: types.GotoOptions = {}): Promise<network.Response | null> {
const progressController = new ProgressController(this._page._logger, this._page._timeoutSettings.navigationTimeout(options), this._apiName('goto'));
abortProgressOnFrameDetach(progressController, this);
return progressController.run(async progress => {
@ -439,6 +436,11 @@ export class Frame {
return context.evaluateHandleInternal(pageFunction, arg);
}
async _evaluateExpressionHandle(expression: string, isFunction: boolean, arg: any): Promise<any> {
const context = await this._mainContext();
return context.evaluateExpressionHandleInternal(expression, isFunction, arg);
}
async evaluate<R, Arg>(pageFunction: js.Func1<Arg, R>, arg: Arg): Promise<R>;
async evaluate<R>(pageFunction: js.Func1<void, R>, arg?: any): Promise<R>;
async evaluate<R, Arg>(pageFunction: js.Func1<Arg, R>, arg: Arg): Promise<R> {
@ -447,6 +449,11 @@ export class Frame {
return context.evaluateInternal(pageFunction, arg);
}
async _evaluateExpression(expression: string, isFunction: boolean, arg: any): Promise<any> {
const context = await this._mainContext();
return context.evaluateExpressionHandleInternal(expression, isFunction, arg);
}
async $(selector: string): Promise<dom.ElementHandle<Element> | null> {
return selectors._query(this, selector);
}
@ -493,10 +500,14 @@ export class Frame {
async $eval<R>(selector: string, pageFunction: js.FuncOn<Element, void, R>, arg?: any): Promise<R>;
async $eval<R, Arg>(selector: string, pageFunction: js.FuncOn<Element, Arg, R>, arg: Arg): Promise<R> {
assertMaxArguments(arguments.length, 3);
return this._$evalExpression(selector, String(pageFunction), typeof pageFunction === 'function', arg);
}
async _$evalExpression(selector: string, expression: string, isFunction: boolean, arg: any): Promise<any> {
const handle = await this.$(selector);
if (!handle)
throw new Error(`Error: failed to find element matching selector "${selector}"`);
const result = await handle.evaluate(pageFunction, arg);
const result = await handle._evaluateExpression(expression, isFunction, true, arg);
handle.dispose();
return result;
}
@ -505,8 +516,12 @@ export class Frame {
async $$eval<R>(selector: string, pageFunction: js.FuncOn<Element[], void, R>, arg?: any): Promise<R>;
async $$eval<R, Arg>(selector: string, pageFunction: js.FuncOn<Element[], Arg, R>, arg: Arg): Promise<R> {
assertMaxArguments(arguments.length, 3);
return this._$$evalExpression(selector, String(pageFunction), typeof pageFunction === 'function', arg);
}
async _$$evalExpression(selector: string, expression: string, isFunction: boolean, arg: any): Promise<any> {
const arrayHandle = await selectors._queryArray(this, selector);
const result = await arrayHandle.evaluate(pageFunction, arg);
const result = await arrayHandle._evaluateExpression(expression, isFunction, true, arg);
arrayHandle.dispose();
return result;
}
@ -804,6 +819,11 @@ export class Frame {
async waitForFunction<R, Arg>(pageFunction: js.Func1<Arg, R>, arg: Arg, options?: types.WaitForFunctionOptions): Promise<js.SmartHandle<R>>;
async waitForFunction<R>(pageFunction: js.Func1<void, R>, arg?: any, options?: types.WaitForFunctionOptions): Promise<js.SmartHandle<R>>;
async waitForFunction<R, Arg>(pageFunction: js.Func1<Arg, R>, arg: Arg, options: types.WaitForFunctionOptions = {}): Promise<js.SmartHandle<R>> {
return this._waitForFunctionExpression(String(pageFunction), typeof pageFunction === 'function', arg, options);
}
async _waitForFunctionExpression<R>(expression: string, isFunction: boolean, arg: any, options: types.WaitForFunctionOptions = {}): Promise<js.SmartHandle<R>> {
const { polling = 'raf' } = options;
if (helper.isString(polling))
assert(polling === 'raf', 'Unknown polling option: ' + polling);
@ -811,7 +831,7 @@ export class Frame {
assert(polling > 0, 'Cannot poll with non-positive interval: ' + polling);
else
throw new Error('Unknown polling option: ' + polling);
const predicateBody = helper.isString(pageFunction) ? 'return (' + pageFunction + ')' : 'return (' + pageFunction + ')(arg)';
const predicateBody = isFunction ? 'return (' + expression + ')(arg)' : 'return (' + expression + ')';
const task = async (context: dom.FrameExecutionContext) => {
const injectedScript = await context.injectedScript();
return context.evaluateHandleInternal(({ injectedScript, predicateBody, polling, arg }) => {

Просмотреть файл

@ -42,8 +42,11 @@ class Helper {
assert(args.length === 0 || (args.length === 1 && args[0] === undefined), 'Cannot evaluate a string with arguments');
return fun;
}
return `(${fun})(${args.map(serializeArgument).join(',')})`;
return Helper.evaluationStringForFunctionBody(String(fun), ...args);
}
static evaluationStringForFunctionBody(functionBody: string, ...args: any[]): string {
return `(${functionBody})(${args.map(serializeArgument).join(',')})`;
function serializeArgument(arg: any): string {
if (Object.is(arg, undefined))
return 'undefined';

Просмотреть файл

@ -18,7 +18,6 @@ import * as dom from './dom';
import * as utilityScriptSource from './generated/utilityScriptSource';
import * as sourceMap from './utils/sourceMap';
import { serializeAsCallArgument } from './common/utilityScriptSerializers';
import { helper } from './helper';
import UtilityScript from './injected/utilityScript';
type ObjectId = string;
@ -106,6 +105,10 @@ export class JSHandle<T = any> {
return evaluate(this._context, false /* returnByValue */, pageFunction, this, arg);
}
_evaluateExpression(expression: string, isFunction: boolean, returnByValue: boolean, arg: any) {
return evaluateExpression(this._context, returnByValue, expression, isFunction, this, arg);
}
async getProperty(propertyName: string): Promise<JSHandle> {
const objectHandle = await this.evaluateHandle((object: any, propertyName) => {
const result: any = {__proto__: null};
@ -147,16 +150,17 @@ export class JSHandle<T = any> {
}
export async function evaluate(context: ExecutionContext, returnByValue: boolean, pageFunction: Function | string, ...args: any[]): Promise<any> {
const utilityScript = await context.utilityScript();
if (helper.isString(pageFunction)) {
const script = `(utilityScript, ...args) => utilityScript.evaluate(...args)` + sourceMap.generateSourceUrl();
return context._delegate.evaluateWithArguments(script, returnByValue, utilityScript, [returnByValue, sourceMap.ensureSourceUrl(pageFunction)], []);
return evaluateExpression(context, returnByValue, String(pageFunction), typeof pageFunction === 'function', ...args);
}
if (typeof pageFunction !== 'function')
throw new Error(`Expected to get |string| or |function| as the first argument, but got "${pageFunction}" instead.`);
const originalText = pageFunction.toString();
let functionText = originalText;
export async function evaluateExpression(context: ExecutionContext, returnByValue: boolean, expression: string, isFunction: boolean, ...args: any[]): Promise<any> {
const utilityScript = await context.utilityScript();
if (!isFunction) {
const script = `(utilityScript, ...args) => utilityScript.evaluate(...args)` + sourceMap.generateSourceUrl();
return context._delegate.evaluateWithArguments(script, returnByValue, utilityScript, [returnByValue, sourceMap.ensureSourceUrl(expression)], []);
}
let functionText = expression;
try {
new Function('(' + functionText + ')');
} catch (e1) {
@ -203,7 +207,7 @@ export async function evaluate(context: ExecutionContext, returnByValue: boolean
utilityScriptObjectIds.push(handle._objectId!);
}
functionText += await sourceMap.generateSourceMapUrl(originalText, functionText);
functionText += await sourceMap.generateSourceMapUrl(expression, functionText);
// See UtilityScript for arguments.
const utilityScriptValues = [returnByValue, functionText, args.length, ...args];

Просмотреть файл

@ -18,35 +18,11 @@ import * as fs from 'fs';
import * as mime from 'mime';
import * as util from 'util';
import * as frames from './frames';
import * as types from './types';
import { assert, helper } from './helper';
import { URLSearchParams } from 'url';
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 function filterCookies(cookies: NetworkCookie[], urls: string | string[] = []): NetworkCookie[] {
if (!Array.isArray(urls))
urls = [ urls ];
export function filterCookies(cookies: types.NetworkCookie[], urls: string[]): types.NetworkCookie[] {
const parsedURLs = urls.map(s => new URL(s));
// Chromiums's cookies are missing sameSite when it is 'None'
return cookies.filter(c => {
@ -65,7 +41,7 @@ export function filterCookies(cookies: NetworkCookie[], urls: string | string[]
});
}
export function rewriteCookies(cookies: SetNetworkCookieParam[]): SetNetworkCookieParam[] {
export function rewriteCookies(cookies: types.SetNetworkCookieParam[]): types.SetNetworkCookieParam[] {
return cookies.map(c => {
assert(c.name, 'Cookie should have a name');
assert(c.value, 'Cookie should have a value');
@ -93,8 +69,6 @@ function stripFragmentFromUrl(url: string): string {
return parsed.href;
}
export type Headers = { [key: string]: string };
export class Request {
readonly _routeDelegate: RouteDelegate | null;
private _response: Response | null = null;
@ -107,13 +81,13 @@ export class Request {
private _resourceType: string;
private _method: string;
private _postData: string | null;
private _headers: Headers;
private _headers: types.Headers;
private _frame: frames.Frame;
private _waitForResponsePromise: Promise<Response | null>;
private _waitForResponsePromiseCallback: (value: Response | null) => void = () => {};
constructor(routeDelegate: RouteDelegate | null, frame: frames.Frame, redirectedFrom: Request | null, documentId: string | undefined,
url: string, resourceType: string, method: string, postData: string | null, headers: Headers) {
url: string, resourceType: string, method: string, postData: string | null, headers: types.Headers) {
assert(!url.startsWith('data:'), 'Data urls should not fire requests');
assert(!(routeDelegate && redirectedFrom), 'Should not be able to intercept redirects');
this._routeDelegate = routeDelegate;
@ -243,7 +217,7 @@ export class Route {
await this._delegate.abort(errorCode);
}
async fulfill(response: FulfillResponse & { path?: string }) {
async fulfill(response: types.FulfillResponse & { path?: string }) {
assert(!this._handled, 'Route is already handled!');
this._handled = true;
if (response.path) {
@ -257,7 +231,7 @@ export class Route {
await this._delegate.fulfill(response);
}
async continue(overrides: { method?: string; headers?: Headers; postData?: string } = {}) {
async continue(overrides: { method?: string; headers?: types.Headers; postData?: string } = {}) {
assert(!this._handled, 'Route is already handled!');
await this._delegate.continue(overrides);
}
@ -275,10 +249,10 @@ export class Response {
private _status: number;
private _statusText: string;
private _url: string;
private _headers: Headers;
private _headers: types.Headers;
private _getResponseBodyCallback: GetResponseBodyCallback;
constructor(request: Request, status: number, statusText: string, headers: Headers, getResponseBodyCallback: GetResponseBodyCallback) {
constructor(request: Request, status: number, statusText: string, headers: types.Headers, getResponseBodyCallback: GetResponseBodyCallback) {
this._request = request;
this._status = status;
this._statusText = statusText;
@ -349,17 +323,10 @@ export class Response {
}
}
export type FulfillResponse = {
status?: number,
headers?: Headers,
contentType?: string,
body?: string | Buffer,
};
export interface RouteDelegate {
abort(errorCode: string): Promise<void>;
fulfill(response: FulfillResponse): Promise<void>;
continue(overrides: { method?: string; headers?: Headers; postData?: string; }): Promise<void>;
fulfill(response: types.FulfillResponse): Promise<void>;
continue(overrides: { method?: string; headers?: types.Headers; postData?: string; }): Promise<void>;
}
// List taken from https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml with extra 306 and 418 codes.
@ -429,8 +396,8 @@ export const STATUS_TEXTS: { [status: string]: string } = {
'511': 'Network Authentication Required',
};
export function verifyHeaders(headers: Headers): Headers {
const result: Headers = {};
export function verifyHeaders(headers: types.Headers): types.Headers {
const result: types.Headers = {};
for (const key of Object.keys(headers)) {
const value = headers[key];
assert(helper.isString(value), `Expected value of header "${key}" to be String, but "${typeof value}" is found.`);
@ -439,7 +406,7 @@ export function verifyHeaders(headers: Headers): Headers {
return result;
}
export function mergeHeaders(headers: (Headers | undefined | null)[]): Headers {
export function mergeHeaders(headers: (types.Headers | undefined | null)[]): types.Headers {
const lowerCaseToValue = new Map<string, string>();
const lowerCaseToOriginalCase = new Map<string, string>();
for (const h of headers) {
@ -451,7 +418,7 @@ export function mergeHeaders(headers: (Headers | undefined | null)[]): Headers {
lowerCaseToValue.set(lower, h[key]);
}
}
const result: Headers = {};
const result: types.Headers = {};
for (const [lower, value] of lowerCaseToValue)
result[lowerCaseToOriginalCase.get(lower)!] = value;
return result;

Просмотреть файл

@ -84,7 +84,7 @@ type PageState = {
viewportSize: types.Size | null;
mediaType: types.MediaType | null;
colorScheme: types.ColorScheme | null;
extraHTTPHeaders: network.Headers | null;
extraHTTPHeaders: types.Headers | null;
};
export class Page extends EventEmitter {
@ -265,7 +265,7 @@ export class Page extends EventEmitter {
await this._delegate.exposeBinding(binding);
}
setExtraHTTPHeaders(headers: network.Headers) {
setExtraHTTPHeaders(headers: types.Headers) {
this._state.extraHTTPHeaders = network.verifyHeaders(headers);
return this._delegate.updateExtraHTTPHeaders();
}
@ -295,7 +295,7 @@ export class Page extends EventEmitter {
return this._attributeToPage(() => this.mainFrame().setContent(html, options));
}
async goto(url: string, options?: frames.GotoOptions): Promise<network.Response | null> {
async goto(url: string, options?: types.GotoOptions): Promise<network.Response | null> {
return this._attributeToPage(() => this.mainFrame().goto(url, options));
}
@ -386,6 +386,10 @@ export class Page extends EventEmitter {
async addInitScript(script: Function | string | { path?: string, content?: string }, arg?: any) {
const source = await helper.evaluationScript(script, arg);
await this._addInitScriptExpression(source);
}
async _addInitScriptExpression(source: string) {
this._evaluateOnNewDocumentSources.push(source);
await this._delegate.evaluateOnNewDocument(source);
}
@ -445,11 +449,11 @@ export class Page extends EventEmitter {
return this._attributeToPage(() => this.mainFrame().title());
}
async close(options: { runBeforeUnload: (boolean | undefined); } = {runBeforeUnload: undefined}) {
async close(options?: { runBeforeUnload?: boolean }) {
if (this._closed)
return;
assert(!this._disconnected, 'Protocol error: Connection closed. Most likely the page has been closed.');
const runBeforeUnload = !!options.runBeforeUnload;
const runBeforeUnload = !!options && !!options.runBeforeUnload;
await this._delegate.closePage(runBeforeUnload);
if (!runBeforeUnload)
await this._closedPromise;

Просмотреть файл

@ -18,7 +18,7 @@ import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import * as util from 'util';
import { BrowserContext, PersistentContextOptions, verifyProxySettings, validateBrowserContextOptions } from '../browserContext';
import { BrowserContext, verifyProxySettings, validateBrowserContextOptions } from '../browserContext';
import { BrowserServer } from './browserServer';
import * as browserPaths from '../install/browserPaths';
import { Loggers, Logger } from '../logger';
@ -34,41 +34,21 @@ import { TimeoutSettings } from '../timeoutSettings';
import { WebSocketServer } from './webSocketServer';
import { LoggerSink } from '../loggerSink';
export type FirefoxUserPrefsOptions = {
firefoxUserPrefs?: { [key: string]: string | number | boolean },
};
type FirefoxPrefsOptions = { firefoxUserPrefs?: { [key: string]: string | number | boolean } };
type LaunchOptions = types.LaunchOptions & { logger?: LoggerSink };
type ConnectOptions = types.ConnectOptions & { logger?: LoggerSink };
export type LaunchOptionsBase = {
executablePath?: string,
args?: string[],
ignoreDefaultArgs?: boolean | string[],
handleSIGINT?: boolean,
handleSIGTERM?: boolean,
handleSIGHUP?: boolean,
timeout?: number,
logger?: LoggerSink,
env?: Env,
headless?: boolean,
devtools?: boolean,
proxy?: types.ProxySettings,
downloadsPath?: string,
};
type ConnectOptions = {
wsEndpoint: string,
slowMo?: number,
logger?: LoggerSink,
timeout?: number,
};
export type LaunchOptions = LaunchOptionsBase & { slowMo?: number };
type LaunchServerOptions = LaunchOptionsBase & { port?: number };
export type LaunchNonPersistentOptions = LaunchOptions & FirefoxPrefsOptions;
type LaunchPersistentOptions = LaunchOptions & types.BrowserContextOptions;
type LaunchServerOptions = types.LaunchServerOptions & { logger?: LoggerSink } & FirefoxPrefsOptions;
export interface BrowserType {
executablePath(): string;
name(): string;
launch(options?: LaunchOptions & FirefoxUserPrefsOptions): Promise<Browser>;
launchServer(options?: LaunchServerOptions & FirefoxUserPrefsOptions): Promise<BrowserServer>;
launchPersistentContext(userDataDir: string, options?: LaunchOptions & PersistentContextOptions): Promise<BrowserContext>;
launch(options?: LaunchNonPersistentOptions): Promise<Browser>;
launchServer(options?: LaunchServerOptions): Promise<BrowserServer>;
launchPersistentContext(userDataDir: string, options?: LaunchPersistentOptions): Promise<BrowserContext>;
connect(options: ConnectOptions): Promise<Browser>;
}
@ -102,7 +82,7 @@ export abstract class BrowserTypeBase implements BrowserType {
return this._name;
}
async launch(options: LaunchOptions = {}): Promise<Browser> {
async launch(options: LaunchNonPersistentOptions = {}): Promise<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 = validateLaunchOptions(options);
@ -111,7 +91,7 @@ export abstract class BrowserTypeBase implements BrowserType {
return browser;
}
async launchPersistentContext(userDataDir: string, options: LaunchOptions & PersistentContextOptions = {}): Promise<BrowserContext> {
async launchPersistentContext(userDataDir: string, options: LaunchPersistentOptions = {}): Promise<BrowserContext> {
assert(!(options as any).port, 'Cannot specify a port without launching as a server.');
options = validateLaunchOptions(options);
const persistent = validateBrowserContextOptions(options);
@ -120,7 +100,7 @@ export abstract class BrowserTypeBase implements BrowserType {
return browser._defaultContext!;
}
async _innerLaunch(progress: Progress, options: LaunchOptions, logger: Loggers, persistent: PersistentContextOptions | undefined, userDataDir?: string): Promise<BrowserBase> {
async _innerLaunch(progress: Progress, options: LaunchOptions, logger: Loggers, persistent: types.BrowserContextOptions | undefined, userDataDir?: string): Promise<BrowserBase> {
options.proxy = options.proxy ? verifyProxySettings(options.proxy) : undefined;
const { browserServer, downloadsPath, transport } = await this._launchServer(progress, options, !!persistent, logger, userDataDir);
if ((options as any).__testHookBeforeCreateBrowser)
@ -246,7 +226,7 @@ export abstract class BrowserTypeBase implements BrowserType {
return { browserServer, downloadsPath, transport };
}
abstract _defaultArgs(options: LaunchOptionsBase, isPersistent: boolean, userDataDir: string): string[];
abstract _defaultArgs(options: types.LaunchOptionsBase, isPersistent: boolean, userDataDir: string): string[];
abstract _connectToTransport(transport: ConnectionTransport, options: BrowserOptions): Promise<BrowserBase>;
abstract _startWebSocketServer(transport: ConnectionTransport, logger: Logger, port: number): WebSocketServer;
abstract _amendEnvironment(env: Env, userDataDir: string, executable: string, browserArguments: string[]): Env;
@ -260,7 +240,7 @@ function copyTestHooks(from: object, to: object) {
}
}
function validateLaunchOptions<Options extends LaunchOptionsBase>(options: Options): Options {
function validateLaunchOptions<Options extends types.LaunchOptionsBase>(options: Options): Options {
const { devtools = false, headless = !helper.isDebugMode() && !devtools } = options;
return { ...options, devtools, headless };
}

Просмотреть файл

@ -21,13 +21,14 @@ import { CRBrowser } from '../chromium/crBrowser';
import * as ws from 'ws';
import { Env } from './processLauncher';
import { kBrowserCloseMessageId } from '../chromium/crConnection';
import { LaunchOptionsBase, BrowserTypeBase } from './browserType';
import { BrowserTypeBase } from './browserType';
import { ConnectionTransport, ProtocolRequest, ProtocolResponse } from '../transport';
import { Logger } from '../logger';
import { BrowserDescriptor } from '../install/browserPaths';
import { CRDevTools } from '../chromium/crDevTools';
import { BrowserOptions } from '../browser';
import { WebSocketServer } from './webSocketServer';
import { LaunchOptionsBase } from '../types';
export class Chromium extends BrowserTypeBase {
private _devtools: CRDevTools | undefined;

Просмотреть файл

@ -21,7 +21,7 @@ import * as path from 'path';
import * as ws from 'ws';
import { FFBrowser } from '../firefox/ffBrowser';
import { kBrowserCloseMessageId } from '../firefox/ffConnection';
import { LaunchOptionsBase, BrowserTypeBase, FirefoxUserPrefsOptions } from './browserType';
import { BrowserTypeBase, LaunchNonPersistentOptions } from './browserType';
import { Env } from './processLauncher';
import { ConnectionTransport, ProtocolResponse, ProtocolRequest } from '../transport';
import { Logger } from '../logger';
@ -56,7 +56,7 @@ export class Firefox extends BrowserTypeBase {
return startWebSocketServer(transport, logger, port);
}
_defaultArgs(options: LaunchOptionsBase & FirefoxUserPrefsOptions, isPersistent: boolean, userDataDir: string): string[] {
_defaultArgs(options: LaunchNonPersistentOptions, isPersistent: boolean, userDataDir: string): string[] {
const { args = [], proxy, devtools, headless } = options;
if (devtools)
console.warn('devtools parameter is not supported as a launch argument in Firefox. You can launch the devtools window manually.');

Просмотреть файл

@ -19,7 +19,7 @@ import { WKBrowser } from '../webkit/wkBrowser';
import { Env } from './processLauncher';
import * as path from 'path';
import { kBrowserCloseMessageId } from '../webkit/wkConnection';
import { LaunchOptionsBase, BrowserTypeBase } from './browserType';
import { BrowserTypeBase } from './browserType';
import { ConnectionTransport, ProtocolResponse, ProtocolRequest } from '../transport';
import * as ws from 'ws';
import { Logger } from '../logger';
@ -27,6 +27,7 @@ import { BrowserOptions } from '../browser';
import { BrowserDescriptor } from '../install/browserPaths';
import { WebSocketServer } from './webSocketServer';
import { assert } from '../helper';
import { LaunchOptionsBase } from '../types';
export class WebKit extends BrowserTypeBase {
constructor(packagePath: string, browser: BrowserDescriptor) {

Просмотреть файл

@ -180,3 +180,85 @@ export type MouseMultiClickOptions = PointerActionOptions & {
};
export type World = 'main' | 'utility';
export type Headers = { [key: string]: string };
export type GotoOptions = NavigateOptions & {
referer?: string,
};
export type FulfillResponse = {
status?: number,
headers?: Headers,
contentType?: string,
body?: string | 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 BrowserContextOptions = {
viewport?: Size | null,
ignoreHTTPSErrors?: boolean,
javaScriptEnabled?: boolean,
bypassCSP?: boolean,
userAgent?: string,
locale?: string,
timezoneId?: string,
geolocation?: Geolocation,
permissions?: string[],
extraHTTPHeaders?: Headers,
offline?: boolean,
httpCredentials?: Credentials,
deviceScaleFactor?: number,
isMobile?: boolean,
hasTouch?: boolean,
colorScheme?: ColorScheme,
acceptDownloads?: boolean,
};
export type Env = {[key: string]: string | number | boolean | undefined};
export type LaunchOptionsBase = {
executablePath?: string,
args?: string[],
ignoreDefaultArgs?: boolean | string[],
handleSIGINT?: boolean,
handleSIGTERM?: boolean,
handleSIGHUP?: boolean,
timeout?: number,
env?: Env,
headless?: boolean,
devtools?: boolean,
proxy?: ProxySettings,
downloadsPath?: string,
};
export type LaunchOptions = LaunchOptionsBase & { slowMo?: number };
export type LaunchServerOptions = LaunchOptionsBase & { port?: number };
export type ConnectOptions = {
wsEndpoint: string,
slowMo?: number,
timeout?: number,
};

Просмотреть файл

@ -15,8 +15,8 @@
* limitations under the License.
*/
import { BrowserBase, BrowserOptions } from '../browser';
import { assertBrowserContextIsNotOwned, BrowserContext, BrowserContextBase, BrowserContextOptions, validateBrowserContextOptions, verifyGeolocation } from '../browserContext';
import { BrowserBase, BrowserOptions, BrowserContextOptions } from '../browser';
import { assertBrowserContextIsNotOwned, BrowserContext, BrowserContextBase, validateBrowserContextOptions, verifyGeolocation } from '../browserContext';
import { Events } from '../events';
import { helper, RegisteredListener, assert } from '../helper';
import * as network from '../network';
@ -202,7 +202,7 @@ export class WKBrowserContext extends BrowserContextBase {
readonly _browserContextId: string | undefined;
readonly _evaluateOnNewDocumentSources: string[];
constructor(browser: WKBrowser, browserContextId: string | undefined, options: BrowserContextOptions) {
constructor(browser: WKBrowser, browserContextId: string | undefined, options: types.BrowserContextOptions) {
super(browser, options);
this._browser = browser;
this._browserContextId = browserContextId;
@ -257,17 +257,17 @@ export class WKBrowserContext extends BrowserContextBase {
throw result;
}
async cookies(urls?: string | string[]): Promise<network.NetworkCookie[]> {
async _doCookies(urls: string[]): Promise<types.NetworkCookie[]> {
const { cookies } = await this._browser._browserSession.send('Playwright.getAllCookies', { browserContextId: this._browserContextId });
return network.filterCookies(cookies.map((c: network.NetworkCookie) => {
return network.filterCookies(cookies.map((c: types.NetworkCookie) => {
const copy: any = { ... c };
copy.expires = c.expires === -1 ? -1 : c.expires / 1000;
delete copy.session;
return copy as network.NetworkCookie;
return copy as types.NetworkCookie;
}), urls);
}
async addCookies(cookies: network.SetNetworkCookieParam[]) {
async addCookies(cookies: types.SetNetworkCookieParam[]) {
const cc = network.rewriteCookies(cookies).map(c => ({
...c,
session: c.expires === -1 || c.expires === undefined,
@ -296,7 +296,7 @@ export class WKBrowserContext extends BrowserContextBase {
await this._browser._browserSession.send('Playwright.setGeolocationOverride', { browserContextId: this._browserContextId, geolocation: payload });
}
async setExtraHTTPHeaders(headers: network.Headers): Promise<void> {
async setExtraHTTPHeaders(headers: types.Headers): Promise<void> {
this._options.extraHTTPHeaders = network.verifyHeaders(headers);
for (const page of this.pages())
await (page._delegate as WKPage).updateExtraHTTPHeaders();
@ -314,8 +314,7 @@ export class WKBrowserContext extends BrowserContextBase {
await (page._delegate as WKPage).updateHttpCredentials();
}
async addInitScript(script: Function | string | { path?: string, content?: string }, arg?: any) {
const source = await helper.evaluationScript(script, arg);
async _doAddInitScript(source: string) {
this._evaluateOnNewDocumentSources.push(source);
for (const page of this.pages())
await (page._delegate as WKPage)._updateBootstrapScript();

Просмотреть файл

@ -18,6 +18,7 @@
import * as frames from '../frames';
import { assert, helper } from '../helper';
import * as network from '../network';
import * as types from '../types';
import { Protocol } from './protocol';
import { WKSession } from './wkConnection';
@ -65,7 +66,7 @@ export class WKInterceptableRequest implements network.RouteDelegate {
await this._session.sendMayFail('Network.interceptRequestWithError', { requestId: this._requestId, errorType });
}
async fulfill(response: network.FulfillResponse) {
async fulfill(response: types.FulfillResponse) {
await this._interceptedPromise;
const base64Encoded = !!response.body && !helper.isString(response.body);
@ -101,7 +102,7 @@ export class WKInterceptableRequest implements network.RouteDelegate {
});
}
async continue(overrides: { method?: string; headers?: network.Headers; postData?: string }) {
async continue(overrides: { method?: string; headers?: types.Headers; postData?: string }) {
await this._interceptedPromise;
// In certain cases, protocol will return error if the request was already canceled
// or the page was closed. We should tolerate these errors.
@ -122,8 +123,8 @@ export class WKInterceptableRequest implements network.RouteDelegate {
}
}
function headersObject(headers: Protocol.Network.Headers): network.Headers {
const result: network.Headers = {};
function headersObject(headers: Protocol.Network.Headers): types.Headers {
const result: types.Headers = {};
for (const key of Object.keys(headers))
result[key.toLowerCase()] = headers[key];
return result;

Просмотреть файл

@ -552,7 +552,7 @@ export class WKPage implements PageDelegate {
await this._updateState('Network.setExtraHTTPHeaders', { headers: this._calculateExtraHTTPHeaders() });
}
_calculateExtraHTTPHeaders(): network.Headers {
_calculateExtraHTTPHeaders(): types.Headers {
const headers = network.mergeHeaders([
this._browserContext._options.extraHTTPHeaders,
this._page._state.extraHTTPHeaders