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.1 to 3.0.2

2

index.js

@@ -21,3 +21,2 @@ /**

for (const className in api) {
// Puppeteer-web excludes certain classes from bundle, e.g. BrowserFetcher.
if (typeof api[className] === 'function')

@@ -30,3 +29,2 @@ helper.installAsyncStackHooks(api[className]);

// If node does not support async await, use the compiled version.
const Puppeteer = require('./lib/Puppeteer');

@@ -33,0 +31,0 @@ const packageJson = require('./package.json');

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

"use strict";
/**

@@ -16,55 +17,7 @@ * Copyright 2018 Google Inc. All rights reserved.

*/
// 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');
/**
* @typedef {Object} SerializedAXNode
* @property {string} role
*
* @property {string=} name
* @property {string|number=} value
* @property {string=} description
*
* @property {string=} keyshortcuts
* @property {string=} roledescription
* @property {string=} valuetext
*
* @property {boolean=} disabled
* @property {boolean=} expanded
* @property {boolean=} focused
* @property {boolean=} modal
* @property {boolean=} multiline
* @property {boolean=} multiselectable
* @property {boolean=} readonly
* @property {boolean=} required
* @property {boolean=} selected
*
* @property {boolean|"mixed"=} checked
* @property {boolean|"mixed"=} pressed
*
* @property {number=} level
* @property {number=} valuemin
* @property {number=} valuemax
*
* @property {string=} autocomplete
* @property {string=} haspopup
* @property {string=} invalid
* @property {string=} orientation
*
* @property {Array<SerializedAXNode>=} children
*/
Object.defineProperty(exports, "__esModule", { value: true });
class Accessibility {
/**
* @param {!CDPSession} client
*/
constructor(client) {
this._client = client;
}
/**
* @param {{interestingOnly?: boolean, root?: ?ElementHandle}=} options
* @return {!Promise<!SerializedAXNode>}
*/
async snapshot(options = {}) {

@@ -87,3 +40,2 @@ const { interestingOnly = true, root = null, } = options;

return serializeTree(needle)[0];
/** @type {!Set<!AXNode>} */
const interestingNodes = new Set();

@@ -96,2 +48,3 @@ collectInterestingNodes(interestingNodes, defaultRoot, false);

}
exports.Accessibility = Accessibility;
/**

@@ -111,9 +64,3 @@ * @param {!Set<!AXNode>} collection

}
/**
* @param {!AXNode} node
* @param {!Set<!AXNode>=} whitelistedNodes
* @return {!Array<!SerializedAXNode>}
*/
function serializeTree(node, whitelistedNodes) {
/** @type {!Array<!SerializedAXNode>} */
const children = [];

@@ -130,8 +77,3 @@ for (const child of node._children)

class AXNode {
/**
* @param {!Protocol.Accessibility.AXNode} payload
*/
constructor(payload) {
this._payload = payload;
/** @type {!Array<!AXNode>} */
this._children = [];

@@ -143,5 +85,5 @@ this._richlyEditable = false;

this._hidden = false;
this._payload = payload;
this._name = this._payload.name ? this._payload.name.value : '';
this._role = this._payload.role ? this._payload.role.value : 'Unknown';
this._cachedHasFocusableChild;
for (const property of this._payload.properties || []) {

@@ -160,5 +102,2 @@ if (property.name === 'editable') {

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

@@ -171,5 +110,2 @@ if (this._richlyEditable)

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

@@ -180,5 +116,2 @@ const role = this._role;

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

@@ -196,6 +129,2 @@ if (this._cachedHasFocusableChild === undefined) {

}
/**
* @param {function(AXNode):boolean} predicate
* @return {?AXNode}
*/
find(predicate) {

@@ -211,5 +140,2 @@ if (predicate(this))

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

@@ -250,5 +176,2 @@ if (!this._children.length)

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

@@ -299,7 +222,3 @@ switch (this._role) {

}
/**
* @return {!SerializedAXNode}
*/
serialize() {
/** @type {!Map<string, number|string|boolean>} */
const properties = new Map();

@@ -314,9 +233,5 @@ for (const property of this._payload.properties || [])

properties.set('description', this._payload.description.value);
/** @type {SerializedAXNode} */
const node = {
role: this._role
};
/** @enum {'name'|'value'|'description'|'keyshortcuts'|'roledescription'|'valuetext'} */
let UserStringProperties; // eslint-disable-line no-unused-vars
/** @type {!Array<UserStringProperties>} */
const userStringProperties = [

@@ -330,6 +245,3 @@ 'name',

];
/**
* @param {UserStringProperties} key
*/
const getUserStringPropertyValue = key => /** @type string */ (properties.get(key));
const getUserStringPropertyValue = (key) => properties.get(key);
for (const userStringProperty of userStringProperties) {

@@ -340,5 +252,2 @@ if (!properties.has(userStringProperty))

}
/** @enum {'disabled'|'expanded'|'focused'|'modal'|'multiline'|'multiselectable'|'readonly'|'required'|'selected'} */
let BooleanProperties; // eslint-disable-line no-unused-vars
/** @type {!Array<BooleanProperties>} */
const booleanProperties = [

@@ -355,6 +264,3 @@ 'disabled',

];
/**
* @param {BooleanProperties} key
*/
const getBooleanPropertyValue = key => /** @type boolean */ (properties.get(key));
const getBooleanPropertyValue = (key) => properties.get(key);
for (const booleanProperty of booleanProperties) {

@@ -370,5 +276,2 @@ // WebArea's treat focus differently than other nodes. They report whether their frame has focus,

}
/** @enum {'checked'|'pressed'} */
let TristateProperties; // eslint-disable-line no-unused-vars
/** @type {!Array<TristateProperties>} */
const tristateProperties = [

@@ -384,5 +287,2 @@ 'checked',

}
/** @enum {'level'|'valuemax'|'valuemin'} */
let NumericalProperties; // eslint-disable-line no-unused-vars
/** @type {!Array<NumericalProperties>} */
const numericalProperties = [

@@ -393,6 +293,3 @@ 'level',

];
/**
* @param {NumericalProperties} key
*/
const getNumericalPropertyValue = key => /** @type number */ (properties.get(key));
const getNumericalPropertyValue = (key) => properties.get(key);
for (const numericalProperty of numericalProperties) {

@@ -403,5 +300,2 @@ if (!properties.has(numericalProperty))

}
/** @enum {'autocomplete'|'haspopup'|'invalid'|'orientation'} */
let TokenProperties; // eslint-disable-line no-unused-vars
/** @type {!Array<TokenProperties>} */
const tokenProperties = [

@@ -413,6 +307,3 @@ 'autocomplete',

];
/**
* @param {TokenProperties} key
*/
const getTokenPropertyValue = key => /** @type string */ (properties.get(key));
const getTokenPropertyValue = (key) => properties.get(key);
for (const tokenProperty of tokenProperties) {

@@ -426,6 +317,2 @@ const value = getTokenPropertyValue(tokenProperty);

}
/**
* @param {!Array<!Protocol.Accessibility.AXNode>} payloads
* @return {!AXNode}
*/
static createTree(payloads) {

@@ -443,2 +330,1 @@ /** @type {!Map<string, !AXNode>} */

}
module.exports = { Accessibility };

4

lib/api.js

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

BrowserContext: require('./Browser').BrowserContext,
BrowserFetcher: require('./BrowserFetcher'),
BrowserFetcher: require('./BrowserFetcher').BrowserFetcher,
CDPSession: require('./Connection').CDPSession,

@@ -41,4 +41,4 @@ ConsoleMessage: require('./Page').ConsoleMessage,

Touchscreen: require('./Input').Touchscreen,
Tracing: require('./Tracing'),
Tracing: require('./Tracing').Tracing,
Worker: require('./Worker').Worker,
};

@@ -309,4 +309,4 @@ /**

['accessibility-events', 'accessibilityEvents'],
['clipboard-read', 'clipboardRead'],
['clipboard-write', 'clipboardWrite'],
['clipboard-read', 'clipboardReadWrite'],
['clipboard-write', 'clipboardReadWrite'],
['payment-handler', 'paymentHandler'],

@@ -313,0 +313,0 @@ // chrome-specific permissions we have.

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

"use strict";
/**

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

*/
const os = require('os');
const fs = require('fs');
const path = require('path');
const util = require('util');
const childProcess = require('child_process');
const extract = require('extract-zip');
const debugFetcher = require('debug')(`puppeteer:fetcher`);
const URL = require('url');
const { helper, assert } = require('./helper');
const removeRecursive = require('rimraf');
// @ts-ignore
const ProxyAgent = require('https-proxy-agent');
// @ts-ignore
const getProxyForUrl = require('proxy-from-env').getProxyForUrl;
Object.defineProperty(exports, "__esModule", { value: true });
const os = require("os");
const fs = require("fs");
const path = require("path");
const util = require("util");
const childProcess = require("child_process");
const https = require("https");
const http = require("http");
const extract = require("extract-zip");
const debug = require("debug");
const removeRecursive = require("rimraf");
const URL = require("url");
const ProxyAgent = require("https-proxy-agent");
const proxy_from_env_1 = require("proxy-from-env");
const helper_1 = require("./helper");
const debugFetcher = debug(`puppeteer:fetcher`);
const downloadURLs = {

@@ -55,8 +58,2 @@ chrome: {

};
/**
* @param {string} product
* @param {string} platform
* @param {string} revision
* @return {string}
*/
function archiveName(product, platform, revision) {

@@ -76,3 +73,2 @@ if (product === 'chrome') {

}
return null;
}

@@ -90,69 +86,57 @@ /**

}
const readdirAsync = helper.promisify(fs.readdir.bind(fs));
const mkdirAsync = helper.promisify(fs.mkdir.bind(fs));
const unlinkAsync = helper.promisify(fs.unlink.bind(fs));
const chmodAsync = helper.promisify(fs.chmod.bind(fs));
const readdirAsync = helper_1.helper.promisify(fs.readdir.bind(fs));
const mkdirAsync = helper_1.helper.promisify(fs.mkdir.bind(fs));
const unlinkAsync = helper_1.helper.promisify(fs.unlink.bind(fs));
const chmodAsync = helper_1.helper.promisify(fs.chmod.bind(fs));
function existsAsync(filePath) {
let fulfill = null;
const promise = new Promise(x => fulfill = x);
fs.access(filePath, err => fulfill(!err));
return promise;
return new Promise(resolve => {
fs.access(filePath, err => resolve(!err));
});
}
/**
*/
class BrowserFetcher {
/**
* @param {string} projectRoot
* @param {!BrowserFetcher.Options=} options
*/
constructor(projectRoot, options = {}) {
this._product = (options.product || 'chrome').toLowerCase();
assert(this._product === 'chrome' || this._product === 'firefox', `Unknown product: "${options.product}"`);
helper_1.assert(this._product === 'chrome' || this._product === 'firefox', `Unknown product: "${options.product}"`);
this._downloadsFolder = options.path || path.join(projectRoot, browserConfig[this._product].destination);
this._downloadHost = options.host || browserConfig[this._product].host;
this._platform = options.platform || '';
if (!this._platform) {
const platform = os.platform();
if (platform === 'darwin')
this._platform = 'mac';
else if (platform === 'linux')
this._platform = 'linux';
else if (platform === 'win32')
this._platform = os.arch() === 'x64' ? 'win64' : 'win32';
assert(this._platform, 'Unsupported platform: ' + os.platform());
this.setPlatform(options.platform);
helper_1.assert(downloadURLs[this._product][this._platform], 'Unsupported platform: ' + this._platform);
}
setPlatform(platformFromOptions) {
if (platformFromOptions) {
this._platform = platformFromOptions;
return;
}
assert(downloadURLs[this._product][this._platform], 'Unsupported platform: ' + this._platform);
const platform = os.platform();
if (platform === 'darwin')
this._platform = 'mac';
else if (platform === 'linux')
this._platform = 'linux';
else if (platform === 'win32')
this._platform = os.arch() === 'x64' ? 'win64' : 'win32';
else
helper_1.assert(this._platform, 'Unsupported platform: ' + os.platform());
}
/**
* @return {string}
*/
platform() {
return this._platform;
}
/**
* @return {string}
*/
product() {
return this._product;
}
/**
* @return {string}
*/
host() {
return this._downloadHost;
}
/**
* @param {string} revision
* @return {!Promise<boolean>}
*/
canDownload(revision) {
const url = downloadURL(this._product, this._platform, this._downloadHost, revision);
let resolve;
const promise = new Promise(x => resolve = x);
const request = httpRequest(url, 'HEAD', response => {
resolve(response.statusCode === 200);
return new Promise(resolve => {
const request = httpRequest(url, 'HEAD', response => {
resolve(response.statusCode === 200);
});
request.on('error', error => {
console.error(error);
resolve(false);
});
});
request.on('error', error => {
console.error(error);
resolve(false);
});
return promise;
}

@@ -186,5 +170,2 @@ /**

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

@@ -196,14 +177,7 @@ if (!await existsAsync(this._downloadsFolder))

}
/**
* @param {string} revision
*/
async remove(revision) {
const folderPath = this._getFolderPath(revision);
assert(await existsAsync(folderPath), `Failed to remove: revision ${revision} is not downloaded`);
helper_1.assert(await existsAsync(folderPath), `Failed to remove: revision ${revision} is not downloaded`);
await new Promise(fulfill => removeRecursive(folderPath, fulfill));
}
/**
* @param {string} revision
* @return {!BrowserFetcher.RevisionInfo}
*/
revisionInfo(revision) {

@@ -248,7 +222,3 @@ const folderPath = this._getFolderPath(revision);

}
module.exports = BrowserFetcher;
/**
* @param {string} folderPath
* @return {?{product: string, platform: string, revision: string}}
*/
exports.BrowserFetcher = BrowserFetcher;
function parseFolderPath(product, folderPath) {

@@ -299,9 +269,2 @@ const name = path.basename(folderPath);

}
/**
* Install from a zip, tar.bz2 or dmg file.
*
* @param {string} archivePath
* @param {string} folderPath
* @return {!Promise<?Error>}
*/
function install(archivePath, folderPath) {

@@ -318,13 +281,40 @@ debugFetcher(`Installing ${archivePath} to ${folderPath}`);

}
/**
* @param {string} zipPath
* @param {string} folderPath
* @return {!Promise<?Error>}
*/
async function extractZip(zipPath, folderPath) {
try {
await extract(zipPath, { dir: folderPath });
const nodeVersion = process.version;
/* There is currently a bug with extract-zip and Node v14.0.0 that
* causes extractZip to silently fail:
* https://github.com/puppeteer/puppeteer/issues/5719
*
* Rather than silenty fail if the user is on Node 14 we instead
* detect that and throw an error directing the user to that bug. The
* rejection message below is surfaced to the user in the command
* line.
*
* The issue seems to be in streams never resolving so we wrap the
* call in a timeout and give it 10s to resolve before deciding on
* an error.
*
* If the user is on Node < 14 we maintain the behaviour we had before
* this patch.
*/
if (nodeVersion.startsWith('v14.')) {
let timeoutReject;
const timeoutPromise = new Promise((resolve, reject) => { timeoutReject = reject; });
const timeoutToken = setTimeout(() => {
const error = new Error(`Puppeteer currently does not work on Node v14 due to an upstream bug. Please see: https://github.com/puppeteer/puppeteer/issues/5719 for details.`);
timeoutReject(error);
}, 10 * 1000);
await Promise.race([
extract(zipPath, { dir: folderPath }),
timeoutPromise
]);
clearTimeout(timeoutToken);
}
catch (error) {
return error;
else {
try {
await extract(zipPath, { dir: folderPath });
}
catch (error) {
return error;
}
}

@@ -338,4 +328,5 @@ }

function extractTar(tarPath, folderPath) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const tar = require('tar-fs');
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-var-requires
const bzip = require('unbzip2-stream');

@@ -362,3 +353,3 @@ return new Promise((fulfill, reject) => {

const mountCommand = `hdiutil attach -nobrowse -noautoopen "${dmgPath}"`;
childProcess.exec(mountCommand, (err, stdout, stderr) => {
childProcess.exec(mountCommand, (err, stdout) => {
if (err)

@@ -376,3 +367,3 @@ return reject(err);

debugFetcher(`Copying ${copyPath} to ${folderPath}`);
childProcess.exec(`cp -R "${copyPath}" "${folderPath}"`, (err, stdout) => {
childProcess.exec(`cp -R "${copyPath}" "${folderPath}"`, err => {
if (err)

@@ -399,6 +390,8 @@ reject(err);

function httpRequest(url, method, response) {
/** @type {Object} */
let options = URL.parse(url);
options.method = method;
const proxyURL = getProxyForUrl(url);
const urlParsed = URL.parse(url);
let options = {
...urlParsed,
method,
};
const proxyURL = proxy_from_env_1.getProxyForUrl(url);
if (proxyURL) {

@@ -414,10 +407,12 @@ if (url.startsWith('http:')) {

else {
/** @type {Object} */
const parsedProxyURL = URL.parse(proxyURL);
parsedProxyURL.secureProxy = parsedProxyURL.protocol === 'https:';
options.agent = new ProxyAgent(parsedProxyURL);
const proxyOptions = {
...parsedProxyURL,
secureProxy: parsedProxyURL.protocol === 'https:',
};
options.agent = new ProxyAgent(proxyOptions);
options.rejectUnauthorized = false;
}
}
const requestCallback = res => {
const requestCallback = (res) => {
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location)

@@ -429,22 +424,6 @@ httpRequest(res.headers.location, method, response);

const request = options.protocol === 'https:' ?
require('https').request(options, requestCallback) :
require('http').request(options, requestCallback);
https.request(options, requestCallback) :
http.request(options, requestCallback);
request.end();
return request;
}
/**
* @typedef {Object} BrowserFetcher.Options
* @property {string=} platform
* @property {string=} product
* @property {string=} path
* @property {string=} host
*/
/**
* @typedef {Object} BrowserFetcher.RevisionInfo
* @property {string} folderPath
* @property {string} executablePath
* @property {string} url
* @property {boolean} local
* @property {string} revision
* @property {string} product
*/

@@ -188,3 +188,3 @@ /**

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

@@ -191,0 +191,0 @@ async setContent(html, options = {}) {

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

"use strict";
/**

@@ -16,2 +17,3 @@ * Copyright 2018 Google Inc. All rights reserved.

*/
Object.defineProperty(exports, "__esModule", { value: true });
class CustomError extends Error {

@@ -26,4 +28,2 @@ constructor(message) {

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

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

"use strict";
/**

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

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

@@ -73,2 +75,1 @@ Close: 'close',

};
module.exports = { Events };
import { Browser as RealBrowser, BrowserContext as RealBrowserContext} from './Browser.js';
import {Target as RealTarget} from './Target.js';
import {Page as RealPage} from './Page.js';
import {Mouse as RealMouse, Keyboard as RealKeyboard, Touchscreen as RealTouchscreen} from './Input.js';
import {Frame as RealFrame, FrameManager as RealFrameManager} from './FrameManager.js';

@@ -11,5 +10,2 @@ import {DOMWorld as RealDOMWorld} from './DOMWorld.js';

module Puppeteer {
export class Mouse extends RealMouse {}
export class Keyboard extends RealKeyboard {}
export class Touchscreen extends RealTouchscreen {}
export class Browser extends RealBrowser {}

@@ -26,2 +22,8 @@ export class BrowserContext extends RealBrowserContext {}

/* TODO(jacktfranklin@): once DOMWorld, Page, and FrameManager are in TS
* we can remove this and instead use the type defined in LifeCycleWatcher
*/
export type PuppeteerLifeCycleEvent = 'load' | 'domcontentloaded' | 'networkidle0' | 'networkidle2';
export interface ConnectionTransport {

@@ -28,0 +30,0 @@ send(string);

@@ -84,3 +84,3 @@ /**

* @param {string} url
* @param {!{referer?: string, timeout?: number, waitUntil?: string|!Array<string>}=} options
* @param {!{referer?: string, timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}

@@ -127,3 +127,3 @@ */

* @param {!Puppeteer.Frame} frame
* @param {!{timeout?: number, waitUntil?: string|!Array<string>}=} options
* @param {!{timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}

@@ -374,3 +374,3 @@ */

* @param {string} url
* @param {!{referer?: string, timeout?: number, waitUntil?: string|!Array<string>}=} options
* @param {!{referer?: string, timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}

@@ -382,3 +382,3 @@ */

/**
* @param {!{timeout?: number, waitUntil?: string|!Array<string>}=} options
* @param {!{timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}

@@ -458,3 +458,3 @@ */

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

@@ -461,0 +461,0 @@ async setContent(html, options = {}) {

@@ -18,10 +18,9 @@ "use strict";

*/
const Errors = require("./Errors");
const Errors_1 = 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);
const util_1 = require("util");
const openAsync = util_1.promisify(fs.open);
const writeAsync = util_1.promisify(fs.write);
const closeAsync = util_1.promisify(fs.close);
exports.debugError = debug('puppeteer:error');

@@ -123,3 +122,3 @@ function assert(value, message) {

eventTimeout = setTimeout(() => {
rejectCallback(new TimeoutError('Timeout exceeded while waiting for event'));
rejectCallback(new Errors_1.TimeoutError('Timeout exceeded while waiting for event'));
}, timeout);

@@ -156,3 +155,3 @@ }

let reject;
const timeoutError = new TimeoutError(`waiting for ${taskName} failed: timeout ${timeout}ms exceeded`);
const timeoutError = new Errors_1.TimeoutError(`waiting for ${taskName} failed: timeout ${timeout}ms exceeded`);
const timeoutPromise = new Promise((resolve, x) => reject = x);

@@ -196,3 +195,3 @@ let timeoutTimer = null;

exports.helper = {
promisify,
promisify: util_1.promisify,
evaluationString,

@@ -199,0 +198,0 @@ readProtocolStream,

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

"use strict";
/**

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

*/
const { assert } = require('./helper');
// CDPSession is used only as a typedef
// eslint-disable-next-line no-unused-vars
const { CDPSession } = require('./Connection');
const { keyDefinitions } = require('./USKeyboardLayout');
/**
* @typedef {Object} KeyDescription
* @property {number} keyCode
* @property {string} key
* @property {string} text
* @property {string} code
* @property {number} location
*/
Object.defineProperty(exports, "__esModule", { value: true });
const helper_1 = require("./helper");
const USKeyboardLayout_1 = require("./USKeyboardLayout");
class Keyboard {
/**
* @param {!CDPSession} client
*/
constructor(client) {
this._client = client;
this._modifiers = 0;
this._pressedKeys = new Set();
this._client = client;
}
/**
* @param {string} key
* @param {{text?: string}=} options
*/
async down(key, options = { text: undefined }) {

@@ -62,6 +46,2 @@ const description = this._keyDescriptionForString(key);

}
/**
* @param {string} key
* @return {number}
*/
_modifierBit(key) {

@@ -78,6 +58,2 @@ if (key === 'Alt')

}
/**
* @param {string} keyString
* @return {KeyDescription}
*/
_keyDescriptionForString(keyString) {

@@ -92,4 +68,4 @@ const shift = this._modifiers & 8;

};
const definition = keyDefinitions[keyString];
assert(definition, `Unknown key: "${keyString}"`);
const definition = USKeyboardLayout_1.keyDefinitions[keyString];
helper_1.assert(definition, `Unknown key: "${keyString}"`);
if (definition.key)

@@ -118,5 +94,2 @@ description.key = definition.key;

}
/**
* @param {string} key
*/
async up(key) {

@@ -135,16 +108,12 @@ const description = this._keyDescriptionForString(key);

}
/**
* @param {string} char
*/
async sendCharacter(char) {
await this._client.send('Input.insertText', { text: char });
}
/**
* @param {string} text
* @param {{delay: (number|undefined)}=} options
*/
charIsKey(char) {
return !!USKeyboardLayout_1.keyDefinitions[char];
}
async type(text, options) {
const delay = (options && options.delay) || null;
for (const char of text) {
if (keyDefinitions[char]) {
if (this.charIsKey(char)) {
await this.press(char, { delay });

@@ -159,6 +128,2 @@ }

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

@@ -172,2 +137,3 @@ const { delay = null } = options;

}
exports.Keyboard = Keyboard;
class Mouse {

@@ -179,14 +145,8 @@ /**

constructor(client, keyboard) {
this._client = client;
this._keyboard = keyboard;
this._x = 0;
this._y = 0;
/** @type {'none'|'left'|'right'|'middle'} */
this._button = 'none';
this._client = client;
this._keyboard = keyboard;
}
/**
* @param {number} x
* @param {number} y
* @param {!{steps?: number}=} options
*/
async move(x, y, options = {}) {

@@ -207,7 +167,2 @@ const { steps = 1 } = options;

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

@@ -231,5 +186,2 @@ const { delay = null } = options;

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

@@ -263,7 +215,4 @@ const { button = 'left', clickCount = 1 } = options;

}
exports.Mouse = Mouse;
class Touchscreen {
/**
* @param {CDPSession} client
* @param {Keyboard} keyboard
*/
constructor(client, keyboard) {

@@ -298,2 +247,2 @@ this._client = client;

}
module.exports = { Keyboard, Mouse, Touchscreen };
exports.Touchscreen = Touchscreen;

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

const path = require('path');
const files = filePaths.map(filePath => path.resolve(filePath));
// eslint-disable-next-line @typescript-eslint/no-var-requires
const fs = require('fs');
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { promisify } = require('util');
const access = promisify(fs.access);
// Locate all files and confirm that they exist.
const files = await Promise.all(filePaths.map(async (filePath) => {
const resolvedPath = path.resolve(filePath);
try {
await access(resolvedPath, fs.constants.R_OK);
}
catch (error) {
if (error.code === 'ENOENT')
throw new Error(`${filePath} does not exist or is not readable`);
}
return resolvedPath;
}));
const { objectId } = this._remoteObject;

@@ -255,0 +271,0 @@ const { node } = await this._client.send('DOM.describeNode', { objectId });

@@ -23,3 +23,3 @@ /**

const childProcess = require('child_process');
const BrowserFetcher = require('./BrowserFetcher');
const { BrowserFetcher } = require('./BrowserFetcher');
const { Connection } = require('./Connection');

@@ -26,0 +26,0 @@ const { Browser } = require('./Browser');

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

"use strict";
/**

@@ -16,12 +17,13 @@ * Copyright 2019 Google Inc. All rights reserved.

*/
const { helper, assert } = require('./helper');
const { Events } = require('./Events');
const { TimeoutError } = require('./Errors');
Object.defineProperty(exports, "__esModule", { value: true });
const helper_1 = require("./helper");
const Events_1 = require("./Events");
const Errors_1 = require("./Errors");
const puppeteerToProtocolLifecycle = new Map([
['load', 'load'],
['domcontentloaded', 'DOMContentLoaded'],
['networkidle0', 'networkIdle'],
['networkidle2', 'networkAlmostIdle'],
]);
class LifecycleWatcher {
/**
* @param {!Puppeteer.FrameManager} frameManager
* @param {!Puppeteer.Frame} frame
* @param {string|!Array<string>} waitUntil
* @param {number} timeout
*/
constructor(frameManager, frame, waitUntil, timeout) {

@@ -34,3 +36,3 @@ if (Array.isArray(waitUntil))

const protocolEvent = puppeteerToProtocolLifecycle.get(value);
assert(protocolEvent, 'Unknown value for options.waitUntil: ' + value);
helper_1.assert(protocolEvent, 'Unknown value for options.waitUntil: ' + value);
return protocolEvent;

@@ -45,7 +47,7 @@ });

this._eventListeners = [
helper.addEventListener(frameManager._client, Events.CDPSession.Disconnected, () => this._terminate(new Error('Navigation failed because browser has disconnected!'))),
helper.addEventListener(this._frameManager, Events.FrameManager.LifecycleEvent, this._checkLifecycleComplete.bind(this)),
helper.addEventListener(this._frameManager, Events.FrameManager.FrameNavigatedWithinDocument, this._navigatedWithinDocument.bind(this)),
helper.addEventListener(this._frameManager, Events.FrameManager.FrameDetached, this._onFrameDetached.bind(this)),
helper.addEventListener(this._frameManager.networkManager(), Events.NetworkManager.Request, this._onRequest.bind(this)),
helper_1.helper.addEventListener(frameManager._client, Events_1.Events.CDPSession.Disconnected, () => this._terminate(new Error('Navigation failed because browser has disconnected!'))),
helper_1.helper.addEventListener(this._frameManager, Events_1.Events.FrameManager.LifecycleEvent, this._checkLifecycleComplete.bind(this)),
helper_1.helper.addEventListener(this._frameManager, Events_1.Events.FrameManager.FrameNavigatedWithinDocument, this._navigatedWithinDocument.bind(this)),
helper_1.helper.addEventListener(this._frameManager, Events_1.Events.FrameManager.FrameDetached, this._onFrameDetached.bind(this)),
helper_1.helper.addEventListener(this._frameManager.networkManager(), Events_1.Events.NetworkManager.Request, this._onRequest.bind(this)),
];

@@ -67,5 +69,2 @@ this._sameDocumentNavigationPromise = new Promise(fulfill => {

}
/**
* @param {!Puppeteer.Request} request
*/
_onRequest(request) {

@@ -76,5 +75,2 @@ if (request.frame() !== this._frame || !request.isNavigationRequest())

}
/**
* @param {!Puppeteer.Frame} frame
*/
_onFrameDetached(frame) {

@@ -87,41 +83,20 @@ if (this._frame === frame) {

}
/**
* @return {?Puppeteer.Response}
*/
navigationResponse() {
return this._navigationRequest ? this._navigationRequest.response() : null;
}
/**
* @param {!Error} error
*/
_terminate(error) {
this._terminationCallback.call(null, error);
}
/**
* @return {!Promise<?Error>}
*/
sameDocumentNavigationPromise() {
return this._sameDocumentNavigationPromise;
}
/**
* @return {!Promise<?Error>}
*/
newDocumentNavigationPromise() {
return this._newDocumentNavigationPromise;
}
/**
* @return {!Promise}
*/
lifecyclePromise() {
return this._lifecyclePromise;
}
/**
* @return {!Promise<?Error>}
*/
timeoutOrTerminationPromise() {
return Promise.race([this._timeoutPromise, this._terminationPromise]);
}
/**
* @return {!Promise<?Error>}
*/
_createTimeoutPromise() {

@@ -132,7 +107,4 @@ if (!this._timeout)

return new Promise(fulfill => this._maximumTimer = setTimeout(fulfill, this._timeout))
.then(() => new TimeoutError(errorMessage));
.then(() => new Errors_1.TimeoutError(errorMessage));
}
/**
* @param {!Puppeteer.Frame} frame
*/
_navigatedWithinDocument(frame) {

@@ -173,12 +145,6 @@ if (frame !== this._frame)

dispose() {
helper.removeEventListeners(this._eventListeners);
helper_1.helper.removeEventListeners(this._eventListeners);
clearTimeout(this._maximumTimer);
}
}
const puppeteerToProtocolLifecycle = new Map([
['load', 'load'],
['domcontentloaded', 'DOMContentLoaded'],
['networkidle0', 'networkIdle'],
['networkidle2', 'networkAlmostIdle'],
]);
module.exports = { LifecycleWatcher };
exports.LifecycleWatcher = LifecycleWatcher;

@@ -27,3 +27,3 @@ /**

const { Keyboard, Mouse, Touchscreen } = require('./Input');
const Tracing = require('./Tracing');
const { Tracing } = require('./Tracing');
const { helper, debugError, assert } = require('./helper');

@@ -613,3 +613,3 @@ const { Coverage } = require('./Coverage');

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

@@ -621,3 +621,3 @@ async setContent(html, options) {

* @param {string} url
* @param {!{referer?: string, timeout?: number, waitUntil?: string|!Array<string>}=} options
* @param {!{referer?: string, timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}

@@ -629,3 +629,3 @@ */

/**
* @param {!{timeout?: number, waitUntil?: string|!Array<string>}=} options
* @param {!{timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}

@@ -642,3 +642,3 @@ */

/**
* @param {!{timeout?: number, waitUntil?: string|!Array<string>}=} options
* @param {!{timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}

@@ -685,3 +685,3 @@ */

/**
* @param {!{timeout?: number, waitUntil?: string|!Array<string>}=} options
* @param {!{timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}

@@ -693,3 +693,3 @@ */

/**
* @param {!{timeout?: number, waitUntil?: string|!Array<string>}=} options
* @param {!{timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}

@@ -701,3 +701,3 @@ */

/**
* @param {!{timeout?: number, waitUntil?: string|!Array<string>}=} options
* @param {!{timeout?: number, waitUntil?: !Puppeteer.PuppeteerLifeCycleEvent|!Array<!Puppeteer.PuppeteerLifeCycleEvent>}=} options
* @return {!Promise<?Puppeteer.Response>}

@@ -704,0 +704,0 @@ */

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

const Launcher = require('./Launcher');
const BrowserFetcher = require('./BrowserFetcher');
const { BrowserFetcher } = require('./BrowserFetcher');
const Errors = require('./Errors');

@@ -118,4 +118,14 @@ const DeviceDescriptors = require('./DeviceDescriptors');

}
/** TODO(jacktfranklin@): Once this file is TS we can type this
* using the BrowserFectcherOptions interface.
*/
/**
* @param {!BrowserFetcher.Options=} options
* @typedef {Object} BrowserFetcherOptions
* @property {('linux'|'mac'|'win32'|'win64')=} platform
* @property {('chrome'|'firefox')=} product
* @property {string=} path
* @property {string=} host
*/
/**
* @param {!BrowserFetcherOptions} options
* @return {!BrowserFetcher}

@@ -122,0 +132,0 @@ */

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

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

@@ -16,20 +18,11 @@ * Copyright 2017 Google Inc. All rights reserved.

*/
const { helper, assert } = require('./helper');
// Used as a TypeDef
// eslint-disable-next-line no-unused-vars
const { CDPSession } = require('./Connection');
const helper_1 = require("./helper");
class Tracing {
/**
* @param {!CDPSession} client
*/
constructor(client) {
this._client = client;
this._recording = false;
this._path = '';
this._client = client;
}
/**
* @param {!{path?: string, screenshots?: boolean, categories?: !Array<string>}} options
*/
async start(options = {}) {
assert(!this._recording, 'Cannot start recording trace while already recording trace.');
helper_1.assert(!this._recording, 'Cannot start recording trace while already recording trace.');
const defaultCategories = [

@@ -51,5 +44,2 @@ '-*', 'devtools.timeline', 'v8.execute', 'disabled-by-default-devtools.timeline',

}
/**
* @return {!Promise<!Buffer>}
*/
async stop() {

@@ -59,3 +49,3 @@ let fulfill;

this._client.once('Tracing.tracingComplete', event => {
helper.readProtocolStream(this._client, event.stream, this._path).then(fulfill);
helper_1.helper.readProtocolStream(this._client, event.stream, this._path).then(fulfill);
});

@@ -67,2 +57,2 @@ await this._client.send('Tracing.end');

}
module.exports = Tracing;
exports.Tracing = Tracing;

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

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

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

*/
const EventEmitter = require('events');
const { debugError } = require('./helper');
const { ExecutionContext } = require('./ExecutionContext');
const { JSHandle } = require('./JSHandle');
// Used as a TypeDef
// eslint-disable-next-line no-unused-vars
const { CDPSession } = require('./Connection');
class Worker extends EventEmitter {
/**
* @param {CDPSession} client
* @param {string} url
* @param {function(string, !Array<!JSHandle>, Protocol.Runtime.StackTrace=):void} consoleAPICalled
* @param {function(!Protocol.Runtime.ExceptionDetails):void} exceptionThrown
*/
const events_1 = require("events");
const helper_1 = require("./helper");
const ExecutionContext_1 = require("./ExecutionContext");
const JSHandle_1 = require("./JSHandle");
class Worker extends events_1.EventEmitter {
constructor(client, url, consoleAPICalled, exceptionThrown) {

@@ -36,39 +29,23 @@ super();

this._executionContextPromise = new Promise(x => this._executionContextCallback = x);
/** @type {function(!Protocol.Runtime.RemoteObject):!JSHandle} */
let jsHandleFactory;
this._client.once('Runtime.executionContextCreated', async (event) => {
jsHandleFactory = remoteObject => new JSHandle(executionContext, client, remoteObject);
const executionContext = new ExecutionContext(client, event.context, null);
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
jsHandleFactory = remoteObject => new JSHandle_1.JSHandle(executionContext, client, remoteObject);
const executionContext = new ExecutionContext_1.ExecutionContext(client, event.context, null);
this._executionContextCallback(executionContext);
});
// This might fail if the target is closed before we recieve all execution contexts.
this._client.send('Runtime.enable', {}).catch(debugError);
this._client.send('Runtime.enable', {}).catch(helper_1.debugError);
this._client.on('Runtime.consoleAPICalled', event => consoleAPICalled(event.type, event.args.map(jsHandleFactory), event.stackTrace));
this._client.on('Runtime.exceptionThrown', exception => exceptionThrown(exception.exceptionDetails));
}
/**
* @return {string}
*/
url() {
return this._url;
}
/**
* @return {!Promise<ExecutionContext>}
*/
async executionContext() {
return this._executionContextPromise;
}
/**
* @param {Function|string} pageFunction
* @param {!Array<*>} args
* @return {!Promise<*>}
*/
async evaluate(pageFunction, ...args) {
return (await this._executionContextPromise).evaluate(pageFunction, ...args);
}
/**
* @param {Function|string} pageFunction
* @param {!Array<*>} args
* @return {!Promise<!JSHandle>}
*/
async evaluateHandle(pageFunction, ...args) {

@@ -78,2 +55,2 @@ return (await this._executionContextPromise).evaluateHandle(pageFunction, ...args);

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

@@ -29,5 +29,3 @@ "main": "index.js",

"apply-next-version": "node utils/apply_next_version.js",
"bundle": "npm run tsc && npx browserify -r ./index.js:puppeteer -o utils/browser/puppeteer-web.js",
"test-types": "node utils/doclint/generate_types && tsc --version && tsc -p utils/doclint/generate_types/test/",
"unit-bundle": "mocha --config mocha-config/browser-bundle-tests.js",
"update-protocol-d-ts": "node utils/protocol-types-generator",

@@ -75,3 +73,3 @@ "test-install": "scripts/test-install.sh"

"expect": "^25.2.7",
"jpeg-js": "^0.3.4",
"jpeg-js": "^0.3.7",
"minimist": "^1.2.0",

@@ -81,3 +79,3 @@ "mocha": "^7.1.1",

"pixelmatch": "^4.0.2",
"pngjs": "^3.3.3",
"pngjs": "^5.0.0",
"text-diff": "^1.0.1",

@@ -84,0 +82,0 @@ "typescript": "3.8.3"

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

###### [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)
###### [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)

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

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

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

@@ -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.1/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.2/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