Socket
Socket
Sign inDemoInstall

puppeteer-core

Package Overview
Dependencies
Maintainers
4
Versions
239
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

puppeteer-core - npm Package Compare versions

Comparing version 3.0.0 to 3.0.1

lib/externs.d.ts

46

install.js

@@ -17,41 +17,2 @@ /**

const fs = require('fs');
const path = require('path');
const child_process = require('child_process');
const {promisify} = require('util');
const fsAccess = promisify(fs.access);
const exec = promisify(child_process.exec);
const fileExists = async filePath => fsAccess(filePath).then(() => true).catch(() => false);
/*
* Now Puppeteer is built with TypeScript, we need to ensure that
* locally we have the generated output before trying to install.
*
* For users installing puppeteer this is fine, they will have the
* generated lib/ directory as we ship it when we publish to npm.
*
* However, if you're cloning the repo to contribute, you won't have the
* generated lib/ directory so this script checks if we need to run
* TypeScript first to ensure the output exists and is in the right
* place.
*/
async function compileTypeScript() {
return exec('npm run tsc').catch(err => {
console.error('Error running TypeScript', err);
process.exit(1);
});
}
async function ensureLibDirectoryExists() {
const libPath = path.join(__dirname, 'lib');
const libExists = await fileExists(libPath);
if (libExists) return;
logPolitely('Compiling TypeScript before install...');
await compileTypeScript();
}
/**

@@ -66,2 +27,5 @@ * This file is part of public API.

*/
const compileTypeScriptIfRequired = require('./typescript-if-required');
const supportedProducts = {

@@ -73,3 +37,3 @@ 'chrome': 'Chromium',

async function download() {
await ensureLibDirectoryExists();
await compileTypeScriptIfRequired();

@@ -79,3 +43,3 @@ const downloadHost = process.env.PUPPETEER_DOWNLOAD_HOST || process.env.npm_config_puppeteer_download_host || process.env.npm_package_config_puppeteer_download_host;

const product = process.env.PUPPETEER_PRODUCT || process.env.npm_config_puppeteer_product || process.env.npm_package_config_puppeteer_product || 'chrome';
const browserFetcher = puppeteer.createBrowserFetcher({ product, host: downloadHost });
const browserFetcher = puppeteer.createBrowserFetcher({product, host: downloadHost});
const revision = await getRevision();

@@ -82,0 +46,0 @@ await fetchBinary(revision);

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

*/
// 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 { ElementHandle } = require('./JSHandle');
/**

@@ -55,3 +61,3 @@ * @typedef {Object} SerializedAXNode

/**
* @param {!Puppeteer.CDPSession} client
* @param {!CDPSession} client
*/

@@ -62,3 +68,3 @@ constructor(client) {

/**
* @param {{interestingOnly?: boolean, root?: ?Puppeteer.ElementHandle}=} options
* @param {{interestingOnly?: boolean, root?: ?ElementHandle}=} options
* @return {!Promise<!SerializedAXNode>}

@@ -65,0 +71,0 @@ */

@@ -21,5 +21,8 @@ /**

const { Events } = require('./Events');
// Used as a TypeDef
// eslint-disable-next-line no-unused-vars
const { Connection } = require('./Connection');
class Browser extends EventEmitter {
/**
* @param {!Puppeteer.Connection} connection
* @param {!Connection} connection
* @param {!Array<string>} contextIds

@@ -37,3 +40,3 @@ * @param {boolean} ignoreHTTPSErrors

/**
* @param {!Puppeteer.Connection} connection
* @param {!Connection} connection
* @param {!Array<string>} contextIds

@@ -251,3 +254,3 @@ * @param {boolean} ignoreHTTPSErrors

/**
* @param {!Puppeteer.Connection} connection
* @param {!Connection} connection
* @param {!Browser} browser

@@ -254,0 +257,0 @@ * @param {?string} contextId

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

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

@@ -16,6 +18,8 @@ * Copyright 2017 Google Inc. All rights reserved.

*/
const { assert } = require('./helper');
const { Events } = require('./Events');
const debugProtocol = require('debug')('puppeteer:protocol');
const EventEmitter = require('events');
const helper_1 = require("./helper");
const EventsModule = require("./Events");
const { Events } = EventsModule;
const debug = require("debug");
const debugProtocol = debug('puppeteer:protocol');
const EventEmitter = require("events");
class Connection extends EventEmitter {

@@ -29,6 +33,7 @@ /**

super();
this._url = url;
this._lastId = 0;
/** @type {!Map<number, {resolve: function, reject: function, error: !Error, method: string}>}*/
this._sessions = new Map();
this._closed = false;
this._callbacks = new Map();
this._url = url;
this._delay = delay;

@@ -38,10 +43,3 @@ this._transport = transport;

this._transport.onclose = this._onClose.bind(this);
/** @type {!Map<string, !CDPSession>}*/
this._sessions = new Map();
this._closed = false;
}
/**
* @param {!CDPSession} session
* @return {!Connection}
*/
static fromSession(session) {

@@ -57,13 +55,5 @@ return session._connection;

}
/**
* @return {string}
*/
url() {
return this._url;
}
/**
* @param {string} method
* @param {!Object=} params
* @return {!Promise<?Object>}
*/
send(method, params = {}) {

@@ -75,6 +65,2 @@ const id = this._rawSend({ method, params });

}
/**
* @param {*} message
* @return {number}
*/
_rawSend(message) {

@@ -87,5 +73,2 @@ const id = ++this._lastId;

}
/**
* @param {string} message
*/
async _onMessage(message) {

@@ -155,11 +138,6 @@ if (this._delay)

}
exports.Connection = Connection;
class CDPSession extends EventEmitter {
/**
* @param {!Connection} connection
* @param {string} targetType
* @param {string} sessionId
*/
constructor(connection, targetType, sessionId) {
super();
/** @type {!Map<number, {resolve: function, reject: function, error: !Error, method: string}>}*/
this._callbacks = new Map();

@@ -170,11 +148,14 @@ this._connection = connection;

}
/**
* @param {string} method
* @param {!Object=} params
* @return {!Promise<?Object>}
*/
send(method, params = {}) {
send(method, params) {
if (!this._connection)
return Promise.reject(new Error(`Protocol error (${method}): Session closed. Most likely the ${this._targetType} has been closed.`));
const id = this._connection._rawSend({ sessionId: this._sessionId, method, params });
const id = this._connection._rawSend({
sessionId: this._sessionId,
method,
/* TODO(jacktfranklin@): once this Firefox bug is solved
* we no longer need the `|| {}` check
* https://bugzilla.mozilla.org/show_bug.cgi?id=1631570
*/
params: params || {}
});
return new Promise((resolve, reject) => {

@@ -184,5 +165,2 @@ this._callbacks.set(id, { resolve, reject, error: new Error(), method });

}
/**
* @param {{id?: number, method: string, params: Object, error: {message: string, data: any}, result?: *}} object
*/
_onMessage(object) {

@@ -198,3 +176,3 @@ if (object.id && this._callbacks.has(object.id)) {

else {
assert(!object.id);
helper_1.assert(!object.id);
this.emit(object.method, object.params);

@@ -216,2 +194,3 @@ }

}
exports.CDPSession = CDPSession;
/**

@@ -238,2 +217,1 @@ * @param {!Error} error

}
module.exports = { Connection, CDPSession };

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

"use strict";
/**

@@ -16,14 +17,6 @@ * Copyright 2017 Google Inc. All rights reserved.

*/
const { helper, debugError, assert } = require('./helper');
const { EVALUATION_SCRIPT_URL } = require('./ExecutionContext');
/**
* @typedef {Object} CoverageEntry
* @property {string} url
* @property {string} text
* @property {!Array<!{start: number, end: number}>} ranges
*/
Object.defineProperty(exports, "__esModule", { value: true });
const helper_1 = require("./helper");
const ExecutionContext_1 = require("./ExecutionContext");
class Coverage {
/**
* @param {!Puppeteer.CDPSession} client
*/
constructor(client) {

@@ -33,23 +26,11 @@ this._jsCoverage = new JSCoverage(client);

}
/**
* @param {!{resetOnNavigation?: boolean, reportAnonymousScripts?: boolean}} options
*/
async startJSCoverage(options) {
return await this._jsCoverage.start(options);
}
/**
* @return {!Promise<!Array<!CoverageEntry>>}
*/
async stopJSCoverage() {
return await this._jsCoverage.stop();
}
/**
* @param {{resetOnNavigation?: boolean}=} options
*/
async startCSSCoverage(options) {
return await this._cssCoverage.start(options);
}
/**
* @return {!Promise<!Array<!CoverageEntry>>}
*/
async stopCSSCoverage() {

@@ -59,9 +40,5 @@ return await this._cssCoverage.stop();

}
module.exports = { Coverage };
exports.Coverage = Coverage;
class JSCoverage {
/**
* @param {!Puppeteer.CDPSession} client
*/
constructor(client) {
this._client = client;
this._enabled = false;

@@ -72,8 +49,7 @@ this._scriptURLs = new Map();

this._resetOnNavigation = false;
this._reportAnonymousScripts = false;
this._client = client;
}
/**
* @param {!{resetOnNavigation?: boolean, reportAnonymousScripts?: boolean}} options
*/
async start(options = {}) {
assert(!this._enabled, 'JSCoverage is already enabled');
helper_1.assert(!this._enabled, 'JSCoverage is already enabled');
const { resetOnNavigation = true, reportAnonymousScripts = false } = options;

@@ -86,4 +62,4 @@ this._resetOnNavigation = resetOnNavigation;

this._eventListeners = [
helper.addEventListener(this._client, 'Debugger.scriptParsed', this._onScriptParsed.bind(this)),
helper.addEventListener(this._client, 'Runtime.executionContextsCleared', this._onExecutionContextsCleared.bind(this)),
helper_1.helper.addEventListener(this._client, 'Debugger.scriptParsed', this._onScriptParsed.bind(this)),
helper_1.helper.addEventListener(this._client, 'Runtime.executionContextsCleared', this._onExecutionContextsCleared.bind(this)),
];

@@ -103,8 +79,5 @@ await Promise.all([

}
/**
* @param {!Protocol.Debugger.scriptParsedPayload} event
*/
async _onScriptParsed(event) {
// Ignore puppeteer-injected scripts
if (event.url === EVALUATION_SCRIPT_URL)
if (event.url === ExecutionContext_1.EVALUATION_SCRIPT_URL)
return;

@@ -121,10 +94,7 @@ // Ignore other anonymous scripts unless the reportAnonymousScripts option is true.

// This might happen if the page has already navigated away.
debugError(e);
helper_1.debugError(e);
}
}
/**
* @return {!Promise<!Array<!CoverageEntry>>}
*/
async stop() {
assert(this._enabled, 'JSCoverage is not enabled');
helper_1.assert(this._enabled, 'JSCoverage is not enabled');
this._enabled = false;

@@ -137,5 +107,5 @@ const result = await Promise.all([

]);
helper.removeEventListeners(this._eventListeners);
helper_1.helper.removeEventListeners(this._eventListeners);
const coverage = [];
const profileResponse = /** @type Protocol.Profiler.takePreciseCoverageReturnValue */ (result[0]);
const profileResponse = result[0];
for (const entry of profileResponse.result) {

@@ -158,7 +128,3 @@ let url = this._scriptURLs.get(entry.scriptId);

class CSSCoverage {
/**
* @param {!Puppeteer.CDPSession} client
*/
constructor(client) {
this._client = client;
this._enabled = false;

@@ -169,8 +135,7 @@ this._stylesheetURLs = new Map();

this._resetOnNavigation = false;
this._reportAnonymousScripts = false;
this._client = client;
}
/**
* @param {{resetOnNavigation?: boolean}=} options
*/
async start(options = {}) {
assert(!this._enabled, 'CSSCoverage is already enabled');
helper_1.assert(!this._enabled, 'CSSCoverage is already enabled');
const { resetOnNavigation = true } = options;

@@ -182,4 +147,4 @@ this._resetOnNavigation = resetOnNavigation;

this._eventListeners = [
helper.addEventListener(this._client, 'CSS.styleSheetAdded', this._onStyleSheet.bind(this)),
helper.addEventListener(this._client, 'Runtime.executionContextsCleared', this._onExecutionContextsCleared.bind(this)),
helper_1.helper.addEventListener(this._client, 'CSS.styleSheetAdded', this._onStyleSheet.bind(this)),
helper_1.helper.addEventListener(this._client, 'Runtime.executionContextsCleared', this._onExecutionContextsCleared.bind(this)),
];

@@ -198,5 +163,2 @@ await Promise.all([

}
/**
* @param {!Protocol.CSS.styleSheetAddedPayload} event
*/
async _onStyleSheet(event) {

@@ -214,10 +176,7 @@ const header = event.header;

// This might happen if the page has already navigated away.
debugError(e);
helper_1.debugError(e);
}
}
/**
* @return {!Promise<!Array<!CoverageEntry>>}
*/
async stop() {
assert(this._enabled, 'CSSCoverage is not enabled');
helper_1.assert(this._enabled, 'CSSCoverage is not enabled');
this._enabled = false;

@@ -229,3 +188,3 @@ const ruleTrackingResponse = await this._client.send('CSS.stopRuleUsageTracking');

]);
helper.removeEventListeners(this._eventListeners);
helper_1.helper.removeEventListeners(this._eventListeners);
// aggregate by styleSheetId

@@ -255,6 +214,2 @@ const styleSheetIdToCoverage = new Map();

}
/**
* @param {!Array<!{startOffset:number, endOffset:number, count:number}>} nestedRanges
* @return {!Array<!{start:number, end:number}>}
*/
function convertToDisjointRanges(nestedRanges) {

@@ -261,0 +216,0 @@ const points = [];

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

"use strict";
/**

@@ -16,40 +17,29 @@ * Copyright 2017 Google Inc. All rights reserved.

*/
const { assert } = require('./helper');
const helper_1 = require("./helper");
var DialogType;
(function (DialogType) {
DialogType["Alert"] = "alert";
DialogType["BeforeUnload"] = "beforeunload";
DialogType["Confirm"] = "confirm";
DialogType["Prompt"] = "prompt";
})(DialogType || (DialogType = {}));
class Dialog {
/**
* @param {!Puppeteer.CDPSession} client
* @param {string} type
* @param {string} message
* @param {(string|undefined)} defaultValue
*/
constructor(client, type, message, defaultValue = '') {
this._handled = false;
this._client = client;
this._type = type;
this._message = message;
this._handled = false;
this._defaultValue = defaultValue;
}
/**
* @return {string}
*/
type() {
return this._type;
}
/**
* @return {string}
*/
message() {
return this._message;
}
/**
* @return {string}
*/
defaultValue() {
return this._defaultValue;
}
/**
* @param {string=} promptText
*/
async accept(promptText) {
assert(!this._handled, 'Cannot accept dialog which is already handled!');
helper_1.assert(!this._handled, 'Cannot accept dialog which is already handled!');
this._handled = true;

@@ -62,3 +52,3 @@ await this._client.send('Page.handleJavaScriptDialog', {

async dismiss() {
assert(!this._handled, 'Cannot dismiss dialog which is already handled!');
helper_1.assert(!this._handled, 'Cannot dismiss dialog which is already handled!');
this._handled = true;

@@ -70,8 +60,3 @@ await this._client.send('Page.handleJavaScriptDialog', {

}
Dialog.Type = {
Alert: 'alert',
BeforeUnload: 'beforeunload',
Confirm: 'confirm',
Prompt: 'prompt'
};
Dialog.Type = DialogType;
module.exports = { Dialog };

@@ -20,2 +20,11 @@ /**

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);

@@ -29,3 +38,3 @@ /**

* @param {!Puppeteer.Frame} frame
* @param {!Puppeteer.TimeoutSettings} timeoutSettings
* @param {!TimeoutSettings} timeoutSettings
*/

@@ -36,5 +45,5 @@ constructor(frameManager, frame, timeoutSettings) {

this._timeoutSettings = timeoutSettings;
/** @type {?Promise<!Puppeteer.ElementHandle>} */
/** @type {?Promise<!ElementHandle>} */
this._documentPromise = null;
/** @type {!Promise<!Puppeteer.ExecutionContext>} */
/** @type {!Promise<!ExecutionContext>} */
this._contextPromise;

@@ -54,3 +63,3 @@ this._contextResolveCallback = null;

/**
* @param {?Puppeteer.ExecutionContext} context
* @param {?ExecutionContext} context
*/

@@ -83,3 +92,3 @@ _setContext(context) {

/**
* @return {!Promise<!Puppeteer.ExecutionContext>}
* @return {!Promise<!ExecutionContext>}
*/

@@ -94,3 +103,3 @@ executionContext() {

* @param {!Array<*>} args
* @return {!Promise<!Puppeteer.JSHandle>}
* @return {!Promise<!JSHandle>}
*/

@@ -112,3 +121,3 @@ async evaluateHandle(pageFunction, ...args) {

* @param {string} selector
* @return {!Promise<?Puppeteer.ElementHandle>}
* @return {!Promise<?ElementHandle>}
*/

@@ -121,3 +130,3 @@ async $(selector) {

/**
* @return {!Promise<!Puppeteer.ElementHandle>}
* @return {!Promise<!ElementHandle>}
*/

@@ -135,3 +144,3 @@ async _document() {

* @param {string} expression
* @return {!Promise<!Array<!Puppeteer.ElementHandle>>}
* @return {!Promise<!Array<!ElementHandle>>}
*/

@@ -166,3 +175,3 @@ async $x(expression) {

* @param {string} selector
* @return {!Promise<!Array<!Puppeteer.ElementHandle>>}
* @return {!Promise<!Array<!ElementHandle>>}
*/

@@ -211,3 +220,3 @@ async $$(selector) {

* @param {!{url?: string, path?: string, content?: string, type?: string}} options
* @return {!Promise<!Puppeteer.ElementHandle>}
* @return {!Promise<!ElementHandle>}
*/

@@ -273,3 +282,3 @@ async addScriptTag(options) {

* @param {!{url?: string, path?: string, content?: string}} options
* @return {!Promise<!Puppeteer.ElementHandle>}
* @return {!Promise<!ElementHandle>}
*/

@@ -394,3 +403,3 @@ async addStyleTag(options) {

* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<?Puppeteer.ElementHandle>}
* @return {!Promise<?ElementHandle>}
*/

@@ -403,3 +412,3 @@ waitForSelector(selector, options) {

* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<?Puppeteer.ElementHandle>}
* @return {!Promise<?ElementHandle>}
*/

@@ -412,3 +421,3 @@ waitForXPath(xpath, options) {

* @param {!{polling?: string|number, timeout?: number}=} options
* @return {!Promise<!Puppeteer.JSHandle>}
* @return {!Promise<!JSHandle>}
*/

@@ -429,3 +438,3 @@ waitForFunction(pageFunction, options = {}, ...args) {

* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<?Puppeteer.ElementHandle>}
* @return {!Promise<?ElementHandle>}
*/

@@ -517,3 +526,3 @@ async _waitForSelectorOrXPath(selectorOrXPath, isXPath, options = {}) {

const runCount = ++this._runCount;
/** @type {?Puppeteer.JSHandle} */
/** @type {?JSHandle} */
let success = null;

@@ -520,0 +529,0 @@ let error = null;

@@ -16,5 +16,8 @@ /**

*/
// Used as a TypeDef
// eslint-disable-next-line no-unused-vars
const { CDPSession } = require('./Connection');
class EmulationManager {
/**
* @param {!Puppeteer.CDPSession} client
* @param {!CDPSession} client
*/

@@ -21,0 +24,0 @@ constructor(client) {

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

"use strict";
/**

@@ -16,12 +17,8 @@ * Copyright 2017 Google Inc. All rights reserved.

*/
const { helper, assert } = require('./helper');
const { createJSHandle, JSHandle } = require('./JSHandle');
const EVALUATION_SCRIPT_URL = '__puppeteer_evaluation_script__';
Object.defineProperty(exports, "__esModule", { value: true });
const helper_1 = require("./helper");
const JSHandle_1 = require("./JSHandle");
exports.EVALUATION_SCRIPT_URL = '__puppeteer_evaluation_script__';
const SOURCE_URL_REGEX = /^[\040\t]*\/\/[@#] sourceURL=\s*(\S*?)\s*$/m;
class ExecutionContext {
/**
* @param {!Puppeteer.CDPSession} client
* @param {!Protocol.Runtime.ExecutionContextDescription} contextPayload
* @param {?Puppeteer.DOMWorld} world
*/
constructor(client, contextPayload, world) {

@@ -32,35 +29,16 @@ this._client = client;

}
/**
* @return {?Puppeteer.Frame}
*/
frame() {
return this._world ? this._world.frame() : null;
}
/**
* @param {Function|string} pageFunction
* @param {...*} args
* @return {!Promise<*>}
*/
async evaluate(pageFunction, ...args) {
return await this._evaluateInternal(true /* returnByValue */, pageFunction, ...args);
return await this._evaluateInternal(true, pageFunction, ...args);
}
/**
* @param {Function|string} pageFunction
* @param {...*} args
* @return {!Promise<!JSHandle>}
*/
async evaluateHandle(pageFunction, ...args) {
return this._evaluateInternal(false /* returnByValue */, pageFunction, ...args);
return this._evaluateInternal(false, pageFunction, ...args);
}
/**
* @param {boolean} returnByValue
* @param {Function|string} pageFunction
* @param {...*} args
* @return {!Promise<*>}
*/
async _evaluateInternal(returnByValue, pageFunction, ...args) {
const suffix = `//# sourceURL=${EVALUATION_SCRIPT_URL}`;
if (helper.isString(pageFunction)) {
const suffix = `//# sourceURL=${exports.EVALUATION_SCRIPT_URL}`;
if (helper_1.helper.isString(pageFunction)) {
const contextId = this._contextId;
const expression = /** @type {string} */ (pageFunction);
const expression = pageFunction;
const expressionWithSourceUrl = SOURCE_URL_REGEX.test(expression) ? expression : expression + '\n' + suffix;

@@ -75,4 +53,4 @@ const { exceptionDetails, result: remoteObject } = await this._client.send('Runtime.evaluate', {

if (exceptionDetails)
throw new Error('Evaluation failed: ' + helper.getExceptionMessage(exceptionDetails));
return returnByValue ? helper.valueFromRemoteObject(remoteObject) : createJSHandle(this, remoteObject);
throw new Error('Evaluation failed: ' + helper_1.helper.getExceptionMessage(exceptionDetails));
return returnByValue ? helper_1.helper.valueFromRemoteObject(remoteObject) : JSHandle_1.createJSHandle(this, remoteObject);
}

@@ -118,4 +96,4 @@ if (typeof pageFunction !== 'function')

if (exceptionDetails)
throw new Error('Evaluation failed: ' + helper.getExceptionMessage(exceptionDetails));
return returnByValue ? helper.valueFromRemoteObject(remoteObject) : createJSHandle(this, remoteObject);
throw new Error('Evaluation failed: ' + helper_1.helper.getExceptionMessage(exceptionDetails));
return returnByValue ? helper_1.helper.valueFromRemoteObject(remoteObject) : JSHandle_1.createJSHandle(this, remoteObject);
/**

@@ -137,3 +115,3 @@ * @param {*} arg

return { unserializableValue: 'NaN' };
const objectHandle = arg && (arg instanceof JSHandle) ? arg : null;
const objectHandle = arg && (arg instanceof JSHandle_1.JSHandle) ? arg : null;
if (objectHandle) {

@@ -152,6 +130,2 @@ if (objectHandle._context !== this)

}
/**
* @param {!Error} error
* @return {!Protocol.Runtime.evaluateReturnValue}
*/
function rewriteError(error) {

@@ -167,18 +141,10 @@ if (error.message.includes('Object reference chain is too long'))

}
/**
* @param {!JSHandle} prototypeHandle
* @return {!Promise<!JSHandle>}
*/
async queryObjects(prototypeHandle) {
assert(!prototypeHandle._disposed, 'Prototype JSHandle is disposed!');
assert(prototypeHandle._remoteObject.objectId, 'Prototype JSHandle must not be referencing primitive value');
helper_1.assert(!prototypeHandle._disposed, 'Prototype JSHandle is disposed!');
helper_1.assert(prototypeHandle._remoteObject.objectId, 'Prototype JSHandle must not be referencing primitive value');
const response = await this._client.send('Runtime.queryObjects', {
prototypeObjectId: prototypeHandle._remoteObject.objectId
});
return createJSHandle(this, response.objects);
return JSHandle_1.createJSHandle(this, response.objects);
}
/**
* @param {Protocol.DOM.BackendNodeId} backendNodeId
* @return {Promise<Puppeteer.ElementHandle>}
*/
async _adoptBackendNodeId(backendNodeId) {

@@ -189,11 +155,7 @@ const { object } = await this._client.send('DOM.resolveNode', {

});
return /** @type {Puppeteer.ElementHandle}*/ (createJSHandle(this, object));
return JSHandle_1.createJSHandle(this, object);
}
/**
* @param {Puppeteer.ElementHandle} elementHandle
* @return {Promise<Puppeteer.ElementHandle>}
*/
async _adoptElementHandle(elementHandle) {
assert(elementHandle.executionContext() !== this, 'Cannot adopt handle that already belongs to this execution context');
assert(this._world, 'Cannot adopt handle without DOMWorld');
helper_1.assert(elementHandle.executionContext() !== this, 'Cannot adopt handle that already belongs to this execution context');
helper_1.assert(this._world, 'Cannot adopt handle without DOMWorld');
const nodeInfo = await this._client.send('DOM.describeNode', {

@@ -205,2 +167,2 @@ objectId: elementHandle._remoteObject.objectId,

}
module.exports = { ExecutionContext, EVALUATION_SCRIPT_URL };
exports.ExecutionContext = ExecutionContext;

@@ -23,9 +23,18 @@ /**

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');
const UTILITY_WORLD_NAME = '__puppeteer_utility_world__';
class FrameManager extends EventEmitter {
/**
* @param {!Puppeteer.CDPSession} client
* @param {!CDPSession} client
* @param {!Puppeteer.Page} page
* @param {boolean} ignoreHTTPSErrors
* @param {!Puppeteer.TimeoutSettings} timeoutSettings
* @param {!TimeoutSettings} timeoutSettings
*/

@@ -99,3 +108,3 @@ constructor(client, page, ignoreHTTPSErrors, timeoutSettings) {

/**
* @param {!Puppeteer.CDPSession} client
* @param {!CDPSession} client
* @param {string} url

@@ -340,3 +349,3 @@ * @param {string} referrer

* @param {!FrameManager} frameManager
* @param {!Puppeteer.CDPSession} client
* @param {!CDPSession} client
* @param {?Frame} parentFrame

@@ -388,3 +397,3 @@ * @param {string} frameId

* @param {!Array<*>} args
* @return {!Promise<!Puppeteer.JSHandle>}
* @return {!Promise<!JSHandle>}
*/

@@ -404,3 +413,3 @@ async evaluateHandle(pageFunction, ...args) {

* @param {string} selector
* @return {!Promise<?Puppeteer.ElementHandle>}
* @return {!Promise<?ElementHandle>}
*/

@@ -412,3 +421,3 @@ async $(selector) {

* @param {string} expression
* @return {!Promise<!Array<!Puppeteer.ElementHandle>>}
* @return {!Promise<!Array<!ElementHandle>>}
*/

@@ -438,3 +447,3 @@ async $x(expression) {

* @param {string} selector
* @return {!Promise<!Array<!Puppeteer.ElementHandle>>}
* @return {!Promise<!Array<!ElementHandle>>}
*/

@@ -489,3 +498,3 @@ async $$(selector) {

* @param {!{url?: string, path?: string, content?: string, type?: string}} options
* @return {!Promise<!Puppeteer.ElementHandle>}
* @return {!Promise<!ElementHandle>}
*/

@@ -497,3 +506,3 @@ async addScriptTag(options) {

* @param {!{url?: string, path?: string, content?: string}} options
* @return {!Promise<!Puppeteer.ElementHandle>}
* @return {!Promise<!ElementHandle>}
*/

@@ -548,3 +557,3 @@ async addStyleTag(options) {

* @param {!Array<*>} args
* @return {!Promise<?Puppeteer.JSHandle>}
* @return {!Promise<?JSHandle>}
*/

@@ -568,3 +577,3 @@ waitFor(selectorOrFunctionOrTimeout, options = {}, ...args) {

* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<?Puppeteer.ElementHandle>}
* @return {!Promise<?ElementHandle>}
*/

@@ -583,3 +592,3 @@ async waitForSelector(selector, options) {

* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<?Puppeteer.ElementHandle>}
* @return {!Promise<?ElementHandle>}
*/

@@ -598,3 +607,3 @@ async waitForXPath(xpath, options) {

* @param {!{polling?: string|number, timeout?: number}=} options
* @return {!Promise<!Puppeteer.JSHandle>}
* @return {!Promise<!JSHandle>}
*/

@@ -601,0 +610,0 @@ waitForFunction(pageFunction, options = {}, ...args) {

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

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

@@ -16,261 +18,190 @@ * Copyright 2017 Google Inc. All rights reserved.

*/
const { TimeoutError } = require('./Errors');
const debugError = require('debug')(`puppeteer:error`);
const fs = require('fs');
class Helper {
/**
* @param {Function|string} fun
* @param {!Array<*>} args
* @return {string}
*/
static evaluationString(fun, ...args) {
if (Helper.isString(fun)) {
assert(args.length === 0, 'Cannot evaluate a string with arguments');
return /** @type {string} */ (fun);
const Errors = require("./Errors");
const debug = require("debug");
const fs = require("fs");
const promisify = require("./promisify");
const { TimeoutError } = Errors;
const openAsync = promisify(fs.open);
const writeAsync = promisify(fs.write);
const closeAsync = promisify(fs.close);
exports.debugError = debug('puppeteer:error');
function assert(value, message) {
if (!value)
throw new Error(message);
}
exports.assert = assert;
function getExceptionMessage(exceptionDetails) {
if (exceptionDetails.exception)
return exceptionDetails.exception.description || exceptionDetails.exception.value;
let message = exceptionDetails.text;
if (exceptionDetails.stackTrace) {
for (const callframe of exceptionDetails.stackTrace.callFrames) {
const location = callframe.url + ':' + callframe.lineNumber + ':' + callframe.columnNumber;
const functionName = callframe.functionName || '<anonymous>';
message += `\n at ${functionName} (${location})`;
}
return `(${fun})(${args.map(serializeArgument).join(',')})`;
/**
* @param {*} arg
* @return {string}
*/
function serializeArgument(arg) {
if (Object.is(arg, undefined))
return 'undefined';
return JSON.stringify(arg);
}
}
/**
* @param {!Protocol.Runtime.ExceptionDetails} exceptionDetails
* @return {string}
*/
static getExceptionMessage(exceptionDetails) {
if (exceptionDetails.exception)
return exceptionDetails.exception.description || exceptionDetails.exception.value;
let message = exceptionDetails.text;
if (exceptionDetails.stackTrace) {
for (const callframe of exceptionDetails.stackTrace.callFrames) {
const location = callframe.url + ':' + callframe.lineNumber + ':' + callframe.columnNumber;
const functionName = callframe.functionName || '<anonymous>';
message += `\n at ${functionName} (${location})`;
}
return message;
}
function valueFromRemoteObject(remoteObject) {
assert(!remoteObject.objectId, 'Cannot extract value when objectId is given');
if (remoteObject.unserializableValue) {
if (remoteObject.type === 'bigint' && typeof BigInt !== 'undefined')
return BigInt(remoteObject.unserializableValue.replace('n', ''));
switch (remoteObject.unserializableValue) {
case '-0':
return -0;
case 'NaN':
return NaN;
case 'Infinity':
return Infinity;
case '-Infinity':
return -Infinity;
default:
throw new Error('Unsupported unserializable value: ' + remoteObject.unserializableValue);
}
return message;
}
/**
* @param {!Protocol.Runtime.RemoteObject} remoteObject
* @return {*}
*/
static valueFromRemoteObject(remoteObject) {
assert(!remoteObject.objectId, 'Cannot extract value when objectId is given');
if (remoteObject.unserializableValue) {
if (remoteObject.type === 'bigint' && typeof BigInt !== 'undefined')
return BigInt(remoteObject.unserializableValue.replace('n', ''));
switch (remoteObject.unserializableValue) {
case '-0':
return -0;
case 'NaN':
return NaN;
case 'Infinity':
return Infinity;
case '-Infinity':
return -Infinity;
default:
throw new Error('Unsupported unserializable value: ' + remoteObject.unserializableValue);
}
}
return remoteObject.value;
return remoteObject.value;
}
async function releaseObject(client, remoteObject) {
if (!remoteObject.objectId)
return;
await client.send('Runtime.releaseObject', { objectId: remoteObject.objectId }).catch(error => {
// Exceptions might happen in case of a page been navigated or closed.
// Swallow these since they are harmless and we don't leak anything in this case.
exports.debugError(error);
});
}
function installAsyncStackHooks(classType) {
for (const methodName of Reflect.ownKeys(classType.prototype)) {
const method = Reflect.get(classType.prototype, methodName);
if (methodName === 'constructor' || typeof methodName !== 'string' || methodName.startsWith('_') || typeof method !== 'function' || method.constructor.name !== 'AsyncFunction')
continue;
Reflect.set(classType.prototype, methodName, function (...args) {
const syncStack = {
stack: ''
};
Error.captureStackTrace(syncStack);
return method.call(this, ...args).catch(e => {
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;
});
});
}
/**
* @param {!Puppeteer.CDPSession} client
* @param {!Protocol.Runtime.RemoteObject} remoteObject
*/
static async releaseObject(client, remoteObject) {
if (!remoteObject.objectId)
}
function addEventListener(emitter, eventName, handler) {
emitter.on(eventName, handler);
return { emitter, eventName, handler };
}
function removeEventListeners(listeners) {
for (const listener of listeners)
listener.emitter.removeListener(listener.eventName, listener.handler);
listeners.length = 0;
}
function isString(obj) {
return typeof obj === 'string' || obj instanceof String;
}
function isNumber(obj) {
return typeof obj === 'number' || obj instanceof Number;
}
async function waitForEvent(emitter, eventName, predicate, timeout, abortPromise) {
let eventTimeout, resolveCallback, rejectCallback;
const promise = new Promise((resolve, reject) => {
resolveCallback = resolve;
rejectCallback = reject;
});
const listener = addEventListener(emitter, eventName, event => {
if (!predicate(event))
return;
await client.send('Runtime.releaseObject', { objectId: remoteObject.objectId }).catch(error => {
// Exceptions might happen in case of a page been navigated or closed.
// Swallow these since they are harmless and we don't leak anything in this case.
debugError(error);
});
resolveCallback(event);
});
if (timeout) {
eventTimeout = setTimeout(() => {
rejectCallback(new TimeoutError('Timeout exceeded while waiting for event'));
}, timeout);
}
/**
* @param {!Object} classType
*/
static installAsyncStackHooks(classType) {
for (const methodName of Reflect.ownKeys(classType.prototype)) {
const method = Reflect.get(classType.prototype, methodName);
if (methodName === 'constructor' || typeof methodName !== 'string' || methodName.startsWith('_') || typeof method !== 'function' || method.constructor.name !== 'AsyncFunction')
continue;
Reflect.set(classType.prototype, methodName, function (...args) {
const syncStack = {};
Error.captureStackTrace(syncStack);
return method.call(this, ...args).catch(e => {
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;
});
});
}
function cleanup() {
removeEventListeners([listener]);
clearTimeout(eventTimeout);
}
/**
* @param {!NodeJS.EventEmitter} emitter
* @param {(string|symbol)} eventName
* @param {function(?):void} handler
* @return {{emitter: !NodeJS.EventEmitter, eventName: (string|symbol), handler: function(?)}}
*/
static addEventListener(emitter, eventName, handler) {
emitter.on(eventName, handler);
return { emitter, eventName, handler };
const result = await Promise.race([promise, abortPromise]).then(r => {
cleanup();
return r;
}, e => {
cleanup();
throw e;
});
if (result instanceof Error)
throw result;
return result;
}
function evaluationString(fun, ...args) {
if (isString(fun)) {
assert(args.length === 0, 'Cannot evaluate a string with arguments');
return fun;
}
/**
* @param {!Array<{emitter: !NodeJS.EventEmitter, eventName: (string|symbol), handler: function(?):void}>} listeners
*/
static removeEventListeners(listeners) {
for (const listener of listeners)
listener.emitter.removeListener(listener.eventName, listener.handler);
listeners.length = 0;
function serializeArgument(arg) {
if (Object.is(arg, undefined))
return 'undefined';
return JSON.stringify(arg);
}
/**
* @param {!Object} obj
* @return {boolean}
*/
static isString(obj) {
return typeof obj === 'string' || obj instanceof String;
return `(${fun})(${args.map(serializeArgument).join(',')})`;
}
async function waitWithTimeout(promise, taskName, timeout) {
let reject;
const timeoutError = new TimeoutError(`waiting for ${taskName} failed: timeout ${timeout}ms exceeded`);
const timeoutPromise = new Promise((resolve, x) => reject = x);
let timeoutTimer = null;
if (timeout)
timeoutTimer = setTimeout(() => reject(timeoutError), timeout);
try {
return await Promise.race([promise, timeoutPromise]);
}
/**
* @param {!Object} obj
* @return {boolean}
*/
static isNumber(obj) {
return typeof obj === 'number' || obj instanceof Number;
finally {
if (timeoutTimer)
clearTimeout(timeoutTimer);
}
/**
* @param {function} nodeFunction
* @return {function}
*/
static promisify(nodeFunction) {
function promisified(...args) {
return new Promise((resolve, reject) => {
function callback(err, ...result) {
if (err)
return reject(err);
if (result.length === 1)
return resolve(result[0]);
return resolve(result);
}
nodeFunction.call(null, ...args, callback);
});
}
return promisified;
}
async function readProtocolStream(client, handle, path) {
let eof = false;
let file;
if (path)
file = await openAsync(path, 'w');
const bufs = [];
while (!eof) {
const response = await client.send('IO.read', { handle });
eof = response.eof;
const buf = Buffer.from(response.data, response.base64Encoded ? 'base64' : undefined);
bufs.push(buf);
if (path)
await writeAsync(file, buf);
}
/**
* @param {!NodeJS.EventEmitter} emitter
* @param {(string|symbol)} eventName
* @param {function} predicate
* @param {number} timeout
* @param {!Promise<!Error>} abortPromise
* @return {!Promise}
*/
static async waitForEvent(emitter, eventName, predicate, timeout, abortPromise) {
let eventTimeout, resolveCallback, rejectCallback;
const promise = new Promise((resolve, reject) => {
resolveCallback = resolve;
rejectCallback = reject;
});
const listener = Helper.addEventListener(emitter, eventName, event => {
if (!predicate(event))
return;
resolveCallback(event);
});
if (timeout) {
eventTimeout = setTimeout(() => {
rejectCallback(new TimeoutError('Timeout exceeded while waiting for event'));
}, timeout);
}
function cleanup() {
Helper.removeEventListeners([listener]);
clearTimeout(eventTimeout);
}
const result = await Promise.race([promise, abortPromise]).then(r => {
cleanup();
return r;
}, e => {
cleanup();
throw e;
});
if (result instanceof Error)
throw result;
return result;
if (path)
await closeAsync(file);
await client.send('IO.close', { handle });
let resultBuffer = null;
try {
resultBuffer = Buffer.concat(bufs);
}
/**
* @template T
* @param {!Promise<T>} promise
* @param {string} taskName
* @param {number} timeout
* @return {!Promise<T>}
*/
static async waitWithTimeout(promise, taskName, timeout) {
let reject;
const timeoutError = new TimeoutError(`waiting for ${taskName} failed: timeout ${timeout}ms exceeded`);
const timeoutPromise = new Promise((resolve, x) => reject = x);
let timeoutTimer = null;
if (timeout)
timeoutTimer = setTimeout(() => reject(timeoutError), timeout);
try {
return await Promise.race([promise, timeoutPromise]);
}
finally {
if (timeoutTimer)
clearTimeout(timeoutTimer);
}
finally {
return resultBuffer;
}
/**
* @param {!Puppeteer.CDPSession} client
* @param {string} handle
* @param {?string} path
* @return {!Promise<!Buffer>}
*/
static async readProtocolStream(client, handle, path) {
let eof = false;
let file;
if (path)
file = await openAsync(path, 'w');
const bufs = [];
while (!eof) {
const response = await client.send('IO.read', { handle });
eof = response.eof;
const buf = Buffer.from(response.data, response.base64Encoded ? 'base64' : undefined);
bufs.push(buf);
if (path)
await writeAsync(file, buf);
}
if (path)
await closeAsync(file);
await client.send('IO.close', { handle });
let resultBuffer = null;
try {
resultBuffer = Buffer.concat(bufs);
}
finally {
return resultBuffer;
}
}
}
const openAsync = Helper.promisify(fs.open);
const writeAsync = Helper.promisify(fs.write);
const closeAsync = Helper.promisify(fs.close);
/**
* @param {*} value
* @param {string=} message
*/
function assert(value, message) {
if (!value)
throw new Error(message);
}
module.exports = {
helper: Helper,
assert,
debugError
exports.helper = {
promisify,
evaluationString,
readProtocolStream,
waitWithTimeout,
waitForEvent,
isString,
isNumber,
addEventListener,
removeEventListeners,
valueFromRemoteObject,
installAsyncStackHooks,
getExceptionMessage,
releaseObject,
};

@@ -17,3 +17,6 @@ /**

const { assert } = require('./helper');
const keyDefinitions = require('./USKeyboardLayout');
// CDPSession is used only as a typedef
// eslint-disable-next-line no-unused-vars
const { CDPSession } = require('./Connection');
const { keyDefinitions } = require('./USKeyboardLayout');
/**

@@ -29,3 +32,3 @@ * @typedef {Object} KeyDescription

/**
* @param {!Puppeteer.CDPSession} client
* @param {!CDPSession} client
*/

@@ -166,3 +169,3 @@ constructor(client) {

/**
* @param {Puppeteer.CDPSession} client
* @param {CDPSession} client
* @param {!Keyboard} keyboard

@@ -254,3 +257,3 @@ */

/**
* @param {Puppeteer.CDPSession} client
* @param {CDPSession} client
* @param {Keyboard} keyboard

@@ -257,0 +260,0 @@ */

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

"use strict";
/**

@@ -16,3 +17,4 @@ * Copyright 2019 Google Inc. All rights reserved.

*/
const { helper, assert, debugError } = require('./helper');
Object.defineProperty(exports, "__esModule", { value: true });
const helper_1 = require("./helper");
function createJSHandle(context, remoteObject) {

@@ -26,40 +28,19 @@ const frame = context.frame();

}
exports.createJSHandle = createJSHandle;
class JSHandle {
/**
* @param {!Puppeteer.ExecutionContext} context
* @param {!Puppeteer.CDPSession} client
* @param {!Protocol.Runtime.RemoteObject} remoteObject
*/
constructor(context, client, remoteObject) {
this._disposed = false;
this._context = context;
this._client = client;
this._remoteObject = remoteObject;
this._disposed = false;
}
/**
* @return {!Puppeteer.ExecutionContext}
*/
executionContext() {
return this._context;
}
/**
* @param {Function|String} pageFunction
* @param {!Array<*>} args
* @return {!Promise<(!Object|undefined)>}
*/
async evaluate(pageFunction, ...args) {
return await this.executionContext().evaluate(pageFunction, this, ...args);
}
/**
* @param {Function|string} pageFunction
* @param {!Array<*>} args
* @return {!Promise<!Puppeteer.JSHandle>}
*/
async evaluateHandle(pageFunction, ...args) {
return await this.executionContext().evaluateHandle(pageFunction, this, ...args);
}
/**
* @param {string} propertyName
* @return {!Promise<?JSHandle>}
*/
async getProperty(propertyName) {

@@ -76,5 +57,2 @@ const objectHandle = await this.evaluateHandle((object, propertyName) => {

}
/**
* @return {!Promise<!Map<string, !JSHandle>>}
*/
async getProperties() {

@@ -93,5 +71,2 @@ const response = await this._client.send('Runtime.getProperties', {

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

@@ -105,9 +80,7 @@ if (this._remoteObject.objectId) {

});
return helper.valueFromRemoteObject(response.result);
return helper_1.helper.valueFromRemoteObject(response.result);
}
return helper.valueFromRemoteObject(this._remoteObject);
return helper_1.helper.valueFromRemoteObject(this._remoteObject);
}
/**
* @return {?Puppeteer.ElementHandle}
*/
/* This always returns null but children can define this and return an ElementHandle */
asElement() {

@@ -120,8 +93,4 @@ return null;

this._disposed = true;
await helper.releaseObject(this._client, this._remoteObject);
await helper_1.helper.releaseObject(this._client, this._remoteObject);
}
/**
* @override
* @return {string}
*/
toString() {

@@ -132,9 +101,10 @@ if (this._remoteObject.objectId) {

}
return 'JSHandle:' + helper.valueFromRemoteObject(this._remoteObject);
return 'JSHandle:' + helper_1.helper.valueFromRemoteObject(this._remoteObject);
}
}
exports.JSHandle = JSHandle;
class ElementHandle extends JSHandle {
/**
* @param {!Puppeteer.ExecutionContext} context
* @param {!Puppeteer.CDPSession} client
* @param {!ExecutionContext} context
* @param {!CDPSession} client
* @param {!Protocol.Runtime.RemoteObject} remoteObject

@@ -150,14 +120,6 @@ * @param {!Puppeteer.Page} page

this._frameManager = frameManager;
this._disposed = false;
}
/**
* @override
* @return {?ElementHandle}
*/
asElement() {
return this;
}
/**
* @return {!Promise<?Puppeteer.Frame>}
*/
async contentFrame() {

@@ -179,2 +141,5 @@ const nodeInfo = await this._client.send('DOM.describeNode', {

if (!pageJavascriptEnabled) {
// Chrome still supports behavior: instant but it's not in the spec so TS shouts
// We don't want to make this breaking change in Puppeteer yet so we'll ignore the line.
// @ts-ignore
element.scrollIntoView({ block: 'center', inline: 'center', behavior: 'instant' });

@@ -190,4 +155,8 @@ return false;

});
if (visibleRatio !== 1.0)
if (visibleRatio !== 1.0) {
// Chrome still supports behavior: instant but it's not in the spec so TS shouts
// We don't want to make this breaking change in Puppeteer yet so we'll ignore the line.
// @ts-ignore
element.scrollIntoView({ block: 'center', inline: 'center', behavior: 'instant' });
}
return false;

@@ -198,5 +167,2 @@ }, this._page._javascriptEnabled);

}
/**
* @return {!Promise<!{x: number, y: number}>}
*/
async _clickablePoint() {

@@ -206,3 +172,3 @@ const [result, layoutMetrics] = await Promise.all([

objectId: this._remoteObject.objectId
}).catch(debugError),
}).catch(helper_1.debugError),
this._client.send('Page.getLayoutMetrics'),

@@ -230,14 +196,7 @@ ]);

}
/**
* @return {!Promise<void|Protocol.DOM.getBoxModelReturnValue>}
*/
_getBoxModel() {
return this._client.send('DOM.getBoxModel', {
objectId: this._remoteObject.objectId
}).catch(error => debugError(error));
}).catch(error => helper_1.debugError(error));
}
/**
* @param {!Array<number>} quad
* @return {!Array<{x: number, y: number}>}
*/
_fromProtocolQuad(quad) {

@@ -268,5 +227,2 @@ return [

}
/**
* @param {!{delay?: number, button?: "left"|"right"|"middle", clickCount?: number}=} options
*/
async click(options) {

@@ -283,3 +239,7 @@ await this._scrollIntoViewIfNeeded();

for (const value of values)
assert(helper.isString(value), 'Values must be strings. Found value "' + value + '" of type "' + (typeof value) + '"');
helper_1.assert(helper_1.helper.isString(value), 'Values must be strings. Found value "' + value + '" of type "' + (typeof value) + '"');
/* TODO(jacktfranklin@): once ExecutionContext is TypeScript, and
* its evaluate function is properly typed with generics we can
* return here and remove the typecasting
*/
return this.evaluate((element, values) => {

@@ -300,37 +260,27 @@ if (element.nodeName.toLowerCase() !== 'select')

}
/**
* @param {!Array<string>} filePaths
*/
async uploadFile(...filePaths) {
const isMultiple = await this.evaluate(element => element.multiple);
assert(filePaths.length <= 1 || isMultiple, 'Multiple file uploads only work with <input type=file multiple>');
// These imports are only needed for `uploadFile`, so keep them
// scoped here to avoid paying the cost unnecessarily.
const isMultiple = await this.evaluate((element) => element.multiple);
helper_1.assert(filePaths.length <= 1 || isMultiple, 'Multiple file uploads only work with <input type=file multiple>');
// This import is only needed for `uploadFile`, so keep it scoped here to avoid paying
// the cost unnecessarily.
// eslint-disable-next-line @typescript-eslint/no-var-requires
const path = require('path');
const mime = require('mime-types');
const fs = require('fs');
const readFileAsync = helper.promisify(fs.readFile);
const promises = filePaths.map(filePath => readFileAsync(filePath));
const files = [];
for (let i = 0; i < filePaths.length; i++) {
const buffer = await promises[i];
const filePath = path.basename(filePaths[i]);
const file = {
name: filePath,
content: buffer.toString('base64'),
mimeType: mime.lookup(filePath),
};
files.push(file);
const files = filePaths.map(filePath => path.resolve(filePath));
const { objectId } = this._remoteObject;
const { node } = await this._client.send('DOM.describeNode', { objectId });
const { backendNodeId } = node;
// The zero-length array is a special case, it seems that DOM.setFileInputFiles does
// not actually update the files in that case, so the solution is to eval the element
// value to a new FileList directly.
if (files.length === 0) {
await this.evaluate((element) => {
element.files = new DataTransfer().files;
// Dispatch events for this case because it should behave akin to a user action.
element.dispatchEvent(new Event('input', { bubbles: true }));
element.dispatchEvent(new Event('change', { bubbles: true }));
});
}
await this.evaluateHandle(async (element, files) => {
const dt = new DataTransfer();
for (const item of files) {
const response = await fetch(`data:${item.mimeType};base64,${item.content}`);
const file = new File([await response.blob()], item.name);
dt.items.add(file);
}
element.files = dt.files;
element.dispatchEvent(new Event('input', { bubbles: true }));
element.dispatchEvent(new Event('change', { bubbles: true }));
}, files);
else {
await this._client.send('DOM.setFileInputFiles', { objectId, files, backendNodeId });
}
}

@@ -345,6 +295,2 @@ async tap() {

}
/**
* @param {string} text
* @param {{delay: (number|undefined)}=} options
*/
async type(text, options) {

@@ -354,6 +300,2 @@ await this.focus();

}
/**
* @param {string} key
* @param {!{delay?: number, text?: string}=} options
*/
async press(key, options) {

@@ -363,5 +305,2 @@ await this.focus();

}
/**
* @return {!Promise<?{x: number, y: number, width: number, height: number}>}
*/
async boundingBox() {

@@ -395,11 +334,6 @@ const result = await this._getBoxModel();

}
/**
*
* @param {!Object=} options
* @returns {!Promise<string|!Buffer>}
*/
async screenshot(options = {}) {
let needsViewportReset = false;
let boundingBox = await this.boundingBox();
assert(boundingBox, 'Node is either not visible or not an HTMLElement');
helper_1.assert(boundingBox, 'Node is either not visible or not an HTMLElement');
const viewport = this._page.viewport();

@@ -416,5 +350,5 @@ if (viewport && (boundingBox.width > viewport.width || boundingBox.height > viewport.height)) {

boundingBox = await this.boundingBox();
assert(boundingBox, 'Node is either not visible or not an HTMLElement');
assert(boundingBox.width !== 0, 'Node has 0 width.');
assert(boundingBox.height !== 0, 'Node has 0 height.');
helper_1.assert(boundingBox, 'Node is either not visible or not an HTMLElement');
helper_1.assert(boundingBox.width !== 0, 'Node has 0 width.');
helper_1.assert(boundingBox.height !== 0, 'Node has 0 height.');
const { layoutViewport: { pageX, pageY } } = await this._client.send('Page.getLayoutMetrics');

@@ -431,6 +365,2 @@ const clip = Object.assign({}, boundingBox);

}
/**
* @param {string} selector
* @return {!Promise<?ElementHandle>}
*/
async $(selector) {

@@ -460,8 +390,2 @@ const handle = await this.evaluateHandle((element, selector) => element.querySelector(selector), selector);

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

@@ -475,8 +399,2 @@ const elementHandle = await this.$(selector);

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

@@ -488,6 +406,2 @@ const arrayHandle = await this.evaluateHandle((element, selector) => Array.from(element.querySelectorAll(selector)), selector);

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

@@ -513,7 +427,4 @@ const arrayHandle = await this.evaluateHandle((element, expression) => {

}
/**
* @returns {!Promise<boolean>}
*/
isIntersectingViewport() {
return this.evaluate(async (element) => {
async isIntersectingViewport() {
return await this.evaluate(async (element) => {
const visibleRatio = await new Promise(resolve => {

@@ -530,2 +441,3 @@ const observer = new IntersectionObserver(entries => {

}
exports.ElementHandle = ElementHandle;
function computeQuadArea(quad) {

@@ -542,11 +454,1 @@ // Compute sum of all directed areas of adjacent triangles

}
/**
* @typedef {Object} BoxModel
* @property {!Array<!{x: number, y: number}>} content
* @property {!Array<!{x: number, y: number}>} padding
* @property {!Array<!{x: number, y: number}>} border
* @property {!Array<!{x: number, y: number}>} margin
* @property {number} width
* @property {number} height
*/
module.exports = { createJSHandle, JSHandle, ElementHandle };

@@ -31,4 +31,4 @@ /**

const { TimeoutError } = require('./Errors');
const WebSocketTransport = require('./WebSocketTransport');
const PipeTransport = require('./PipeTransport');
const { WebSocketTransport } = require('./WebSocketTransport');
const { PipeTransport } = require('./PipeTransport');
const mkdtempAsync = helper.promisify(fs.mkdtemp);

@@ -35,0 +35,0 @@ const removeFolderAsync = helper.promisify(removeFolder);

@@ -19,5 +19,8 @@ /**

const { Events } = require('./Events');
// CDPSession is used only as a typedef
// eslint-disable-next-line no-unused-vars
const { CDPSession } = require('./Connection');
class NetworkManager extends EventEmitter {
/**
* @param {!Puppeteer.CDPSession} client
* @param {!CDPSession} client
* @param {!Puppeteer.FrameManager} frameManager

@@ -293,3 +296,3 @@ */

/**
* @param {!Puppeteer.CDPSession} client
* @param {!CDPSession} client
* @param {?Puppeteer.Frame} frame

@@ -481,3 +484,3 @@ * @param {string} interceptionId

/**
* @param {!Puppeteer.CDPSession} client
* @param {!CDPSession} client
* @param {!Request} request

@@ -484,0 +487,0 @@ * @param {!Protocol.Network.Response} responsePayload

@@ -20,3 +20,5 @@ /**

const { Events } = require('./Events');
const { Connection } = require('./Connection');
// CDPSession is used only as a typedef
// eslint-disable-next-line no-unused-vars
const { Connection, CDPSession } = require('./Connection');
const { Dialog } = require('./Dialog');

@@ -30,13 +32,19 @@ const { EmulationManager } = require('./EmulationManager');

const { Worker: PuppeteerWorker } = require('./Worker');
const { createJSHandle } = require('./JSHandle');
// 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);
class Page extends EventEmitter {
/**
* @param {!Puppeteer.CDPSession} client
* @param {!CDPSession} client
* @param {!Puppeteer.Target} target
* @param {boolean} ignoreHTTPSErrors
* @param {?Puppeteer.Viewport} defaultViewport
* @param {!Puppeteer.TaskQueue} screenshotTaskQueue
* @param {!TaskQueue} screenshotTaskQueue
* @return {!Promise<!Page>}

@@ -52,6 +60,6 @@ */

/**
* @param {!Puppeteer.CDPSession} client
* @param {!CDPSession} client
* @param {!Puppeteer.Target} target
* @param {boolean} ignoreHTTPSErrors
* @param {!Puppeteer.TaskQueue} screenshotTaskQueue
* @param {!TaskQueue} screenshotTaskQueue
*/

@@ -282,3 +290,3 @@ constructor(client, target, ignoreHTTPSErrors, screenshotTaskQueue) {

* @param {string} selector
* @return {!Promise<?Puppeteer.ElementHandle>}
* @return {!Promise<?ElementHandle>}
*/

@@ -291,3 +299,3 @@ async $(selector) {

* @param {!Array<*>} args
* @return {!Promise<!Puppeteer.JSHandle>}
* @return {!Promise<!JSHandle>}
*/

@@ -299,4 +307,4 @@ async evaluateHandle(pageFunction, ...args) {

/**
* @param {!Puppeteer.JSHandle} prototypeHandle
* @return {!Promise<!Puppeteer.JSHandle>}
* @param {!JSHandle} prototypeHandle
* @return {!Promise<!JSHandle>}
*/

@@ -327,3 +335,3 @@ async queryObjects(prototypeHandle) {

* @param {string} selector
* @return {!Promise<!Array<!Puppeteer.ElementHandle>>}
* @return {!Promise<!Array<!ElementHandle>>}
*/

@@ -335,3 +343,3 @@ async $$(selector) {

* @param {string} expression
* @return {!Promise<!Array<!Puppeteer.ElementHandle>>}
* @return {!Promise<!Array<!ElementHandle>>}
*/

@@ -389,3 +397,3 @@ async $x(expression) {

* @param {!{url?: string, path?: string, content?: string, type?: string}} options
* @return {!Promise<!Puppeteer.ElementHandle>}
* @return {!Promise<!ElementHandle>}
*/

@@ -397,3 +405,3 @@ async addScriptTag(options) {

* @param {!{url?: string, path?: string, content?: string}} options
* @return {!Promise<!Puppeteer.ElementHandle>}
* @return {!Promise<!ElementHandle>}
*/

@@ -562,3 +570,3 @@ async addStyleTag(options) {

* @param {string} type
* @param {!Array<!Puppeteer.JSHandle>} args
* @param {!Array<!JSHandle>} args
* @param {Protocol.Runtime.StackTrace=} stackTrace

@@ -1007,3 +1015,3 @@ */

* @param {!Array<*>} args
* @return {!Promise<!Puppeteer.JSHandle>}
* @return {!Promise<!JSHandle>}
*/

@@ -1016,3 +1024,3 @@ waitFor(selectorOrFunctionOrTimeout, options = {}, ...args) {

* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<?Puppeteer.ElementHandle>}
* @return {!Promise<?ElementHandle>}
*/

@@ -1025,3 +1033,3 @@ waitForSelector(selector, options = {}) {

* @param {!{visible?: boolean, hidden?: boolean, timeout?: number}=} options
* @return {!Promise<?Puppeteer.ElementHandle>}
* @return {!Promise<?ElementHandle>}
*/

@@ -1035,3 +1043,3 @@ waitForXPath(xpath, options = {}) {

* @param {!Array<*>} args
* @return {!Promise<!Puppeteer.JSHandle>}
* @return {!Promise<!JSHandle>}
*/

@@ -1194,3 +1202,3 @@ waitForFunction(pageFunction, options = {}, ...args) {

* @param {string} text
* @param {!Array<!Puppeteer.JSHandle>} args
* @param {!Array<!JSHandle>} args
* @param {ConsoleMessage.Location} location

@@ -1217,3 +1225,3 @@ */

/**
* @return {!Array<!Puppeteer.JSHandle>}
* @return {!Array<!JSHandle>}
*/

@@ -1232,4 +1240,4 @@ args() {

/**
* @param {Puppeteer.CDPSession} client
* @param {Puppeteer.ElementHandle} element
* @param {CDPSession} client
* @param {ElementHandle} element
* @param {!Protocol.Page.fileChooserOpenedPayload} event

@@ -1236,0 +1244,0 @@ */

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

"use strict";
/**

@@ -16,11 +17,4 @@ * Copyright 2018 Google Inc. All rights reserved.

*/
const { helper, debugError } = require('./helper');
/**
* @implements {!Puppeteer.ConnectionTransport}
*/
const helper_1 = require("./helper");
class PipeTransport {
/**
* @param {!NodeJS.WritableStream} pipeWrite
* @param {!NodeJS.ReadableStream} pipeRead
*/
constructor(pipeWrite, pipeRead) {

@@ -30,9 +24,9 @@ this._pipeWrite = pipeWrite;

this._eventListeners = [
helper.addEventListener(pipeRead, 'data', buffer => this._dispatch(buffer)),
helper.addEventListener(pipeRead, 'close', () => {
helper_1.helper.addEventListener(pipeRead, 'data', buffer => this._dispatch(buffer)),
helper_1.helper.addEventListener(pipeRead, 'close', () => {
if (this.onclose)
this.onclose.call(null);
}),
helper.addEventListener(pipeRead, 'error', debugError),
helper.addEventListener(pipeWrite, 'error', debugError),
helper_1.helper.addEventListener(pipeRead, 'error', helper_1.debugError),
helper_1.helper.addEventListener(pipeWrite, 'error', helper_1.debugError),
];

@@ -42,5 +36,2 @@ this.onmessage = null;

}
/**
* @param {string} message
*/
send(message) {

@@ -50,5 +41,2 @@ this._pipeWrite.write(message);

}
/**
* @param {!Buffer} buffer
*/
_dispatch(buffer) {

@@ -75,5 +63,5 @@ let end = buffer.indexOf('\0');

this._pipeWrite = null;
helper.removeEventListeners(this._eventListeners);
helper_1.helper.removeEventListeners(this._eventListeners);
}
}
module.exports = PipeTransport;
module.exports = { PipeTransport };

@@ -19,2 +19,9 @@ /**

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');
class Target {

@@ -24,6 +31,6 @@ /**

* @param {!Puppeteer.BrowserContext} browserContext
* @param {!function():!Promise<!Puppeteer.CDPSession>} sessionFactory
* @param {!function():!Promise<!CDPSession>} sessionFactory
* @param {boolean} ignoreHTTPSErrors
* @param {?Puppeteer.Viewport} defaultViewport
* @param {!Puppeteer.TaskQueue} screenshotTaskQueue
* @param {!TaskQueue} screenshotTaskQueue
*/

@@ -61,3 +68,3 @@ constructor(targetInfo, browserContext, sessionFactory, ignoreHTTPSErrors, defaultViewport, screenshotTaskQueue) {

/**
* @return {!Promise<!Puppeteer.CDPSession>}
* @return {!Promise<!CDPSession>}
*/

@@ -64,0 +71,0 @@ createCDPSession() {

@@ -0,1 +1,22 @@

"use strict";
/**
* Copyright 2020 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.
*/
/* TODO(jacktfranklin@): once we are calling this from TS files we can
* avoid the horrible void | any type and instead make use of generics
* to make this into TaskQueue<T> and let the caller tell us what types
* the promise in the queue should return.
*/
class TaskQueue {

@@ -5,6 +26,2 @@ constructor() {

}
/**
* @param {Function} task
* @return {!Promise}
*/
postTask(task) {

@@ -11,0 +28,0 @@ const result = this._chain.then(task);

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

"use strict";
/**

@@ -22,5 +23,2 @@ * Copyright 2019 Google Inc. All rights reserved.

}
/**
* @param {number} timeout
*/
setDefaultTimeout(timeout) {

@@ -35,5 +33,2 @@ this._defaultTimeout = timeout;

}
/**
* @return {number}
*/
navigationTimeout() {

@@ -40,0 +35,0 @@ if (this._defaultNavigationTimeout !== null)

@@ -17,5 +17,8 @@ /**

const { helper, assert } = require('./helper');
// Used as a TypeDef
// eslint-disable-next-line no-unused-vars
const { CDPSession } = require('./Connection');
class Tracing {
/**
* @param {!Puppeteer.CDPSession} client
* @param {!CDPSession} client
*/

@@ -22,0 +25,0 @@ constructor(client) {

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

"use strict";
/**

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

*/
/**
* @typedef {Object} KeyDefinition
* @property {number=} keyCode
* @property {number=} shiftKeyCode
* @property {string=} key
* @property {string=} shiftKey
* @property {string=} code
* @property {string=} text
* @property {string=} shiftText
* @property {number=} location
*/
/**
* @type {Object<string, KeyDefinition>}
*/
module.exports = {
Object.defineProperty(exports, "__esModule", { value: true });
exports.keyDefinitions = {
'0': { 'keyCode': 48, 'key': '0', 'code': 'Digit0' },

@@ -33,0 +21,0 @@ '1': { 'keyCode': 49, 'key': '1', 'code': 'Digit1' },

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

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

@@ -16,24 +18,4 @@ * Copyright 2018 Google Inc. All rights reserved.

*/
const NodeWebSocket = require('ws');
/**
* @implements {!Puppeteer.ConnectionTransport}
*/
const NodeWebSocket = require("ws");
class WebSocketTransport {
/**
* @param {string} url
* @return {!Promise<!WebSocketTransport>}
*/
static create(url) {
return new Promise((resolve, reject) => {
const ws = new NodeWebSocket(url, [], {
perMessageDeflate: false,
maxPayload: 256 * 1024 * 1024,
});
ws.addEventListener('open', () => resolve(new WebSocketTransport(ws)));
ws.addEventListener('error', reject);
});
}
/**
* @param {!NodeWebSocket} ws
*/
constructor(ws) {

@@ -45,3 +27,3 @@ this._ws = ws;

});
this._ws.addEventListener('close', event => {
this._ws.addEventListener('close', () => {
if (this.onclose)

@@ -55,5 +37,12 @@ this.onclose.call(null);

}
/**
* @param {string} message
*/
static create(url) {
return new Promise((resolve, reject) => {
const ws = new NodeWebSocket(url, [], {
perMessageDeflate: false,
maxPayload: 256 * 1024 * 1024,
});
ws.addEventListener('open', () => resolve(new WebSocketTransport(ws)));
ws.addEventListener('error', reject);
});
}
send(message) {

@@ -66,2 +55,2 @@ this._ws.send(message);

}
module.exports = WebSocketTransport;
exports.WebSocketTransport = WebSocketTransport;

@@ -20,5 +20,8 @@ /**

const { JSHandle } = require('./JSHandle');
// Used as a TypeDef
// eslint-disable-next-line no-unused-vars
const { CDPSession } = require('./Connection');
class Worker extends EventEmitter {
/**
* @param {Puppeteer.CDPSession} client
* @param {CDPSession} client
* @param {string} url

@@ -25,0 +28,0 @@ * @param {function(string, !Array<!JSHandle>, Protocol.Runtime.StackTrace=):void} consoleAPICalled

{
"name": "puppeteer-core",
"version": "3.0.0",
"version": "3.0.1",
"description": "A high-level API to control headless Chrome over the DevTools Protocol",

@@ -21,5 +21,7 @@ "main": "index.js",

"test": "npm run tsc && npm run lint --silent && npm run coverage && npm run test-doclint && npm run test-types",
"prepare": "node typescript-if-required.js",
"prepublishOnly": "npm run tsc",
"dev-install": "npm run tsc && node install.js",
"lint": "([ \"$CI\" = true ] && eslint --ext js --ext ts --quiet -f codeframe . || eslint --ext js --ext ts .) && npm run tsc && npm run doc",
"eslint": "([ \"$CI\" = true ] && eslint --ext js --ext ts --quiet -f codeframe . || eslint --ext js --ext ts .)",
"lint": "npm run eslint && npm run tsc && npm run doc",
"doc": "node utils/doclint/cli.js",

@@ -31,4 +33,13 @@ "tsc": "tsc --version && tsc -p . && cp src/protocol.d.ts lib/ && cp src/externs.d.ts lib/",

"unit-bundle": "mocha --config mocha-config/browser-bundle-tests.js",
"update-protocol-d-ts": "node utils/protocol-types-generator"
"update-protocol-d-ts": "node utils/protocol-types-generator",
"test-install": "scripts/test-install.sh"
},
"files": [
"lib/",
"Errors.js",
"DeviceDescriptors.js",
"index.js",
"install.js",
"typescript-if-required.js"
],
"author": "The Chromium Authors",

@@ -35,0 +46,0 @@ "license": "Apache-2.0",

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

###### [API](https://github.com/puppeteer/puppeteer/blob/v3.0.0/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.1/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.0/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.1/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.0/docs/api.md#).
of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/puppeteer/puppeteer/blob/v3.0.1/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.0/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.1/docs/api.md#pagesetviewportviewport).

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

See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v3.0.0/docs/api.md#pagepdfoptions) for more information about creating pdfs.
See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v3.0.1/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.0/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.1/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.0/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.1/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.0/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.1/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.0/docs/api.md)
- [API Documentation](https://github.com/puppeteer/puppeteer/blob/v3.0.1/docs/api.md)
- [Examples](https://github.com/puppeteer/puppeteer/tree/master/examples/)

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

From Puppeteer v2.1.0 onwards you can specify [`puppeteer.launch({product: 'firefox'})`](https://github.com/puppeteer/puppeteer/blob/v3.0.0/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.1/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.

@@ -409,3 +409,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.0/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.1/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).

@@ -412,0 +412,0 @@

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc