fix(lint): webkit linting

This commit is contained in:
Pavel Feldman 2019-11-18 21:26:53 -08:00
parent 48e9719d8a
commit 6abc91b0db
11 changed files with 72 additions and 250 deletions

View file

@ -17,13 +17,12 @@
import * as childProcess from 'child_process'; import * as childProcess from 'child_process';
import { EventEmitter } from 'events'; import { EventEmitter } from 'events';
import { Connection, ConnectionEvents } from './Connection'; import { Connection } from './Connection';
import { Events } from '../Events'; import { Events } from '../Events';
import { RegisteredListener, assert, helper } from '../helper'; import { RegisteredListener, assert, helper } from '../helper';
import { Page, Viewport } from './Page'; import { Page, Viewport } from './Page';
import { Target } from './Target'; import { Target } from './Target';
import { TaskQueue } from './TaskQueue'; import { TaskQueue } from './TaskQueue';
import { Protocol } from './protocol';
export class Browser extends EventEmitter { export class Browser extends EventEmitter {
_defaultViewport: Viewport; _defaultViewport: Viewport;
@ -146,11 +145,11 @@ export class Browser extends EventEmitter {
async _onTargetCreated({targetInfo}) { async _onTargetCreated({targetInfo}) {
let context = null; let context = null;
if (targetInfo.browserContextId) { if (targetInfo.browserContextId) {
context = this._contexts.get(targetInfo.browserContextId);
// FIXME: we don't know about the default context id, so assume that all targets from // FIXME: we don't know about the default context id, so assume that all targets from
// unknown contexts are created in the 'default' context which can in practice be represented // unknown contexts are created in the 'default' context which can in practice be represented
// by multiple actual contexts in WebKit. Solving this properly will require adding context // by multiple actual contexts in WebKit. Solving this properly will require adding context
// lifecycle events. // lifecycle events.
context = this._contexts.get(targetInfo.browserContextId);
// if (!context) // if (!context)
// throw new Error(`Target ${targetId} created in unknown browser context ${browserContextId}.`); // throw new Error(`Target ${targetId} created in unknown browser context ${browserContextId}.`);
} }
@ -177,8 +176,7 @@ export class Browser extends EventEmitter {
target.browserContext().emit(Events.BrowserContext.TargetDestroyed, target); target.browserContext().emit(Events.BrowserContext.TargetDestroyed, target);
} }
async _onProvisionalTargetCommitted({oldTargetId, newTargetId}) async _onProvisionalTargetCommitted({oldTargetId, newTargetId}) {
{
const oldTarget = this._targets.get(oldTargetId); const oldTarget = this._targets.get(oldTargetId);
if (!oldTarget._pagePromise) if (!oldTarget._pagePromise)
return; return;

View file

@ -89,7 +89,7 @@ export class Connection extends EventEmitter {
else else
callback.resolve(object.result); callback.resolve(object.result);
} else { } else {
assert(this._closed, "Received response for unknown callback: " + object.id); assert(this._closed, 'Received response for unknown callback: ' + object.id);
} }
} else { } else {
this.emit(object.method, object.params); this.emit(object.method, object.params);
@ -114,16 +114,16 @@ export class Connection extends EventEmitter {
} else if (object.method === 'Target.dispatchMessageFromTarget') { } else if (object.method === 'Target.dispatchMessageFromTarget') {
const session = this._sessions.get(object.params.targetId); const session = this._sessions.get(object.params.targetId);
if (!session) if (!session)
throw new Error("Unknown target: " + object.params.targetId); throw new Error('Unknown target: ' + object.params.targetId);
session._dispatchMessageFromTarget(object.params.message); session._dispatchMessageFromTarget(object.params.message);
} else if (object.method === 'Target.didCommitProvisionalTarget') { } else if (object.method === 'Target.didCommitProvisionalTarget') {
const {oldTargetId, newTargetId} = object.params; const {oldTargetId, newTargetId} = object.params;
const newSession = this._sessions.get(newTargetId); const newSession = this._sessions.get(newTargetId);
if (!newSession) if (!newSession)
throw new Error("Unknown new target: " + newTargetId); throw new Error('Unknown new target: ' + newTargetId);
const oldSession = this._sessions.get(oldTargetId); const oldSession = this._sessions.get(oldTargetId);
if (!oldSession) if (!oldSession)
throw new Error("Unknown old target: " + oldTargetId); throw new Error('Unknown old target: ' + oldTargetId);
} }
} }
@ -188,28 +188,28 @@ export class TargetSession extends EventEmitter {
method, method,
params params
}; };
debugWrappedMessage("SEND ► " + JSON.stringify(messageObj, null, 2)); debugWrappedMessage('SEND ► ' + JSON.stringify(messageObj, null, 2));
this._out.push(messageObj); this._out.push(messageObj);
// Serialize message before adding callback in case JSON throws. // Serialize message before adding callback in case JSON throws.
const message = JSON.stringify(messageObj); const message = JSON.stringify(messageObj);
const result = new Promise<Protocol.CommandReturnValues[T]>((resolve, reject) => { const result = new Promise<Protocol.CommandReturnValues[T]>((resolve, reject) => {
this._callbacks.set(innerId, {resolve, reject, error: new Error(), method}); this._callbacks.set(innerId, {resolve, reject, error: new Error(), method});
}); });
this._connection.send("Target.sendMessageToTarget", { this._connection.send('Target.sendMessageToTarget', {
message: message, targetId: this._sessionId message: message, targetId: this._sessionId
}).catch(e => { }).catch(e => {
// There is a possible race of the connection closure. We may have received // There is a possible race of the connection closure. We may have received
// targetDestroyed notification before response for the command, in that // targetDestroyed notification before response for the command, in that
// case it's safe to swallow the exception.g // case it's safe to swallow the exception.g
const callback = this._callbacks.get(innerId); const callback = this._callbacks.get(innerId);
assert(!callback, "Callback was not rejected when target was destroyed."); assert(!callback, 'Callback was not rejected when target was destroyed.');
}); });
return result; return result;
} }
_dispatchMessageFromTarget(message: string) { _dispatchMessageFromTarget(message: string) {
const object = JSON.parse(message); const object = JSON.parse(message);
debugWrappedMessage("◀ RECV " + JSON.stringify(object, null, 2)); debugWrappedMessage('◀ RECV ' + JSON.stringify(object, null, 2));
this._in.push(object); this._in.push(object);
if (object.id && this._callbacks.has(object.id)) { if (object.id && this._callbacks.has(object.id)) {
const callback = this._callbacks.get(object.id); const callback = this._callbacks.get(object.id);
@ -219,8 +219,6 @@ export class TargetSession extends EventEmitter {
else else
callback.resolve(object.result); callback.resolve(object.result);
} else { } else {
if (object.id)
console.log(JSON.stringify(object, null, 2));
assert(!object.id); assert(!object.id);
// console.log(`[${this._sessionId}] ${object.method}`); // console.log(`[${this._sessionId}] ${object.method}`);
this.emit(object.method, object.params); this.emit(object.method, object.params);

View file

@ -103,7 +103,7 @@ export class ExecutionContext {
return void 0; return void 0;
throw e; throw e;
} }
} };
return this._session.send('Runtime.callFunctionOn', { return this._session.send('Runtime.callFunctionOn', {
// Serialize object using standard JSON implementation to correctly pass 'undefined'. // Serialize object using standard JSON implementation to correctly pass 'undefined'.
functionDeclaration: serializeFunction + '\n' + suffix + '\n', functionDeclaration: serializeFunction + '\n' + suffix + '\n',
@ -121,7 +121,8 @@ export class ExecutionContext {
}); });
} }
return valueFromRemoteObject(response.result); return valueFromRemoteObject(response.result);
}).catch(rewriteError); } }).catch(rewriteError);
}
if (typeof pageFunction !== 'function') if (typeof pageFunction !== 'function')
throw new Error(`Expected to get |string| or |function| as the first argument, but got "${pageFunction}" instead.`); throw new Error(`Expected to get |string| or |function| as the first argument, but got "${pageFunction}" instead.`);
@ -147,10 +148,10 @@ export class ExecutionContext {
let serializableArgs; let serializableArgs;
if (args.some(isUnserializable)) { if (args.some(isUnserializable)) {
serializableArgs = []; serializableArgs = [];
let paramStrings = []; const paramStrings = [];
for (let arg of args) { for (const arg of args) {
if (isUnserializable(arg)) { if (isUnserializable(arg)) {
paramStrings.push(unserializableToString(arg)) paramStrings.push(unserializableToString(arg));
} else { } else {
paramStrings.push('arguments[' + serializableArgs.length + ']'); paramStrings.push('arguments[' + serializableArgs.length + ']');
serializableArgs.push(arg); serializableArgs.push(arg);
@ -198,7 +199,7 @@ export class ExecutionContext {
if (response.wasThrown) if (response.wasThrown)
throw new Error('Evaluation failed: ' + response.result.description); throw new Error('Evaluation failed: ' + response.result.description);
if (!returnByValue) if (!returnByValue)
return createJSHandle(this, response.result);; return createJSHandle(this, response.result);
if (response.result.objectId) { if (response.result.objectId) {
const serializeFunction = function() { const serializeFunction = function() {
try { try {
@ -208,7 +209,7 @@ export class ExecutionContext {
return void 0; return void 0;
throw e; throw e;
} }
} };
return this._session.send('Runtime.callFunctionOn', { return this._session.send('Runtime.callFunctionOn', {
// Serialize object using standard JSON implementation to correctly pass 'undefined'. // Serialize object using standard JSON implementation to correctly pass 'undefined'.
functionDeclaration: serializeFunction + '\n' + suffix + '\n', functionDeclaration: serializeFunction + '\n' + suffix + '\n',
@ -294,7 +295,7 @@ export class ExecutionContext {
async _contextGlobalObjectId() { async _contextGlobalObjectId() {
if (!this._globalObjectId) { if (!this._globalObjectId) {
const globalObject = await this._session.send('Runtime.evaluate', { expression: "this", contextId: this._contextId }); const globalObject = await this._session.send('Runtime.evaluate', { expression: 'this', contextId: this._contextId });
this._globalObjectId = globalObject.result.objectId; this._globalObjectId = globalObject.result.objectId;
} }
return this._globalObjectId; return this._globalObjectId;

View file

@ -16,17 +16,18 @@
*/ */
import * as EventEmitter from 'events'; import * as EventEmitter from 'events';
import * as fs from 'fs'; import * as fs from 'fs';
import {helper, assert, debugError, RegisteredListener} from '../helper';
import { TimeoutError } from '../Errors'; import { TimeoutError } from '../Errors';
import { Events } from '../Events'; import { Events } from '../Events';
import {ExecutionContext, EVALUATION_SCRIPT_URL} from './ExecutionContext'; import { assert, debugError, helper, RegisteredListener } from '../helper';
import {NetworkManager, Response, Request, NetworkManagerEvents} from './NetworkManager';
import { TargetSession } from './Connection';
import { Page } from './Page';
import { TimeoutSettings } from '../TimeoutSettings'; import { TimeoutSettings } from '../TimeoutSettings';
import { JSHandle, ElementHandle } from './JSHandle'; import { TargetSession } from './Connection';
import { ExecutionContext } from './ExecutionContext';
import { ElementHandle, JSHandle } from './JSHandle';
import { NetworkManager, NetworkManagerEvents, Request, Response } from './NetworkManager';
import { Page } from './Page';
import { Protocol } from './protocol'; import { Protocol } from './protocol';
const readFileAsync = helper.promisify(fs.readFile); const readFileAsync = helper.promisify(fs.readFile);
export const FrameManagerEvents = { export const FrameManagerEvents = {
FrameNavigatedWithinDocument: Symbol('FrameNavigatedWithinDocument'), FrameNavigatedWithinDocument: Symbol('FrameNavigatedWithinDocument'),
TargetSwappedOnNavigation: Symbol('TargetSwappedOnNavigation'), TargetSwappedOnNavigation: Symbol('TargetSwappedOnNavigation'),
@ -34,7 +35,8 @@ export const FrameManagerEvents = {
FrameAttached: Symbol('FrameAttached'), FrameAttached: Symbol('FrameAttached'),
FrameDetached: Symbol('FrameDetached'), FrameDetached: Symbol('FrameDetached'),
FrameNavigated: Symbol('FrameNavigated'), FrameNavigated: Symbol('FrameNavigated'),
} };
export class FrameManager extends EventEmitter { export class FrameManager extends EventEmitter {
_session: TargetSession; _session: TargetSession;
_page: Page; _page: Page;
@ -71,8 +73,7 @@ export class FrameManager extends EventEmitter {
]); ]);
} }
_addSessionListeners() _addSessionListeners() {
{
this._sessionListeners = [ this._sessionListeners = [
helper.addEventListener(this._session, 'Page.frameNavigated', event => this._onFrameNavigated(event.frame)), helper.addEventListener(this._session, 'Page.frameNavigated', event => this._onFrameNavigated(event.frame)),
helper.addEventListener(this._session, 'Page.navigatedWithinDocument', event => this._onFrameNavigatedWithinDocument(event.frameId, event.url)), helper.addEventListener(this._session, 'Page.navigatedWithinDocument', event => this._onFrameNavigatedWithinDocument(event.frameId, event.url)),
@ -82,8 +83,7 @@ export class FrameManager extends EventEmitter {
]; ];
} }
async _swapTargetOnNavigation(newSession) async _swapTargetOnNavigation(newSession) {
{
helper.removeEventListeners(this._sessionListeners); helper.removeEventListeners(this._sessionListeners);
this.disconnectFromTarget(); this.disconnectFromTarget();
this._session = newSession; this._session = newSession;
@ -210,7 +210,7 @@ export class FrameManager extends EventEmitter {
return; return;
/** @type {!ExecutionContext} */ /** @type {!ExecutionContext} */
const context: ExecutionContext = new ExecutionContext(this._session, contextPayload, frame); const context: ExecutionContext = new ExecutionContext(this._session, contextPayload, frame);
frame._setContext(context) frame._setContext(context);
this._contextIdToContext.set(contextPayload.id, context); this._contextIdToContext.set(contextPayload.id, context);
} }
@ -521,7 +521,7 @@ export class Frame {
return this._detached; return this._detached;
} }
async click(selector: string, options: { delay?: number; button?: "left" | "right" | "middle"; clickCount?: number; } | undefined) { async click(selector: string, options: { delay?: number; button?: 'left' | 'right' | 'middle'; clickCount?: number; } | undefined) {
const handle = await this.$(selector); const handle = await this.$(selector);
assert(handle, 'No node found for selector: ' + selector); assert(handle, 'No node found for selector: ' + selector);
await handle.click(options); await handle.click(options);
@ -696,7 +696,7 @@ class NextNavigationWatchdog {
constructor(frame, timeout) { constructor(frame, timeout) {
this._frame = frame; this._frame = frame;
this._newDocumentNavigationPromise = new Promise(fulfill => { this._newDocumentNavigationPromise = new Promise(fulfill => {
this._newDocumentNavigationCallback = fulfill this._newDocumentNavigationCallback = fulfill;
}); });
this._sameDocumentNavigationPromise = new Promise(fulfill => { this._sameDocumentNavigationPromise = new Promise(fulfill => {
this._sameDocumentNavigationCallback = fulfill; this._sameDocumentNavigationCallback = fulfill;
@ -742,7 +742,7 @@ class NextNavigationWatchdog {
break; break;
} }
} catch (e) { } catch (e) {
console.log("_onTargetReconnected " + e); debugError('_onTargetReconnected ' + e);
} }
} }

View file

@ -68,7 +68,6 @@ export class Keyboard {
const ControlKey = 1 << 1; const ControlKey = 1 << 1;
const AltKey = 1 << 2; const AltKey = 1 << 2;
const MetaKey = 1 << 3; const MetaKey = 1 << 3;
const CapsLockKey = 1 << 4;
if (key === 'Alt') if (key === 'Alt')
return AltKey; return AltKey;
if (key === 'Control') if (key === 'Control')

View file

@ -14,16 +14,15 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import * as path from 'path';
import * as fs from 'fs'; import * as fs from 'fs';
import { assert, debugError, helper } from '../helper';
import { TargetSession } from './Connection'; import { TargetSession } from './Connection';
import { ExecutionContext } from './ExecutionContext'; import { ExecutionContext } from './ExecutionContext';
import { Frame, FrameManager } from './FrameManager'; import { FrameManager } from './FrameManager';
import { assert, debugError, helper } from '../helper'; import { Button } from './Input';
import { valueFromRemoteObject, releaseObject } from './protocolHelper';
import { Page } from './Page'; import { Page } from './Page';
import { Modifier, Button } from './Input';
import { Protocol } from './protocol'; import { Protocol } from './protocol';
import { releaseObject, valueFromRemoteObject } from './protocolHelper';
const writeFileAsync = helper.promisify(fs.writeFile); const writeFileAsync = helper.promisify(fs.writeFile);
export type ClickOptions = { export type ClickOptions = {
@ -173,7 +172,7 @@ export class ElementHandle extends JSHandle {
this._client.send('DOM.getContentQuads', { this._client.send('DOM.getContentQuads', {
objectId: this._remoteObject.objectId objectId: this._remoteObject.objectId
}).catch(debugError), }).catch(debugError),
this._page.evaluate(() => { return { clientWidth: innerWidth, clientHeight: innerHeight} }), this._page.evaluate(() => ({ clientWidth: innerWidth, clientHeight: innerHeight })),
]); ]);
if (!result || !result.quads.length) if (!result || !result.quads.length)
throw new Error('Node is either not visible or not an HTMLElement'); throw new Error('Node is either not visible or not an HTMLElement');

View file

@ -15,14 +15,12 @@
* limitations under the License. * limitations under the License.
*/ */
import * as childProcess from 'child_process'; import * as childProcess from 'child_process';
import * as path from 'path'; import { debugError, helper } from '../helper';
import { Browser } from './Browser'; import { Browser } from './Browser';
import { BrowserFetcher } from './BrowserFetcher'; import { BrowserFetcher } from './BrowserFetcher';
import { Connection } from './Connection'; import { Connection } from './Connection';
import { debugError, helper } from '../helper';
import { Viewport } from './Page'; import { Viewport } from './Page';
import { PipeTransport } from './PipeTransport'; import { PipeTransport } from './PipeTransport';
import * as os from 'os';
export class Launcher { export class Launcher {
@ -43,7 +41,6 @@ export class Launcher {
handleSIGINT = true, handleSIGINT = true,
handleSIGTERM = true, handleSIGTERM = true,
handleSIGHUP = true, handleSIGHUP = true,
headless = true,
defaultViewport = {width: 800, height: 600}, defaultViewport = {width: 800, height: 600},
slowMo = 0 slowMo = 0
} = options; } = options;
@ -100,8 +97,7 @@ export class Launcher {
try { try {
const transport = new PipeTransport(webkitProcess.stdio[3] as NodeJS.WritableStream, webkitProcess.stdio[4] as NodeJS.ReadableStream); const transport = new PipeTransport(webkitProcess.stdio[3] as NodeJS.WritableStream, webkitProcess.stdio[4] as NodeJS.ReadableStream);
connection = new Connection('', transport, slowMo); connection = new Connection('', transport, slowMo);
const browser = new Browser(connection, defaultViewport, webkitProcess const browser = new Browser(connection, defaultViewport, webkitProcess, gracefullyCloseWebkit);
, gracefullyCloseWebkit);
return browser; return browser;
} catch (e) { } catch (e) {
killWebKit(); killWebKit();

View file

@ -310,79 +310,3 @@ export class Response {
return this._request.frame(); return this._request.frame();
} }
} }
function headersArray(headers: { [s: string]: string; }): { name: string; value: string; }[] {
const result = [];
for (const name in headers) {
if (headers[name] !== undefined)
result.push({name, value: headers[name] + ''});
}
return result;
}
// List taken from https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml with extra 306 and 418 codes.
const STATUS_TEXTS = {
'100': 'Continue',
'101': 'Switching Protocols',
'102': 'Processing',
'103': 'Early Hints',
'200': 'OK',
'201': 'Created',
'202': 'Accepted',
'203': 'Non-Authoritative Information',
'204': 'No Content',
'205': 'Reset Content',
'206': 'Partial Content',
'207': 'Multi-Status',
'208': 'Already Reported',
'226': 'IM Used',
'300': 'Multiple Choices',
'301': 'Moved Permanently',
'302': 'Found',
'303': 'See Other',
'304': 'Not Modified',
'305': 'Use Proxy',
'306': 'Switch Proxy',
'307': 'Temporary Redirect',
'308': 'Permanent Redirect',
'400': 'Bad Request',
'401': 'Unauthorized',
'402': 'Payment Required',
'403': 'Forbidden',
'404': 'Not Found',
'405': 'Method Not Allowed',
'406': 'Not Acceptable',
'407': 'Proxy Authentication Required',
'408': 'Request Timeout',
'409': 'Conflict',
'410': 'Gone',
'411': 'Length Required',
'412': 'Precondition Failed',
'413': 'Payload Too Large',
'414': 'URI Too Long',
'415': 'Unsupported Media Type',
'416': 'Range Not Satisfiable',
'417': 'Expectation Failed',
'418': 'I\'m a teapot',
'421': 'Misdirected Request',
'422': 'Unprocessable Entity',
'423': 'Locked',
'424': 'Failed Dependency',
'425': 'Too Early',
'426': 'Upgrade Required',
'428': 'Precondition Required',
'429': 'Too Many Requests',
'431': 'Request Header Fields Too Large',
'451': 'Unavailable For Legal Reasons',
'500': 'Internal Server Error',
'501': 'Not Implemented',
'502': 'Bad Gateway',
'503': 'Service Unavailable',
'504': 'Gateway Timeout',
'505': 'HTTP Version Not Supported',
'506': 'Variant Also Negotiates',
'507': 'Insufficient Storage',
'508': 'Loop Detected',
'510': 'Not Extended',
'511': 'Network Authentication Required',
};

View file

@ -21,7 +21,7 @@ import * as mime from 'mime';
import { TargetSession, TargetSessionEvents } from './Connection'; import { TargetSession, TargetSessionEvents } from './Connection';
import { Events } from '../Events'; import { Events } from '../Events';
import { Frame, FrameManager, FrameManagerEvents } from './FrameManager'; import { Frame, FrameManager, FrameManagerEvents } from './FrameManager';
import { assert, helper, RegisteredListener } from '../helper'; import { assert, debugError, helper, RegisteredListener } from '../helper';
import { valueFromRemoteObject } from './protocolHelper'; import { valueFromRemoteObject } from './protocolHelper';
import { Keyboard, Mouse } from './Input'; import { Keyboard, Mouse } from './Input';
import { createJSHandle, ElementHandle, JSHandle, ClickOptions } from './JSHandle'; import { createJSHandle, ElementHandle, JSHandle, ClickOptions } from './JSHandle';
@ -113,14 +113,11 @@ export class Page extends EventEmitter {
}); });
} }
async _swapTargetOnNavigation(newSession : TargetSession, newTarget : Target) async _swapTargetOnNavigation(newSession : TargetSession, newTarget : Target) {
{
this._setSession(newSession); this._setSession(newSession);
this._setTarget(newTarget); this._setTarget(newTarget);
await this._frameManager._swapTargetOnNavigation(newSession); await this._frameManager._swapTargetOnNavigation(newSession);
await this._initialize().catch(e => debugError('failed to enable agents after swap: ' + e));
await this._initialize().catch(e => console.log('failed to enable agents after swap: ' + e));
} }
target(): Target { target(): Target {
@ -148,7 +145,7 @@ export class Page extends EventEmitter {
derivedType = 'timeEnd'; derivedType = 'timeEnd';
const mainFrameContext = await this.mainFrame().executionContext(); const mainFrameContext = await this.mainFrame().executionContext();
const handles = (parameters || []).map(p => { const handles = (parameters || []).map(p => {
let context = null;; let context = null;
if (p.objectId) { if (p.objectId) {
const objectId = JSON.parse(p.objectId); const objectId = JSON.parse(p.objectId);
context = this._frameManager._contextIdToContext.get(objectId.injectedScriptId); context = this._frameManager._contextIdToContext.get(objectId.injectedScriptId);
@ -239,7 +236,7 @@ export class Page extends EventEmitter {
}; };
if (!cookie.url && pageURL.startsWith('http')) if (!cookie.url && pageURL.startsWith('http'))
item.url = pageURL; item.url = pageURL;
await this._session.send('Page.deleteCookie', item).catch(e => console.log("deleting " + JSON.stringify(item) + " => " +e)); await this._session.send('Page.deleteCookie', item).catch(e => debugError('deleting ' + JSON.stringify(item) + ' => ' + e));
} }
} }
@ -388,22 +385,22 @@ export class Page extends EventEmitter {
async _screenshotTask(options?: ScreenshotOptions): Promise<Buffer | string> { async _screenshotTask(options?: ScreenshotOptions): Promise<Buffer | string> {
const params: Protocol.Page.snapshotRectParameters = { x: 0, y: 0, width: 800, height: 600, coordinateSystem: 'Page' }; const params: Protocol.Page.snapshotRectParameters = { x: 0, y: 0, width: 800, height: 600, coordinateSystem: 'Page' };
if (options.fullPage) { if (options.fullPage) {
const pageSize = await this.evaluate(() => { const pageSize = await this.evaluate(() =>
return { ({
width: document.body.scrollWidth, width: document.body.scrollWidth,
height: document.body.scrollHeight height: document.body.scrollHeight
}; }));
});
Object.assign(params, pageSize); Object.assign(params, pageSize);
} else if (options.clip) } else if (options.clip) {
Object.assign(params, options.clip); Object.assign(params, options.clip);
else if (this._viewport) } else if (this._viewport) {
Object.assign(params, this._viewport); Object.assign(params, this._viewport);
}
const [, result] = await Promise.all([ const [, result] = await Promise.all([
this._session._connection.send('Target.activate', { targetId: this._target._targetId }), this._session._connection.send('Target.activate', { targetId: this._target._targetId }),
this._session.send('Page.snapshotRect', params), this._session.send('Page.snapshotRect', params),
]).catch(e => { ]).catch(e => {
console.log('Failed to take screenshot: ' + e); debugError('Failed to take screenshot: ' + e);
throw e; throw e;
}); });
const prefix = 'data:image/png;base64,'; const prefix = 'data:image/png;base64,';
@ -421,7 +418,7 @@ export class Page extends EventEmitter {
this.browser()._connection.send('Target.close', { this.browser()._connection.send('Target.close', {
targetId: this._target._targetId targetId: this._target._targetId
}).catch(e => { }).catch(e => {
console.log(e); debugError(e);
}); });
await this._target._isClosedPromise; await this._target._isClosedPromise;
} }
@ -516,76 +513,6 @@ type ScreenshotOptions = {
encoding?: string, encoding?: string,
} }
type MediaFeature = {
name: string,
value: string
}
const supportedMetrics: Set<string> = new Set([
'Timestamp',
'Documents',
'Frames',
'JSEventListeners',
'Nodes',
'LayoutCount',
'RecalcStyleCount',
'LayoutDuration',
'RecalcStyleDuration',
'ScriptDuration',
'TaskDuration',
'JSHeapUsedSize',
'JSHeapTotalSize',
]);
const PagePaperFormats = {
letter: {width: 8.5, height: 11},
legal: {width: 8.5, height: 14},
tabloid: {width: 11, height: 17},
ledger: {width: 17, height: 11},
a0: {width: 33.1, height: 46.8 },
a1: {width: 23.4, height: 33.1 },
a2: {width: 16.54, height: 23.4 },
a3: {width: 11.7, height: 16.54 },
a4: {width: 8.27, height: 11.7 },
a5: {width: 5.83, height: 8.27 },
a6: {width: 4.13, height: 5.83 },
};
const unitToPixels = {
'px': 1,
'in': 96,
'cm': 37.8,
'mm': 3.78
};
function convertPrintParameterToInches(parameter: (string | number | undefined)): (number | undefined) {
if (typeof parameter === 'undefined')
return undefined;
let pixels: number;
if (helper.isNumber(parameter)) {
// Treat numbers as pixel values to be aligned with phantom's paperSize.
pixels = parameter as number;
} else if (helper.isString(parameter)) {
const text: string = parameter as string;
let unit = text.substring(text.length - 2).toLowerCase();
let valueText = '';
if (unitToPixels.hasOwnProperty(unit)) {
valueText = text.substring(0, text.length - 2);
} else {
// In case of unknown unit try to parse the whole parameter as number of pixels.
// This is consistent with phantom's paperSize behavior.
unit = 'px';
valueText = text;
}
const value = Number(valueText);
assert(!isNaN(value), 'Failed to parse parameter value: ' + text);
pixels = value * unitToPixels[unit];
} else {
throw new Error('page.pdf() Cannot handle parameter type: ' + (typeof parameter));
}
return pixels / 96;
}
type NetworkCookie = { type NetworkCookie = {
name: string, name: string,
value: string, value: string,
@ -599,19 +526,6 @@ type NetworkCookie = {
sameSite?: 'Strict'|'Lax'|'Extended'|'None' sameSite?: 'Strict'|'Lax'|'Extended'|'None'
}; };
type NetworkCookieParam = {
name: string,
value: string,
url?: string,
domain?: string,
path?: string,
expires?: number,
httpOnly?: boolean,
secure?: boolean,
sameSite?: 'Strict'|'Lax'
};
type DeleteNetworkCookieParam = { type DeleteNetworkCookieParam = {
name: string, name: string,
url?: string, url?: string,

View file

@ -15,13 +15,10 @@
* limitations under the License. * limitations under the License.
*/ */
import { Browser, BrowserContext } from './Browser';
import { TargetSession, Connection } from './Connection';
import { Events } from '../Events';
import { Page, Viewport } from './Page';
import { TaskQueue } from './TaskQueue';
import { Protocol } from './protocol';
import { helper, RegisteredListener } from '../helper'; import { helper, RegisteredListener } from '../helper';
import { Browser, BrowserContext } from './Browser';
import { Page } from './Page';
import { Protocol } from './protocol';
export class Target { export class Target {
private _browserContext: BrowserContext; private _browserContext: BrowserContext;

View file

@ -14,15 +14,11 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import * as fs from 'fs';
import {helper, assert, debugError} from '../helper'; import { assert, debugError } from '../helper';
import { TargetSession } from './Connection'; import { TargetSession } from './Connection';
import { Protocol } from './protocol'; import { Protocol } from './protocol';
const openAsync = helper.promisify(fs.open);
const writeAsync = helper.promisify(fs.write);
const closeAsync = helper.promisify(fs.close);
export function valueFromRemoteObject(remoteObject: Protocol.Runtime.RemoteObject): any { export function valueFromRemoteObject(remoteObject: Protocol.Runtime.RemoteObject): any {
assert(!remoteObject.objectId, 'Cannot extract value when objectId is given'); assert(!remoteObject.objectId, 'Cannot extract value when objectId is given');
if (remoteObject.type === 'number') { if (remoteObject.type === 'number') {