commit
44ef81e4cd
|
|
@ -17,13 +17,12 @@
|
|||
|
||||
import * as childProcess from 'child_process';
|
||||
import { EventEmitter } from 'events';
|
||||
import { Connection, ConnectionEvents } from './Connection';
|
||||
import { Connection } from './Connection';
|
||||
import { Events } from '../Events';
|
||||
import { RegisteredListener, assert, helper } from '../helper';
|
||||
import { Page, Viewport } from './Page';
|
||||
import { Target } from './Target';
|
||||
import { TaskQueue } from './TaskQueue';
|
||||
import { Protocol } from './protocol';
|
||||
|
||||
export class Browser extends EventEmitter {
|
||||
_defaultViewport: Viewport;
|
||||
|
|
@ -101,7 +100,7 @@ export class Browser extends EventEmitter {
|
|||
return this._createPageInContext(this._defaultContext._id);
|
||||
}
|
||||
|
||||
async _createPageInContext(browserContextId?: string ): Promise<Page> {
|
||||
async _createPageInContext(browserContextId?: string): Promise<Page> {
|
||||
const {targetId} = await this._connection.send('Browser.createPage', {browserContextId});
|
||||
const target = this._targets.get(targetId);
|
||||
return await target.page();
|
||||
|
|
@ -146,11 +145,11 @@ export class Browser extends EventEmitter {
|
|||
async _onTargetCreated({targetInfo}) {
|
||||
let context = null;
|
||||
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
|
||||
// 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
|
||||
// lifecycle events.
|
||||
context = this._contexts.get(targetInfo.browserContextId);
|
||||
// if (!context)
|
||||
// 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);
|
||||
}
|
||||
|
||||
async _onProvisionalTargetCommitted({oldTargetId, newTargetId})
|
||||
{
|
||||
async _onProvisionalTargetCommitted({oldTargetId, newTargetId}) {
|
||||
const oldTarget = this._targets.get(oldTargetId);
|
||||
if (!oldTarget._pagePromise)
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ export class Connection extends EventEmitter {
|
|||
else
|
||||
callback.resolve(object.result);
|
||||
} else {
|
||||
assert(this._closed, "Received response for unknown callback: " + object.id);
|
||||
assert(this._closed, 'Received response for unknown callback: ' + object.id);
|
||||
}
|
||||
} else {
|
||||
this.emit(object.method, object.params);
|
||||
|
|
@ -114,16 +114,16 @@ export class Connection extends EventEmitter {
|
|||
} else if (object.method === 'Target.dispatchMessageFromTarget') {
|
||||
const session = this._sessions.get(object.params.targetId);
|
||||
if (!session)
|
||||
throw new Error("Unknown target: " + object.params.targetId);
|
||||
throw new Error('Unknown target: ' + object.params.targetId);
|
||||
session._dispatchMessageFromTarget(object.params.message);
|
||||
} else if (object.method === 'Target.didCommitProvisionalTarget') {
|
||||
const {oldTargetId, newTargetId} = object.params;
|
||||
const newSession = this._sessions.get(newTargetId);
|
||||
if (!newSession)
|
||||
throw new Error("Unknown new target: " + newTargetId);
|
||||
throw new Error('Unknown new target: ' + newTargetId);
|
||||
const oldSession = this._sessions.get(oldTargetId);
|
||||
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,
|
||||
params
|
||||
};
|
||||
debugWrappedMessage("SEND ► " + JSON.stringify(messageObj, null, 2));
|
||||
debugWrappedMessage('SEND ► ' + JSON.stringify(messageObj, null, 2));
|
||||
this._out.push(messageObj);
|
||||
// Serialize message before adding callback in case JSON throws.
|
||||
const message = JSON.stringify(messageObj);
|
||||
const result = new Promise<Protocol.CommandReturnValues[T]>((resolve, reject) => {
|
||||
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
|
||||
}).catch(e => {
|
||||
// There is a possible race of the connection closure. We may have received
|
||||
// targetDestroyed notification before response for the command, in that
|
||||
// case it's safe to swallow the exception.g
|
||||
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;
|
||||
}
|
||||
|
||||
_dispatchMessageFromTarget(message: string) {
|
||||
const object = JSON.parse(message);
|
||||
debugWrappedMessage("◀ RECV " + JSON.stringify(object, null, 2));
|
||||
debugWrappedMessage('◀ RECV ' + JSON.stringify(object, null, 2));
|
||||
this._in.push(object);
|
||||
if (object.id && this._callbacks.has(object.id)) {
|
||||
const callback = this._callbacks.get(object.id);
|
||||
|
|
@ -219,8 +219,6 @@ export class TargetSession extends EventEmitter {
|
|||
else
|
||||
callback.resolve(object.result);
|
||||
} else {
|
||||
if (object.id)
|
||||
console.log(JSON.stringify(object, null, 2));
|
||||
assert(!object.id);
|
||||
// console.log(`[${this._sessionId}] ${object.method}`);
|
||||
this.emit(object.method, object.params);
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@ export class ExecutionContext {
|
|||
return void 0;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
};
|
||||
return this._session.send('Runtime.callFunctionOn', {
|
||||
// Serialize object using standard JSON implementation to correctly pass 'undefined'.
|
||||
functionDeclaration: serializeFunction + '\n' + suffix + '\n',
|
||||
|
|
@ -121,7 +121,8 @@ export class ExecutionContext {
|
|||
});
|
||||
}
|
||||
return valueFromRemoteObject(response.result);
|
||||
}).catch(rewriteError); }
|
||||
}).catch(rewriteError);
|
||||
}
|
||||
|
||||
if (typeof pageFunction !== 'function')
|
||||
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;
|
||||
if (args.some(isUnserializable)) {
|
||||
serializableArgs = [];
|
||||
let paramStrings = [];
|
||||
for (let arg of args) {
|
||||
const paramStrings = [];
|
||||
for (const arg of args) {
|
||||
if (isUnserializable(arg)) {
|
||||
paramStrings.push(unserializableToString(arg))
|
||||
paramStrings.push(unserializableToString(arg));
|
||||
} else {
|
||||
paramStrings.push('arguments[' + serializableArgs.length + ']');
|
||||
serializableArgs.push(arg);
|
||||
|
|
@ -172,7 +173,7 @@ export class ExecutionContext {
|
|||
returnByValue: false,
|
||||
emulateUserGesture: true
|
||||
});
|
||||
} catch(err) {
|
||||
} catch (err) {
|
||||
if (err instanceof TypeError && err.message.startsWith('Converting circular structure to JSON'))
|
||||
err.message += ' Are you passing a nested JSHandle?';
|
||||
throw err;
|
||||
|
|
@ -198,7 +199,7 @@ export class ExecutionContext {
|
|||
if (response.wasThrown)
|
||||
throw new Error('Evaluation failed: ' + response.result.description);
|
||||
if (!returnByValue)
|
||||
return createJSHandle(this, response.result);;
|
||||
return createJSHandle(this, response.result);
|
||||
if (response.result.objectId) {
|
||||
const serializeFunction = function() {
|
||||
try {
|
||||
|
|
@ -208,7 +209,7 @@ export class ExecutionContext {
|
|||
return void 0;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
};
|
||||
return this._session.send('Runtime.callFunctionOn', {
|
||||
// Serialize object using standard JSON implementation to correctly pass 'undefined'.
|
||||
functionDeclaration: serializeFunction + '\n' + suffix + '\n',
|
||||
|
|
@ -294,7 +295,7 @@ export class ExecutionContext {
|
|||
|
||||
async _contextGlobalObjectId() {
|
||||
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;
|
||||
}
|
||||
return this._globalObjectId;
|
||||
|
|
|
|||
|
|
@ -16,17 +16,18 @@
|
|||
*/
|
||||
import * as EventEmitter from 'events';
|
||||
import * as fs from 'fs';
|
||||
import {helper, assert, debugError, RegisteredListener} from '../helper';
|
||||
import {TimeoutError} from '../Errors';
|
||||
import {Events} from '../Events';
|
||||
import {ExecutionContext, EVALUATION_SCRIPT_URL} from './ExecutionContext';
|
||||
import {NetworkManager, Response, Request, NetworkManagerEvents} from './NetworkManager';
|
||||
import { TargetSession } from './Connection';
|
||||
import { Page } from './Page';
|
||||
import { TimeoutError } from '../Errors';
|
||||
import { Events } from '../Events';
|
||||
import { assert, debugError, helper, RegisteredListener } from '../helper';
|
||||
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';
|
||||
const readFileAsync = helper.promisify(fs.readFile);
|
||||
|
||||
export const FrameManagerEvents = {
|
||||
FrameNavigatedWithinDocument: Symbol('FrameNavigatedWithinDocument'),
|
||||
TargetSwappedOnNavigation: Symbol('TargetSwappedOnNavigation'),
|
||||
|
|
@ -34,7 +35,8 @@ export const FrameManagerEvents = {
|
|||
FrameAttached: Symbol('FrameAttached'),
|
||||
FrameDetached: Symbol('FrameDetached'),
|
||||
FrameNavigated: Symbol('FrameNavigated'),
|
||||
}
|
||||
};
|
||||
|
||||
export class FrameManager extends EventEmitter {
|
||||
_session: TargetSession;
|
||||
_page: Page;
|
||||
|
|
@ -71,8 +73,7 @@ export class FrameManager extends EventEmitter {
|
|||
]);
|
||||
}
|
||||
|
||||
_addSessionListeners()
|
||||
{
|
||||
_addSessionListeners() {
|
||||
this._sessionListeners = [
|
||||
helper.addEventListener(this._session, 'Page.frameNavigated', event => this._onFrameNavigated(event.frame)),
|
||||
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);
|
||||
this.disconnectFromTarget();
|
||||
this._session = newSession;
|
||||
|
|
@ -95,7 +95,7 @@ export class FrameManager extends EventEmitter {
|
|||
|
||||
disconnectFromTarget() {
|
||||
for (const frame of this.frames())
|
||||
frame._setContext(null);
|
||||
frame._setContext(null);
|
||||
// this._mainFrame = null;
|
||||
}
|
||||
|
||||
|
|
@ -210,7 +210,7 @@ export class FrameManager extends EventEmitter {
|
|||
return;
|
||||
/** @type {!ExecutionContext} */
|
||||
const context: ExecutionContext = new ExecutionContext(this._session, contextPayload, frame);
|
||||
frame._setContext(context)
|
||||
frame._setContext(context);
|
||||
this._contextIdToContext.set(contextPayload.id, context);
|
||||
}
|
||||
|
||||
|
|
@ -282,7 +282,7 @@ export class Frame {
|
|||
}
|
||||
|
||||
async waitForNavigation(): Promise<Response | null> {
|
||||
//FIXME: this method only works for main frames.
|
||||
// FIXME: this method only works for main frames.
|
||||
const watchDog = new NextNavigationWatchdog(this, 10000);
|
||||
return watchDog.waitForNavigation();
|
||||
}
|
||||
|
|
@ -521,7 +521,7 @@ export class Frame {
|
|||
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);
|
||||
assert(handle, 'No node found for selector: ' + selector);
|
||||
await handle.click(options);
|
||||
|
|
@ -586,7 +586,7 @@ export class Frame {
|
|||
return this.waitForFunction(selectorOrFunctionOrTimeout, options, ...args);
|
||||
return Promise.reject(new Error('Unsupported target type: ' + (typeof selectorOrFunctionOrTimeout)));
|
||||
}
|
||||
|
||||
|
||||
async title(): Promise<string> {
|
||||
return this.evaluate(() => document.title);
|
||||
}
|
||||
|
|
@ -696,7 +696,7 @@ class NextNavigationWatchdog {
|
|||
constructor(frame, timeout) {
|
||||
this._frame = frame;
|
||||
this._newDocumentNavigationPromise = new Promise(fulfill => {
|
||||
this._newDocumentNavigationCallback = fulfill
|
||||
this._newDocumentNavigationCallback = fulfill;
|
||||
});
|
||||
this._sameDocumentNavigationPromise = new Promise(fulfill => {
|
||||
this._sameDocumentNavigationCallback = fulfill;
|
||||
|
|
@ -742,7 +742,7 @@ class NextNavigationWatchdog {
|
|||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("_onTargetReconnected " + e);
|
||||
debugError('_onTargetReconnected ' + e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ export class Keyboard {
|
|||
const ControlKey = 1 << 1;
|
||||
const AltKey = 1 << 2;
|
||||
const MetaKey = 1 << 3;
|
||||
const CapsLockKey = 1 << 4;
|
||||
if (key === 'Alt')
|
||||
return AltKey;
|
||||
if (key === 'Control')
|
||||
|
|
|
|||
|
|
@ -14,16 +14,15 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs';
|
||||
import { assert, debugError, helper } from '../helper';
|
||||
import { TargetSession } from './Connection';
|
||||
import { ExecutionContext } from './ExecutionContext';
|
||||
import { Frame, FrameManager } from './FrameManager';
|
||||
import { assert, debugError, helper } from '../helper';
|
||||
import { valueFromRemoteObject, releaseObject } from './protocolHelper';
|
||||
import { FrameManager } from './FrameManager';
|
||||
import { Button } from './Input';
|
||||
import { Page } from './Page';
|
||||
import { Modifier, Button } from './Input';
|
||||
import { Protocol } from './protocol';
|
||||
import { releaseObject, valueFromRemoteObject } from './protocolHelper';
|
||||
const writeFileAsync = helper.promisify(fs.writeFile);
|
||||
|
||||
export type ClickOptions = {
|
||||
|
|
@ -173,7 +172,7 @@ export class ElementHandle extends JSHandle {
|
|||
this._client.send('DOM.getContentQuads', {
|
||||
objectId: this._remoteObject.objectId
|
||||
}).catch(debugError),
|
||||
this._page.evaluate(() => { return { clientWidth: innerWidth, clientHeight: innerHeight} }),
|
||||
this._page.evaluate(() => ({ clientWidth: innerWidth, clientHeight: innerHeight })),
|
||||
]);
|
||||
if (!result || !result.quads.length)
|
||||
throw new Error('Node is either not visible or not an HTMLElement');
|
||||
|
|
|
|||
|
|
@ -15,14 +15,12 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
import * as childProcess from 'child_process';
|
||||
import * as path from 'path';
|
||||
import { debugError, helper } from '../helper';
|
||||
import { Browser } from './Browser';
|
||||
import { BrowserFetcher } from './BrowserFetcher';
|
||||
import { Connection } from './Connection';
|
||||
import { debugError, helper } from '../helper';
|
||||
import { Viewport } from './Page';
|
||||
import { PipeTransport } from './PipeTransport';
|
||||
import * as os from 'os';
|
||||
|
||||
|
||||
export class Launcher {
|
||||
|
|
@ -43,7 +41,6 @@ export class Launcher {
|
|||
handleSIGINT = true,
|
||||
handleSIGTERM = true,
|
||||
handleSIGHUP = true,
|
||||
headless = true,
|
||||
defaultViewport = {width: 800, height: 600},
|
||||
slowMo = 0
|
||||
} = options;
|
||||
|
|
@ -56,7 +53,7 @@ export class Launcher {
|
|||
throw new Error(missingText);
|
||||
webkitExecutable = executablePath;
|
||||
}
|
||||
|
||||
|
||||
let stdio: ('ignore' | 'pipe')[] = ['pipe', 'pipe', 'pipe'];
|
||||
if (dumpio)
|
||||
stdio = ['ignore', 'pipe', 'pipe', 'pipe', 'pipe'];
|
||||
|
|
@ -100,8 +97,7 @@ export class Launcher {
|
|||
try {
|
||||
const transport = new PipeTransport(webkitProcess.stdio[3] as NodeJS.WritableStream, webkitProcess.stdio[4] as NodeJS.ReadableStream);
|
||||
connection = new Connection('', transport, slowMo);
|
||||
const browser = new Browser(connection, defaultViewport, webkitProcess
|
||||
, gracefullyCloseWebkit);
|
||||
const browser = new Browser(connection, defaultViewport, webkitProcess, gracefullyCloseWebkit);
|
||||
return browser;
|
||||
} catch (e) {
|
||||
killWebKit();
|
||||
|
|
|
|||
|
|
@ -310,79 +310,3 @@ export class Response {
|
|||
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',
|
||||
};
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import * as mime from 'mime';
|
|||
import { TargetSession, TargetSessionEvents } from './Connection';
|
||||
import { Events } from '../Events';
|
||||
import { Frame, FrameManager, FrameManagerEvents } from './FrameManager';
|
||||
import { assert, helper, RegisteredListener } from '../helper';
|
||||
import { assert, debugError, helper, RegisteredListener } from '../helper';
|
||||
import { valueFromRemoteObject } from './protocolHelper';
|
||||
import { Keyboard, Mouse } from './Input';
|
||||
import { createJSHandle, ElementHandle, JSHandle, ClickOptions } from './JSHandle';
|
||||
|
|
@ -70,7 +70,7 @@ export class Page extends EventEmitter {
|
|||
this._frameManager = new FrameManager(session, this, this._timeoutSettings);
|
||||
|
||||
this._screenshotTaskQueue = screenshotTaskQueue;
|
||||
|
||||
|
||||
this._setSession(session);
|
||||
this._setTarget(target);
|
||||
|
||||
|
|
@ -113,14 +113,11 @@ export class Page extends EventEmitter {
|
|||
});
|
||||
}
|
||||
|
||||
async _swapTargetOnNavigation(newSession : TargetSession, newTarget : Target)
|
||||
{
|
||||
this._setSession(newSession);
|
||||
async _swapTargetOnNavigation(newSession : TargetSession, newTarget : Target) {
|
||||
this._setSession(newSession);
|
||||
this._setTarget(newTarget);
|
||||
|
||||
await this._frameManager._swapTargetOnNavigation(newSession);
|
||||
|
||||
await this._initialize().catch(e => console.log('failed to enable agents after swap: ' + e));
|
||||
await this._initialize().catch(e => debugError('failed to enable agents after swap: ' + e));
|
||||
}
|
||||
|
||||
target(): Target {
|
||||
|
|
@ -140,7 +137,7 @@ export class Page extends EventEmitter {
|
|||
}
|
||||
|
||||
async _onConsoleMessage(event : Protocol.Console.messageAddedPayload) {
|
||||
const {type, level, text, parameters, url, line:lineNumber, column:columnNumber} = event.message;
|
||||
const { type, level, text, parameters, url, line: lineNumber, column: columnNumber } = event.message;
|
||||
let derivedType: string = type;
|
||||
if (type === 'log')
|
||||
derivedType = level;
|
||||
|
|
@ -148,7 +145,7 @@ export class Page extends EventEmitter {
|
|||
derivedType = 'timeEnd';
|
||||
const mainFrameContext = await this.mainFrame().executionContext();
|
||||
const handles = (parameters || []).map(p => {
|
||||
let context = null;;
|
||||
let context = null;
|
||||
if (p.objectId) {
|
||||
const objectId = JSON.parse(p.objectId);
|
||||
context = this._frameManager._contextIdToContext.get(objectId.injectedScriptId);
|
||||
|
|
@ -169,7 +166,7 @@ export class Page extends EventEmitter {
|
|||
const formattedText = textTokens.length ? textTokens.join(' ') : text;
|
||||
this.emit(Events.Page.Console, new ConsoleMessage(derivedType, formattedText, handles, location));
|
||||
}
|
||||
|
||||
|
||||
mainFrame(): Frame {
|
||||
return this._frameManager.mainFrame();
|
||||
}
|
||||
|
|
@ -239,7 +236,7 @@ export class Page extends EventEmitter {
|
|||
};
|
||||
if (!cookie.url && pageURL.startsWith('http'))
|
||||
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> {
|
||||
const params: Protocol.Page.snapshotRectParameters = { x: 0, y: 0, width: 800, height: 600, coordinateSystem: 'Page' };
|
||||
if (options.fullPage) {
|
||||
const pageSize = await this.evaluate(() => {
|
||||
return {
|
||||
const pageSize = await this.evaluate(() =>
|
||||
({
|
||||
width: document.body.scrollWidth,
|
||||
height: document.body.scrollHeight
|
||||
};
|
||||
});
|
||||
}));
|
||||
Object.assign(params, pageSize);
|
||||
} else if (options.clip)
|
||||
} else if (options.clip) {
|
||||
Object.assign(params, options.clip);
|
||||
else if (this._viewport)
|
||||
} else if (this._viewport) {
|
||||
Object.assign(params, this._viewport);
|
||||
}
|
||||
const [, result] = await Promise.all([
|
||||
this._session._connection.send('Target.activate', { targetId: this._target._targetId }),
|
||||
this._session.send('Page.snapshotRect', params),
|
||||
]).catch(e => {
|
||||
console.log('Failed to take screenshot: ' + e);
|
||||
debugError('Failed to take screenshot: ' + e);
|
||||
throw e;
|
||||
});
|
||||
const prefix = 'data:image/png;base64,';
|
||||
|
|
@ -421,7 +418,7 @@ export class Page extends EventEmitter {
|
|||
this.browser()._connection.send('Target.close', {
|
||||
targetId: this._target._targetId
|
||||
}).catch(e => {
|
||||
console.log(e);
|
||||
debugError(e);
|
||||
});
|
||||
await this._target._isClosedPromise;
|
||||
}
|
||||
|
|
@ -516,76 +513,6 @@ type ScreenshotOptions = {
|
|||
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 = {
|
||||
name: string,
|
||||
value: string,
|
||||
|
|
@ -599,19 +526,6 @@ type NetworkCookie = {
|
|||
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 = {
|
||||
name: string,
|
||||
url?: string,
|
||||
|
|
|
|||
|
|
@ -15,13 +15,10 @@
|
|||
* 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 { Browser, BrowserContext } from './Browser';
|
||||
import { Page } from './Page';
|
||||
import { Protocol } from './protocol';
|
||||
|
||||
export class Target {
|
||||
private _browserContext: BrowserContext;
|
||||
|
|
|
|||
|
|
@ -14,15 +14,11 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* 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 { 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 {
|
||||
assert(!remoteObject.objectId, 'Cannot extract value when objectId is given');
|
||||
if (remoteObject.type === 'number') {
|
||||
|
|
|
|||
Loading…
Reference in a new issue