Socket
Socket
Sign inDemoInstall

puppeteer-core

Package Overview
Dependencies
8
Maintainers
2
Versions
222
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.19.0 to 1.20.0

x.js

49

CONTRIBUTING.md

@@ -15,4 +15,4 @@ <!-- gen:toc -->

- [For Project Maintainers](#for-project-maintainers)
* [Releasing to NPM](#releasing-to-npm)
* [Updating NPM dist tags](#updating-npm-dist-tags)
* [Releasing to npm](#releasing-to-npm)
* [Updating npm dist tags](#updating-npm-dist-tags)
<!-- gen:stop -->

@@ -80,2 +80,3 @@

When authoring new API methods, consider the following:
- Expose as little information as needed. When in doubt, don’t expose new information.

@@ -128,5 +129,5 @@ - Methods are used in favor of getters/setters.

All public API should have a descriptive entry in the [docs/api.md](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md). There's a [documentation linter](https://github.com/GoogleChrome/puppeteer/tree/master/utils/doclint) which makes sure documentation is aligned with the codebase.
All public API should have a descriptive entry in [`docs/api.md`](https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md). There's a [documentation linter](https://github.com/GoogleChrome/puppeteer/tree/master/utils/doclint) which makes sure documentation is aligned with the codebase.
To run documentation linter, use:
To run the documentation linter, use:

@@ -153,3 +154,3 @@ ```bash

Puppeteer tests are located in [test/test.js](https://github.com/GoogleChrome/puppeteer/blob/master/test/test.js)
Puppeteer tests are located in [`test/test.js`](https://github.com/GoogleChrome/puppeteer/blob/master/test/test.js)
and are written with a [TestRunner](https://github.com/GoogleChrome/puppeteer/tree/master/utils/testrunner) framework.

@@ -185,3 +186,3 @@ Despite being named 'unit', these are integration tests, making sure public API methods and events work as expected.

expect(response.ok).toBe(true);
})
});
```

@@ -197,3 +198,3 @@

expect(response.ok).toBe(true);
})
});
```

@@ -227,3 +228,3 @@

Every public API method or event should be called at least once in tests. To ensure this, there's a coverage command which tracks calls to public API and reports back if some methods/events were not called.
Every public API method or event should be called at least once in tests. To ensure this, there's a `coverage` command which tracks calls to public API and reports back if some methods/events were not called.

@@ -242,7 +243,8 @@ Run coverage:

## Releasing to NPM
## Releasing to npm
Releasing to NPM consists of 3 phases:
Releasing to npm consists of the following phases:
1. Source Code: mark a release.
1. Bump `package.json` version following the SEMVER rules and send a PR titled `'chore: mark version vXXX.YYY.ZZZ'` ([example](https://github.com/GoogleChrome/puppeteer/commit/808bf8e5582482a1d849ff22a51e52024810905c)).
1. Bump `package.json` version following the SEMVER rules, run `npm run doc` to update the docs accordingly, and send a PR titled `'chore: mark version vXXX.YYY.ZZZ'` ([example](https://github.com/GoogleChrome/puppeteer/commit/808bf8e5582482a1d849ff22a51e52024810905c)).
2. Make sure the PR passes **all checks**.

@@ -252,12 +254,12 @@ - **WHY**: there are linters in place that help to avoid unnecessary errors, e.g. [like this](https://github.com/GoogleChrome/puppeteer/pull/2446)

4. Once merged, publish release notes using the "create new tag" option.
- **NOTE**: tag names are prefixed with `'v'`, e.g. for version `1.4.0` tag is `v1.4.0`.
2. Publish `puppeteer` to NPM.
- **NOTE**: tag names are prefixed with `'v'`, e.g. for version `1.4.0` the tag is `v1.4.0`.
2. Publish `puppeteer` to npm.
1. On your local machine, pull from [upstream](https://github.com/GoogleChrome/puppeteer) and make sure the last commit is the one just merged.
2. Run `git status` and make sure there are no untracked files.
- **WHY**: this is to avoid bundling unnecessary files to NPM package
- **WHY**: this is to avoid adding unnecessary files to the npm package.
3. Run [`pkgfiles`](https://www.npmjs.com/package/pkgfiles) to make sure you don't publish anything unnecessary.
4. Run `npm publish`. This will publish `puppeteer` package.
3. Publish `puppeteer-core` to NPM.
1. Run `./utils/prepare_puppeteer_core.js`. The script will change the name inside `package.json` to `puppeteer-core`.
2. Run `npm publish`. This will publish `puppeteer-core` package.
4. Run `npm publish`. This publishes the `puppeteer` package.
3. Publish `puppeteer-core` to npm.
1. Run `./utils/prepare_puppeteer_core.js`. The script changes the name inside `package.json` to `puppeteer-core`.
2. Run `npm publish`. This publishes the `puppeteer-core` package.
3. Run `git reset --hard` to reset the changes to `package.json`.

@@ -269,8 +271,9 @@ 4. Source Code: mark post-release.

## Updating NPM dist tags
## Updating npm dist tags
For both `puppeteer` and `puppeteer-firefox` we maintain the following NPM Tags:
- `chrome-*` tags, e.g. `chrome-75` and so on. These tags match Puppeteer version that corresponds to the `chrome-*` release.
- `chrome-stable` tag. This tag points to the Puppeteer version that works with current Chrome stable.
For both `puppeteer` and `puppeteer-core` we maintain the following npm tags:
- `chrome-*` tags, e.g. `chrome-75` and so on. These tags match the Puppeteer version that corresponds to the `chrome-*` release.
- `chrome-stable` tag. This tag points to the Puppeteer version that works with the current Chrome stable release.
These tags are updated on every Puppeteer release.

@@ -280,3 +283,3 @@

Manging tags 101:
Managing tags 101:

@@ -283,0 +286,0 @@ ```bash

@@ -475,2 +475,26 @@ /**

{
'name': 'iPhone XR',
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1',
'viewport': {
'width': 414,
'height': 896,
'deviceScaleFactor': 3,
'isMobile': true,
'hasTouch': true,
'isLandscape': false
}
},
{
'name': 'iPhone XR landscape',
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1',
'viewport': {
'width': 896,
'height': 414,
'deviceScaleFactor': 3,
'isMobile': true,
'hasTouch': true,
'isLandscape': true
}
},
{
'name': 'JioPhone 2',

@@ -477,0 +501,0 @@ 'userAgent': 'Mozilla/5.0 (Mobile; LYF/F300B/LYF-F300B-001-01-15-130718-i;Android; rv:48.0) Gecko/48.0 Firefox/48.0 KAIOS/2.5',

@@ -392,24 +392,12 @@ /**

/**
* @param {string} selector
* @param {!Array<string>} values
* @return {!Promise<!Array<string>>}
*/
select(selector, ...values){
for (const value of values)
assert(helper.isString(value), 'Values must be strings. Found value "' + value + '" of type "' + (typeof value) + '"');
return this.$eval(selector, (element, values) => {
if (element.nodeName.toLowerCase() !== 'select')
throw new Error('Element is not a <select> element.');
const options = Array.from(element.options);
element.value = undefined;
for (const option of options) {
option.selected = values.includes(option.value);
if (option.selected && !element.multiple)
break;
}
element.dispatchEvent(new Event('input', { 'bubbles': true }));
element.dispatchEvent(new Event('change', { 'bubbles': true }));
return options.filter(option => option.selected).map(option => option.value);
}, values);
* @param {string} selector
* @param {!Array<string>} values
* @return {!Promise<!Array<string>>}
*/
async select(selector, ...values) {
const handle = await this.$(selector);
assert(handle, 'No node found for selector: ' + selector);
const result = await handle.select(...values);
await handle.dispose();
return result;
}

@@ -416,0 +404,0 @@

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

this._page = page;
this._networkManager = new NetworkManager(client, ignoreHTTPSErrors);
this._networkManager.setFrameManager(this);
this._networkManager = new NetworkManager(client, ignoreHTTPSErrors, this);
this._timeoutSettings = timeoutSettings;

@@ -42,0 +41,0 @@ /** @type {!Map<string, !Frame>} */

@@ -179,5 +179,7 @@ /**

* @param {function} predicate
* @param {number} timeout
* @param {!Promise<!Error>} abortPromise
* @return {!Promise}
*/
static waitForEvent(emitter, eventName, predicate, timeout) {
static async waitForEvent(emitter, eventName, predicate, timeout, abortPromise) {
let eventTimeout, resolveCallback, rejectCallback;

@@ -191,3 +193,2 @@ const promise = new Promise((resolve, reject) => {

return;
cleanup();
resolveCallback(event);

@@ -197,3 +198,2 @@ });

eventTimeout = setTimeout(() => {
cleanup();
rejectCallback(new TimeoutError('Timeout exceeded while waiting for event'));

@@ -206,3 +206,12 @@ }, timeout);

}
return promise;
const result = await Promise.race([promise, abortPromise]).then(r => {
cleanup();
return r;
}, e => {
cleanup();
throw e;
});
if (result instanceof Error)
throw result;
return result;
}

@@ -209,0 +218,0 @@

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

/**
* @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

@@ -55,7 +73,7 @@ * @return {!Promise<?JSHandle>}

async getProperty(propertyName) {
const objectHandle = await this._context.evaluateHandle((object, propertyName) => {
const objectHandle = await this.evaluateHandle((object, propertyName) => {
const result = {__proto__: null};
result[propertyName] = object[propertyName];
return result;
}, this, propertyName);
}, propertyName);
const properties = await objectHandle.getProperties();

@@ -165,3 +183,3 @@ const result = properties.get(propertyName) || null;

async _scrollIntoViewIfNeeded() {
const error = await this.executionContext().evaluate(async(element, pageJavascriptEnabled) => {
const error = await this.evaluate(async(element, pageJavascriptEnabled) => {
if (!element.isConnected)

@@ -186,3 +204,3 @@ return 'Node is detached from document';

return false;
}, this, this._page._javascriptEnabled);
}, this._page._javascriptEnabled);
if (error)

@@ -274,2 +292,26 @@ throw new Error(error);

/**
* @param {!Array<string>} values
* @return {!Promise<!Array<string>>}
*/
async select(...values) {
for (const value of values)
assert(helper.isString(value), 'Values must be strings. Found value "' + value + '" of type "' + (typeof value) + '"');
return this.evaluate((element, values) => {
if (element.nodeName.toLowerCase() !== 'select')
throw new Error('Element is not a <select> element.');
const options = Array.from(element.options);
element.value = undefined;
for (const option of options) {
option.selected = values.includes(option.value);
if (option.selected && !element.multiple)
break;
}
element.dispatchEvent(new Event('input', { 'bubbles': true }));
element.dispatchEvent(new Event('change', { 'bubbles': true }));
return options.filter(option => option.selected).map(option => option.value);
}, values);
}
/**
* @param {!Array<string>} filePaths

@@ -290,3 +332,3 @@ */

async focus() {
await this.executionContext().evaluate(element => element.focus(), this);
await this.evaluate(element => element.focus());
}

@@ -401,5 +443,5 @@

async $(selector) {
const handle = await this.executionContext().evaluateHandle(
const handle = await this.evaluateHandle(
(element, selector) => element.querySelector(selector),
this, selector
selector
);

@@ -418,5 +460,5 @@ const element = handle.asElement();

async $$(selector) {
const arrayHandle = await this.executionContext().evaluateHandle(
const arrayHandle = await this.evaluateHandle(
(element, selector) => element.querySelectorAll(selector),
this, selector
selector
);

@@ -444,3 +486,3 @@ const properties = await arrayHandle.getProperties();

throw new Error(`Error: failed to find element matching selector "${selector}"`);
const result = await this.executionContext().evaluate(pageFunction, elementHandle, ...args);
const result = await elementHandle.evaluate(pageFunction, ...args);
await elementHandle.dispose();

@@ -457,8 +499,8 @@ return result;

async $$eval(selector, pageFunction, ...args) {
const arrayHandle = await this.executionContext().evaluateHandle(
const arrayHandle = await this.evaluateHandle(
(element, selector) => Array.from(element.querySelectorAll(selector)),
this, selector
selector
);
const result = await this.executionContext().evaluate(pageFunction, arrayHandle, ...args);
const result = await arrayHandle.evaluate(pageFunction, ...args);
await arrayHandle.dispose();

@@ -473,3 +515,3 @@ return result;

async $x(expression) {
const arrayHandle = await this.executionContext().evaluateHandle(
const arrayHandle = await this.evaluateHandle(
(element, expression) => {

@@ -484,3 +526,3 @@ const document = element.ownerDocument || element;

},
this, expression
expression
);

@@ -502,3 +544,3 @@ const properties = await arrayHandle.getProperties();

isIntersectingViewport() {
return this.executionContext().evaluate(async element => {
return this.evaluate(async element => {
const visibleRatio = await new Promise(resolve => {

@@ -512,3 +554,3 @@ const observer = new IntersectionObserver(entries => {

return visibleRatio > 0;
}, this);
});
}

@@ -515,0 +557,0 @@ }

@@ -49,5 +49,4 @@ /**

'--disable-extensions',
// TODO: Support OOOPIF. @see https://github.com/GoogleChrome/puppeteer/issues/2548
// BlinkGenPropertyTrees disabled due to crbug.com/937609
'--disable-features=site-per-process,TranslateUI,BlinkGenPropertyTrees',
'--disable-features=TranslateUI,BlinkGenPropertyTrees',
'--disable-hang-monitor',

@@ -54,0 +53,0 @@ '--disable-ipc-flooding-protection',

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

* @param {!Puppeteer.CDPSession} client
* @param {!Puppeteer.FrameManager} frameManager
*/
constructor(client, ignoreHTTPSErrors) {
constructor(client, ignoreHTTPSErrors, frameManager) {
super();
this._client = client;
this._ignoreHTTPSErrors = ignoreHTTPSErrors;
this._frameManager = null;
this._frameManager = frameManager;
/** @type {!Map<string, !Request>} */

@@ -65,9 +66,2 @@ this._requestIdToRequest = new Map();

/**
* @param {!Puppeteer.FrameManager} frameManager
*/
setFrameManager(frameManager) {
this._frameManager = frameManager;
}
/**
* @param {?{username: string, password: string}} credentials

@@ -239,3 +233,3 @@ */

}
const frame = event.frameId && this._frameManager ? this._frameManager.frame(event.frameId) : null;
const frame = event.frameId ? this._frameManager.frame(event.frameId) : null;
const request = new Request(this._client, frame, interceptionId, this._userRequestInterceptionEnabled, event, redirectChain);

@@ -729,4 +723,6 @@ this._requestIdToRequest.set(event.requestId, request);

const result = [];
for (const name in headers)
result.push({name, value: headers[name] + ''});
for (const name in headers) {
if (!Object.is(headers[name], undefined))
result.push({name, value: headers[name] + ''});
}
return result;

@@ -733,0 +729,0 @@ }

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

_sessionClosePromise() {
if (!this._disconnectPromise)
this._disconnectPromise = new Promise(fulfill => this._client.once(Events.CDPSession.Disconnected, () => fulfill(new Error('Target closed'))));
return this._disconnectPromise;
}
/**

@@ -713,3 +719,3 @@ * @param {(string|Function)} urlOrPredicate

return false;
}, timeout);
}, timeout, this._sessionClosePromise());
}

@@ -732,3 +738,3 @@

return false;
}, timeout);
}, timeout, this._sessionClosePromise());
}

@@ -885,3 +891,3 @@

assert(options.clip.width !== 0, 'Expected options.clip.width not to be 0.');
assert(options.clip.height !== 0, 'Expected options.clip.width not to be 0.');
assert(options.clip.height !== 0, 'Expected options.clip.height not to be 0.');
}

@@ -888,0 +894,0 @@ return this._screenshotTaskQueue.postTask(this._screenshotTask.bind(this, screenshotType, options));

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

const {Worker} = require('./Worker');
const {Connection} = require('./Connection');

@@ -88,12 +87,5 @@ class Target {

if (!this._workerPromise) {
this._workerPromise = this._sessionFactory().then(async client => {
// Top level workers have a fake page wrapping the actual worker.
const [targetAttached] = await Promise.all([
new Promise(x => client.once('Target.attachedToTarget', x)),
client.send('Target.setAutoAttach', {autoAttach: true, waitForDebuggerOnStart: false, flatten: true}),
]);
const session = Connection.fromSession(client).session(targetAttached.sessionId);
// TODO(einbinder): Make workers send their console logs.
return new Worker(session, this._targetInfo.url, () => {} /* consoleAPICalled */, () => {} /* exceptionThrown */);
});
// TODO(einbinder): Make workers send their console logs.
this._workerPromise = this._sessionFactory()
.then(client => new Worker(client, this._targetInfo.url, () => {} /* consoleAPICalled */, () => {} /* exceptionThrown */));
}

@@ -100,0 +92,0 @@ return this._workerPromise;

@@ -475,2 +475,26 @@ /**

{
'name': 'iPhone XR',
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1',
'viewport': {
'width': 414,
'height': 896,
'deviceScaleFactor': 3,
'isMobile': true,
'hasTouch': true,
'isLandscape': false
}
},
{
'name': 'iPhone XR landscape',
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1',
'viewport': {
'width': 896,
'height': 414,
'deviceScaleFactor': 3,
'isMobile': true,
'hasTouch': true,
'isLandscape': true
}
},
{
'name': 'JioPhone 2',

@@ -477,0 +501,0 @@ 'userAgent': 'Mozilla/5.0 (Mobile; LYF/F300B/LYF-F300B-001-01-15-130718-i;Android; rv:48.0) Gecko/48.0 Firefox/48.0 KAIOS/2.5',

@@ -886,25 +886,39 @@ /**

/**
* @param {string} selector
* @param {!Array<string>} values
* @return {!Promise<!Array<string>>}
*/
select(selector, ...values){
for (const value of values)
assert(helper.isString(value), 'Values must be strings. Found value "' + value + '" of type "' + (typeof value) + '"');
return this.$eval(selector, (element, values) => {
if (element.nodeName.toLowerCase() !== 'select')
throw new Error('Element is not a <select> element.');
const options = Array.from(element.options);
element.value = undefined;
for (const option of options) {
option.selected = values.includes(option.value);
if (option.selected && !element.multiple)
break;
* @param {string} selector
* @param {!Array<string>} values
* @return {!Promise<!Array<string>>}
*/
/* async */ select(selector, ...values) {return (fn => {
const gen = fn.call(this);
return new Promise((resolve, reject) => {
function step(key, arg) {
let info, value;
try {
info = gen[key](arg);
value = info.value;
} catch (error) {
reject(error);
return;
}
element.dispatchEvent(new Event('input', { 'bubbles': true }));
element.dispatchEvent(new Event('change', { 'bubbles': true }));
return options.filter(option => option.selected).map(option => option.value);
}, values);
}
if (info.done) {
resolve(value);
} else {
return Promise.resolve(value).then(
value => {
step('next', value);
},
err => {
step('throw', err);
});
}
}
return step('next');
});
})(function*(){
const handle = (yield this.$(selector));
assert(handle, 'No node found for selector: ' + selector);
const result = (yield handle.select(...values));
(yield handle.dispose());
return result;
});}

@@ -911,0 +925,0 @@ /**

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

this._page = page;
this._networkManager = new NetworkManager(client, ignoreHTTPSErrors);
this._networkManager.setFrameManager(this);
this._networkManager = new NetworkManager(client, ignoreHTTPSErrors, this);
this._timeoutSettings = timeoutSettings;

@@ -42,0 +41,0 @@ /** @type {!Map<string, !Frame>} */

@@ -205,5 +205,33 @@ /**

* @param {function} predicate
* @param {number} timeout
* @param {!Promise<!Error>} abortPromise
* @return {!Promise}
*/
static waitForEvent(emitter, eventName, predicate, timeout) {
static /* async */ waitForEvent(emitter, eventName, predicate, timeout, abortPromise) {return (fn => {
const gen = fn.call(this);
return new Promise((resolve, reject) => {
function step(key, arg) {
let info, value;
try {
info = gen[key](arg);
value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
return Promise.resolve(value).then(
value => {
step('next', value);
},
err => {
step('throw', err);
});
}
}
return step('next');
});
})(function*(){
let eventTimeout, resolveCallback, rejectCallback;

@@ -217,3 +245,2 @@ const promise = new Promise((resolve, reject) => {

return;
cleanup();
resolveCallback(event);

@@ -223,3 +250,2 @@ });

eventTimeout = setTimeout(() => {
cleanup();
rejectCallback(new TimeoutError('Timeout exceeded while waiting for event'));

@@ -232,4 +258,13 @@ }, timeout);

}
return promise;
}
const result = (yield Promise.race([promise, abortPromise]).then(r => {
cleanup();
return r;
}, e => {
cleanup();
throw e;
}));
if (result instanceof Error)
throw result;
return result;
});}

@@ -236,0 +271,0 @@ /**

@@ -50,2 +50,72 @@ /**

/**
* @param {Function|String} pageFunction
* @param {!Array<*>} args
* @return {!Promise<(!Object|undefined)>}
*/
/* async */ evaluate(pageFunction, ...args) {return (fn => {
const gen = fn.call(this);
return new Promise((resolve, reject) => {
function step(key, arg) {
let info, value;
try {
info = gen[key](arg);
value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
return Promise.resolve(value).then(
value => {
step('next', value);
},
err => {
step('throw', err);
});
}
}
return step('next');
});
})(function*(){
return (yield this.executionContext().evaluate(pageFunction, this, ...args));
});}
/**
* @param {Function|string} pageFunction
* @param {!Array<*>} args
* @return {!Promise<!Puppeteer.JSHandle>}
*/
/* async */ evaluateHandle(pageFunction, ...args) {return (fn => {
const gen = fn.call(this);
return new Promise((resolve, reject) => {
function step(key, arg) {
let info, value;
try {
info = gen[key](arg);
value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
return Promise.resolve(value).then(
value => {
step('next', value);
},
err => {
step('throw', err);
});
}
}
return step('next');
});
})(function*(){
return (yield this.executionContext().evaluateHandle(pageFunction, this, ...args));
});}
/**
* @param {string} propertyName

@@ -81,7 +151,7 @@ * @return {!Promise<?JSHandle>}

})(function*(){
const objectHandle = (yield this._context.evaluateHandle((object, propertyName) => {
const objectHandle = (yield this.evaluateHandle((object, propertyName) => {
const result = {__proto__: null};
result[propertyName] = object[propertyName];
return result;
}, this, propertyName));
}, propertyName));
const properties = (yield objectHandle.getProperties());

@@ -321,3 +391,3 @@ const result = properties.get(propertyName) || null;

})(function*(){
const error = (yield this.executionContext().evaluate(/* async */(element, pageJavascriptEnabled) => {return (fn => {
const error = (yield this.evaluate(/* async */(element, pageJavascriptEnabled) => {return (fn => {
const gen = fn.call(this);

@@ -368,3 +438,3 @@ return new Promise((resolve, reject) => {

return false;
});}, this, this._page._javascriptEnabled));
});}, this._page._javascriptEnabled));
if (error)

@@ -534,2 +604,52 @@ throw new Error(error);

/**
* @param {!Array<string>} values
* @return {!Promise<!Array<string>>}
*/
/* async */ select(...values) {return (fn => {
const gen = fn.call(this);
return new Promise((resolve, reject) => {
function step(key, arg) {
let info, value;
try {
info = gen[key](arg);
value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
return Promise.resolve(value).then(
value => {
step('next', value);
},
err => {
step('throw', err);
});
}
}
return step('next');
});
})(function*(){
for (const value of values)
assert(helper.isString(value), 'Values must be strings. Found value "' + value + '" of type "' + (typeof value) + '"');
return this.evaluate((element, values) => {
if (element.nodeName.toLowerCase() !== 'select')
throw new Error('Element is not a <select> element.');
const options = Array.from(element.options);
element.value = undefined;
for (const option of options) {
option.selected = values.includes(option.value);
if (option.selected && !element.multiple)
break;
}
element.dispatchEvent(new Event('input', { 'bubbles': true }));
element.dispatchEvent(new Event('change', { 'bubbles': true }));
return options.filter(option => option.selected).map(option => option.value);
}, values);
});}
/**
* @param {!Array<string>} filePaths

@@ -628,3 +748,3 @@ */

})(function*(){
(yield this.executionContext().evaluate(element => element.focus(), this));
(yield this.evaluate(element => element.focus()));
});}

@@ -895,5 +1015,5 @@

})(function*(){
const handle = (yield this.executionContext().evaluateHandle(
const handle = (yield this.evaluateHandle(
(element, selector) => element.querySelector(selector),
this, selector
selector
));

@@ -938,5 +1058,5 @@ const element = handle.asElement();

})(function*(){
const arrayHandle = (yield this.executionContext().evaluateHandle(
const arrayHandle = (yield this.evaluateHandle(
(element, selector) => element.querySelectorAll(selector),
this, selector
selector
));

@@ -990,3 +1110,3 @@ const properties = (yield arrayHandle.getProperties());

throw new Error(`Error: failed to find element matching selector "${selector}"`);
const result = (yield this.executionContext().evaluate(pageFunction, elementHandle, ...args));
const result = (yield elementHandle.evaluate(pageFunction, ...args));
(yield elementHandle.dispose());

@@ -1029,8 +1149,8 @@ return result;

})(function*(){
const arrayHandle = (yield this.executionContext().evaluateHandle(
const arrayHandle = (yield this.evaluateHandle(
(element, selector) => Array.from(element.querySelectorAll(selector)),
this, selector
selector
));
const result = (yield this.executionContext().evaluate(pageFunction, arrayHandle, ...args));
const result = (yield arrayHandle.evaluate(pageFunction, ...args));
(yield arrayHandle.dispose());

@@ -1071,3 +1191,3 @@ return result;

})(function*(){
const arrayHandle = (yield this.executionContext().evaluateHandle(
const arrayHandle = (yield this.evaluateHandle(
(element, expression) => {

@@ -1082,3 +1202,3 @@ const document = element.ownerDocument || element;

},
this, expression
expression
));

@@ -1100,3 +1220,3 @@ const properties = (yield arrayHandle.getProperties());

isIntersectingViewport() {
return this.executionContext().evaluate(/* async */ element => {return (fn => {
return this.evaluate(/* async */ element => {return (fn => {
const gen = fn.call(this);

@@ -1136,3 +1256,3 @@ return new Promise((resolve, reject) => {

return visibleRatio > 0;
});}, this);
});});
}

@@ -1139,0 +1259,0 @@ }

@@ -49,5 +49,4 @@ /**

'--disable-extensions',
// TODO: Support OOOPIF. @see https://github.com/GoogleChrome/puppeteer/issues/2548
// BlinkGenPropertyTrees disabled due to crbug.com/937609
'--disable-features=site-per-process,TranslateUI,BlinkGenPropertyTrees',
'--disable-features=TranslateUI,BlinkGenPropertyTrees',
'--disable-hang-monitor',

@@ -54,0 +53,0 @@ '--disable-ipc-flooding-protection',

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

* @param {!Puppeteer.CDPSession} client
* @param {!Puppeteer.FrameManager} frameManager
*/
constructor(client, ignoreHTTPSErrors) {
constructor(client, ignoreHTTPSErrors, frameManager) {
super();
this._client = client;
this._ignoreHTTPSErrors = ignoreHTTPSErrors;
this._frameManager = null;
this._frameManager = frameManager;
/** @type {!Map<string, !Request>} */

@@ -91,9 +92,2 @@ this._requestIdToRequest = new Map();

/**
* @param {!Puppeteer.FrameManager} frameManager
*/
setFrameManager(frameManager) {
this._frameManager = frameManager;
}
/**
* @param {?{username: string, password: string}} credentials

@@ -473,3 +467,3 @@ */

}
const frame = event.frameId && this._frameManager ? this._frameManager.frame(event.frameId) : null;
const frame = event.frameId ? this._frameManager.frame(event.frameId) : null;
const request = new Request(this._client, frame, interceptionId, this._userRequestInterceptionEnabled, event, redirectChain);

@@ -1119,4 +1113,6 @@ this._requestIdToRequest.set(event.requestId, request);

const result = [];
for (const name in headers)
result.push({name, value: headers[name] + ''});
for (const name in headers) {
if (!Object.is(headers[name], undefined))
result.push({name, value: headers[name] + ''});
}
return result;

@@ -1123,0 +1119,0 @@ }

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

const {Worker} = require('./Worker');
const {Connection} = require('./Connection');

@@ -166,39 +165,6 @@ class Target {

if (!this._workerPromise) {
this._workerPromise = this._sessionFactory().then(/* async */ client => {return (fn => {
const gen = fn.call(this);
return new Promise((resolve, reject) => {
function step(key, arg) {
let info, value;
try {
info = gen[key](arg);
value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
return Promise.resolve(value).then(
value => {
step('next', value);
},
err => {
step('throw', err);
});
}
// TODO(einbinder): Make workers send their console logs.
this._workerPromise = this._sessionFactory()
.then(client => new Worker(client, this._targetInfo.url, () => {} /* consoleAPICalled */, () => {} /* exceptionThrown */));
}
return step('next');
});
})(function*(){
// Top level workers have a fake page wrapping the actual worker.
const [targetAttached] = (yield Promise.all([
new Promise(x => client.once('Target.attachedToTarget', x)),
client.send('Target.setAutoAttach', {autoAttach: true, waitForDebuggerOnStart: false, flatten: true}),
]));
const session = Connection.fromSession(client).session(targetAttached.sessionId);
// TODO(einbinder): Make workers send their console logs.
return new Worker(session, this._targetInfo.url, () => {} /* consoleAPICalled */, () => {} /* exceptionThrown */);
});});
}
return this._workerPromise;

@@ -205,0 +171,0 @@ });}

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

@@ -11,3 +11,3 @@ "main": "index.js",

"puppeteer": {
"chromium_revision": "674921"
"chromium_revision": "686378"
},

@@ -19,3 +19,3 @@ "scripts": {

"test-doclint": "node utils/doclint/check_public_api/test/test.js && node utils/doclint/preprocessor/test.js",
"test": "npm run lint --silent && npm run coverage && npm run test-doclint && npm run test-node6-transformer && npm run test-types",
"test": "npm run lint --silent && npm run coverage && npm run test-doclint && npm run test-node6-transformer && npm run test-types && node utils/testrunner/test/test.js",
"install": "node install.js",

@@ -22,0 +22,0 @@ "lint": "([ \"$CI\" = true ] && eslint --quiet -f codeframe . || eslint .) && npm run tsc && npm run doc",

# Puppeteer
<!-- [START badges] -->
[![Linux Build Status](https://img.shields.io/travis/com/GoogleChrome/puppeteer/master.svg)](https://travis-ci.com/GoogleChrome/puppeteer) [![Windows Build Status](https://img.shields.io/appveyor/ci/aslushnikov/puppeteer/master.svg?logo=appveyor)](https://ci.appveyor.com/project/aslushnikov/puppeteer/branch/master) [![Build Status](https://api.cirrus-ci.com/github/GoogleChrome/puppeteer.svg)](https://cirrus-ci.com/github/GoogleChrome/puppeteer) [![NPM puppeteer package](https://img.shields.io/npm/v/puppeteer.svg)](https://npmjs.org/package/puppeteer)
[![Linux Build Status](https://img.shields.io/travis/com/GoogleChrome/puppeteer/master.svg)](https://travis-ci.com/GoogleChrome/puppeteer) [![Windows Build Status](https://img.shields.io/appveyor/ci/aslushnikov/puppeteer/master.svg?logo=appveyor)](https://ci.appveyor.com/project/aslushnikov/puppeteer/branch/master) [![Build Status](https://api.cirrus-ci.com/github/GoogleChrome/puppeteer.svg)](https://cirrus-ci.com/github/GoogleChrome/puppeteer) [![NPM puppeteer package](https://img.shields.io/npm/v/puppeteer.svg)](https://npmjs.org/package/puppeteer) [![Issue resolution status](https://isitmaintained.com/badge/resolution/GoogleChrome/puppeteer.svg)](https://github.com/GoogleChrome/puppeteer/issues)
<!-- [END badges] -->

@@ -9,3 +9,3 @@

###### [API](https://github.com/GoogleChrome/puppeteer/blob/v1.19.0/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/GoogleChrome/puppeteer/blob/master/CONTRIBUTING.md) | [Troubleshooting](https://github.com/GoogleChrome/puppeteer/blob/master/docs/troubleshooting.md)
###### [API](https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/GoogleChrome/puppeteer/blob/master/CONTRIBUTING.md) | [Troubleshooting](https://github.com/GoogleChrome/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, see [Environment variables](https://github.com/GoogleChrome/puppeteer/blob/v1.19.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, see [Environment variables](https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md#environment-variables).

@@ -65,3 +65,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/GoogleChrome/puppeteer/blob/v1.19.0/docs/api.md#).
of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md#).

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

Puppeteer sets an initial page size to 800px x 600px, which defines the screenshot size. The page size can be customized with [`Page.setViewport()`](https://github.com/GoogleChrome/puppeteer/blob/v1.19.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/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md#pagesetviewportviewport).

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

See [`Page.pdf()`](https://github.com/GoogleChrome/puppeteer/blob/v1.19.0/docs/api.md#pagepdfoptions) for more information about creating pdfs.
See [`Page.pdf()`](https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md#pagepdfoptions) for more information about creating pdfs.

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

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

@@ -163,3 +163,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/GoogleChrome/puppeteer/blob/v1.19.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/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md#puppeteerlaunchoptions) when launching a browser:

@@ -180,3 +180,3 @@ ```js

See [`Puppeteer.launch()`](https://github.com/GoogleChrome/puppeteer/blob/v1.19.0/docs/api.md#puppeteerlaunchoptions) for more information.
See [`Puppeteer.launch()`](https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md#puppeteerlaunchoptions) for more information.

@@ -193,3 +193,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/GoogleChrome/puppeteer/blob/v1.19.0/docs/api.md)
- [API Documentation](https://github.com/GoogleChrome/puppeteer/blob/v1.20.0/docs/api.md)
- [Examples](https://github.com/GoogleChrome/puppeteer/tree/master/examples/)

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

Look for `chromium_revision` in [package.json](https://github.com/GoogleChrome/puppeteer/blob/master/package.json).
Look for `chromium_revision` in [package.json](https://github.com/GoogleChrome/puppeteer/blob/master/package.json). To find the corresponding Chromium commit and version number, search for the revision prefixed by an `r` in [OmahaProxy](https://omahaproxy.appspot.com/)'s "Find Releases" section.

@@ -385,3 +385,3 @@ #### Q: What’s considered a “Navigation”?

* 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/GoogleChrome/puppeteer/blob/v1.19.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/GoogleChrome/puppeteer/blob/v1.20.0/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).

@@ -388,0 +388,0 @@

Sorry, the diff of this file is not supported yet

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

SocketSocket SOC 2 Logo

Product

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

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc