Socket
Socket
Sign inDemoInstall

puppeteer-core

Package Overview
Dependencies
12
Maintainers
4
Versions
222
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 3.0.2 to 3.0.3

lib/ConnectionTransport.js

2

index.js

@@ -28,3 +28,3 @@ /**

const Puppeteer = require('./lib/Puppeteer');
const {Puppeteer} = require('./lib/Puppeteer');
const packageJson = require('./package.json');

@@ -31,0 +31,0 @@ let preferredRevision = packageJson.puppeteer.chromium_revision;

@@ -16,2 +16,6 @@ /**

*/
/* This file is used in two places:
* 1) the coverage-utils use it to gain a list of all methods we check for test coverage on
* 2) index.js uses it to iterate through all methods and call helper.installAsyncStackHooks on
*/
module.exports = {

@@ -34,3 +38,3 @@ Accessibility: require('./Accessibility').Accessibility,

Page: require('./Page').Page,
Puppeteer: require('./Puppeteer'),
Puppeteer: require('./Puppeteer').Puppeteer,
Request: require('./NetworkManager').Request,

@@ -37,0 +41,0 @@ Response: require('./NetworkManager').Response,

@@ -0,1 +1,2 @@

"use strict";
/**

@@ -16,48 +17,24 @@ * Copyright 2017 Google Inc. All rights reserved.

*/
const { helper, assert } = require('./helper');
const { Target } = require('./Target');
const EventEmitter = require('events');
const { TaskQueue } = require('./TaskQueue');
const { Events } = require('./Events');
// Used as a TypeDef
// eslint-disable-next-line no-unused-vars
const { Connection } = require('./Connection');
Object.defineProperty(exports, "__esModule", { value: true });
const helper_1 = require("./helper");
const Target_1 = require("./Target");
const EventEmitter = require("events");
const TaskQueue_1 = require("./TaskQueue");
const Events_1 = require("./Events");
class Browser extends EventEmitter {
/**
* @param {!Connection} connection
* @param {!Array<string>} contextIds
* @param {boolean} ignoreHTTPSErrors
* @param {?Puppeteer.Viewport} defaultViewport
* @param {?Puppeteer.ChildProcess} process
* @param {function()=} closeCallback
*/
static async create(connection, contextIds, ignoreHTTPSErrors, defaultViewport, process, closeCallback) {
const browser = new Browser(connection, contextIds, ignoreHTTPSErrors, defaultViewport, process, closeCallback);
await connection.send('Target.setDiscoverTargets', { discover: true });
return browser;
}
/**
* @param {!Connection} connection
* @param {!Array<string>} contextIds
* @param {boolean} ignoreHTTPSErrors
* @param {?Puppeteer.Viewport} defaultViewport
* @param {?Puppeteer.ChildProcess} process
* @param {(function():Promise)=} closeCallback
*/
constructor(connection, contextIds, ignoreHTTPSErrors, defaultViewport, process, closeCallback) {
super();
this._screenshotTaskQueue = new TaskQueue_1.TaskQueue();
this._ignoreHTTPSErrors = ignoreHTTPSErrors;
this._defaultViewport = defaultViewport;
this._process = process;
this._screenshotTaskQueue = new TaskQueue();
this._screenshotTaskQueue = new TaskQueue_1.TaskQueue();
this._connection = connection;
this._closeCallback = closeCallback || new Function();
this._closeCallback = closeCallback || function () { };
this._defaultContext = new BrowserContext(this._connection, this, null);
/** @type {Map<string, BrowserContext>} */
this._contexts = new Map();
for (const contextId of contextIds)
this._contexts.set(contextId, new BrowserContext(this._connection, this, contextId));
/** @type {Map<string, Target>} */
this._targets = new Map();
this._connection.on(Events.Connection.Disconnected, () => this.emit(Events.Browser.Disconnected));
this._connection.on(Events_1.Events.Connection.Disconnected, () => this.emit(Events_1.Events.Browser.Disconnected));
this._connection.on('Target.targetCreated', this._targetCreated.bind(this));

@@ -67,11 +44,10 @@ this._connection.on('Target.targetDestroyed', this._targetDestroyed.bind(this));

}
/**
* @return {?Puppeteer.ChildProcess}
*/
static async create(connection, contextIds, ignoreHTTPSErrors, defaultViewport, process, closeCallback) {
const browser = new Browser(connection, contextIds, ignoreHTTPSErrors, defaultViewport, process, closeCallback);
await connection.send('Target.setDiscoverTargets', { discover: true });
return browser;
}
process() {
return this._process;
}
/**
* @return {!Promise<!BrowserContext>}
*/
async createIncognitoBrowserContext() {

@@ -83,11 +59,5 @@ const { browserContextId } = await this._connection.send('Target.createBrowserContext');

}
/**
* @return {!Array<!BrowserContext>}
*/
browserContexts() {
return [this._defaultContext, ...Array.from(this._contexts.values())];
}
/**
* @return {!BrowserContext}
*/
defaultBrowserContext() {

@@ -97,4 +67,4 @@ return this._defaultContext;

/**
* @param {?string} contextId
*/
* @param {?string} contextId
*/
async _disposeContext(contextId) {

@@ -104,5 +74,2 @@ await this._connection.send('Target.disposeBrowserContext', { browserContextId: contextId || undefined });

}
/**
* @param {!Protocol.Target.targetCreatedPayload} event
*/
async _targetCreated(event) {

@@ -112,13 +79,13 @@ const targetInfo = event.targetInfo;

const context = (browserContextId && this._contexts.has(browserContextId)) ? this._contexts.get(browserContextId) : this._defaultContext;
const target = new Target(targetInfo, context, () => this._connection.createSession(targetInfo), this._ignoreHTTPSErrors, this._defaultViewport, this._screenshotTaskQueue);
assert(!this._targets.has(event.targetInfo.targetId), 'Target should not exist before targetCreated');
const target = new Target_1.Target(targetInfo, context, () => this._connection.createSession(targetInfo), this._ignoreHTTPSErrors, this._defaultViewport, this._screenshotTaskQueue);
helper_1.assert(!this._targets.has(event.targetInfo.targetId), 'Target should not exist before targetCreated');
this._targets.set(event.targetInfo.targetId, target);
if (await target._initializedPromise) {
this.emit(Events.Browser.TargetCreated, target);
context.emit(Events.BrowserContext.TargetCreated, target);
this.emit(Events_1.Events.Browser.TargetCreated, target);
context.emit(Events_1.Events.BrowserContext.TargetCreated, target);
}
}
/**
* @param {{targetId: string}} event
*/
* @param {{targetId: string}} event
*/
async _targetDestroyed(event) {

@@ -130,12 +97,12 @@ const target = this._targets.get(event.targetId);

if (await target._initializedPromise) {
this.emit(Events.Browser.TargetDestroyed, target);
target.browserContext().emit(Events.BrowserContext.TargetDestroyed, target);
this.emit(Events_1.Events.Browser.TargetDestroyed, target);
target.browserContext().emit(Events_1.Events.BrowserContext.TargetDestroyed, target);
}
}
/**
* @param {!Protocol.Target.targetInfoChangedPayload} event
*/
* @param {!Protocol.Target.targetInfoChangedPayload} event
*/
_targetInfoChanged(event) {
const target = this._targets.get(event.targetInfo.targetId);
assert(target, 'target should exist before targetInfoChanged');
helper_1.assert(target, 'target should exist before targetInfoChanged');
const previousURL = target.url();

@@ -145,38 +112,22 @@ const wasInitialized = target._isInitialized;

if (wasInitialized && previousURL !== target.url()) {
this.emit(Events.Browser.TargetChanged, target);
target.browserContext().emit(Events.BrowserContext.TargetChanged, target);
this.emit(Events_1.Events.Browser.TargetChanged, target);
target.browserContext().emit(Events_1.Events.BrowserContext.TargetChanged, target);
}
}
/**
* @return {string}
*/
wsEndpoint() {
return this._connection.url();
}
/**
* @return {!Promise<!Puppeteer.Page>}
*/
async newPage() {
return this._defaultContext.newPage();
}
/**
* @param {?string} contextId
* @return {!Promise<!Puppeteer.Page>}
*/
async _createPageInContext(contextId) {
const { targetId } = await this._connection.send('Target.createTarget', { url: 'about:blank', browserContextId: contextId || undefined });
const target = await this._targets.get(targetId);
assert(await target._initializedPromise, 'Failed to create target for page');
helper_1.assert(await target._initializedPromise, 'Failed to create target for page');
const page = await target.page();
return page;
}
/**
* @return {!Array<!Target>}
*/
targets() {
return Array.from(this._targets.values()).filter(target => target._isInitialized);
}
/**
* @return {!Target}
*/
target() {

@@ -186,6 +137,6 @@ return this.targets().find(target => target.type() === 'browser');

/**
* @param {function(!Target):boolean} predicate
* @param {{timeout?: number}=} options
* @return {!Promise<!Target>}
*/
* @param {function(!Target):boolean} predicate
* @param {{timeout?: number}=} options
* @return {!Promise<!Target>}
*/
async waitForTarget(predicate, options = {}) {

@@ -198,16 +149,13 @@ const { timeout = 30000 } = options;

const targetPromise = new Promise(x => resolve = x);
this.on(Events.Browser.TargetCreated, check);
this.on(Events.Browser.TargetChanged, check);
this.on(Events_1.Events.Browser.TargetCreated, check);
this.on(Events_1.Events.Browser.TargetChanged, check);
try {
if (!timeout)
return await targetPromise;
return await helper.waitWithTimeout(targetPromise, 'target', timeout);
return await helper_1.helper.waitWithTimeout(targetPromise, 'target', timeout);
}
finally {
this.removeListener(Events.Browser.TargetCreated, check);
this.removeListener(Events.Browser.TargetChanged, check);
this.removeListener(Events_1.Events.Browser.TargetCreated, check);
this.removeListener(Events_1.Events.Browser.TargetChanged, check);
}
/**
* @param {!Target} target
*/
function check(target) {

@@ -218,5 +166,2 @@ if (predicate(target))

}
/**
* @return {!Promise<!Array<!Puppeteer.Page>>}
*/
async pages() {

@@ -227,5 +172,2 @@ const contextPages = await Promise.all(this.browserContexts().map(context => context.pages()));

}
/**
* @return {!Promise<string>}
*/
async version() {

@@ -235,5 +177,2 @@ const version = await this._getVersion();

}
/**
* @return {!Promise<string>}
*/
async userAgent() {

@@ -250,11 +189,5 @@ const version = await this._getVersion();

}
/**
* @return {boolean}
*/
isConnected() {
return !this._connection._closed;
}
/**
* @return {!Promise<!Object>}
*/
_getVersion() {

@@ -264,8 +197,4 @@ return this._connection.send('Browser.getVersion');

}
exports.Browser = Browser;
class BrowserContext extends EventEmitter {
/**
* @param {!Connection} connection
* @param {!Browser} browser
* @param {?string} contextId
*/
constructor(connection, browser, contextId) {

@@ -277,19 +206,8 @@ super();

}
/**
* @return {!Array<!Target>} target
*/
targets() {
return this._browser.targets().filter(target => target.browserContext() === this);
}
/**
* @param {function(!Target):boolean} predicate
* @param {{timeout?: number}=} options
* @return {!Promise<!Target>}
*/
waitForTarget(predicate, options) {
return this._browser.waitForTarget(target => target.browserContext() === this && predicate(target), options);
}
/**
* @return {!Promise<!Array<!Puppeteer.Page>>}
*/
async pages() {

@@ -301,12 +219,5 @@ const pages = await Promise.all(this.targets()

}
/**
* @return {boolean}
*/
isIncognito() {
return !!this._id;
}
/**
* @param {string} origin
* @param {!Array<string>} permissions
*/
async overridePermissions(origin, permissions) {

@@ -317,3 +228,4 @@ const webPermissionToProtocol = new Map([

['notifications', 'notifications'],
['push', 'push'],
// TODO: push isn't a valid type?
// ['push', 'push'],
['camera', 'videoCapture'],

@@ -344,11 +256,5 @@ ['microphone', 'audioCapture'],

}
/**
* @return {!Promise<!Puppeteer.Page>}
*/
newPage() {
return this._browser._createPageInContext(this._id);
}
/**
* @return {!Browser}
*/
browser() {

@@ -358,6 +264,6 @@ return this._browser;

async close() {
assert(this._id, 'Non-incognito profiles cannot be closed!');
helper_1.assert(this._id, 'Non-incognito profiles cannot be closed!');
await this._browser._disposeContext(this._id);
}
}
module.exports = { Browser, BrowserContext };
exports.BrowserContext = BrowserContext;

@@ -375,3 +375,3 @@ "use strict";

}
return new Promise(mountAndCopy).catch(err => { console.error(err); }).finally(unmount);
return new Promise(mountAndCopy).catch(error => { console.error(error); }).finally(unmount);
}

@@ -378,0 +378,0 @@ function httpRequest(url, method, response) {

@@ -19,4 +19,3 @@ "use strict";

const helper_1 = require("./helper");
const EventsModule = require("./Events");
const { Events } = EventsModule;
const Events_1 = require("./Events");
const debug = require("debug");

@@ -26,7 +25,2 @@ const debugProtocol = debug('puppeteer:protocol');

class Connection extends EventEmitter {
/**
* @param {string} url
* @param {!Puppeteer.ConnectionTransport} transport
* @param {number=} delay
*/
constructor(url, transport, delay = 0) {

@@ -57,3 +51,3 @@ super();

}
send(method, params = {}) {
send(method, params) {
const id = this._rawSend({ method, params });

@@ -120,3 +114,3 @@ return new Promise((resolve, reject) => {

this._sessions.clear();
this.emit(Events.Connection.Disconnected);
this.emit(Events_1.Events.Connection.Disconnected);
}

@@ -185,3 +179,3 @@ dispose() {

this._connection = null;
this.emit(Events.CDPSession.Disconnected);
this.emit(Events_1.Events.CDPSession.Disconnected);
}

@@ -188,0 +182,0 @@ }

@@ -86,5 +86,5 @@ "use strict";

}
catch (e) {
catch (error) {
// This might happen if the page has already navigated away.
helper_1.debugError(e);
helper_1.debugError(error);
}

@@ -163,5 +163,5 @@ }

}
catch (e) {
catch (error) {
// This might happen if the page has already navigated away.
helper_1.debugError(e);
helper_1.debugError(error);
}

@@ -168,0 +168,0 @@ }

@@ -17,2 +17,3 @@ "use strict";

*/
Object.defineProperty(exports, "__esModule", { value: true });
const devices = [

@@ -873,4 +874,4 @@ {

const devicesMap = {};
exports.devicesMap = devicesMap;
for (const device of devices)
devicesMap[device.name] = device;
module.exports = devicesMap;

@@ -17,3 +17,7 @@ "use strict";

*/
Object.defineProperty(exports, "__esModule", { value: true });
const helper_1 = require("./helper");
/* TODO(jacktfranklin): protocol.d.ts defines this
* so let's ditch this and avoid the duplication
*/
var DialogType;

@@ -25,3 +29,3 @@ (function (DialogType) {

DialogType["Prompt"] = "prompt";
})(DialogType || (DialogType = {}));
})(DialogType = exports.DialogType || (exports.DialogType = {}));
class Dialog {

@@ -60,3 +64,3 @@ constructor(client, type, message, defaultValue = '') {

}
exports.Dialog = Dialog;
Dialog.Type = DialogType;
module.exports = { Dialog };

@@ -0,1 +1,2 @@

"use strict";
/**

@@ -16,42 +17,21 @@ * Copyright 2019 Google Inc. All rights reserved.

*/
const fs = require('fs');
const { helper, assert } = require('./helper');
const { LifecycleWatcher } = require('./LifecycleWatcher');
const { TimeoutError } = require('./Errors');
// Used as a TypeDef
// eslint-disable-next-line no-unused-vars
const { JSHandle, ElementHandle } = require('./JSHandle');
// Used as a TypeDef
// eslint-disable-next-line no-unused-vars
const { ExecutionContext } = require('./ExecutionContext');
// Used as a TypeDef
// eslint-disable-next-line no-unused-vars
const { TimeoutSettings } = require('./TimeoutSettings');
const readFileAsync = helper.promisify(fs.readFile);
/**
* @unrestricted
*/
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs");
const helper_1 = require("./helper");
const LifecycleWatcher_1 = require("./LifecycleWatcher");
const Errors_1 = require("./Errors");
const QueryHandler_1 = require("./QueryHandler");
const readFileAsync = helper_1.helper.promisify(fs.readFile);
class DOMWorld {
/**
* @param {!Puppeteer.FrameManager} frameManager
* @param {!Puppeteer.Frame} frame
* @param {!TimeoutSettings} timeoutSettings
*/
constructor(frameManager, frame, timeoutSettings) {
this._documentPromise = null;
this._contextPromise = null;
this._contextResolveCallback = null;
this._detached = false;
this._waitTasks = new Set();
this._frameManager = frameManager;
this._frame = frame;
this._timeoutSettings = timeoutSettings;
/** @type {?Promise<!ElementHandle>} */
this._documentPromise = null;
/** @type {!Promise<!ExecutionContext>} */
this._contextPromise;
this._contextResolveCallback = null;
this._setContext(null);
/** @type {!Set<!WaitTask>} */
this._waitTasks = new Set();
this._detached = false;
}
/**
* @return {!Puppeteer.Frame}
*/
frame() {

@@ -77,5 +57,2 @@ return this._frame;

}
/**
* @return {boolean}
*/
_hasContext() {

@@ -124,5 +101,2 @@ return !this._contextResolveCallback;

}
/**
* @return {!Promise<!ElementHandle>}
*/
async _document() {

@@ -137,6 +111,2 @@ if (this._documentPromise)

}
/**
* @param {string} expression
* @return {!Promise<!Array<!ElementHandle>>}
*/
async $x(expression) {

@@ -147,8 +117,2 @@ const document = await this._document();

}
/**
* @param {string} selector
* @param {Function|string} pageFunction
* @param {!Array<*>} args
* @return {!Promise<(!Object|undefined)>}
*/
async $eval(selector, pageFunction, ...args) {

@@ -158,8 +122,2 @@ const document = await this._document();

}
/**
* @param {string} selector
* @param {Function|string} pageFunction
* @param {!Array<*>} args
* @return {!Promise<(!Object|undefined)>}
*/
async $$eval(selector, pageFunction, ...args) {

@@ -179,5 +137,2 @@ const document = await this._document();

}
/**
* @return {!Promise<String>}
*/
async content() {

@@ -193,6 +148,2 @@ return await this.evaluate(() => {

}
/**
* @param {string} html
* @param {!{timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
*/
async setContent(html, options = {}) {

@@ -207,3 +158,3 @@ const { waitUntil = ['load'], timeout = this._timeoutSettings.navigationTimeout(), } = options;

}, html);
const watcher = new LifecycleWatcher(this._frameManager, this._frame, waitUntil, timeout);
const watcher = new LifecycleWatcher_1.LifecycleWatcher(this._frameManager, this._frame, waitUntil, timeout);
const error = await Promise.race([

@@ -243,7 +194,2 @@ watcher.timeoutOrTerminationPromise(),

throw new Error('Provide an object with a `url`, `path` or `content` property');
/**
* @param {string} url
* @param {string} type
* @return {!Promise<!HTMLElement>}
*/
async function addScriptUrl(url, type) {

@@ -262,7 +208,2 @@ const script = document.createElement('script');

}
/**
* @param {string} content
* @param {string} type
* @return {!HTMLElement}
*/
function addScriptContent(content, type = 'text/javascript') {

@@ -280,6 +221,2 @@ const script = document.createElement('script');

}
/**
* @param {!{url?: string, path?: string, content?: string}} options
* @return {!Promise<!ElementHandle>}
*/
async addStyleTag(options) {

@@ -307,6 +244,2 @@ const { url = null, path = null, content = null } = options;

throw new Error('Provide an object with a `url`, `path` or `content` property');
/**
* @param {string} url
* @return {!Promise<!HTMLElement>}
*/
async function addStyleUrl(url) {

@@ -324,6 +257,2 @@ const link = document.createElement('link');

}
/**
* @param {string} content
* @return {!Promise<!HTMLElement>}
*/
async function addStyleContent(content) {

@@ -342,38 +271,23 @@ const style = document.createElement('style');

}
/**
* @param {string} selector
* @param {!{delay?: number, button?: "left"|"right"|"middle", clickCount?: number}=} options
*/
async click(selector, options) {
const handle = await this.$(selector);
assert(handle, 'No node found for selector: ' + selector);
helper_1.assert(handle, 'No node found for selector: ' + selector);
await handle.click(options);
await handle.dispose();
}
/**
* @param {string} selector
*/
async focus(selector) {
const handle = await this.$(selector);
assert(handle, 'No node found for selector: ' + selector);
helper_1.assert(handle, 'No node found for selector: ' + selector);
await handle.focus();
await handle.dispose();
}
/**
* @param {string} selector
*/
async hover(selector) {
const handle = await this.$(selector);
assert(handle, 'No node found for selector: ' + selector);
helper_1.assert(handle, 'No node found for selector: ' + selector);
await handle.hover();
await handle.dispose();
}
/**
* @param {string} selector
* @param {!Array<string>} values
* @return {!Promise<!Array<string>>}
*/
async select(selector, ...values) {
const handle = await this.$(selector);
assert(handle, 'No node found for selector: ' + selector);
helper_1.assert(handle, 'No node found for selector: ' + selector);
const result = await handle.select(...values);

@@ -383,59 +297,27 @@ await handle.dispose();

}
/**
* @param {string} selector
*/
async tap(selector) {
const handle = await this.$(selector);
assert(handle, 'No node found for selector: ' + selector);
helper_1.assert(handle, 'No node found for selector: ' + selector);
await handle.tap();
await handle.dispose();
}
/**
* @param {string} selector
* @param {string} text
* @param {{delay: (number|undefined)}=} options
*/
async type(selector, text, options) {
const handle = await this.$(selector);
assert(handle, 'No node found for selector: ' + selector);
helper_1.assert(handle, 'No node found for selector: ' + selector);
await handle.type(text, options);
await handle.dispose();
}
/**
* @param {string} selector
* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<?ElementHandle>}
*/
waitForSelector(selector, options) {
return this._waitForSelectorOrXPath(selector, false, options);
}
/**
* @param {string} xpath
* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<?ElementHandle>}
*/
waitForXPath(xpath, options) {
return this._waitForSelectorOrXPath(xpath, true, options);
}
/**
* @param {Function|string} pageFunction
* @param {!{polling?: string|number, timeout?: number}=} options
* @return {!Promise<!JSHandle>}
*/
waitForFunction(pageFunction, options = {}, ...args) {
const { polling = 'raf', timeout = this._timeoutSettings.timeout(), } = options;
return new WaitTask(this, pageFunction, 'function', polling, timeout, ...args).promise;
return new WaitTask(this, pageFunction, undefined, 'function', polling, timeout, ...args).promise;
}
/**
* @return {!Promise<string>}
*/
async title() {
return this.evaluate(() => document.title);
}
/**
* @param {string} selectorOrXPath
* @param {boolean} isXPath
* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<?ElementHandle>}
*/
async _waitForSelectorOrXPath(selectorOrXPath, isXPath, options = {}) {

@@ -445,3 +327,4 @@ const { visible: waitForVisible = false, hidden: waitForHidden = false, timeout = this._timeoutSettings.timeout(), } = options;

const title = `${isXPath ? 'XPath' : 'selector'} "${selectorOrXPath}"${waitForHidden ? ' to be hidden' : ''}`;
const waitTask = new WaitTask(this, predicate, title, polling, timeout, selectorOrXPath, isXPath, waitForVisible, waitForHidden);
const { updatedSelector, queryHandler } = QueryHandler_1.getQueryHandlerAndSelector(selectorOrXPath, (element, selector) => document.querySelector(selector));
const waitTask = new WaitTask(this, predicate, queryHandler, title, polling, timeout, updatedSelector, isXPath, waitForVisible, waitForHidden);
const handle = await waitTask.promise;

@@ -463,3 +346,3 @@ if (!handle.asElement()) {

? document.evaluate(selectorOrXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue
: document.querySelector(selectorOrXPath);
: predicateQueryHandler ? predicateQueryHandler(document, selectorOrXPath) : document.querySelector(selectorOrXPath);
if (!node)

@@ -469,3 +352,3 @@ return waitForHidden;

return node;
const element = /** @type {Element} */ (node.nodeType === Node.TEXT_NODE ? node.parentElement : node);
const element = (node.nodeType === Node.TEXT_NODE ? node.parentElement : node);
const style = window.getComputedStyle(element);

@@ -475,5 +358,2 @@ const isVisible = style && style.visibility !== 'hidden' && hasVisibleBoundingBox();

return success ? node : null;
/**
* @return {boolean}
*/
function hasVisibleBoundingBox() {

@@ -486,21 +366,29 @@ const rect = element.getBoundingClientRect();

}
exports.DOMWorld = DOMWorld;
class WaitTask {
/**
* @param {!DOMWorld} domWorld
* @param {Function|string} predicateBody
* @param {string|number} polling
* @param {number} timeout
* @param {!Array<*>} args
*/
constructor(domWorld, predicateBody, title, polling, timeout, ...args) {
if (helper.isString(polling))
assert(polling === 'raf' || polling === 'mutation', 'Unknown polling option: ' + polling);
else if (helper.isNumber(polling))
assert(polling > 0, 'Cannot poll with non-positive interval: ' + polling);
constructor(domWorld, predicateBody, predicateQueryHandlerBody, title, polling, timeout, ...args) {
this._runCount = 0;
this._terminated = false;
if (helper_1.helper.isString(polling))
helper_1.assert(polling === 'raf' || polling === 'mutation', 'Unknown polling option: ' + polling);
else if (helper_1.helper.isNumber(polling))
helper_1.assert(polling > 0, 'Cannot poll with non-positive interval: ' + polling);
else
throw new Error('Unknown polling options: ' + polling);
function getPredicateBody(predicateBody, predicateQueryHandlerBody) {
if (helper_1.helper.isString(predicateBody))
return `return (${predicateBody});`;
if (predicateQueryHandlerBody) {
return `
return (function wrapper(args) {
const predicateQueryHandler = ${predicateQueryHandlerBody};
return (${predicateBody})(...args);
})(args);`;
}
return `return (${predicateBody})(...args);`;
}
this._domWorld = domWorld;
this._polling = polling;
this._timeout = timeout;
this._predicateBody = helper.isString(predicateBody) ? 'return (' + predicateBody + ')' : 'return (' + predicateBody + ')(...args)';
this._predicateBody = getPredicateBody(predicateBody, predicateQueryHandlerBody);
this._args = args;

@@ -516,3 +404,3 @@ this._runCount = 0;

if (timeout) {
const timeoutError = new TimeoutError(`waiting for ${title} failed: timeout ${timeout}ms exceeded`);
const timeoutError = new Errors_1.TimeoutError(`waiting for ${title} failed: timeout ${timeout}ms exceeded`);
this._timeoutTimer = setTimeout(() => this.terminate(timeoutError), timeout);

@@ -522,5 +410,2 @@ }

}
/**
* @param {!Error} error
*/
terminate(error) {

@@ -539,4 +424,4 @@ this._terminated = true;

}
catch (e) {
error = e;
catch (error_) {
error = error_;
}

@@ -551,3 +436,3 @@ if (this._terminated || runCount !== this._runCount) {

// throw an error - ignore this predicate run altogether.
if (!error && await this._domWorld.evaluate(s => !s, success).catch(e => true)) {
if (!error && await this._domWorld.evaluate(s => !s, success).catch(() => true)) {
await success.dispose();

@@ -573,11 +458,4 @@ return;

this._domWorld._waitTasks.delete(this);
this._runningTask = null;
}
}
/**
* @param {string} predicateBody
* @param {string} polling
* @param {number} timeout
* @return {!Promise<*>}
*/
async function waitForPredicatePageFunction(predicateBody, polling, timeout, ...args) {

@@ -598,3 +476,3 @@ const predicate = new Function('...args', predicateBody);

function pollMutation() {
const success = predicate.apply(null, args);
const success = predicate(...args);
if (success)

@@ -604,3 +482,3 @@ return Promise.resolve(success);

const result = new Promise(x => fulfill = x);
const observer = new MutationObserver(mutations => {
const observer = new MutationObserver(() => {
if (timedOut) {

@@ -610,3 +488,3 @@ observer.disconnect();

}
const success = predicate.apply(null, args);
const success = predicate(...args);
if (success) {

@@ -624,5 +502,2 @@ observer.disconnect();

}
/**
* @return {!Promise<*>}
*/
function pollRaf() {

@@ -638,3 +513,3 @@ let fulfill;

}
const success = predicate.apply(null, args);
const success = predicate(...args);
if (success)

@@ -646,6 +521,2 @@ fulfill(success);

}
/**
* @param {number} pollInterval
* @return {!Promise<*>}
*/
function pollInterval(pollInterval) {

@@ -661,3 +532,3 @@ let fulfill;

}
const success = predicate.apply(null, args);
const success = predicate(...args);
if (success)

@@ -670,2 +541,1 @@ fulfill(success);

}
module.exports = { DOMWorld };

@@ -1,32 +0,9 @@

/**
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Used as a TypeDef
// eslint-disable-next-line no-unused-vars
const { CDPSession } = require('./Connection');
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
class EmulationManager {
/**
* @param {!CDPSession} client
*/
constructor(client) {
this._client = client;
this._emulatingMobile = false;
this._hasTouch = false;
this._client = client;
}
/**
* @param {!Puppeteer.Viewport} viewport
* @return {Promise<boolean>}
*/
async emulateViewport(viewport) {

@@ -37,3 +14,2 @@ const mobile = viewport.isMobile || false;

const deviceScaleFactor = viewport.deviceScaleFactor || 1;
/** @type {Protocol.Emulation.ScreenOrientation} */
const screenOrientation = viewport.isLandscape ? { angle: 90, type: 'landscapePrimary' } : { angle: 0, type: 'portraitPrimary' };

@@ -53,2 +29,2 @@ const hasTouch = viewport.hasTouch || false;

}
module.exports = { EmulationManager };
exports.EmulationManager = EmulationManager;

@@ -28,1 +28,4 @@ "use strict";

exports.TimeoutError = TimeoutError;
exports.puppeteerErrors = {
TimeoutError,
};

@@ -60,3 +60,3 @@ "use strict";

}
catch (e1) {
catch (error) {
// This means we might have a function shorthand. Try another

@@ -71,3 +71,3 @@ // time prefixing 'function '.

}
catch (e2) {
catch (error) {
// We tried hard to serialize, but there's a weird beast here.

@@ -88,6 +88,6 @@ throw new Error('Passed function is not well-serializable!');

}
catch (err) {
if (err instanceof TypeError && err.message.startsWith('Converting circular structure to JSON'))
err.message += ' Are you passing a nested JSHandle?';
throw err;
catch (error) {
if (error instanceof TypeError && error.message.startsWith('Converting circular structure to JSON'))
error.message += ' Are you passing a nested JSHandle?';
throw error;
}

@@ -94,0 +94,0 @@ const { exceptionDetails, result: remoteObject } = await callFunctionOnPromise.catch(rewriteError);

@@ -0,1 +1,2 @@

"use strict";
/**

@@ -16,38 +17,21 @@ * Copyright 2017 Google Inc. All rights reserved.

*/
const EventEmitter = require('events');
const { helper, assert, debugError } = require('./helper');
const { Events } = require('./Events');
const { ExecutionContext, EVALUATION_SCRIPT_URL } = require('./ExecutionContext');
const { LifecycleWatcher } = require('./LifecycleWatcher');
const { DOMWorld } = require('./DOMWorld');
const { NetworkManager } = require('./NetworkManager');
// Used as a TypeDef
// eslint-disable-next-line no-unused-vars
const { TimeoutSettings } = require('./TimeoutSettings');
// Used as a TypeDef
// eslint-disable-next-line no-unused-vars
const { CDPSession } = require('./Connection');
// Used as a TypeDef
// eslint-disable-next-line no-unused-vars
const { JSHandle, ElementHandle } = require('./JSHandle');
Object.defineProperty(exports, "__esModule", { value: true });
const EventEmitter = require("events");
const helper_1 = require("./helper");
const Events_1 = require("./Events");
const ExecutionContext_1 = require("./ExecutionContext");
const LifecycleWatcher_1 = require("./LifecycleWatcher");
const DOMWorld_1 = require("./DOMWorld");
const NetworkManager_1 = require("./NetworkManager");
const UTILITY_WORLD_NAME = '__puppeteer_utility_world__';
class FrameManager extends EventEmitter {
/**
* @param {!CDPSession} client
* @param {!Puppeteer.Page} page
* @param {boolean} ignoreHTTPSErrors
* @param {!TimeoutSettings} timeoutSettings
*/
constructor(client, page, ignoreHTTPSErrors, timeoutSettings) {
super();
this._frames = new Map();
this._contextIdToContext = new Map();
this._isolatedWorlds = new Set();
this._client = client;
this._page = page;
this._networkManager = new NetworkManager(client, ignoreHTTPSErrors, this);
this._networkManager = new NetworkManager_1.NetworkManager(client, ignoreHTTPSErrors, this);
this._timeoutSettings = timeoutSettings;
/** @type {!Map<string, !Frame>} */
this._frames = new Map();
/** @type {!Map<number, !ExecutionContext>} */
this._contextIdToContext = new Map();
/** @type {!Set<string>} */
this._isolatedWorlds = new Set();
this._client.on('Page.frameAttached', event => this._onFrameAttached(event.frameId, event.parentFrameId));

@@ -60,3 +44,3 @@ this._client.on('Page.frameNavigated', event => this._onFrameNavigated(event.frame));

this._client.on('Runtime.executionContextDestroyed', event => this._onExecutionContextDestroyed(event.executionContextId));
this._client.on('Runtime.executionContextsCleared', event => this._onExecutionContextsCleared());
this._client.on('Runtime.executionContextsCleared', () => this._onExecutionContextsCleared());
this._client.on('Page.lifecycleEvent', event => this._onLifecycleEvent(event));

@@ -69,3 +53,3 @@ }

]);
const { frameTree } = /** @type Protocol.Page.getFrameTreeReturnValue*/ (result[1]);
const { frameTree } = result[1];
this._handleFrameTree(frameTree);

@@ -78,18 +62,9 @@ await Promise.all([

}
/**
* @return {!NetworkManager}
*/
networkManager() {
return this._networkManager;
}
/**
* @param {!Puppeteer.Frame} frame
* @param {string} url
* @param {!{referer?: string, timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}
*/
async navigateFrame(frame, url, options = {}) {
assertNoLegacyNavigationOptions(options);
const { referer = this._networkManager.extraHTTPHeaders()['referer'], waitUntil = ['load'], timeout = this._timeoutSettings.navigationTimeout(), } = options;
const watcher = new LifecycleWatcher(this, frame, waitUntil, timeout);
const watcher = new LifecycleWatcher_1.LifecycleWatcher(this, frame, waitUntil, timeout);
let ensureNewDocumentNavigation = false;

@@ -110,9 +85,2 @@ let error = await Promise.race([

return watcher.navigationResponse();
/**
* @param {!CDPSession} client
* @param {string} url
* @param {string} referrer
* @param {string} frameId
* @return {!Promise<?Error>}
*/
async function navigate(client, url, referrer, frameId) {

@@ -129,11 +97,6 @@ try {

}
/**
* @param {!Puppeteer.Frame} frame
* @param {!{timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}
*/
async waitForFrameNavigation(frame, options = {}) {
assertNoLegacyNavigationOptions(options);
const { waitUntil = ['load'], timeout = this._timeoutSettings.navigationTimeout(), } = options;
const watcher = new LifecycleWatcher(this, frame, waitUntil, timeout);
const watcher = new LifecycleWatcher_1.LifecycleWatcher(this, frame, waitUntil, timeout);
const error = await Promise.race([

@@ -149,5 +112,2 @@ watcher.timeoutOrTerminationPromise(),

}
/**
* @param {!Protocol.Page.lifecycleEventPayload} event
*/
_onLifecycleEvent(event) {

@@ -158,7 +118,4 @@ const frame = this._frames.get(event.frameId);

frame._onLifecycleEvent(event.loaderId, event.name);
this.emit(Events.FrameManager.LifecycleEvent, frame);
this.emit(Events_1.Events.FrameManager.LifecycleEvent, frame);
}
/**
* @param {string} frameId
*/
_onFrameStoppedLoading(frameId) {

@@ -169,7 +126,4 @@ const frame = this._frames.get(frameId);

frame._onLoadingStopped();
this.emit(Events.FrameManager.LifecycleEvent, frame);
this.emit(Events_1.Events.FrameManager.LifecycleEvent, frame);
}
/**
* @param {!Protocol.Page.FrameTree} frameTree
*/
_handleFrameTree(frameTree) {

@@ -184,47 +138,27 @@ if (frameTree.frame.parentId)

}
/**
* @return {!Puppeteer.Page}
*/
page() {
return this._page;
}
/**
* @return {!Frame}
*/
mainFrame() {
return this._mainFrame;
}
/**
* @return {!Array<!Frame>}
*/
frames() {
return Array.from(this._frames.values());
}
/**
* @param {!string} frameId
* @return {?Frame}
*/
frame(frameId) {
return this._frames.get(frameId) || null;
}
/**
* @param {string} frameId
* @param {?string} parentFrameId
*/
_onFrameAttached(frameId, parentFrameId) {
if (this._frames.has(frameId))
return;
assert(parentFrameId);
helper_1.assert(parentFrameId);
const parentFrame = this._frames.get(parentFrameId);
const frame = new Frame(this, this._client, parentFrame, frameId);
this._frames.set(frame._id, frame);
this.emit(Events.FrameManager.FrameAttached, frame);
this.emit(Events_1.Events.FrameManager.FrameAttached, frame);
}
/**
* @param {!Protocol.Page.Frame} framePayload
*/
_onFrameNavigated(framePayload) {
const isMainFrame = !framePayload.parentId;
let frame = isMainFrame ? this._mainFrame : this._frames.get(framePayload.id);
assert(isMainFrame || frame, 'We either navigate top level or have old version of the navigated frame');
helper_1.assert(isMainFrame || frame, 'We either navigate top level or have old version of the navigated frame');
// Detach all child frames first.

@@ -251,7 +185,4 @@ if (frame) {

frame._navigated(framePayload);
this.emit(Events.FrameManager.FrameNavigated, frame);
this.emit(Events_1.Events.FrameManager.FrameNavigated, frame);
}
/**
* @param {string} name
*/
async _ensureIsolatedWorld(name) {

@@ -262,3 +193,3 @@ if (this._isolatedWorlds.has(name))

await this._client.send('Page.addScriptToEvaluateOnNewDocument', {
source: `//# sourceURL=${EVALUATION_SCRIPT_URL}`,
source: `//# sourceURL=${ExecutionContext_1.EVALUATION_SCRIPT_URL}`,
worldName: name,

@@ -270,8 +201,4 @@ }),

worldName: name,
}).catch(debugError))); // frames might be removed before we send this
}).catch(helper_1.debugError))); // frames might be removed before we send this
}
/**
* @param {string} frameId
* @param {string} url
*/
_onFrameNavigatedWithinDocument(frameId, url) {

@@ -282,8 +209,5 @@ const frame = this._frames.get(frameId);

frame._navigatedWithinDocument(url);
this.emit(Events.FrameManager.FrameNavigatedWithinDocument, frame);
this.emit(Events.FrameManager.FrameNavigated, frame);
this.emit(Events_1.Events.FrameManager.FrameNavigatedWithinDocument, frame);
this.emit(Events_1.Events.FrameManager.FrameNavigated, frame);
}
/**
* @param {string} frameId
*/
_onFrameDetached(frameId) {

@@ -295,3 +219,4 @@ const frame = this._frames.get(frameId);

_onExecutionContextCreated(contextPayload) {
const frameId = contextPayload.auxData ? contextPayload.auxData.frameId : null;
const auxData = contextPayload.auxData;
const frameId = auxData ? auxData.frameId : null;
const frame = this._frames.get(frameId) || null;

@@ -312,4 +237,3 @@ let world = null;

this._isolatedWorlds.add(contextPayload.name);
/** @type {!ExecutionContext} */
const context = new ExecutionContext(this._client, contextPayload, world);
const context = new ExecutionContext_1.ExecutionContext(this._client, contextPayload, world);
if (world)

@@ -337,14 +261,7 @@ world._setContext(context);

}
/**
* @param {number} contextId
* @return {!ExecutionContext}
*/
executionContextById(contextId) {
const context = this._contextIdToContext.get(contextId);
assert(context, 'INTERNAL ERROR: missing context with id = ' + contextId);
helper_1.assert(context, 'INTERNAL ERROR: missing context with id = ' + contextId);
return context;
}
/**
* @param {!Frame} frame
*/
_removeFramesRecursively(frame) {

@@ -355,16 +272,12 @@ for (const child of frame.childFrames())

this._frames.delete(frame._id);
this.emit(Events.FrameManager.FrameDetached, frame);
this.emit(Events_1.Events.FrameManager.FrameDetached, frame);
}
}
/**
* @unrestricted
*/
exports.FrameManager = FrameManager;
class Frame {
/**
* @param {!FrameManager} frameManager
* @param {!CDPSession} client
* @param {?Frame} parentFrame
* @param {string} frameId
*/
constructor(frameManager, client, parentFrame, frameId) {
this._url = '';
this._detached = false;
this._loaderId = '';
this._lifecycleEvents = new Set();
this._frameManager = frameManager;

@@ -377,9 +290,4 @@ this._client = client;

this._loaderId = '';
/** @type {!Set<string>} */
this._lifecycleEvents = new Set();
/** @type {!DOMWorld} */
this._mainWorld = new DOMWorld(frameManager, this, frameManager._timeoutSettings);
/** @type {!DOMWorld} */
this._secondaryWorld = new DOMWorld(frameManager, this, frameManager._timeoutSettings);
/** @type {!Set<!Frame>} */
this._mainWorld = new DOMWorld_1.DOMWorld(frameManager, this, frameManager._timeoutSettings);
this._secondaryWorld = new DOMWorld_1.DOMWorld(frameManager, this, frameManager._timeoutSettings);
this._childFrames = new Set();

@@ -389,186 +297,81 @@ if (this._parentFrame)

}
/**
* @param {string} url
* @param {!{referer?: string, timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}
*/
async goto(url, options) {
return await this._frameManager.navigateFrame(this, url, options);
}
/**
* @param {!{timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}
*/
async waitForNavigation(options) {
return await this._frameManager.waitForFrameNavigation(this, options);
}
/**
* @return {!Promise<!ExecutionContext>}
*/
executionContext() {
return this._mainWorld.executionContext();
}
/**
* @param {Function|string} pageFunction
* @param {!Array<*>} args
* @return {!Promise<!JSHandle>}
*/
async evaluateHandle(pageFunction, ...args) {
return this._mainWorld.evaluateHandle(pageFunction, ...args);
}
/**
* @param {Function|string} pageFunction
* @param {!Array<*>} args
* @return {!Promise<*>}
*/
async evaluate(pageFunction, ...args) {
return this._mainWorld.evaluate(pageFunction, ...args);
}
/**
* @param {string} selector
* @return {!Promise<?ElementHandle>}
*/
async $(selector) {
return this._mainWorld.$(selector);
}
/**
* @param {string} expression
* @return {!Promise<!Array<!ElementHandle>>}
*/
async $x(expression) {
return this._mainWorld.$x(expression);
}
/**
* @param {string} selector
* @param {Function|string} pageFunction
* @param {!Array<*>} args
* @return {!Promise<(!Object|undefined)>}
*/
async $eval(selector, pageFunction, ...args) {
return this._mainWorld.$eval(selector, pageFunction, ...args);
}
/**
* @param {string} selector
* @param {Function|string} pageFunction
* @param {!Array<*>} args
* @return {!Promise<(!Object|undefined)>}
*/
async $$eval(selector, pageFunction, ...args) {
return this._mainWorld.$$eval(selector, pageFunction, ...args);
}
/**
* @param {string} selector
* @return {!Promise<!Array<!ElementHandle>>}
*/
async $$(selector) {
return this._mainWorld.$$(selector);
}
/**
* @return {!Promise<String>}
*/
async content() {
return this._secondaryWorld.content();
}
/**
* @param {string} html
* @param {!{timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
*/
async setContent(html, options = {}) {
return this._secondaryWorld.setContent(html, options);
}
/**
* @return {string}
*/
name() {
return this._name || '';
}
/**
* @return {string}
*/
url() {
return this._url;
}
/**
* @return {?Frame}
*/
parentFrame() {
return this._parentFrame;
}
/**
* @return {!Array.<!Frame>}
*/
childFrames() {
return Array.from(this._childFrames);
}
/**
* @return {boolean}
*/
isDetached() {
return this._detached;
}
/**
* @param {!{url?: string, path?: string, content?: string, type?: string}} options
* @return {!Promise<!ElementHandle>}
*/
async addScriptTag(options) {
return this._mainWorld.addScriptTag(options);
}
/**
* @param {!{url?: string, path?: string, content?: string}} options
* @return {!Promise<!ElementHandle>}
*/
async addStyleTag(options) {
return this._mainWorld.addStyleTag(options);
}
/**
* @param {string} selector
* @param {!{delay?: number, button?: "left"|"right"|"middle", clickCount?: number}=} options
*/
async click(selector, options) {
return this._secondaryWorld.click(selector, options);
}
/**
* @param {string} selector
*/
async focus(selector) {
return this._secondaryWorld.focus(selector);
}
/**
* @param {string} selector
*/
async hover(selector) {
return this._secondaryWorld.hover(selector);
}
/**
* @param {string} selector
* @param {!Array<string>} values
* @return {!Promise<!Array<string>>}
*/
select(selector, ...values) {
return this._secondaryWorld.select(selector, ...values);
}
/**
* @param {string} selector
*/
async tap(selector) {
return this._secondaryWorld.tap(selector);
}
/**
* @param {string} selector
* @param {string} text
* @param {{delay: (number|undefined)}=} options
*/
async type(selector, text, options) {
return this._mainWorld.type(selector, text, options);
}
/**
* @param {(string|number|Function)} selectorOrFunctionOrTimeout
* @param {!Object=} options
* @param {!Array<*>} args
* @return {!Promise<?JSHandle>}
*/
waitFor(selectorOrFunctionOrTimeout, options = {}, ...args) {
const xPathPattern = '//';
if (helper.isString(selectorOrFunctionOrTimeout)) {
const string = /** @type {string} */ (selectorOrFunctionOrTimeout);
if (helper_1.helper.isString(selectorOrFunctionOrTimeout)) {
const string = selectorOrFunctionOrTimeout;
if (string.startsWith(xPathPattern))

@@ -578,4 +381,4 @@ return this.waitForXPath(string, options);

}
if (helper.isNumber(selectorOrFunctionOrTimeout))
return new Promise(fulfill => setTimeout(fulfill, /** @type {number} */ (selectorOrFunctionOrTimeout)));
if (helper_1.helper.isNumber(selectorOrFunctionOrTimeout))
return new Promise(fulfill => setTimeout(fulfill, selectorOrFunctionOrTimeout));
if (typeof selectorOrFunctionOrTimeout === 'function')

@@ -585,7 +388,2 @@ return this.waitForFunction(selectorOrFunctionOrTimeout, options, ...args);

}
/**
* @param {string} selector
* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<?ElementHandle>}
*/
async waitForSelector(selector, options) {

@@ -600,7 +398,2 @@ const handle = await this._secondaryWorld.waitForSelector(selector, options);

}
/**
* @param {string} xpath
* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<?ElementHandle>}
*/
async waitForXPath(xpath, options) {

@@ -615,35 +408,15 @@ const handle = await this._secondaryWorld.waitForXPath(xpath, options);

}
/**
* @param {Function|string} pageFunction
* @param {!{polling?: string|number, timeout?: number}=} options
* @return {!Promise<!JSHandle>}
*/
waitForFunction(pageFunction, options = {}, ...args) {
return this._mainWorld.waitForFunction(pageFunction, options, ...args);
}
/**
* @return {!Promise<string>}
*/
async title() {
return this._secondaryWorld.title();
}
/**
* @param {!Protocol.Page.Frame} framePayload
*/
_navigated(framePayload) {
this._name = framePayload.name;
// TODO(lushnikov): remove this once requestInterception has loaderId exposed.
this._navigationURL = framePayload.url;
this._url = framePayload.url;
}
/**
* @param {string} url
*/
_navigatedWithinDocument(url) {
this._url = url;
}
/**
* @param {string} loaderId
* @param {string} name
*/
_onLifecycleEvent(loaderId, name) {

@@ -669,7 +442,7 @@ if (name === 'init') {

}
exports.Frame = Frame;
function assertNoLegacyNavigationOptions(options) {
assert(options['networkIdleTimeout'] === undefined, 'ERROR: networkIdleTimeout option is no longer supported.');
assert(options['networkIdleInflight'] === undefined, 'ERROR: networkIdleInflight option is no longer supported.');
assert(options.waitUntil !== 'networkidle', 'ERROR: "networkidle" option is no longer supported. Use "networkidle2" instead');
helper_1.assert(options['networkIdleTimeout'] === undefined, 'ERROR: networkIdleTimeout option is no longer supported.');
helper_1.assert(options['networkIdleInflight'] === undefined, 'ERROR: networkIdleInflight option is no longer supported.');
helper_1.assert(options.waitUntil !== 'networkidle', 'ERROR: "networkidle" option is no longer supported. Use "networkidle2" instead');
}
module.exports = { FrameManager, Frame };

@@ -83,8 +83,8 @@ "use strict";

Error.captureStackTrace(syncStack);
return method.call(this, ...args).catch(e => {
return method.call(this, ...args).catch(error => {
const stack = syncStack.stack.substring(syncStack.stack.indexOf('\n') + 1);
const clientStack = stack.substring(stack.indexOf('\n'));
if (e instanceof Error && e.stack && !e.stack.includes(clientStack))
e.stack += '\n -- ASYNC --\n' + stack;
throw e;
if (error instanceof Error && error.stack && !error.stack.includes(clientStack))
error.stack += '\n -- ASYNC --\n' + stack;
throw error;
});

@@ -132,5 +132,5 @@ });

return r;
}, e => {
}, error => {
cleanup();
throw e;
throw error;
});

@@ -137,0 +137,0 @@ if (result instanceof Error)

@@ -19,2 +19,3 @@ "use strict";

const helper_1 = require("./helper");
const QueryHandler_1 = require("./QueryHandler");
function createJSHandle(context, remoteObject) {

@@ -101,9 +102,2 @@ const frame = context.frame();

class ElementHandle extends JSHandle {
/**
* @param {!ExecutionContext} context
* @param {!CDPSession} client
* @param {!Protocol.Runtime.RemoteObject} remoteObject
* @param {!Puppeteer.Page} page
* @param {!Puppeteer.FrameManager} frameManager
*/
constructor(context, client, remoteObject, page, frameManager) {

@@ -199,8 +193,2 @@ super(context, client, remoteObject);

}
/**
* @param {!Array<{x: number, y: number}>} quad
* @param {number} width
* @param {number} height
* @return {!Array<{x: number, y: number}>}
*/
_intersectQuadWithViewport(quad, width, height) {

@@ -222,6 +210,2 @@ return quad.map(point => ({

}
/**
* @param {!Array<string>} values
* @return {!Promise<!Array<string>>}
*/
async select(...values) {

@@ -365,3 +349,5 @@ for (const value of values)

async $(selector) {
const handle = await this.evaluateHandle((element, selector) => element.querySelector(selector), selector);
const defaultHandler = (element, selector) => element.querySelector(selector);
const { updatedSelector, queryHandler } = QueryHandler_1.getQueryHandlerAndSelector(selector, defaultHandler);
const handle = await this.evaluateHandle(queryHandler, updatedSelector);
const element = handle.asElement();

@@ -373,8 +359,6 @@ if (element)

}
/**
* @param {string} selector
* @return {!Promise<!Array<!ElementHandle>>}
*/
async $$(selector) {
const arrayHandle = await this.evaluateHandle((element, selector) => element.querySelectorAll(selector), selector);
const defaultHandler = (element, selector) => element.querySelectorAll(selector);
const { updatedSelector, queryHandler } = QueryHandler_1.getQueryHandlerAndSelector(selector, defaultHandler);
const arrayHandle = await this.evaluateHandle(queryHandler, updatedSelector);
const properties = await arrayHandle.getProperties();

@@ -399,3 +383,5 @@ await arrayHandle.dispose();

async $$eval(selector, pageFunction, ...args) {
const arrayHandle = await this.evaluateHandle((element, selector) => Array.from(element.querySelectorAll(selector)), selector);
const defaultHandler = (element, selector) => Array.from(element.querySelectorAll(selector));
const { updatedSelector, queryHandler } = QueryHandler_1.getQueryHandlerAndSelector(selector, defaultHandler);
const arrayHandle = await this.evaluateHandle(queryHandler, updatedSelector);
const result = await arrayHandle.evaluate(pageFunction, ...args);

@@ -402,0 +388,0 @@ await arrayHandle.dispose();

@@ -0,1 +1,3 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**

@@ -16,32 +18,25 @@ * Copyright 2017 Google Inc. All rights reserved.

*/
const os = require('os');
const path = require('path');
const http = require('http');
const https = require('https');
const URL = require('url');
const removeFolder = require('rimraf');
const childProcess = require('child_process');
const { BrowserFetcher } = require('./BrowserFetcher');
const { Connection } = require('./Connection');
const { Browser } = require('./Browser');
const readline = require('readline');
const fs = require('fs');
const { helper, assert, debugError } = require('./helper');
const debugLauncher = require('debug')(`puppeteer:launcher`);
const { TimeoutError } = require('./Errors');
const { WebSocketTransport } = require('./WebSocketTransport');
const { PipeTransport } = require('./PipeTransport');
const mkdtempAsync = helper.promisify(fs.mkdtemp);
const removeFolderAsync = helper.promisify(removeFolder);
const writeFileAsync = helper.promisify(fs.writeFile);
const os = require("os");
const path = require("path");
const http = require("http");
const https = require("https");
const URL = require("url");
const fs = require("fs");
const readline = require("readline");
const debug = require("debug");
const removeFolder = require("rimraf");
const childProcess = require("child_process");
const BrowserFetcher_1 = require("./BrowserFetcher");
const Connection_1 = require("./Connection");
const Browser_1 = require("./Browser");
const helper_1 = require("./helper");
const Errors_1 = require("./Errors");
const WebSocketTransport_1 = require("./WebSocketTransport");
const PipeTransport_1 = require("./PipeTransport");
const mkdtempAsync = helper_1.helper.promisify(fs.mkdtemp);
const removeFolderAsync = helper_1.helper.promisify(removeFolder);
const writeFileAsync = helper_1.helper.promisify(fs.writeFile);
const debugLauncher = debug('puppeteer:launcher');
class BrowserRunner {
/**
* @param {string} executablePath
* @param {!Array<string>} processArguments
* @param {string=} tempDirectory
*/
constructor(executablePath, processArguments, tempDirectory) {
this._executablePath = executablePath;
this._processArguments = processArguments;
this._tempDirectory = tempDirectory;
this.proc = null;

@@ -51,9 +46,8 @@ this.connection = null;

this._listeners = [];
this._executablePath = executablePath;
this._processArguments = processArguments;
this._tempDirectory = tempDirectory;
}
/**
* @param {!(Launcher.LaunchOptions)=} options
*/
start(options = {}) {
const { handleSIGINT, handleSIGTERM, handleSIGHUP, dumpio, env, pipe } = options;
/** @type {!Array<"ignore"|"pipe">} */
let stdio = ['pipe', 'pipe', 'pipe'];

@@ -66,3 +60,3 @@ if (pipe) {

}
assert(!this.proc, 'This process has previously been started.');
helper_1.assert(!this.proc, 'This process has previously been started.');
debugLauncher(`Calling ${this._executablePath} ${this._processArguments.join(' ')}`);

@@ -82,3 +76,3 @@ this.proc = childProcess.spawn(this._executablePath, this._processArguments, {

this._closed = false;
this._processClosing = new Promise((fulfill, reject) => {
this._processClosing = new Promise(fulfill => {
this.proc.once('exit', () => {

@@ -90,3 +84,3 @@ this._closed = true;

.then(() => fulfill())
.catch(err => console.error(err));
.catch(error => console.error(error));
}

@@ -98,17 +92,14 @@ else {

});
this._listeners = [helper.addEventListener(process, 'exit', this.kill.bind(this))];
this._listeners = [helper_1.helper.addEventListener(process, 'exit', this.kill.bind(this))];
if (handleSIGINT)
this._listeners.push(helper.addEventListener(process, 'SIGINT', () => { this.kill(); process.exit(130); }));
this._listeners.push(helper_1.helper.addEventListener(process, 'SIGINT', () => { this.kill(); process.exit(130); }));
if (handleSIGTERM)
this._listeners.push(helper.addEventListener(process, 'SIGTERM', this.close.bind(this)));
this._listeners.push(helper_1.helper.addEventListener(process, 'SIGTERM', this.close.bind(this)));
if (handleSIGHUP)
this._listeners.push(helper.addEventListener(process, 'SIGHUP', this.close.bind(this)));
this._listeners.push(helper_1.helper.addEventListener(process, 'SIGHUP', this.close.bind(this)));
}
/**
* @return {Promise}
*/
close() {
if (this._closed)
return Promise.resolve();
helper.removeEventListeners(this._listeners);
helper_1.helper.removeEventListeners(this._listeners);
if (this._tempDirectory) {

@@ -120,3 +111,3 @@ this.kill();

this.connection.send('Browser.close').catch(error => {
debugError(error);
helper_1.debugError(error);
this.kill();

@@ -127,5 +118,4 @@ });

}
// This function has to be sync to be used as 'exit' event handler.
kill() {
helper.removeEventListeners(this._listeners);
helper_1.helper.removeEventListeners(this._listeners);
if (this.proc && this.proc.pid && !this.proc.killed && !this._closed) {

@@ -157,10 +147,10 @@ try {

const browserWSEndpoint = await waitForWSEndpoint(this.proc, timeout, preferredRevision);
const transport = await WebSocketTransport.create(browserWSEndpoint);
this.connection = new Connection(browserWSEndpoint, transport, slowMo);
const transport = await WebSocketTransport_1.WebSocketTransport.create(browserWSEndpoint);
this.connection = new Connection_1.Connection(browserWSEndpoint, transport, slowMo);
}
else {
// stdio was assigned during start(), and the 'pipe' option there adds the 4th and 5th items to stdio array
const { 3: pipeWrite, 4: pipeRead } = /** @type {!Array<any>} */ (this.proc.stdio);
const transport = new PipeTransport(/** @type {!NodeJS.WritableStream} */ pipeWrite, /** @type {!NodeJS.ReadableStream} */ pipeRead);
this.connection = new Connection('', transport, slowMo);
const { 3: pipeWrite, 4: pipeRead } = this.proc.stdio;
const transport = new PipeTransport_1.PipeTransport(pipeWrite, pipeRead);
this.connection = new Connection_1.Connection('', transport, slowMo);
}

@@ -170,11 +160,3 @@ return this.connection;

}
/**
* @implements {!Puppeteer.ProductLauncher}
*/
class ChromeLauncher {
/**
* @param {string} projectRoot
* @param {string} preferredRevision
* @param {boolean} isPuppeteerCore
*/
constructor(projectRoot, preferredRevision, isPuppeteerCore) {

@@ -185,6 +167,2 @@ this._projectRoot = projectRoot;

}
/**
* @param {!(Launcher.LaunchOptions & Launcher.ChromeArgOptions & Launcher.BrowserOptions)=} options
* @return {!Promise<!Browser>}
*/
async launch(options = {}) {

@@ -219,3 +197,3 @@ const { ignoreDefaultArgs = false, args = [], dumpio = false, executablePath = null, pipe = false, env = process.env, handleSIGINT = true, handleSIGTERM = true, handleSIGHUP = true, ignoreHTTPSErrors = false, defaultViewport = { width: 800, height: 600 }, slowMo = 0, timeout = 30000 } = options;

const connection = await runner.setupConnection({ usePipe, timeout, slowMo, preferredRevision: this._preferredRevision });
const browser = await Browser.create(connection, [], ignoreHTTPSErrors, defaultViewport, runner.proc, runner.close.bind(runner));
const browser = await Browser_1.Browser.create(connection, [], ignoreHTTPSErrors, defaultViewport, runner.proc, runner.close.bind(runner));
await browser.waitForTarget(t => t.type() === 'page');

@@ -272,47 +250,29 @@ return browser;

}
/**
* @return {string}
*/
executablePath() {
return resolveExecutablePath(this).executablePath;
}
/**
* @return {string}
*/
get product() {
return 'chrome';
}
/**
* @param {!(Launcher.BrowserOptions & {browserWSEndpoint?: string, browserURL?: string, transport?: !Puppeteer.ConnectionTransport})} options
* @return {!Promise<!Browser>}
*/
async connect(options) {
const { browserWSEndpoint, browserURL, ignoreHTTPSErrors = false, defaultViewport = { width: 800, height: 600 }, transport, slowMo = 0, } = options;
assert(Number(!!browserWSEndpoint) + Number(!!browserURL) + Number(!!transport) === 1, 'Exactly one of browserWSEndpoint, browserURL or transport must be passed to puppeteer.connect');
helper_1.assert(Number(!!browserWSEndpoint) + Number(!!browserURL) + Number(!!transport) === 1, 'Exactly one of browserWSEndpoint, browserURL or transport must be passed to puppeteer.connect');
let connection = null;
if (transport) {
connection = new Connection('', transport, slowMo);
connection = new Connection_1.Connection('', transport, slowMo);
}
else if (browserWSEndpoint) {
const connectionTransport = await WebSocketTransport.create(browserWSEndpoint);
connection = new Connection(browserWSEndpoint, connectionTransport, slowMo);
const connectionTransport = await WebSocketTransport_1.WebSocketTransport.create(browserWSEndpoint);
connection = new Connection_1.Connection(browserWSEndpoint, connectionTransport, slowMo);
}
else if (browserURL) {
const connectionURL = await getWSEndpoint(browserURL);
const connectionTransport = await WebSocketTransport.create(connectionURL);
connection = new Connection(connectionURL, connectionTransport, slowMo);
const connectionTransport = await WebSocketTransport_1.WebSocketTransport.create(connectionURL);
connection = new Connection_1.Connection(connectionURL, connectionTransport, slowMo);
}
const { browserContextIds } = await connection.send('Target.getBrowserContexts');
return Browser.create(connection, browserContextIds, ignoreHTTPSErrors, defaultViewport, null, () => connection.send('Browser.close').catch(debugError));
return Browser_1.Browser.create(connection, browserContextIds, ignoreHTTPSErrors, defaultViewport, null, () => connection.send('Browser.close').catch(helper_1.debugError));
}
}
/**
* @implements {!Puppeteer.ProductLauncher}
*/
class FirefoxLauncher {
/**
* @param {string} projectRoot
* @param {string} preferredRevision
* @param {boolean} isPuppeteerCore
*/
constructor(projectRoot, preferredRevision, isPuppeteerCore) {

@@ -323,6 +283,2 @@ this._projectRoot = projectRoot;

}
/**
* @param {!(Launcher.LaunchOptions & Launcher.ChromeArgOptions & Launcher.BrowserOptions & {extraPrefsFirefox?: !object})=} options
* @return {!Promise<!Browser>}
*/
async launch(options = {}) {

@@ -357,3 +313,3 @@ const { ignoreDefaultArgs = false, args = [], dumpio = false, executablePath = null, pipe = false, env = process.env, handleSIGINT = true, handleSIGTERM = true, handleSIGHUP = true, ignoreHTTPSErrors = false, defaultViewport = { width: 800, height: 600 }, slowMo = 0, timeout = 30000, extraPrefsFirefox = {} } = options;

const connection = await runner.setupConnection({ usePipe: pipe, timeout, slowMo, preferredRevision: this._preferredRevision });
const browser = await Browser.create(connection, [], ignoreHTTPSErrors, defaultViewport, runner.proc, runner.close.bind(runner));
const browser = await Browser_1.Browser.create(connection, [], ignoreHTTPSErrors, defaultViewport, runner.proc, runner.close.bind(runner));
await browser.waitForTarget(t => t.type() === 'page');

@@ -367,28 +323,21 @@ return browser;

}
/**
* @param {!(Launcher.BrowserOptions & {browserWSEndpoint?: string, browserURL?: string, transport?: !Puppeteer.ConnectionTransport})} options
* @return {!Promise<!Browser>}
*/
async connect(options) {
const { browserWSEndpoint, browserURL, ignoreHTTPSErrors = false, defaultViewport = { width: 800, height: 600 }, transport, slowMo = 0, } = options;
assert(Number(!!browserWSEndpoint) + Number(!!browserURL) + Number(!!transport) === 1, 'Exactly one of browserWSEndpoint, browserURL or transport must be passed to puppeteer.connect');
helper_1.assert(Number(!!browserWSEndpoint) + Number(!!browserURL) + Number(!!transport) === 1, 'Exactly one of browserWSEndpoint, browserURL or transport must be passed to puppeteer.connect');
let connection = null;
if (transport) {
connection = new Connection('', transport, slowMo);
connection = new Connection_1.Connection('', transport, slowMo);
}
else if (browserWSEndpoint) {
const connectionTransport = await WebSocketTransport.create(browserWSEndpoint);
connection = new Connection(browserWSEndpoint, connectionTransport, slowMo);
const connectionTransport = await WebSocketTransport_1.WebSocketTransport.create(browserWSEndpoint);
connection = new Connection_1.Connection(browserWSEndpoint, connectionTransport, slowMo);
}
else if (browserURL) {
const connectionURL = await getWSEndpoint(browserURL);
const connectionTransport = await WebSocketTransport.create(connectionURL);
connection = new Connection(connectionURL, connectionTransport, slowMo);
const connectionTransport = await WebSocketTransport_1.WebSocketTransport.create(connectionURL);
connection = new Connection_1.Connection(connectionURL, connectionTransport, slowMo);
}
const { browserContextIds } = await connection.send('Target.getBrowserContexts');
return Browser.create(connection, browserContextIds, ignoreHTTPSErrors, defaultViewport, null, () => connection.send('Browser.close').catch(debugError));
return Browser_1.Browser.create(connection, browserContextIds, ignoreHTTPSErrors, defaultViewport, null, () => connection.send('Browser.close').catch(helper_1.debugError));
}
/**
* @return {string}
*/
executablePath() {

@@ -400,3 +349,3 @@ return resolveExecutablePath(this).executablePath;

if (this._preferredRevision === 'latest') {
const browserFetcher = new BrowserFetcher(this._projectRoot, { product: this.product });
const browserFetcher = new BrowserFetcher_1.BrowserFetcher(this._projectRoot, { product: this.product });
const localRevisions = await browserFetcher.localRevisions();

@@ -407,12 +356,5 @@ if (localRevisions[0])

}
/**
* @return {string}
*/
get product() {
return 'firefox';
}
/**
* @param {!Launcher.ChromeArgOptions=} options
* @return {!Array<string>}
*/
defaultArgs(options = {}) {

@@ -437,6 +379,2 @@ const firefoxArguments = [

}
/**
* @param {!Object=} extraPrefs
* @return {!Promise<string>}
*/
async _createProfile(extraPrefs) {

@@ -612,8 +550,2 @@ const profilePath = await mkdtempAsync(path.join(os.tmpdir(), 'puppeteer_dev_firefox_profile-'));

}
/**
* @param {!Puppeteer.ChildProcess} browserProcess
* @param {number} timeout
* @param {string} preferredRevision
* @return {!Promise<string>}
*/
function waitForWSEndpoint(browserProcess, timeout, preferredRevision) {

@@ -624,6 +556,6 @@ return new Promise((resolve, reject) => {

const listeners = [
helper.addEventListener(rl, 'line', onLine),
helper.addEventListener(rl, 'close', () => onClose()),
helper.addEventListener(browserProcess, 'exit', () => onClose()),
helper.addEventListener(browserProcess, 'error', error => onClose(error))
helper_1.helper.addEventListener(rl, 'line', onLine),
helper_1.helper.addEventListener(rl, 'close', () => onClose()),
helper_1.helper.addEventListener(browserProcess, 'exit', () => onClose()),
helper_1.helper.addEventListener(browserProcess, 'error', error => onClose(error))
];

@@ -646,7 +578,4 @@ const timeoutId = timeout ? setTimeout(onTimeout, timeout) : 0;

cleanup();
reject(new TimeoutError(`Timed out after ${timeout} ms while trying to connect to the browser! Only Chrome at revision r${preferredRevision} is guaranteed to work.`));
reject(new Errors_1.TimeoutError(`Timed out after ${timeout} ms while trying to connect to the browser! Only Chrome at revision r${preferredRevision} is guaranteed to work.`));
}
/**
* @param {string} line
*/
function onLine(line) {

@@ -663,10 +592,6 @@ stderr += line + '\n';

clearTimeout(timeoutId);
helper.removeEventListeners(listeners);
helper_1.helper.removeEventListeners(listeners);
}
});
}
/**
* @param {string} browserURL
* @return {!Promise<string>}
*/
function getWSEndpoint(browserURL) {

@@ -692,12 +617,7 @@ let resolve, reject;

request.end();
return promise.catch(e => {
e.message = `Failed to fetch browser webSocket url from ${endpointURL}: ` + e.message;
throw e;
return promise.catch(error => {
error.message = `Failed to fetch browser webSocket url from ${endpointURL}: ` + error.message;
throw error;
});
}
/**
* @param {ChromeLauncher|FirefoxLauncher} launcher
*
* @return {{executablePath: string, missingText: ?string}}
*/
function resolveExecutablePath(launcher) {

@@ -712,3 +632,3 @@ // puppeteer-core doesn't take into account PUPPETEER_* env variables.

}
const browserFetcher = new BrowserFetcher(launcher._projectRoot, { product: launcher.product });
const browserFetcher = new BrowserFetcher_1.BrowserFetcher(launcher._projectRoot, { product: launcher.product });
if (!launcher._isPuppeteerCore && launcher.product === 'chrome') {

@@ -726,9 +646,2 @@ const revision = process.env['PUPPETEER_CHROMIUM_REVISION'];

}
/**
* @param {string} projectRoot
* @param {string} preferredRevision
* @param {boolean} isPuppeteerCore
* @param {string=} product
* @return {!Puppeteer.ProductLauncher}
*/
function Launcher(projectRoot, preferredRevision, isPuppeteerCore, product) {

@@ -746,27 +659,2 @@ // puppeteer-core doesn't take into account PUPPETEER_* env variables.

}
/**
* @typedef {Object} Launcher.ChromeArgOptions
* @property {boolean=} headless
* @property {Array<string>=} args
* @property {string=} userDataDir
* @property {boolean=} devtools
*/
/**
* @typedef {Object} Launcher.LaunchOptions
* @property {string=} executablePath
* @property {boolean|Array<string>=} ignoreDefaultArgs
* @property {boolean=} handleSIGINT
* @property {boolean=} handleSIGTERM
* @property {boolean=} handleSIGHUP
* @property {number=} timeout
* @property {boolean=} dumpio
* @property {!Object<string, string | undefined>=} env
* @property {boolean=} pipe
*/
/**
* @typedef {Object} Launcher.BrowserOptions
* @property {boolean=} ignoreHTTPSErrors
* @property {(?Puppeteer.Viewport)=} defaultViewport
* @property {number=} slowMo
*/
module.exports = Launcher;
exports.default = Launcher;

@@ -42,3 +42,2 @@ "use strict";

this._timeout = timeout;
/** @type {?Puppeteer.Request} */
this._navigationRequest = null;

@@ -122,3 +121,3 @@ this._eventListeners = [

/**
* @param {!Puppeteer.Frame} frame
* @param {!Frame} frame
* @param {!Array<string>} expectedLifecycle

@@ -125,0 +124,0 @@ * @return {boolean}

@@ -0,1 +1,3 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**

@@ -16,28 +18,13 @@ * Copyright 2017 Google Inc. All rights reserved.

*/
const EventEmitter = require('events');
const { helper, assert, debugError } = require('./helper');
const { Events } = require('./Events');
// CDPSession is used only as a typedef
// eslint-disable-next-line no-unused-vars
const { CDPSession } = require('./Connection');
const EventEmitter = require("events");
const helper_1 = require("./helper");
const Events_1 = require("./Events");
class NetworkManager extends EventEmitter {
/**
* @param {!CDPSession} client
* @param {!Puppeteer.FrameManager} frameManager
*/
constructor(client, ignoreHTTPSErrors, frameManager) {
super();
this._client = client;
this._ignoreHTTPSErrors = ignoreHTTPSErrors;
this._frameManager = frameManager;
/** @type {!Map<string, !Request>} */
this._requestIdToRequest = new Map();
/** @type {!Map<string, !Protocol.Network.requestWillBeSentPayload>} */
this._requestIdToRequestWillBeSentEvent = new Map();
/** @type {!Object<string, string>} */
this._extraHTTPHeaders = {};
this._offline = false;
/** @type {?{username: string, password: string}} */
this._credentials = null;
/** @type {!Set<string>} */
this._attemptedAuthentications = new Set();

@@ -47,4 +34,6 @@ this._userRequestInterceptionEnabled = false;

this._userCacheDisabled = false;
/** @type {!Map<string, string>} */
this._requestIdToInterceptionId = new Map();
this._client = client;
this._ignoreHTTPSErrors = ignoreHTTPSErrors;
this._frameManager = frameManager;
this._client.on('Fetch.requestPaused', this._onRequestPaused.bind(this));

@@ -63,5 +52,2 @@ this._client.on('Fetch.authRequired', this._onAuthRequired.bind(this));

}
/**
* @param {?{username: string, password: string}} credentials
*/
async authenticate(credentials) {

@@ -71,5 +57,2 @@ this._credentials = credentials;

}
/**
* @param {!Object<string, string>} extraHTTPHeaders
*/
async setExtraHTTPHeaders(extraHTTPHeaders) {

@@ -79,3 +62,3 @@ this._extraHTTPHeaders = {};

const value = extraHTTPHeaders[key];
assert(helper.isString(value), `Expected value of header "${key}" to be String, but "${typeof value}" is found.`);
helper_1.assert(helper_1.helper.isString(value), `Expected value of header "${key}" to be String, but "${typeof value}" is found.`);
this._extraHTTPHeaders[key.toLowerCase()] = value;

@@ -85,11 +68,5 @@ }

}
/**
* @return {!Object<string, string>}
*/
extraHTTPHeaders() {
return Object.assign({}, this._extraHTTPHeaders);
}
/**
* @param {boolean} value
*/
async setOfflineMode(value) {

@@ -107,11 +84,5 @@ if (this._offline === value)

}
/**
* @param {string} userAgent
*/
async setUserAgent(userAgent) {
await this._client.send('Network.setUserAgentOverride', { userAgent });
}
/**
* @param {boolean} enabled
*/
async setCacheEnabled(enabled) {

@@ -121,5 +92,2 @@ this._userCacheDisabled = !enabled;

}
/**
* @param {boolean} value
*/
async setRequestInterception(value) {

@@ -155,5 +123,2 @@ this._userRequestInterceptionEnabled = value;

}
/**
* @param {!Protocol.Network.requestWillBeSentPayload} event
*/
_onRequestWillBeSent(event) {

@@ -179,3 +144,2 @@ // Request interception doesn't happen for data URLs with Network Service.

_onAuthRequired(event) {
/** @type {"Default"|"CancelAuth"|"ProvideCredentials"} */
let response = 'Default';

@@ -193,7 +157,4 @@ if (this._attemptedAuthentications.has(event.requestId)) {

authChallengeResponse: { response, username, password },
}).catch(debugError);
}).catch(helper_1.debugError);
}
/**
* @param {!Protocol.Fetch.requestPausedPayload} event
*/
_onRequestPaused(event) {

@@ -203,3 +164,3 @@ if (!this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled) {

requestId: event.requestId
}).catch(debugError);
}).catch(helper_1.debugError);
}

@@ -217,6 +178,2 @@ const requestId = event.networkId;

}
/**
* @param {!Protocol.Network.requestWillBeSentPayload} event
* @param {?string} interceptionId
*/
_onRequest(event, interceptionId) {

@@ -235,7 +192,4 @@ let redirectChain = [];

this._requestIdToRequest.set(event.requestId, request);
this.emit(Events.NetworkManager.Request, request);
this.emit(Events_1.Events.NetworkManager.Request, request);
}
/**
* @param {!Protocol.Network.requestServedFromCachePayload} event
*/
_onRequestServedFromCache(event) {

@@ -246,6 +200,2 @@ const request = this._requestIdToRequest.get(event.requestId);

}
/**
* @param {!Request} request
* @param {!Protocol.Network.Response} responsePayload
*/
_handleRequestRedirect(request, responsePayload) {

@@ -258,8 +208,5 @@ const response = new Response(this._client, request, responsePayload);

this._attemptedAuthentications.delete(request._interceptionId);
this.emit(Events.NetworkManager.Response, response);
this.emit(Events.NetworkManager.RequestFinished, request);
this.emit(Events_1.Events.NetworkManager.Response, response);
this.emit(Events_1.Events.NetworkManager.RequestFinished, request);
}
/**
* @param {!Protocol.Network.responseReceivedPayload} event
*/
_onResponseReceived(event) {

@@ -272,7 +219,4 @@ const request = this._requestIdToRequest.get(event.requestId);

request._response = response;
this.emit(Events.NetworkManager.Response, response);
this.emit(Events_1.Events.NetworkManager.Response, response);
}
/**
* @param {!Protocol.Network.loadingFinishedPayload} event
*/
_onLoadingFinished(event) {

@@ -290,7 +234,4 @@ const request = this._requestIdToRequest.get(event.requestId);

this._attemptedAuthentications.delete(request._interceptionId);
this.emit(Events.NetworkManager.RequestFinished, request);
this.emit(Events_1.Events.NetworkManager.RequestFinished, request);
}
/**
* @param {!Protocol.Network.loadingFailedPayload} event
*/
_onLoadingFailed(event) {

@@ -308,15 +249,13 @@ const request = this._requestIdToRequest.get(event.requestId);

this._attemptedAuthentications.delete(request._interceptionId);
this.emit(Events.NetworkManager.RequestFailed, request);
this.emit(Events_1.Events.NetworkManager.RequestFailed, request);
}
}
exports.NetworkManager = NetworkManager;
class Request {
/**
* @param {!CDPSession} client
* @param {?Puppeteer.Frame} frame
* @param {string} interceptionId
* @param {boolean} allowInterception
* @param {!Protocol.Network.requestWillBeSentPayload} event
* @param {!Array<!Request>} redirectChain
*/
constructor(client, frame, interceptionId, allowInterception, event, redirectChain) {
this._interceptionHandled = false;
this._response = null;
this._failureText = null;
this._headers = {};
this._fromMemoryCache = false;
this._client = client;

@@ -327,5 +266,2 @@ this._requestId = event.requestId;

this._allowInterception = allowInterception;
this._interceptionHandled = false;
this._response = null;
this._failureText = null;
this._url = event.request.url;

@@ -335,3 +271,2 @@ this._resourceType = event.type.toLowerCase();

this._postData = event.request.postData;
this._headers = {};
this._frame = frame;

@@ -341,55 +276,27 @@ this._redirectChain = redirectChain;

this._headers[key.toLowerCase()] = event.request.headers[key];
this._fromMemoryCache = false;
}
/**
* @return {string}
*/
url() {
return this._url;
}
/**
* @return {string}
*/
resourceType() {
return this._resourceType;
}
/**
* @return {string}
*/
method() {
return this._method;
}
/**
* @return {string|undefined}
*/
postData() {
return this._postData;
}
/**
* @return {!Object}
*/
headers() {
return this._headers;
}
/**
* @return {?Response}
*/
response() {
return this._response;
}
/**
* @return {?Puppeteer.Frame}
*/
frame() {
return this._frame;
}
/**
* @return {boolean}
*/
isNavigationRequest() {
return this._isNavigationRequest;
}
/**
* @return {!Array<!Request>}
*/
redirectChain() {

@@ -408,5 +315,2 @@ return this._redirectChain.slice();

}
/**
* @param {!{url?: string, method?:string, postData?: string, headers?: !Object}} overrides
*/
async continue(overrides = {}) {

@@ -416,4 +320,4 @@ // Request interception is not supported for data: urls.

return;
assert(this._allowInterception, 'Request Interception is not enabled!');
assert(!this._interceptionHandled, 'Request is already handled!');
helper_1.assert(this._allowInterception, 'Request Interception is not enabled!');
helper_1.assert(!this._interceptionHandled, 'Request is already handled!');
const { url, method, postData, headers } = overrides;

@@ -430,8 +334,5 @@ this._interceptionHandled = true;

// or the page was closed. We should tolerate these errors.
debugError(error);
helper_1.debugError(error);
});
}
/**
* @param {!{status: number, headers: Object, contentType: string, body: (string|Buffer)}} response
*/
async respond(response) {

@@ -441,7 +342,6 @@ // Mocking responses for dataURL requests is not currently supported.

return;
assert(this._allowInterception, 'Request Interception is not enabled!');
assert(!this._interceptionHandled, 'Request is already handled!');
helper_1.assert(this._allowInterception, 'Request Interception is not enabled!');
helper_1.assert(!this._interceptionHandled, 'Request is already handled!');
this._interceptionHandled = true;
const responseBody = response.body && helper.isString(response.body) ? Buffer.from(/** @type {string} */ (response.body)) : /** @type {?Buffer} */ (response.body || null);
/** @type {!Object<string, string>} */
const responseBody = response.body && helper_1.helper.isString(response.body) ? Buffer.from(response.body) : response.body || null;
const responseHeaders = {};

@@ -465,8 +365,5 @@ if (response.headers) {

// or the page was closed. We should tolerate these errors.
debugError(error);
helper_1.debugError(error);
});
}
/**
* @param {string=} errorCode
*/
async abort(errorCode = 'failed') {

@@ -477,5 +374,5 @@ // Request interception is not supported for data: urls.

const errorReason = errorReasons[errorCode];
assert(errorReason, 'Unknown error code: ' + errorCode);
assert(this._allowInterception, 'Request Interception is not enabled!');
assert(!this._interceptionHandled, 'Request is already handled!');
helper_1.assert(errorReason, 'Unknown error code: ' + errorCode);
helper_1.assert(this._allowInterception, 'Request Interception is not enabled!');
helper_1.assert(!this._interceptionHandled, 'Request is already handled!');
this._interceptionHandled = true;

@@ -488,6 +385,7 @@ await this._client.send('Fetch.failRequest', {

// or the page was closed. We should tolerate these errors.
debugError(error);
helper_1.debugError(error);
});
}
}
exports.Request = Request;
const errorReasons = {

@@ -510,11 +408,7 @@ 'aborted': 'Aborted',

class Response {
/**
* @param {!CDPSession} client
* @param {!Request} request
* @param {!Protocol.Network.Response} responsePayload
*/
constructor(client, request, responsePayload) {
this._contentPromise = null;
this._headers = {};
this._client = client;
this._request = request;
this._contentPromise = null;
this._bodyLoadedPromise = new Promise(fulfill => {

@@ -532,3 +426,2 @@ this._bodyLoadedPromiseFulfill = fulfill;

this._fromServiceWorker = !!responsePayload.fromServiceWorker;
this._headers = {};
for (const key of Object.keys(responsePayload.headers))

@@ -538,47 +431,23 @@ this._headers[key.toLowerCase()] = responsePayload.headers[key];

}
/**
* @return {{ip: string, port: number}}
*/
remoteAddress() {
return this._remoteAddress;
}
/**
* @return {string}
*/
url() {
return this._url;
}
/**
* @return {boolean}
*/
ok() {
return this._status === 0 || (this._status >= 200 && this._status <= 299);
}
/**
* @return {number}
*/
status() {
return this._status;
}
/**
* @return {string}
*/
statusText() {
return this._statusText;
}
/**
* @return {!Object}
*/
headers() {
return this._headers;
}
/**
* @return {?SecurityDetails}
*/
securityDetails() {
return this._securityDetails;
}
/**
* @return {!Promise<!Buffer>}
*/
buffer() {

@@ -597,5 +466,2 @@ if (!this._contentPromise) {

}
/**
* @return {!Promise<string>}
*/
async text() {

@@ -605,5 +471,2 @@ const content = await this.buffer();

}
/**
* @return {!Promise<!Object>}
*/
async json() {

@@ -613,23 +476,11 @@ const content = await this.text();

}
/**
* @return {!Request}
*/
request() {
return this._request;
}
/**
* @return {boolean}
*/
fromCache() {
return this._fromDiskCache || this._request._fromMemoryCache;
}
/**
* @return {boolean}
*/
fromServiceWorker() {
return this._fromServiceWorker;
}
/**
* @return {?Puppeteer.Frame}
*/
frame() {

@@ -639,40 +490,23 @@ return this._request.frame();

}
exports.Response = Response;
class SecurityDetails {
/**
* @param {!Protocol.Network.SecurityDetails} securityPayload
*/
constructor(securityPayload) {
this._subjectName = securityPayload['subjectName'];
this._issuer = securityPayload['issuer'];
this._validFrom = securityPayload['validFrom'];
this._validTo = securityPayload['validTo'];
this._protocol = securityPayload['protocol'];
this._subjectName = securityPayload.subjectName;
this._issuer = securityPayload.issuer;
this._validFrom = securityPayload.validFrom;
this._validTo = securityPayload.validTo;
this._protocol = securityPayload.protocol;
}
/**
* @return {string}
*/
subjectName() {
return this._subjectName;
}
/**
* @return {string}
*/
issuer() {
return this._issuer;
}
/**
* @return {number}
*/
validFrom() {
return this._validFrom;
}
/**
* @return {number}
*/
validTo() {
return this._validTo;
}
/**
* @return {string}
*/
protocol() {

@@ -682,6 +516,3 @@ return this._protocol;

}
/**
* @param {Object<string, string>} headers
* @return {!Array<{name: string, value: string}>}
*/
exports.SecurityDetails = SecurityDetails;
function headersArray(headers) {

@@ -761,2 +592,1 @@ const result = [];

};
module.exports = { Request, Response, NetworkManager, SecurityDetails };

@@ -0,1 +1,2 @@

"use strict";
/**

@@ -16,72 +17,55 @@ * Copyright 2017 Google Inc. All rights reserved.

*/
const fs = require('fs');
const EventEmitter = require('events');
const mime = require('mime');
const { Events } = require('./Events');
// CDPSession is used only as a typedef
// eslint-disable-next-line no-unused-vars
const { Connection, CDPSession } = require('./Connection');
const { Dialog } = require('./Dialog');
const { EmulationManager } = require('./EmulationManager');
const { FrameManager } = require('./FrameManager');
const { Keyboard, Mouse, Touchscreen } = require('./Input');
const { Tracing } = require('./Tracing');
const { helper, debugError, assert } = require('./helper');
const { Coverage } = require('./Coverage');
const { Worker: PuppeteerWorker } = require('./Worker');
// Import used as typedef
// eslint-disable-next-line no-unused-vars
const { createJSHandle, JSHandle, ElementHandle } = require('./JSHandle');
const { Accessibility } = require('./Accessibility');
const { TimeoutSettings } = require('./TimeoutSettings');
// This import is used as a TypeDef, but ESLint's rule doesn't
// understand that unfortunately.
// eslint-disable-next-line no-unused-vars
const { TaskQueue } = require('./TaskQueue');
const writeFileAsync = helper.promisify(fs.writeFile);
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs");
const EventEmitter = require("events");
const mime = require("mime");
const Events_1 = require("./Events");
const Connection_1 = require("./Connection");
const Dialog_1 = require("./Dialog");
const EmulationManager_1 = require("./EmulationManager");
const FrameManager_1 = require("./FrameManager");
const Input_1 = require("./Input");
const Tracing_1 = require("./Tracing");
const helper_1 = require("./helper");
const Coverage_1 = require("./Coverage");
const Worker_1 = require("./Worker");
const JSHandle_1 = require("./JSHandle");
const Accessibility_1 = require("./Accessibility");
const TimeoutSettings_1 = require("./TimeoutSettings");
const writeFileAsync = helper_1.helper.promisify(fs.writeFile);
const paperFormats = {
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 },
};
class Page extends EventEmitter {
/**
* @param {!CDPSession} client
* @param {!Puppeteer.Target} target
* @param {boolean} ignoreHTTPSErrors
* @param {?Puppeteer.Viewport} defaultViewport
* @param {!TaskQueue} screenshotTaskQueue
* @return {!Promise<!Page>}
*/
static async create(client, target, ignoreHTTPSErrors, defaultViewport, screenshotTaskQueue) {
const page = new Page(client, target, ignoreHTTPSErrors, screenshotTaskQueue);
await page._initialize();
if (defaultViewport)
await page.setViewport(defaultViewport);
return page;
}
/**
* @param {!CDPSession} client
* @param {!Puppeteer.Target} target
* @param {boolean} ignoreHTTPSErrors
* @param {!TaskQueue} screenshotTaskQueue
*/
constructor(client, target, ignoreHTTPSErrors, screenshotTaskQueue) {
super();
this._closed = false;
this._timeoutSettings = new TimeoutSettings_1.TimeoutSettings();
this._pageBindings = new Map();
this._javascriptEnabled = true;
this._workers = new Map();
// TODO: improve this typedef - it's a function that takes a file chooser or something?
this._fileChooserInterceptors = new Set();
this._client = client;
this._target = target;
this._keyboard = new Keyboard(client);
this._mouse = new Mouse(client, this._keyboard);
this._timeoutSettings = new TimeoutSettings();
this._touchscreen = new Touchscreen(client, this._keyboard);
this._accessibility = new Accessibility(client);
/** @type {!FrameManager} */
this._frameManager = new FrameManager(client, this, ignoreHTTPSErrors, this._timeoutSettings);
this._emulationManager = new EmulationManager(client);
this._tracing = new Tracing(client);
/** @type {!Map<string, Function>} */
this._pageBindings = new Map();
this._coverage = new Coverage(client);
this._javascriptEnabled = true;
/** @type {?Puppeteer.Viewport} */
this._keyboard = new Input_1.Keyboard(client);
this._mouse = new Input_1.Mouse(client, this._keyboard);
this._touchscreen = new Input_1.Touchscreen(client, this._keyboard);
this._accessibility = new Accessibility_1.Accessibility(client);
this._frameManager = new FrameManager_1.FrameManager(client, this, ignoreHTTPSErrors, this._timeoutSettings);
this._emulationManager = new EmulationManager_1.EmulationManager(client);
this._tracing = new Tracing_1.Tracing(client);
this._coverage = new Coverage_1.Coverage(client);
this._screenshotTaskQueue = screenshotTaskQueue;
this._viewport = null;
this._screenshotTaskQueue = screenshotTaskQueue;
/** @type {!Map<string, PuppeteerWorker>} */
this._workers = new Map();
client.on('Target.attachedToTarget', event => {

@@ -92,9 +76,9 @@ if (event.targetInfo.type !== 'worker') {

sessionId: event.sessionId
}).catch(debugError);
}).catch(helper_1.debugError);
return;
}
const session = Connection.fromSession(client).session(event.sessionId);
const worker = new PuppeteerWorker(session, event.targetInfo.url, this._addConsoleMessage.bind(this), this._handleException.bind(this));
const session = Connection_1.Connection.fromSession(client).session(event.sessionId);
const worker = new Worker_1.Worker(session, event.targetInfo.url, this._addConsoleMessage.bind(this), this._handleException.bind(this));
this._workers.set(event.sessionId, worker);
this.emit(Events.Page.WorkerCreated, worker);
this.emit(Events_1.Events.Page.WorkerCreated, worker);
});

@@ -105,16 +89,16 @@ client.on('Target.detachedFromTarget', event => {

return;
this.emit(Events.Page.WorkerDestroyed, worker);
this.emit(Events_1.Events.Page.WorkerDestroyed, worker);
this._workers.delete(event.sessionId);
});
this._frameManager.on(Events.FrameManager.FrameAttached, event => this.emit(Events.Page.FrameAttached, event));
this._frameManager.on(Events.FrameManager.FrameDetached, event => this.emit(Events.Page.FrameDetached, event));
this._frameManager.on(Events.FrameManager.FrameNavigated, event => this.emit(Events.Page.FrameNavigated, event));
this._frameManager.on(Events_1.Events.FrameManager.FrameAttached, event => this.emit(Events_1.Events.Page.FrameAttached, event));
this._frameManager.on(Events_1.Events.FrameManager.FrameDetached, event => this.emit(Events_1.Events.Page.FrameDetached, event));
this._frameManager.on(Events_1.Events.FrameManager.FrameNavigated, event => this.emit(Events_1.Events.Page.FrameNavigated, event));
const networkManager = this._frameManager.networkManager();
networkManager.on(Events.NetworkManager.Request, event => this.emit(Events.Page.Request, event));
networkManager.on(Events.NetworkManager.Response, event => this.emit(Events.Page.Response, event));
networkManager.on(Events.NetworkManager.RequestFailed, event => this.emit(Events.Page.RequestFailed, event));
networkManager.on(Events.NetworkManager.RequestFinished, event => this.emit(Events.Page.RequestFinished, event));
networkManager.on(Events_1.Events.NetworkManager.Request, event => this.emit(Events_1.Events.Page.Request, event));
networkManager.on(Events_1.Events.NetworkManager.Response, event => this.emit(Events_1.Events.Page.Response, event));
networkManager.on(Events_1.Events.NetworkManager.RequestFailed, event => this.emit(Events_1.Events.Page.RequestFailed, event));
networkManager.on(Events_1.Events.NetworkManager.RequestFinished, event => this.emit(Events_1.Events.Page.RequestFinished, event));
this._fileChooserInterceptors = new Set();
client.on('Page.domContentEventFired', event => this.emit(Events.Page.DOMContentLoaded));
client.on('Page.loadEventFired', event => this.emit(Events.Page.Load));
client.on('Page.domContentEventFired', () => this.emit(Events_1.Events.Page.DOMContentLoaded));
client.on('Page.loadEventFired', () => this.emit(Events_1.Events.Page.Load));
client.on('Runtime.consoleAPICalled', event => this._onConsoleAPI(event));

@@ -124,3 +108,3 @@ client.on('Runtime.bindingCalled', event => this._onBindingCalled(event));

client.on('Runtime.exceptionThrown', exception => this._handleException(exception.exceptionDetails));
client.on('Inspector.targetCrashed', event => this._onTargetCrashed());
client.on('Inspector.targetCrashed', () => this._onTargetCrashed());
client.on('Performance.metrics', event => this._emitMetrics(event));

@@ -130,6 +114,13 @@ client.on('Log.entryAdded', event => this._onLogEntryAdded(event));

this._target._isClosedPromise.then(() => {
this.emit(Events.Page.Close);
this.emit(Events_1.Events.Page.Close);
this._closed = true;
});
}
static async create(client, target, ignoreHTTPSErrors, defaultViewport, screenshotTaskQueue) {
const page = new Page(client, target, ignoreHTTPSErrors, screenshotTaskQueue);
await page._initialize();
if (defaultViewport)
await page.setViewport(defaultViewport);
return page;
}
async _initialize() {

@@ -143,5 +134,2 @@ await Promise.all([

}
/**
* @param {!Protocol.Page.fileChooserOpenedPayload} event
*/
async _onFileChooser(event) {

@@ -159,6 +147,2 @@ if (!this._fileChooserInterceptors.size)

}
/**
* @param {!{timeout?: number}=} options
* @return !Promise<!FileChooser>}
*/
async waitForFileChooser(options = {}) {

@@ -171,10 +155,7 @@ if (!this._fileChooserInterceptors.size)

this._fileChooserInterceptors.add(callback);
return helper.waitWithTimeout(promise, 'waiting for file chooser', timeout).catch(e => {
return helper_1.helper.waitWithTimeout(promise, 'waiting for file chooser', timeout).catch(error => {
this._fileChooserInterceptors.delete(callback);
throw e;
throw error;
});
}
/**
* @param {!{longitude: number, latitude: number, accuracy: (number|undefined)}} options
*/
async setGeolocation(options) {

@@ -190,17 +171,8 @@ const { longitude, latitude, accuracy = 0 } = options;

}
/**
* @return {!Puppeteer.Target}
*/
target() {
return this._target;
}
/**
* @return {!Puppeteer.Browser}
*/
browser() {
return this._target.browser();
}
/**
* @return {!Puppeteer.BrowserContext}
*/
browserContext() {

@@ -212,96 +184,48 @@ return this._target.browserContext();

}
/**
* @param {!Protocol.Log.entryAddedPayload} event
*/
_onLogEntryAdded(event) {
const { level, text, args, source, url, lineNumber } = event.entry;
if (args)
args.map(arg => helper.releaseObject(this._client, arg));
args.map(arg => helper_1.helper.releaseObject(this._client, arg));
if (source !== 'worker')
this.emit(Events.Page.Console, new ConsoleMessage(level, text, [], { url, lineNumber }));
this.emit(Events_1.Events.Page.Console, new ConsoleMessage(level, text, [], { url, lineNumber }));
}
/**
* @return {!Puppeteer.Frame}
*/
mainFrame() {
return this._frameManager.mainFrame();
}
/**
* @return {!Keyboard}
*/
get keyboard() {
return this._keyboard;
}
/**
* @return {!Touchscreen}
*/
get touchscreen() {
return this._touchscreen;
}
/**
* @return {!Coverage}
*/
get coverage() {
return this._coverage;
}
/**
* @return {!Tracing}
*/
get tracing() {
return this._tracing;
}
/**
* @return {!Accessibility}
*/
get accessibility() {
return this._accessibility;
}
/**
* @return {!Array<Puppeteer.Frame>}
*/
frames() {
return this._frameManager.frames();
}
/**
* @return {!Array<!PuppeteerWorker>}
*/
workers() {
return Array.from(this._workers.values());
}
/**
* @param {boolean} value
*/
async setRequestInterception(value) {
return this._frameManager.networkManager().setRequestInterception(value);
}
/**
* @param {boolean} enabled
*/
setOfflineMode(enabled) {
return this._frameManager.networkManager().setOfflineMode(enabled);
}
/**
* @param {number} timeout
*/
setDefaultNavigationTimeout(timeout) {
this._timeoutSettings.setDefaultNavigationTimeout(timeout);
}
/**
* @param {number} timeout
*/
setDefaultTimeout(timeout) {
this._timeoutSettings.setDefaultTimeout(timeout);
}
/**
* @param {string} selector
* @return {!Promise<?ElementHandle>}
*/
async $(selector) {
return this.mainFrame().$(selector);
}
/**
* @param {Function|string} pageFunction
* @param {!Array<*>} args
* @return {!Promise<!JSHandle>}
*/
async evaluateHandle(pageFunction, ...args) {

@@ -311,6 +235,2 @@ const context = await this.mainFrame().executionContext();

}
/**
* @param {!JSHandle} prototypeHandle
* @return {!Promise<!JSHandle>}
*/
async queryObjects(prototypeHandle) {

@@ -320,38 +240,14 @@ const context = await this.mainFrame().executionContext();

}
/**
* @param {string} selector
* @param {Function|string} pageFunction
* @param {!Array<*>} args
* @return {!Promise<(!Object|undefined)>}
*/
async $eval(selector, pageFunction, ...args) {
return this.mainFrame().$eval(selector, pageFunction, ...args);
}
/**
* @param {string} selector
* @param {Function|string} pageFunction
* @param {!Array<*>} args
* @return {!Promise<(!Object|undefined)>}
*/
async $$eval(selector, pageFunction, ...args) {
return this.mainFrame().$$eval(selector, pageFunction, ...args);
}
/**
* @param {string} selector
* @return {!Promise<!Array<!ElementHandle>>}
*/
async $$(selector) {
return this.mainFrame().$$(selector);
}
/**
* @param {string} expression
* @return {!Promise<!Array<!ElementHandle>>}
*/
async $x(expression) {
return this.mainFrame().$x(expression);
}
/**
* @param {!Array<string>} urls
* @return {!Promise<!Array<Network.Cookie>>}
*/
async cookies(...urls) {

@@ -362,3 +258,3 @@ const originalCookies = (await this._client.send('Network.getCookies', {

const unsupportedCookieAttributes = ['priority'];
const filterUnsupportedAttributes = cookie => {
const filterUnsupportedAttributes = (cookie) => {
for (const attr of unsupportedCookieAttributes)

@@ -370,5 +266,2 @@ delete cookie[attr];

}
/**
* @param {Array<Protocol.Network.deleteCookiesParameters>} cookies
*/
async deleteCookie(...cookies) {

@@ -383,5 +276,2 @@ const pageURL = this.url();

}
/**
* @param {Array<Network.CookieParam>} cookies
*/
async setCookie(...cookies) {

@@ -394,4 +284,4 @@ const pageURL = this.url();

item.url = pageURL;
assert(item.url !== 'about:blank', `Blank page can not have cookie "${item.name}"`);
assert(!String.prototype.startsWith.call(item.url || '', 'data:'), `Data URL page can not have cookie "${item.name}"`);
helper_1.assert(item.url !== 'about:blank', `Blank page can not have cookie "${item.name}"`);
helper_1.assert(!String.prototype.startsWith.call(item.url || '', 'data:'), `Data URL page can not have cookie "${item.name}"`);
return item;

@@ -403,20 +293,8 @@ });

}
/**
* @param {!{url?: string, path?: string, content?: string, type?: string}} options
* @return {!Promise<!ElementHandle>}
*/
async addScriptTag(options) {
return this.mainFrame().addScriptTag(options);
}
/**
* @param {!{url?: string, path?: string, content?: string}} options
* @return {!Promise<!ElementHandle>}
*/
async addStyleTag(options) {
return this.mainFrame().addStyleTag(options);
}
/**
* @param {string} name
* @param {Function} puppeteerFunction
*/
async exposeFunction(name, puppeteerFunction) {

@@ -426,9 +304,12 @@ if (this._pageBindings.has(name))

this._pageBindings.set(name, puppeteerFunction);
const expression = helper.evaluationString(addPageBinding, name);
const expression = helper_1.helper.evaluationString(addPageBinding, name);
await this._client.send('Runtime.addBinding', { name: name });
await this._client.send('Page.addScriptToEvaluateOnNewDocument', { source: expression });
await Promise.all(this.frames().map(frame => frame.evaluate(expression).catch(debugError)));
await Promise.all(this.frames().map(frame => frame.evaluate(expression).catch(helper_1.debugError)));
function addPageBinding(bindingName) {
const win = /** @type * */ (window);
const binding = /** @type function(string):* */ (win[bindingName]);
/* Cast window to any here as we're about to add properties to it
* via win[bindingName] which TypeScript doesn't like.
*/
const win = window;
const binding = win[bindingName];
win[bindingName] = (...args) => {

@@ -449,23 +330,11 @@ const me = window[bindingName];

}
/**
* @param {?{username: string, password: string}} credentials
*/
async authenticate(credentials) {
return this._frameManager.networkManager().authenticate(credentials);
}
/**
* @param {!Object<string, string>} headers
*/
async setExtraHTTPHeaders(headers) {
return this._frameManager.networkManager().setExtraHTTPHeaders(headers);
}
/**
* @param {string} userAgent
*/
async setUserAgent(userAgent) {
return this._frameManager.networkManager().setUserAgent(userAgent);
}
/**
* @return {!Promise<!Metrics>}
*/
async metrics() {

@@ -475,7 +344,4 @@ const response = await this._client.send('Performance.getMetrics');

}
/**
* @param {!Protocol.Performance.metricsPayload} event
*/
_emitMetrics(event) {
this.emit(Events.Page.Metrics, {
this.emit(Events_1.Events.Page.Metrics, {
title: event.title,

@@ -485,6 +351,2 @@ metrics: this._buildMetricsObject(event.metrics)

}
/**
* @param {?Array<!Protocol.Performance.Metric>} metrics
* @return {!Metrics}
*/
_buildMetricsObject(metrics) {

@@ -498,14 +360,8 @@ const result = {};

}
/**
* @param {!Protocol.Runtime.ExceptionDetails} exceptionDetails
*/
_handleException(exceptionDetails) {
const message = helper.getExceptionMessage(exceptionDetails);
const message = helper_1.helper.getExceptionMessage(exceptionDetails);
const err = new Error(message);
err.stack = ''; // Don't report clientside error with a node stack attached
this.emit(Events.Page.PageError, err);
this.emit(Events_1.Events.Page.PageError, err);
}
/**
* @param {!Protocol.Runtime.consoleAPICalledPayload} event
*/
async _onConsoleAPI(event) {

@@ -529,8 +385,5 @@ if (event.executionContextId === 0) {

const context = this._frameManager.executionContextById(event.executionContextId);
const values = event.args.map(arg => createJSHandle(context, arg));
const values = event.args.map(arg => JSHandle_1.createJSHandle(context, arg));
this._addConsoleMessage(event.type, values, event.stackTrace);
}
/**
* @param {!Protocol.Runtime.bindingCalledPayload} event
*/
async _onBindingCalled(event) {

@@ -541,16 +394,11 @@ const { name, seq, args } = JSON.parse(event.payload);

const result = await this._pageBindings.get(name)(...args);
expression = helper.evaluationString(deliverResult, name, seq, result);
expression = helper_1.helper.evaluationString(deliverResult, name, seq, result);
}
catch (error) {
if (error instanceof Error)
expression = helper.evaluationString(deliverError, name, seq, error.message, error.stack);
expression = helper_1.helper.evaluationString(deliverError, name, seq, error.message, error.stack);
else
expression = helper.evaluationString(deliverErrorValue, name, seq, error);
expression = helper_1.helper.evaluationString(deliverErrorValue, name, seq, error);
}
this._client.send('Runtime.evaluate', { expression, contextId: event.executionContextId }).catch(debugError);
/**
* @param {string} name
* @param {number} seq
* @param {*} result
*/
this._client.send('Runtime.evaluate', { expression, contextId: event.executionContextId }).catch(helper_1.debugError);
function deliverResult(name, seq, result) {

@@ -560,8 +408,2 @@ window[name]['callbacks'].get(seq).resolve(result);

}
/**
* @param {string} name
* @param {number} seq
* @param {string} message
* @param {string} stack
*/
function deliverError(name, seq, message, stack) {

@@ -573,7 +415,2 @@ const error = new Error(message);

}
/**
* @param {string} name
* @param {number} seq
* @param {*} value
*/
function deliverErrorValue(name, seq, value) {

@@ -584,9 +421,4 @@ window[name]['callbacks'].get(seq).reject(value);

}
/**
* @param {string} type
* @param {!Array<!JSHandle>} args
* @param {Protocol.Runtime.StackTrace=} stackTrace
*/
_addConsoleMessage(type, args, stackTrace) {
if (!this.listenerCount(Events.Page.Console)) {
if (!this.listenerCount(Events_1.Events.Page.Console)) {
args.forEach(arg => arg.dispose());

@@ -601,3 +433,3 @@ return;

else
textTokens.push(helper.valueFromRemoteObject(remoteObject));
textTokens.push(helper_1.helper.valueFromRemoteObject(remoteObject));
}

@@ -610,3 +442,3 @@ const location = stackTrace && stackTrace.callFrames.length ? {

const message = new ConsoleMessage(type, textTokens.join(' '), args, location);
this.emit(Events.Page.Console, message);
this.emit(Events_1.Events.Page.Console, message);
}

@@ -616,44 +448,25 @@ _onDialog(event) {

if (event.type === 'alert')
dialogType = Dialog.Type.Alert;
dialogType = Dialog_1.Dialog.Type.Alert;
else if (event.type === 'confirm')
dialogType = Dialog.Type.Confirm;
dialogType = Dialog_1.Dialog.Type.Confirm;
else if (event.type === 'prompt')
dialogType = Dialog.Type.Prompt;
dialogType = Dialog_1.Dialog.Type.Prompt;
else if (event.type === 'beforeunload')
dialogType = Dialog.Type.BeforeUnload;
assert(dialogType, 'Unknown javascript dialog type: ' + event.type);
const dialog = new Dialog(this._client, dialogType, event.message, event.defaultPrompt);
this.emit(Events.Page.Dialog, dialog);
dialogType = Dialog_1.Dialog.Type.BeforeUnload;
helper_1.assert(dialogType, 'Unknown javascript dialog type: ' + event.type);
const dialog = new Dialog_1.Dialog(this._client, dialogType, event.message, event.defaultPrompt);
this.emit(Events_1.Events.Page.Dialog, dialog);
}
/**
* @return {!string}
*/
url() {
return this.mainFrame().url();
}
/**
* @return {!Promise<string>}
*/
async content() {
return await this._frameManager.mainFrame().content();
}
/**
* @param {string} html
* @param {!{timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
*/
async setContent(html, options) {
await this._frameManager.mainFrame().setContent(html, options);
}
/**
* @param {string} url
* @param {!{referer?: string, timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}
*/
async goto(url, options) {
return await this._frameManager.mainFrame().goto(url, options);
}
/**
* @param {!{timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}
*/
async reload(options) {

@@ -664,9 +477,4 @@ const result = await Promise.all([

]);
const response = /** @type Puppeteer.Response */ (result[0]);
return response;
return result[0];
}
/**
* @param {!{timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}
*/
async waitForNavigation(options = {}) {

@@ -677,14 +485,9 @@ return await this._frameManager.mainFrame().waitForNavigation(options);

if (!this._disconnectPromise)
this._disconnectPromise = new Promise(fulfill => this._client.once(Events.CDPSession.Disconnected, () => fulfill(new Error('Target closed'))));
this._disconnectPromise = new Promise(fulfill => this._client.once(Events_1.Events.CDPSession.Disconnected, () => fulfill(new Error('Target closed'))));
return this._disconnectPromise;
}
/**
* @param {(string|Function)} urlOrPredicate
* @param {!{timeout?: number}=} options
* @return {!Promise<!Puppeteer.Request>}
*/
async waitForRequest(urlOrPredicate, options = {}) {
const { timeout = this._timeoutSettings.timeout(), } = options;
return helper.waitForEvent(this._frameManager.networkManager(), Events.NetworkManager.Request, request => {
if (helper.isString(urlOrPredicate))
return helper_1.helper.waitForEvent(this._frameManager.networkManager(), Events_1.Events.NetworkManager.Request, request => {
if (helper_1.helper.isString(urlOrPredicate))
return (urlOrPredicate === request.url());

@@ -696,11 +499,6 @@ if (typeof urlOrPredicate === 'function')

}
/**
* @param {(string|Function)} urlOrPredicate
* @param {!{timeout?: number}=} options
* @return {!Promise<!Puppeteer.Response>}
*/
async waitForResponse(urlOrPredicate, options = {}) {
const { timeout = this._timeoutSettings.timeout(), } = options;
return helper.waitForEvent(this._frameManager.networkManager(), Events.NetworkManager.Response, response => {
if (helper.isString(urlOrPredicate))
return helper_1.helper.waitForEvent(this._frameManager.networkManager(), Events_1.Events.NetworkManager.Response, response => {
if (helper_1.helper.isString(urlOrPredicate))
return (urlOrPredicate === response.url());

@@ -712,20 +510,8 @@ if (typeof urlOrPredicate === 'function')

}
/**
* @param {!{timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}
*/
async goBack(options) {
return this._go(-1, options);
}
/**
* @param {!{timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}
*/
async goForward(options) {
return this._go(+1, options);
}
/**
* @param {!{timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}
*/
async _go(delta, options) {

@@ -740,4 +526,3 @@ const history = await this._client.send('Page.getNavigationHistory');

]);
const response = /** @type Puppeteer.Response */ (result[0]);
return response;
return result[0];
}

@@ -747,5 +532,2 @@ async bringToFront() {

}
/**
* @param {!{viewport: !Puppeteer.Viewport, userAgent: string}} options
*/
async emulate(options) {

@@ -757,5 +539,2 @@ await Promise.all([

}
/**
* @param {boolean} enabled
*/
async setJavaScriptEnabled(enabled) {

@@ -767,18 +546,9 @@ if (this._javascriptEnabled === enabled)

}
/**
* @param {boolean} enabled
*/
async setBypassCSP(enabled) {
await this._client.send('Page.setBypassCSP', { enabled });
}
/**
* @param {?string} type
*/
async emulateMediaType(type) {
assert(type === 'screen' || type === 'print' || type === null, 'Unsupported media type: ' + type);
helper_1.assert(type === 'screen' || type === 'print' || type === null, 'Unsupported media type: ' + type);
await this._client.send('Emulation.setEmulatedMedia', { media: type || '' });
}
/**
* @param {?Array<MediaFeature>} features
*/
async emulateMediaFeatures(features) {

@@ -790,3 +560,3 @@ if (features === null)

const name = mediaFeature.name;
assert(/^prefers-(?:color-scheme|reduced-motion)$/.test(name), 'Unsupported media feature: ' + name);
helper_1.assert(/^prefers-(?:color-scheme|reduced-motion)$/.test(name), 'Unsupported media feature: ' + name);
return true;

@@ -797,5 +567,2 @@ });

}
/**
* @param {?string} timezoneId
*/
async emulateTimezone(timezoneId) {

@@ -805,11 +572,8 @@ try {

}
catch (exception) {
if (exception.message.includes('Invalid timezone'))
catch (error) {
if (error.message.includes('Invalid timezone'))
throw new Error(`Invalid timezone ID: ${timezoneId}`);
throw exception;
throw error;
}
}
/**
* @param {!Puppeteer.Viewport} viewport
*/
async setViewport(viewport) {

@@ -821,34 +585,15 @@ const needsReload = await this._emulationManager.emulateViewport(viewport);

}
/**
* @return {?Puppeteer.Viewport}
*/
viewport() {
return this._viewport;
}
/**
* @param {Function|string} pageFunction
* @param {!Array<*>} args
* @return {!Promise<*>}
*/
async evaluate(pageFunction, ...args) {
return this._frameManager.mainFrame().evaluate(pageFunction, ...args);
}
/**
* @param {Function|string} pageFunction
* @param {!Array<*>} args
*/
async evaluateOnNewDocument(pageFunction, ...args) {
const source = helper.evaluationString(pageFunction, ...args);
const source = helper_1.helper.evaluationString(pageFunction, ...args);
await this._client.send('Page.addScriptToEvaluateOnNewDocument', { source });
}
/**
* @param {boolean} enabled
*/
async setCacheEnabled(enabled = true) {
await this._frameManager.networkManager().setCacheEnabled(enabled);
}
/**
* @param {!ScreenshotOptions=} options
* @return {!Promise<!Buffer|!String>}
*/
async screenshot(options = {}) {

@@ -859,3 +604,3 @@ let screenshotType = null;

if (options.type) {
assert(options.type === 'png' || options.type === 'jpeg', 'Unknown options.type value: ' + options.type);
helper_1.assert(options.type === 'png' || options.type === 'jpeg', 'Unknown options.type value: ' + options.type);
screenshotType = options.type;

@@ -869,3 +614,3 @@ }

screenshotType = 'jpeg';
assert(screenshotType, 'Unsupported screenshot mime type: ' + mimeType);
helper_1.assert(screenshotType, 'Unsupported screenshot mime type: ' + mimeType);
}

@@ -875,23 +620,18 @@ if (!screenshotType)

if (options.quality) {
assert(screenshotType === 'jpeg', 'options.quality is unsupported for the ' + screenshotType + ' screenshots');
assert(typeof options.quality === 'number', 'Expected options.quality to be a number but found ' + (typeof options.quality));
assert(Number.isInteger(options.quality), 'Expected options.quality to be an integer');
assert(options.quality >= 0 && options.quality <= 100, 'Expected options.quality to be between 0 and 100 (inclusive), got ' + options.quality);
helper_1.assert(screenshotType === 'jpeg', 'options.quality is unsupported for the ' + screenshotType + ' screenshots');
helper_1.assert(typeof options.quality === 'number', 'Expected options.quality to be a number but found ' + (typeof options.quality));
helper_1.assert(Number.isInteger(options.quality), 'Expected options.quality to be an integer');
helper_1.assert(options.quality >= 0 && options.quality <= 100, 'Expected options.quality to be between 0 and 100 (inclusive), got ' + options.quality);
}
assert(!options.clip || !options.fullPage, 'options.clip and options.fullPage are exclusive');
helper_1.assert(!options.clip || !options.fullPage, 'options.clip and options.fullPage are exclusive');
if (options.clip) {
assert(typeof options.clip.x === 'number', 'Expected options.clip.x to be a number but found ' + (typeof options.clip.x));
assert(typeof options.clip.y === 'number', 'Expected options.clip.y to be a number but found ' + (typeof options.clip.y));
assert(typeof options.clip.width === 'number', 'Expected options.clip.width to be a number but found ' + (typeof options.clip.width));
assert(typeof options.clip.height === 'number', 'Expected options.clip.height to be a number but found ' + (typeof options.clip.height));
assert(options.clip.width !== 0, 'Expected options.clip.width not to be 0.');
assert(options.clip.height !== 0, 'Expected options.clip.height not to be 0.');
helper_1.assert(typeof options.clip.x === 'number', 'Expected options.clip.x to be a number but found ' + (typeof options.clip.x));
helper_1.assert(typeof options.clip.y === 'number', 'Expected options.clip.y to be a number but found ' + (typeof options.clip.y));
helper_1.assert(typeof options.clip.width === 'number', 'Expected options.clip.width to be a number but found ' + (typeof options.clip.width));
helper_1.assert(typeof options.clip.height === 'number', 'Expected options.clip.height to be a number but found ' + (typeof options.clip.height));
helper_1.assert(options.clip.width !== 0, 'Expected options.clip.width not to be 0.');
helper_1.assert(options.clip.height !== 0, 'Expected options.clip.height not to be 0.');
}
return this._screenshotTaskQueue.postTask(this._screenshotTask.bind(this, screenshotType, options));
}
/**
* @param {"png"|"jpeg"} format
* @param {!ScreenshotOptions=} options
* @return {!Promise<!Buffer|!String>}
*/
async _screenshotTask(format, options) {

@@ -907,3 +647,2 @@ await this._client.send('Target.activateTarget', { targetId: this._target._targetId });

const { isMobile = false, deviceScaleFactor = 1, isLandscape = false } = this._viewport || {};
/** @type {!Protocol.Emulation.ScreenOrientation} */
const screenOrientation = isLandscape ? { angle: 90, type: 'landscapePrimary' } : { angle: 0, type: 'portraitPrimary' };

@@ -932,6 +671,2 @@ await this._client.send('Emulation.setDeviceMetricsOverride', { mobile: isMobile, width, height, deviceScaleFactor, screenOrientation });

}
/**
* @param {!PDFOptions=} options
* @return {!Promise<!Buffer>}
*/
async pdf(options = {}) {

@@ -942,4 +677,4 @@ const { scale = 1, displayHeaderFooter = false, headerTemplate = '', footerTemplate = '', printBackground = false, landscape = false, pageRanges = '', preferCSSPageSize = false, margin = {}, path = null } = options;

if (options.format) {
const format = Page.PaperFormats[options.format.toLowerCase()];
assert(format, 'Unknown paper format: ' + options.format);
const format = paperFormats[options.format.toLowerCase()];
helper_1.assert(format, 'Unknown paper format: ' + options.format);
paperWidth = format.width;

@@ -973,15 +708,9 @@ paperHeight = format.height;

});
return await helper.readProtocolStream(this._client, result.stream, path);
return await helper_1.helper.readProtocolStream(this._client, result.stream, path);
}
/**
* @return {!Promise<string>}
*/
async title() {
return this.mainFrame().title();
}
/**
* @param {!{runBeforeUnload: (boolean|undefined)}=} options
*/
async close(options = { runBeforeUnload: undefined }) {
assert(!!this._client._connection, 'Protocol error: Connection closed. Most likely the page has been closed.');
helper_1.assert(!!this._client._connection, 'Protocol error: Connection closed. Most likely the page has been closed.');
const runBeforeUnload = !!options.runBeforeUnload;

@@ -996,86 +725,35 @@ if (runBeforeUnload) {

}
/**
* @return {boolean}
*/
isClosed() {
return this._closed;
}
/**
* @return {!Mouse}
*/
get mouse() {
return this._mouse;
}
/**
* @param {string} selector
* @param {!{delay?: number, button?: "left"|"right"|"middle", clickCount?: number}=} options
*/
click(selector, options = {}) {
return this.mainFrame().click(selector, options);
}
/**
* @param {string} selector
*/
focus(selector) {
return this.mainFrame().focus(selector);
}
/**
* @param {string} selector
*/
hover(selector) {
return this.mainFrame().hover(selector);
}
/**
* @param {string} selector
* @param {!Array<string>} values
* @return {!Promise<!Array<string>>}
*/
select(selector, ...values) {
return this.mainFrame().select(selector, ...values);
}
/**
* @param {string} selector
*/
tap(selector) {
return this.mainFrame().tap(selector);
}
/**
* @param {string} selector
* @param {string} text
* @param {{delay: (number|undefined)}=} options
*/
type(selector, text, options) {
return this.mainFrame().type(selector, text, options);
}
/**
* @param {(string|number|Function)} selectorOrFunctionOrTimeout
* @param {!{visible?: boolean, hidden?: boolean, timeout?: number, polling?: string|number}=} options
* @param {!Array<*>} args
* @return {!Promise<!JSHandle>}
*/
waitFor(selectorOrFunctionOrTimeout, options = {}, ...args) {
return this.mainFrame().waitFor(selectorOrFunctionOrTimeout, options, ...args);
}
/**
* @param {string} selector
* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<?ElementHandle>}
*/
waitForSelector(selector, options = {}) {
return this.mainFrame().waitForSelector(selector, options);
}
/**
* @param {string} xpath
* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<?ElementHandle>}
*/
waitForXPath(xpath, options = {}) {
return this.mainFrame().waitForXPath(xpath, options);
}
/**
* @param {Function} pageFunction
* @param {!{polling?: string|number, timeout?: number}=} options
* @param {!Array<*>} args
* @return {!Promise<!JSHandle>}
*/
waitForFunction(pageFunction, options = {}, ...args) {

@@ -1085,50 +763,3 @@ return this.mainFrame().waitForFunction(pageFunction, options, ...args);

}
/**
* @typedef {Object} PDFOptions
* @property {number=} scale
* @property {boolean=} displayHeaderFooter
* @property {string=} headerTemplate
* @property {string=} footerTemplate
* @property {boolean=} printBackground
* @property {boolean=} landscape
* @property {string=} pageRanges
* @property {string=} format
* @property {string|number=} width
* @property {string|number=} height
* @property {boolean=} preferCSSPageSize
* @property {!{top?: string|number, bottom?: string|number, left?: string|number, right?: string|number}=} margin
* @property {string=} path
*/
/**
* @typedef {Object} Metrics
* @property {number=} Timestamp
* @property {number=} Documents
* @property {number=} Frames
* @property {number=} JSEventListeners
* @property {number=} Nodes
* @property {number=} LayoutCount
* @property {number=} RecalcStyleCount
* @property {number=} LayoutDuration
* @property {number=} RecalcStyleDuration
* @property {number=} ScriptDuration
* @property {number=} TaskDuration
* @property {number=} JSHeapUsedSize
* @property {number=} JSHeapTotalSize
*/
/**
* @typedef {Object} ScreenshotOptions
* @property {string=} type
* @property {string=} path
* @property {boolean=} fullPage
* @property {{x: number, y: number, width: number, height: number}=} clip
* @property {number=} quality
* @property {boolean=} omitBackground
* @property {string=} encoding
*/
/**
* @typedef {Object} MediaFeature
* @property {string} name
* @property {string} value
*/
/** @type {!Set<string>} */
exports.Page = Page;
const supportedMetrics = new Set([

@@ -1149,16 +780,2 @@ 'Timestamp',

]);
/** @enum {!{width: number, height: number}} */
Page.PaperFormats = {
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 = {

@@ -1170,6 +787,2 @@ 'px': 1,

};
/**
* @param {(string|number|undefined)} parameter
* @return {(number|undefined)}
*/
function convertPrintParameterToInches(parameter) {

@@ -1179,7 +792,7 @@ if (typeof parameter === 'undefined')

let pixels;
if (helper.isNumber(parameter)) {
if (helper_1.helper.isNumber(parameter)) {
// Treat numbers as pixel values to be aligned with phantom's paperSize.
pixels = /** @type {number} */ (parameter);
}
else if (helper.isString(parameter)) {
else if (helper_1.helper.isString(parameter)) {
const text = /** @type {string} */ (parameter);

@@ -1198,3 +811,3 @@ let unit = text.substring(text.length - 2).toLowerCase();

const value = Number(valueText);
assert(!isNaN(value), 'Failed to parse parameter value: ' + text);
helper_1.assert(!isNaN(value), 'Failed to parse parameter value: ' + text);
pixels = value * unitToPixels[unit];

@@ -1207,40 +820,3 @@ }

}
/**
* @typedef {Object} Network.Cookie
* @property {string} name
* @property {string} value
* @property {string} domain
* @property {string} path
* @property {number} expires
* @property {number} size
* @property {boolean} httpOnly
* @property {boolean} secure
* @property {boolean} session
* @property {("Strict"|"Lax"|"Extended"|"None")=} sameSite
*/
/**
* @typedef {Object} Network.CookieParam
* @property {string} name
* @property {string} value
* @property {string=} url
* @property {string=} domain
* @property {string=} path
* @property {number=} expires
* @property {boolean=} httpOnly
* @property {boolean=} secure
* @property {("Strict"|"Lax")=} sameSite
*/
/**
* @typedef {Object} ConsoleMessage.Location
* @property {string=} url
* @property {number=} lineNumber
* @property {number=} columnNumber
*/
class ConsoleMessage {
/**
* @param {string} type
* @param {string} text
* @param {!Array<!JSHandle>} args
* @param {ConsoleMessage.Location} location
*/
constructor(type, text, args, location = {}) {

@@ -1252,23 +828,11 @@ this._type = type;

}
/**
* @return {string}
*/
type() {
return this._type;
}
/**
* @return {string}
*/
text() {
return this._text;
}
/**
* @return {!Array<!JSHandle>}
*/
args() {
return this._args;
}
/**
* @return {Object}
*/
location() {

@@ -1278,37 +842,23 @@ return this._location;

}
exports.ConsoleMessage = ConsoleMessage;
class FileChooser {
/**
* @param {CDPSession} client
* @param {ElementHandle} element
* @param {!Protocol.Page.fileChooserOpenedPayload} event
*/
constructor(client, element, event) {
this._handled = false;
this._client = client;
this._element = element;
this._multiple = event.mode !== 'selectSingle';
this._handled = false;
}
/**
* @return {boolean}
*/
isMultiple() {
return this._multiple;
}
/**
* @param {!Array<string>} filePaths
* @return {!Promise}
*/
async accept(filePaths) {
assert(!this._handled, 'Cannot accept FileChooser which is already handled!');
helper_1.assert(!this._handled, 'Cannot accept FileChooser which is already handled!');
this._handled = true;
await this._element.uploadFile(...filePaths);
}
/**
* @return {!Promise}
*/
async cancel() {
assert(!this._handled, 'Cannot cancel FileChooser which is already handled!');
helper_1.assert(!this._handled, 'Cannot cancel FileChooser which is already handled!');
this._handled = true;
}
}
module.exports = { Page, ConsoleMessage, FileChooser };
exports.FileChooser = FileChooser;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**

@@ -62,2 +63,2 @@ * Copyright 2018 Google Inc. All rights reserved.

}
module.exports = { PipeTransport };
exports.PipeTransport = PipeTransport;

@@ -0,1 +1,3 @@

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
/**

@@ -16,14 +18,10 @@ * Copyright 2017 Google Inc. All rights reserved.

*/
const Launcher = require('./Launcher');
const { BrowserFetcher } = require('./BrowserFetcher');
const Errors = require('./Errors');
const DeviceDescriptors = require('./DeviceDescriptors');
module.exports = class {
/**
* @param {string} projectRoot
* @param {string} preferredRevision
* @param {boolean} isPuppeteerCore
* @param {string} productName
*/
const Launcher_1 = require("./Launcher");
const BrowserFetcher_1 = require("./BrowserFetcher");
const Errors_1 = require("./Errors");
const DeviceDescriptors_1 = require("./DeviceDescriptors");
const QueryHandler = require("./QueryHandler");
class Puppeteer {
constructor(projectRoot, preferredRevision, isPuppeteerCore, productName) {
this._changedProduct = false;
this._projectRoot = projectRoot;

@@ -35,6 +33,2 @@ this._preferredRevision = preferredRevision;

}
/**
* @param {!(Launcher.LaunchOptions & Launcher.ChromeArgOptions & Launcher.BrowserOptions & {product?: string, extraPrefsFirefox?: !object})=} options
* @return {!Promise<!Puppeteer.Browser>}
*/
launch(options = {}) {

@@ -45,6 +39,2 @@ if (options.product)

}
/**
* @param {!(Launcher.BrowserOptions & {browserWSEndpoint?: string, browserURL?: string, transport?: !Puppeteer.ConnectionTransport}) & {product?: string}=} options
* @return {!Promise<!Puppeteer.Browser>}
*/
connect(options) {

@@ -55,5 +45,2 @@ if (options.product)

}
/**
* @param {string} name
*/
set _productName(name) {

@@ -64,20 +51,12 @@ if (this.__productName !== name)

}
/**
* @return {string}
*/
get _productName() {
return this.__productName;
}
/**
* @return {string}
*/
executablePath() {
return this._launcher.executablePath();
}
/**
* @return {!Puppeteer.ProductLauncher}
*/
get _launcher() {
if (!this._lazyLauncher || this._lazyLauncher.product !== this._productName || this._changedProduct) {
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-var-requires
const packageJson = require('../package.json');

@@ -93,48 +72,38 @@ switch (this._productName) {

this._changedProduct = false;
this._lazyLauncher = Launcher(this._projectRoot, this._preferredRevision, this._isPuppeteerCore, this._productName);
this._lazyLauncher = Launcher_1.default(this._projectRoot, this._preferredRevision, this._isPuppeteerCore, this._productName);
}
return this._lazyLauncher;
}
/**
* @return {string}
*/
get product() {
return this._launcher.product;
}
/**
* @return {Object}
*/
get devices() {
return DeviceDescriptors;
return DeviceDescriptors_1.devicesMap;
}
/**
* @return {Object}
*/
get errors() {
return Errors;
return Errors_1.puppeteerErrors;
}
/**
* @param {!Launcher.ChromeArgOptions=} options
* @return {!Array<string>}
*/
defaultArgs(options) {
return this._launcher.defaultArgs(options);
}
/** TODO(jacktfranklin@): Once this file is TS we can type this
* using the BrowserFectcherOptions interface.
*/
/**
* @typedef {Object} BrowserFetcherOptions
* @property {('linux'|'mac'|'win32'|'win64')=} platform
* @property {('chrome'|'firefox')=} product
* @property {string=} path
* @property {string=} host
*/
/**
* @param {!BrowserFetcherOptions} options
* @return {!BrowserFetcher}
*/
createBrowserFetcher(options) {
return new BrowserFetcher(this._projectRoot, options);
return new BrowserFetcher_1.BrowserFetcher(this._projectRoot, options);
}
};
// eslint-disable-next-line @typescript-eslint/camelcase
__experimental_registerCustomQueryHandler(name, queryHandler) {
QueryHandler.registerCustomQueryHandler(name, queryHandler);
}
// eslint-disable-next-line @typescript-eslint/camelcase
__experimental_unregisterCustomQueryHandler(name) {
QueryHandler.unregisterCustomQueryHandler(name);
}
// eslint-disable-next-line @typescript-eslint/camelcase
__experimental_customQueryHandlers() {
return QueryHandler.customQueryHandlers();
}
// eslint-disable-next-line @typescript-eslint/camelcase
__experimental_clearQueryHandlers() {
QueryHandler.clearQueryHandlers();
}
}
exports.Puppeteer = Puppeteer;

@@ -0,1 +1,2 @@

"use strict";
/**

@@ -16,21 +17,7 @@ * Copyright 2019 Google Inc. All rights reserved.

*/
const { Events } = require('./Events');
const { Page } = require('./Page');
const { Worker: PuppeteerWorker } = require('./Worker');
// CDPSession is used only as a typedef
// eslint-disable-next-line no-unused-vars
const { CDPSession } = require('./Connection');
// This import is used as a TypeDef, but ESLint's rule doesn't
// understand that unfortunately.
// eslint-disable-next-line no-unused-vars
const { TaskQueue } = require('./TaskQueue');
Object.defineProperty(exports, "__esModule", { value: true });
const Events_1 = require("./Events");
const Page_1 = require("./Page");
const Worker_1 = require("./Worker");
class Target {
/**
* @param {!Protocol.Target.TargetInfo} targetInfo
* @param {!Puppeteer.BrowserContext} browserContext
* @param {!function():!Promise<!CDPSession>} sessionFactory
* @param {boolean} ignoreHTTPSErrors
* @param {?Puppeteer.Viewport} defaultViewport
* @param {!TaskQueue} screenshotTaskQueue
*/
constructor(targetInfo, browserContext, sessionFactory, ignoreHTTPSErrors, defaultViewport, screenshotTaskQueue) {

@@ -55,6 +42,6 @@ this._targetInfo = targetInfo;

const openerPage = await opener._pagePromise;
if (!openerPage.listenerCount(Events.Page.Popup))
if (!openerPage.listenerCount(Events_1.Events.Page.Popup))
return true;
const popupPage = await this.page();
openerPage.emit(Events.Page.Popup, popupPage);
openerPage.emit(Events_1.Events.Page.Popup, popupPage);
return true;

@@ -67,21 +54,12 @@ });

}
/**
* @return {!Promise<!CDPSession>}
*/
createCDPSession() {
return this._sessionFactory();
}
/**
* @return {!Promise<?Page>}
*/
async page() {
if ((this._targetInfo.type === 'page' || this._targetInfo.type === 'background_page') && !this._pagePromise) {
this._pagePromise = this._sessionFactory()
.then(client => Page.create(client, this, this._ignoreHTTPSErrors, this._defaultViewport, this._screenshotTaskQueue));
.then(client => Page_1.Page.create(client, this, this._ignoreHTTPSErrors, this._defaultViewport, this._screenshotTaskQueue));
}
return this._pagePromise;
}
/**
* @return {!Promise<?PuppeteerWorker>}
*/
async worker() {

@@ -93,15 +71,9 @@ if (this._targetInfo.type !== 'service_worker' && this._targetInfo.type !== 'shared_worker')

this._workerPromise = this._sessionFactory()
.then(client => new PuppeteerWorker(client, this._targetInfo.url, () => { } /* consoleAPICalled */, () => { } /* exceptionThrown */));
.then(client => new Worker_1.Worker(client, this._targetInfo.url, () => { } /* consoleAPICalled */, () => { } /* exceptionThrown */));
}
return this._workerPromise;
}
/**
* @return {string}
*/
url() {
return this._targetInfo.url;
}
/**
* @return {"page"|"background_page"|"service_worker"|"shared_worker"|"other"|"browser"}
*/
type() {

@@ -113,17 +85,8 @@ const type = this._targetInfo.type;

}
/**
* @return {!Puppeteer.Browser}
*/
browser() {
return this._browserContext.browser();
}
/**
* @return {!Puppeteer.BrowserContext}
*/
browserContext() {
return this._browserContext;
}
/**
* @return {?Puppeteer.Target}
*/
opener() {

@@ -135,5 +98,2 @@ const { openerId } = this._targetInfo;

}
/**
* @param {!Protocol.Target.TargetInfo} targetInfo
*/
_targetInfoChanged(targetInfo) {

@@ -148,2 +108,2 @@ this._targetInfo = targetInfo;

}
module.exports = { Target };
exports.Target = Target;

@@ -17,2 +17,3 @@ "use strict";

*/
Object.defineProperty(exports, "__esModule", { value: true });
/* TODO(jacktfranklin@): once we are calling this from TS files we can

@@ -33,2 +34,2 @@ * avoid the horrible void | any type and instead make use of generics

}
module.exports = { TaskQueue };
exports.TaskQueue = TaskQueue;

@@ -17,2 +17,3 @@ "use strict";

*/
Object.defineProperty(exports, "__esModule", { value: true });
const DEFAULT_TIMEOUT = 30000;

@@ -46,2 +47,2 @@ class TimeoutSettings {

}
module.exports = { TimeoutSettings };
exports.TimeoutSettings = TimeoutSettings;
{
"name": "puppeteer-core",
"version": "3.0.2",
"version": "3.0.3",
"description": "A high-level API to control headless Chrome over the DevTools Protocol",

@@ -16,3 +16,4 @@ "main": "index.js",

"unit": "mocha --config mocha-config/puppeteer-unit-tests.js",
"coverage": "cross-env COVERAGE=1 npm run unit",
"unit-with-coverage": "cross-env COVERAGE=1 npm run unit",
"assert-unit-coverage": "cross-env COVERAGE=1 mocha --config mocha-config/coverage-tests.js",
"funit": "PUPPETEER_PRODUCT=firefox npm run unit",

@@ -28,6 +29,7 @@ "debug-unit": "node --inspect-brk test/test.js",

"doc": "node utils/doclint/cli.js",
"tsc": "tsc --version && tsc -p . && cp src/protocol.d.ts lib/ && cp src/externs.d.ts lib/",
"tsc": "tsc --version && tsc -p . && cp src/protocol.d.ts lib/",
"apply-next-version": "node utils/apply_next_version.js",
"test-types": "node utils/doclint/generate_types && tsc --version && tsc -p utils/doclint/generate_types/test/",
"update-protocol-d-ts": "node utils/protocol-types-generator",
"update-protocol-d-ts": "node utils/protocol-types-generator update",
"compare-protocol-d-ts": "node utils/protocol-types-generator compare",
"test-install": "scripts/test-install.sh"

@@ -72,2 +74,3 @@ },

"eslint-plugin-mocha": "^6.3.0",
"eslint-plugin-unicorn": "^19.0.1",
"esprima": "^4.0.0",

@@ -74,0 +77,0 @@ "expect": "^25.2.7",

@@ -9,3 +9,3 @@ # Puppeteer

###### [API](https://github.com/puppeteer/puppeteer/blob/v3.0.2/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/puppeteer/puppeteer/blob/master/CONTRIBUTING.md) | [Troubleshooting](https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md)
###### [API](https://github.com/puppeteer/puppeteer/blob/v3.0.3/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/puppeteer/puppeteer/blob/master/CONTRIBUTING.md) | [Troubleshooting](https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md)

@@ -41,3 +41,3 @@ > Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the [DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/). Puppeteer runs [headless](https://developers.google.com/web/updates/2017/04/headless-chrome) by default, but can be configured to run full (non-headless) Chrome or Chromium.

Note: When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API. To skip the download, or to download a different browser, see [Environment variables](https://github.com/puppeteer/puppeteer/blob/v3.0.2/docs/api.md#environment-variables).
Note: When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API. To skip the download, or to download a different browser, see [Environment variables](https://github.com/puppeteer/puppeteer/blob/v3.0.3/docs/api.md#environment-variables).

@@ -68,3 +68,3 @@

Puppeteer will be familiar to people using other browser testing frameworks. You create an instance
of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/puppeteer/puppeteer/blob/v3.0.2/docs/api.md#).
of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/puppeteer/puppeteer/blob/v3.0.3/docs/api.md#).

@@ -94,3 +94,3 @@ **Example** - navigating to https://example.com and saving a screenshot as *example.png*:

Puppeteer sets an initial page size to 800×600px, which defines the screenshot size. The page size can be customized with [`Page.setViewport()`](https://github.com/puppeteer/puppeteer/blob/v3.0.2/docs/api.md#pagesetviewportviewport).
Puppeteer sets an initial page size to 800×600px, which defines the screenshot size. The page size can be customized with [`Page.setViewport()`](https://github.com/puppeteer/puppeteer/blob/v3.0.3/docs/api.md#pagesetviewportviewport).

@@ -120,3 +120,3 @@ **Example** - create a PDF.

See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v3.0.2/docs/api.md#pagepdfoptions) for more information about creating pdfs.
See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v3.0.3/docs/api.md#pagepdfoptions) for more information about creating pdfs.

@@ -156,3 +156,3 @@ **Example** - evaluate script in the context of the page

See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v3.0.2/docs/api.md#pageevaluatepagefunction-args) for more information on `evaluate` and related methods like `evaluateOnNewDocument` and `exposeFunction`.
See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v3.0.3/docs/api.md#pageevaluatepagefunction-args) for more information on `evaluate` and related methods like `evaluateOnNewDocument` and `exposeFunction`.

@@ -166,3 +166,3 @@ <!-- [END getstarted] -->

Puppeteer launches Chromium in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). To launch a full version of Chromium, set the [`headless` option](https://github.com/puppeteer/puppeteer/blob/v3.0.2/docs/api.md#puppeteerlaunchoptions) when launching a browser:
Puppeteer launches Chromium in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). To launch a full version of Chromium, set the [`headless` option](https://github.com/puppeteer/puppeteer/blob/v3.0.3/docs/api.md#puppeteerlaunchoptions) when launching a browser:

@@ -183,3 +183,3 @@ ```js

You can also use Puppeteer with Firefox Nightly (experimental support). See [`Puppeteer.launch()`](https://github.com/puppeteer/puppeteer/blob/v3.0.2/docs/api.md#puppeteerlaunchoptions) for more information.
You can also use Puppeteer with Firefox Nightly (experimental support). See [`Puppeteer.launch()`](https://github.com/puppeteer/puppeteer/blob/v3.0.3/docs/api.md#puppeteerlaunchoptions) for more information.

@@ -196,3 +196,3 @@ See [`this article`](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) for a description of the differences between Chromium and Chrome. [`This article`](https://chromium.googlesource.com/chromium/src/+/master/docs/chromium_browser_vs_google_chrome.md) describes some differences for Linux users.

- [API Documentation](https://github.com/puppeteer/puppeteer/blob/v3.0.2/docs/api.md)
- [API Documentation](https://github.com/puppeteer/puppeteer/blob/v3.0.3/docs/api.md)
- [Examples](https://github.com/puppeteer/puppeteer/tree/master/examples/)

@@ -210,3 +210,5 @@ - [Community list of Puppeteer resources](https://github.com/transitive-bullshit/awesome-puppeteer)

const browser = await puppeteer.launch({headless: false});
```js
const browser = await puppeteer.launch({headless: false});
```

@@ -216,6 +218,8 @@ 2. Slow it down - the `slowMo` option slows down Puppeteer operations by the

const browser = await puppeteer.launch({
headless: false,
slowMo: 250 // slow down by 250ms
});
```js
const browser = await puppeteer.launch({
headless: false,
slowMo: 250 // slow down by 250ms
});
```

@@ -225,5 +229,7 @@ 3. Capture console output - You can listen for the `console` event.

page.on('console', msg => console.log('PAGE LOG:', msg.text()));
```js
page.on('console', msg => console.log('PAGE LOG:', msg.text()));
await page.evaluate(() => console.log(`url is ${location.href}`));
await page.evaluate(() => console.log(`url is ${location.href}`));
```

@@ -238,3 +244,5 @@ 4. Use debugger in application code browser

`const browser = await puppeteer.launch({devtools: true});`
```js
const browser = await puppeteer.launch({devtools: true});
```

@@ -251,3 +259,5 @@ - Change default test timeout:

`await page.evaluate(() => {debugger;});`
```js
await page.evaluate(() => {debugger;});
```

@@ -265,6 +275,8 @@ The test will now stop executing in the above evaluate statement, and chromium will stop in debug mode.

- Add `debugger;` to your test, eg:
```
```js
debugger;
await page.click('a[target=_blank]');
```
- Set `headless` to `false`

@@ -318,3 +330,3 @@ - Run `node --inspect-brk`, eg `node --inspect-brk node_modules/.bin/jest tests`

From Puppeteer v2.1.0 onwards you can specify [`puppeteer.launch({product: 'firefox'})`](https://github.com/puppeteer/puppeteer/blob/v3.0.2/docs/api.md#puppeteerlaunchoptions) to run your Puppeteer scripts in Firefox Nightly, without any additional custom patches. While [an older experiment](https://www.npmjs.com/package/puppeteer-firefox) required a patched version of Firefox, [the current approach](https://wiki.mozilla.org/Remote) works with “stock” Firefox.
From Puppeteer v2.1.0 onwards you can specify [`puppeteer.launch({product: 'firefox'})`](https://github.com/puppeteer/puppeteer/blob/v3.0.3/docs/api.md#puppeteerlaunchoptions) to run your Puppeteer scripts in Firefox Nightly, without any additional custom patches. While [an older experiment](https://www.npmjs.com/package/puppeteer-firefox) required a patched version of Firefox, [the current approach](https://wiki.mozilla.org/Remote) works with “stock” Firefox.

@@ -415,3 +427,3 @@ We will continue to collaborate with other browser vendors to bring Puppeteer support to browsers such as Safari.

* Puppeteer is bundled with Chromium — not Chrome — and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://github.com/puppeteer/puppeteer/blob/v3.0.2/docs/api.md#puppeteerlaunchoptions). You should only use this configuration if you need an official release of Chrome that supports these media formats.)
* Puppeteer is bundled with Chromium — not Chrome — and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://github.com/puppeteer/puppeteer/blob/v3.0.3/docs/api.md#puppeteerlaunchoptions). You should only use this configuration if you need an official release of Chrome that supports these media formats.)
* Since Puppeteer (in all configurations) controls a desktop version of Chromium/Chrome, features that are only supported by the mobile version of Chrome are not supported. This means that Puppeteer [does not support HTTP Live Streaming (HLS)](https://caniuse.com/#feat=http-live-streaming).

@@ -418,0 +430,0 @@

@@ -40,4 +40,4 @@ /**

async function compileTypeScript() {
return exec('npm run tsc').catch(err => {
console.error('Error running TypeScript', err);
return exec('npm run tsc').catch(error => {
console.error('Error running TypeScript', error);
process.exit(1);

@@ -44,0 +44,0 @@ });

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc