puppeteer-core
Advanced tools
Comparing version 10.2.0 to 10.4.0
@@ -5,2 +5,37 @@ # Changelog | ||
## [10.4.0](https://github.com/puppeteer/puppeteer/compare/v10.2.0...v10.4.0) (2021-09-21) | ||
### Features | ||
* add webp to screenshot options ([#7565](https://github.com/puppeteer/puppeteer/issues/7565)) ([43a9268](https://github.com/puppeteer/puppeteer/commit/43a926832505a57922016907a264165676424557)) | ||
* **page:** expose page.client() ([#7582](https://github.com/puppeteer/puppeteer/issues/7582)) ([99ca842](https://github.com/puppeteer/puppeteer/commit/99ca842124a1edef5e66426621885141a9feaca5)) | ||
* **page:** mark page.client() as internal ([#7585](https://github.com/puppeteer/puppeteer/issues/7585)) ([8451951](https://github.com/puppeteer/puppeteer/commit/84519514831f304f9076ca235fe474f797616b2c)) | ||
* add ability to specify offsets for JSHandle.click ([#7573](https://github.com/puppeteer/puppeteer/issues/7573)) ([2b5c001](https://github.com/puppeteer/puppeteer/commit/2b5c0019dc3744196c5858edeaa901dff9973ef5)) | ||
* add durableStorage to allowed permissions ([#5295](https://github.com/puppeteer/puppeteer/issues/5295)) ([eda5171](https://github.com/puppeteer/puppeteer/commit/eda51712790b9260626dc53cfb58a72805c45582)) | ||
* add id option to addScriptTag ([#5477](https://github.com/puppeteer/puppeteer/issues/5477)) ([300be5d](https://github.com/puppeteer/puppeteer/commit/300be5d167b6e7e532e725fdb86966081a5d0093)) | ||
* add more Android models to DeviceDescriptors ([#7210](https://github.com/puppeteer/puppeteer/issues/7210)) ([b5020dc](https://github.com/puppeteer/puppeteer/commit/b5020dc04121b265c77662237dfb177d6de06053)), closes [/github.com/aerokube/moon-deploy/blob/master/moon-local.yaml#L199](https://github.com/puppeteer//github.com/aerokube/moon-deploy/blob/master/moon-local.yaml/issues/L199) | ||
* add proxy and bypass list parameters to createIncognitoBrowserContext ([#7516](https://github.com/puppeteer/puppeteer/issues/7516)) ([8e45a1c](https://github.com/puppeteer/puppeteer/commit/8e45a1c882207cc36e87be2a917b661eb841c4bf)), closes [#678](https://github.com/puppeteer/puppeteer/issues/678) | ||
* add threshold to Page.isIntersectingViewport ([#6497](https://github.com/puppeteer/puppeteer/issues/6497)) ([54c4318](https://github.com/puppeteer/puppeteer/commit/54c43180161c3c512e4698e7f2e85ce3c6f0ab50)) | ||
* add unit test support for bisect ([#7553](https://github.com/puppeteer/puppeteer/issues/7553)) ([a0b1f6b](https://github.com/puppeteer/puppeteer/commit/a0b1f6b401abae2fbc5a8987061644adfaa7b482)) | ||
* add User-Agent with Puppeteer version to WebSocket request ([#5614](https://github.com/puppeteer/puppeteer/issues/5614)) ([6a2bf0a](https://github.com/puppeteer/puppeteer/commit/6a2bf0aabaa4df72c7838f5a6cd742e8f9c72be6)) | ||
* extend husky checks ([#7574](https://github.com/puppeteer/puppeteer/issues/7574)) ([7316086](https://github.com/puppeteer/puppeteer/commit/73160869417275200be19bd37372b6218dbc5f63)) | ||
* **api:** implement `Page.waitForNetworkIdle()` ([#5140](https://github.com/puppeteer/puppeteer/issues/5140)) ([3c6029c](https://github.com/puppeteer/puppeteer/commit/3c6029c702291ca7ef637b66e78d72e03156fe58)) | ||
* **coverage:** option for raw V8 script coverage ([#6454](https://github.com/puppeteer/puppeteer/issues/6454)) ([cb4470a](https://github.com/puppeteer/puppeteer/commit/cb4470a6d9b0a7f73836458bb3d5779eb85ac5f2)) | ||
* support timeout for page.pdf() call ([#7508](https://github.com/puppeteer/puppeteer/issues/7508)) ([f90af66](https://github.com/puppeteer/puppeteer/commit/f90af6639d801e764bdb479b9543b7f8f2b926df)) | ||
* **typescript:** allow using puppeteer without dom lib ([#6998](https://github.com/puppeteer/puppeteer/issues/6998)) ([723052d](https://github.com/puppeteer/puppeteer/commit/723052d5bb3c3d1d3908508467512bea4d8fdc80)), closes [#6989](https://github.com/puppeteer/puppeteer/issues/6989) | ||
### Bug Fixes | ||
* **docs:** deploy includes website documentation ([#7469](https://github.com/puppeteer/puppeteer/issues/7469)) ([6fde41c](https://github.com/puppeteer/puppeteer/commit/6fde41c6b6657986df1bbce3f2e0f7aa499f2be4)) | ||
* **docs:** names in version 9.1.1 ([#7517](https://github.com/puppeteer/puppeteer/issues/7517)) ([44b22bb](https://github.com/puppeteer/puppeteer/commit/44b22bbc2629e3c75c1494b299a66790b371fb0a)) | ||
* **frame:** fix Frame.waitFor's XPath pattern detection ([#5184](https://github.com/puppeteer/puppeteer/issues/5184)) ([caa2b73](https://github.com/puppeteer/puppeteer/commit/caa2b732fe58f32ec03f2a9fa8568f20188203c5)) | ||
* **install:** respect environment proxy config when downloading Firef… ([#6577](https://github.com/puppeteer/puppeteer/issues/6577)) ([9399c97](https://github.com/puppeteer/puppeteer/commit/9399c9786fba4e45e1c5485ddbb197d2d4f1735f)), closes [#6573](https://github.com/puppeteer/puppeteer/issues/6573) | ||
* added names in V9.1.1 ([#7547](https://github.com/puppeteer/puppeteer/issues/7547)) ([d132b8b](https://github.com/puppeteer/puppeteer/commit/d132b8b041696e6d5b9a99d0be1acf1cf943efef)) | ||
* **test:** tweak waitForNetworkIdle delay in test between downloads ([#7564](https://github.com/puppeteer/puppeteer/issues/7564)) ([a21b737](https://github.com/puppeteer/puppeteer/commit/a21b7376e7feaf23066d67948d52480516f42496)) | ||
* **types:** allow evaluate functions to take a readonly array as an argument ([#7072](https://github.com/puppeteer/puppeteer/issues/7072)) ([491614c](https://github.com/puppeteer/puppeteer/commit/491614c7f8cfa50b902d0275064e611c2a48c3b2)) | ||
* update firefox prefs documentation link ([#7539](https://github.com/puppeteer/puppeteer/issues/7539)) ([2aec355](https://github.com/puppeteer/puppeteer/commit/2aec35553bc6e0305f40837bb3665ddbd02aa889)) | ||
* use non-deprecated tracing categories api ([#7413](https://github.com/puppeteer/puppeteer/issues/7413)) ([040a0e5](https://github.com/puppeteer/puppeteer/commit/040a0e561b4f623f7929130b90be129f94ebb642)) | ||
## [10.2.0](https://github.com/puppeteer/puppeteer/compare/v10.1.0...v10.2.0) (2021-08-04) | ||
@@ -7,0 +42,0 @@ |
@@ -28,7 +28,7 @@ "use strict"; | ||
} | ||
const normalizeValue = (value) => value.replace(/ +/g, ' ').trim(); | ||
const knownAttributes = new Set(['name', 'role']); | ||
const attributeRegexp = /\[\s*(?<attribute>\w+)\s*=\s*"(?<value>\\.|[^"\\]*)"\s*\]/g; | ||
function parseAriaSelector(selector) { | ||
const normalize = (value) => value.replace(/ +/g, ' ').trim(); | ||
const knownAttributes = new Set(['name', 'role']); | ||
const queryOptions = {}; | ||
const attributeRegexp = /\[\s*(?<attribute>\w+)\s*=\s*"(?<value>\\.|[^"\\]*)"\s*\]/g; | ||
const defaultName = selector.replace(attributeRegexp, (_, attribute, value) => { | ||
@@ -38,7 +38,7 @@ attribute = attribute.trim(); | ||
throw new Error(`Unknown aria attribute "${attribute}" in selector`); | ||
queryOptions[attribute] = normalize(value); | ||
queryOptions[attribute] = normalizeValue(value); | ||
return ''; | ||
}); | ||
if (defaultName && !queryOptions.name) | ||
queryOptions.name = normalize(defaultName); | ||
queryOptions.name = normalizeValue(defaultName); | ||
return queryOptions; | ||
@@ -45,0 +45,0 @@ } |
@@ -22,2 +22,3 @@ /** | ||
export declare const assert: (value: unknown, message?: string) => void; | ||
export declare const assertNever: (value: never, message?: string) => void; | ||
//# sourceMappingURL=assert.d.ts.map |
@@ -18,3 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.assert = void 0; | ||
exports.assertNever = exports.assert = void 0; | ||
/** | ||
@@ -30,2 +30,7 @@ * Asserts that the given value is truthy. | ||
exports.assert = assert; | ||
const assertNever = (value, message) => { | ||
if (value) | ||
throw new Error(message); | ||
}; | ||
exports.assertNever = assertNever; | ||
//# sourceMappingURL=assert.js.map |
@@ -25,2 +25,18 @@ /** | ||
/** | ||
* BrowserContext options. | ||
* | ||
* @public | ||
*/ | ||
export interface BrowserContextOptions { | ||
/** | ||
* Proxy server with optional port to use for all requests. | ||
* Username and password can be set in `Page.authenticate`. | ||
*/ | ||
proxyServer?: string; | ||
/** | ||
* Bypass the proxy for the given semi-colon-separated list of hosts. | ||
*/ | ||
proxyBypassList?: string[]; | ||
} | ||
/** | ||
* @internal | ||
@@ -36,3 +52,3 @@ */ | ||
*/ | ||
export declare type Permission = 'geolocation' | 'midi' | 'notifications' | 'camera' | 'microphone' | 'background-sync' | 'ambient-light-sensor' | 'accelerometer' | 'gyroscope' | 'magnetometer' | 'accessibility-events' | 'clipboard-read' | 'clipboard-write' | 'payment-handler' | 'idle-detection' | 'midi-sysex'; | ||
export declare type Permission = 'geolocation' | 'midi' | 'notifications' | 'camera' | 'microphone' | 'background-sync' | 'ambient-light-sensor' | 'accelerometer' | 'gyroscope' | 'magnetometer' | 'accessibility-events' | 'clipboard-read' | 'clipboard-write' | 'payment-handler' | 'persistent-storage' | 'idle-detection' | 'midi-sysex'; | ||
/** | ||
@@ -182,3 +198,3 @@ * @public | ||
*/ | ||
createIncognitoBrowserContext(): Promise<BrowserContext>; | ||
createIncognitoBrowserContext(options?: BrowserContextOptions): Promise<BrowserContext>; | ||
/** | ||
@@ -185,0 +201,0 @@ * Returns an array of all open browser contexts. In a newly created browser, this will |
@@ -41,2 +41,3 @@ "use strict"; | ||
['payment-handler', 'paymentHandler'], | ||
['persistent-storage', 'durableStorage'], | ||
['idle-detection', 'idleDetection'], | ||
@@ -145,4 +146,8 @@ // chrome-specific permissions we have. | ||
*/ | ||
async createIncognitoBrowserContext() { | ||
const { browserContextId } = await this._connection.send('Target.createBrowserContext'); | ||
async createIncognitoBrowserContext(options = {}) { | ||
const { proxyServer = '', proxyBypassList = [] } = options; | ||
const { browserContextId } = await this._connection.send('Target.createBrowserContext', { | ||
proxyServer, | ||
proxyBypassList: proxyBypassList && proxyBypassList.join(','), | ||
}); | ||
const context = new BrowserContext(this._connection, this, browserContextId); | ||
@@ -149,0 +154,0 @@ this._contexts.set(browserContextId, context); |
@@ -86,3 +86,3 @@ import { Protocol } from 'devtools-protocol'; | ||
* Useful links: {@link https://chromedevtools.github.io/devtools-protocol/ | DevTools Protocol Viewer} | ||
* and {@link https://github.com/aslushnikov/getting-started-with-cdp/blob/master/README.md | Getting Started with DevTools Protocol}. | ||
* and {@link https://github.com/aslushnikov/getting-started-with-cdp/blob/HEAD/README.md | Getting Started with DevTools Protocol}. | ||
* | ||
@@ -89,0 +89,0 @@ * @example |
@@ -176,3 +176,3 @@ "use strict"; | ||
* Useful links: {@link https://chromedevtools.github.io/devtools-protocol/ | DevTools Protocol Viewer} | ||
* and {@link https://github.com/aslushnikov/getting-started-with-cdp/blob/master/README.md | Getting Started with DevTools Protocol}. | ||
* and {@link https://github.com/aslushnikov/getting-started-with-cdp/blob/HEAD/README.md | Getting Started with DevTools Protocol}. | ||
* | ||
@@ -179,0 +179,0 @@ * @example |
@@ -45,2 +45,12 @@ /** | ||
/** | ||
* The CoverageEntry class for JavaScript | ||
* @public | ||
*/ | ||
export interface JSCoverageEntry extends CoverageEntry { | ||
/** | ||
* Raw V8 script coverage entry. | ||
*/ | ||
rawScriptCoverage?: Protocol.Profiler.ScriptCoverage; | ||
} | ||
/** | ||
* Set of configurable options for JS coverage. | ||
@@ -58,2 +68,6 @@ * @public | ||
reportAnonymousScripts?: boolean; | ||
/** | ||
* Whether the result includes raw V8 script coverage entries. | ||
*/ | ||
includeRawScriptCoverage?: boolean; | ||
} | ||
@@ -136,3 +150,3 @@ /** | ||
*/ | ||
stopJSCoverage(): Promise<CoverageEntry[]>; | ||
stopJSCoverage(): Promise<JSCoverageEntry[]>; | ||
/** | ||
@@ -164,2 +178,3 @@ * @param options - Set of configurable options for coverage, defaults to | ||
_reportAnonymousScripts: boolean; | ||
_includeRawScriptCoverage: boolean; | ||
constructor(client: CDPSession); | ||
@@ -169,6 +184,7 @@ start(options?: { | ||
reportAnonymousScripts?: boolean; | ||
includeRawScriptCoverage?: boolean; | ||
}): Promise<void>; | ||
_onExecutionContextsCleared(): void; | ||
_onScriptParsed(event: Protocol.Debugger.ScriptParsedEvent): Promise<void>; | ||
stop(): Promise<CoverageEntry[]>; | ||
stop(): Promise<JSCoverageEntry[]>; | ||
} | ||
@@ -175,0 +191,0 @@ /** |
@@ -119,2 +119,3 @@ "use strict"; | ||
this._reportAnonymousScripts = false; | ||
this._includeRawScriptCoverage = false; | ||
this._client = client; | ||
@@ -124,5 +125,6 @@ } | ||
assert_js_1.assert(!this._enabled, 'JSCoverage is already enabled'); | ||
const { resetOnNavigation = true, reportAnonymousScripts = false } = options; | ||
const { resetOnNavigation = true, reportAnonymousScripts = false, includeRawScriptCoverage = false, } = options; | ||
this._resetOnNavigation = resetOnNavigation; | ||
this._reportAnonymousScripts = reportAnonymousScripts; | ||
this._includeRawScriptCoverage = includeRawScriptCoverage; | ||
this._enabled = true; | ||
@@ -138,3 +140,3 @@ this._scriptURLs.clear(); | ||
this._client.send('Profiler.startPreciseCoverage', { | ||
callCount: false, | ||
callCount: this._includeRawScriptCoverage, | ||
detailed: true, | ||
@@ -194,3 +196,8 @@ }), | ||
const ranges = convertToDisjointRanges(flattenRanges); | ||
coverage.push({ url, ranges, text }); | ||
if (!this._includeRawScriptCoverage) { | ||
coverage.push({ url, ranges, text }); | ||
} | ||
else { | ||
coverage.push({ url, ranges, text, rawScriptCoverage: entry }); | ||
} | ||
} | ||
@@ -197,0 +204,0 @@ return coverage; |
@@ -165,2 +165,74 @@ "use strict"; | ||
{ | ||
name: 'Galaxy S8', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36', | ||
viewport: { | ||
width: 360, | ||
height: 740, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
name: 'Galaxy S8 landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36', | ||
viewport: { | ||
width: 740, | ||
height: 360, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
name: 'Galaxy S9+', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36', | ||
viewport: { | ||
width: 320, | ||
height: 658, | ||
deviceScaleFactor: 4.5, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
name: 'Galaxy S9+ landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36', | ||
viewport: { | ||
width: 658, | ||
height: 320, | ||
deviceScaleFactor: 4.5, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
name: 'Galaxy Tab S4', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Safari/537.36', | ||
viewport: { | ||
width: 712, | ||
height: 1138, | ||
deviceScaleFactor: 2.25, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
name: 'Galaxy Tab S4 landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Safari/537.36', | ||
viewport: { | ||
width: 1138, | ||
height: 712, | ||
deviceScaleFactor: 2.25, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
name: 'iPad', | ||
@@ -945,2 +1017,50 @@ userAgent: 'Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1', | ||
}, | ||
{ | ||
name: 'Pixel 3', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.158 Mobile Safari/537.36', | ||
viewport: { | ||
width: 393, | ||
height: 786, | ||
deviceScaleFactor: 2.75, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
name: 'Pixel 3 landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.158 Mobile Safari/537.36', | ||
viewport: { | ||
width: 786, | ||
height: 393, | ||
deviceScaleFactor: 2.75, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
name: 'Pixel 4', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36', | ||
viewport: { | ||
width: 353, | ||
height: 745, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
name: 'Pixel 4 landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36', | ||
viewport: { | ||
width: 745, | ||
height: 353, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
]; | ||
@@ -947,0 +1067,0 @@ /** |
@@ -93,2 +93,3 @@ /** | ||
content?: string; | ||
id?: string; | ||
type?: string; | ||
@@ -95,0 +96,0 @@ }): Promise<ElementHandle>; |
@@ -164,7 +164,7 @@ "use strict"; | ||
async addScriptTag(options) { | ||
const { url = null, path = null, content = null, type = '' } = options; | ||
const { url = null, path = null, content = null, id = '', type = '', } = options; | ||
if (url !== null) { | ||
try { | ||
const context = await this.executionContext(); | ||
return (await context.evaluateHandle(addScriptUrl, url, type)).asElement(); | ||
return (await context.evaluateHandle(addScriptUrl, url, id, type)).asElement(); | ||
} | ||
@@ -183,12 +183,14 @@ catch (error) { | ||
const context = await this.executionContext(); | ||
return (await context.evaluateHandle(addScriptContent, contents, type)).asElement(); | ||
return (await context.evaluateHandle(addScriptContent, contents, id, type)).asElement(); | ||
} | ||
if (content !== null) { | ||
const context = await this.executionContext(); | ||
return (await context.evaluateHandle(addScriptContent, content, type)).asElement(); | ||
return (await context.evaluateHandle(addScriptContent, content, id, type)).asElement(); | ||
} | ||
throw new Error('Provide an object with a `url`, `path` or `content` property'); | ||
async function addScriptUrl(url, type) { | ||
async function addScriptUrl(url, id, type) { | ||
const script = document.createElement('script'); | ||
script.src = url; | ||
if (id) | ||
script.id = id; | ||
if (type) | ||
@@ -204,6 +206,8 @@ script.type = type; | ||
} | ||
function addScriptContent(content, type = 'text/javascript') { | ||
function addScriptContent(content, id, type = 'text/javascript') { | ||
const script = document.createElement('script'); | ||
script.type = type; | ||
script.text = content; | ||
if (id) | ||
script.id = id; | ||
let error = null; | ||
@@ -210,0 +214,0 @@ script.onerror = (e) => (error = e); |
@@ -40,3 +40,3 @@ /** | ||
*/ | ||
export declare type JSONArray = Serializable[]; | ||
export declare type JSONArray = readonly Serializable[]; | ||
/** | ||
@@ -43,0 +43,0 @@ * @public |
@@ -28,2 +28,3 @@ "use strict"; | ||
const UTILITY_WORLD_NAME = '__puppeteer_utility_world__'; | ||
const xPathPattern = /^\(\/\/[^\)]+\)|^\/\//; | ||
/** | ||
@@ -769,7 +770,6 @@ * We use symbols to prevent external parties listening to these events. | ||
waitFor(selectorOrFunctionOrTimeout, options = {}, ...args) { | ||
const xPathPattern = '//'; | ||
console.warn('waitFor is deprecated and will be removed in a future release. See https://github.com/puppeteer/puppeteer/issues/6214 for details and how to migrate your code.'); | ||
if (helper_js_1.helper.isString(selectorOrFunctionOrTimeout)) { | ||
const string = selectorOrFunctionOrTimeout; | ||
if (string.startsWith(xPathPattern)) | ||
if (xPathPattern.test(string)) | ||
return this.waitForXPath(string, options); | ||
@@ -776,0 +776,0 @@ return this.waitForSelector(string, options); |
@@ -238,3 +238,6 @@ /** | ||
private _scrollIntoViewIfNeeded; | ||
clickablePoint(): Promise<Point>; | ||
/** | ||
* Returns the middle point within an element unless a specific offset is provided. | ||
*/ | ||
clickablePoint(offset?: Offset): Promise<Point>; | ||
private _getBoxModel; | ||
@@ -429,3 +432,5 @@ private _fromProtocolQuad; | ||
*/ | ||
isIntersectingViewport(): Promise<boolean>; | ||
isIntersectingViewport(options?: { | ||
threshold?: number; | ||
}): Promise<boolean>; | ||
} | ||
@@ -435,2 +440,15 @@ /** | ||
*/ | ||
export interface Offset { | ||
/** | ||
* x-offset for the clickable point relative to the top-left corder of the border box. | ||
*/ | ||
x: number; | ||
/** | ||
* y-offset for the clickable point relative to the top-left corder of the border box. | ||
*/ | ||
y: number; | ||
} | ||
/** | ||
* @public | ||
*/ | ||
export interface ClickOptions { | ||
@@ -451,2 +469,6 @@ /** | ||
clickCount?: number; | ||
/** | ||
* Offset for the clickable point relative to the top-left corder of the border box. | ||
*/ | ||
offset?: Offset; | ||
} | ||
@@ -453,0 +475,0 @@ /** |
@@ -320,3 +320,6 @@ "use strict"; | ||
} | ||
async clickablePoint() { | ||
/** | ||
* Returns the middle point within an element unless a specific offset is provided. | ||
*/ | ||
async clickablePoint(offset) { | ||
const [result, layoutMetrics] = await Promise.all([ | ||
@@ -331,3 +334,3 @@ this._client | ||
if (!result || !result.quads.length) | ||
throw new Error('Node is either not visible or not an HTMLElement'); | ||
throw new Error('Node is either not clickable or not an HTMLElement'); | ||
// Filter out quads that have too small area to click into. | ||
@@ -341,5 +344,25 @@ // Fallback to `layoutViewport` in case of using Firefox. | ||
if (!quads.length) | ||
throw new Error('Node is either not visible or not an HTMLElement'); | ||
throw new Error('Node is either not clickable or not an HTMLElement'); | ||
const quad = quads[0]; | ||
if (offset) { | ||
// Return the point of the first quad identified by offset. | ||
let minX = Number.MAX_SAFE_INTEGER; | ||
let minY = Number.MAX_SAFE_INTEGER; | ||
for (const point of quad) { | ||
if (point.x < minX) { | ||
minX = point.x; | ||
} | ||
if (point.y < minY) { | ||
minY = point.y; | ||
} | ||
} | ||
if (minX !== Number.MAX_SAFE_INTEGER && | ||
minY !== Number.MAX_SAFE_INTEGER) { | ||
return { | ||
x: minX + offset.x, | ||
y: minY + offset.y, | ||
}; | ||
} | ||
} | ||
// Return the middle point of the first quad. | ||
const quad = quads[0]; | ||
let x = 0; | ||
@@ -395,3 +418,3 @@ let y = 0; | ||
await this._scrollIntoViewIfNeeded(); | ||
const { x, y } = await this.clickablePoint(); | ||
const { x, y } = await this.clickablePoint(options.offset); | ||
await this._page.mouse.click(x, y, options); | ||
@@ -781,4 +804,5 @@ } | ||
*/ | ||
async isIntersectingViewport() { | ||
return await this.evaluate(async (element) => { | ||
async isIntersectingViewport(options) { | ||
const { threshold = 0 } = options || {}; | ||
return await this.evaluate(async (element, threshold) => { | ||
const visibleRatio = await new Promise((resolve) => { | ||
@@ -791,4 +815,4 @@ const observer = new IntersectionObserver((entries) => { | ||
}); | ||
return visibleRatio > 0; | ||
}); | ||
return threshold === 1 ? visibleRatio === 1 : visibleRatio > threshold; | ||
}, threshold); | ||
} | ||
@@ -795,0 +819,0 @@ } |
@@ -77,2 +77,3 @@ /** | ||
extraHTTPHeaders(): Record<string, string>; | ||
numRequestsInProgress(): number; | ||
setOfflineMode(value: boolean): Promise<void>; | ||
@@ -79,0 +80,0 @@ emulateNetworkConditions(networkConditions: NetworkConditions | null): Promise<void>; |
@@ -124,2 +124,7 @@ "use strict"; | ||
} | ||
numRequestsInProgress() { | ||
return [...this._requestIdToRequest].filter(([, request]) => { | ||
return !request.response(); | ||
}).length; | ||
} | ||
async setOfflineMode(value) { | ||
@@ -126,0 +131,0 @@ this._emulatedNetworkConditions.offline = value; |
@@ -145,2 +145,7 @@ /** | ||
omitBackground?: boolean; | ||
/** | ||
* Timeout in milliseconds | ||
* @defaultValue 30000 | ||
*/ | ||
timeout?: number; | ||
} | ||
@@ -147,0 +152,0 @@ /** |
@@ -65,3 +65,2 @@ "use strict"; | ||
'disabled-by-default-v8.cpu_profiler', | ||
'disabled-by-default-v8.cpu_profiler.hires', | ||
]; | ||
@@ -71,2 +70,6 @@ const { path = null, screenshots = false, categories = defaultCategories, } = options; | ||
categories.push('disabled-by-default-devtools.screenshot'); | ||
const excludedCategories = categories | ||
.filter((cat) => cat.startsWith('-')) | ||
.map((cat) => cat.slice(1)); | ||
const includedCategories = categories.filter((cat) => !cat.startsWith('-')); | ||
this._path = path; | ||
@@ -76,3 +79,6 @@ this._recording = true; | ||
transferMode: 'ReturnAsStream', | ||
categories: categories.join(','), | ||
traceConfig: { | ||
excludedCategories, | ||
includedCategories, | ||
}, | ||
}); | ||
@@ -79,0 +85,0 @@ } |
@@ -56,3 +56,3 @@ "use strict"; | ||
const assert_js_1 = require("../common/assert.js"); | ||
const debugFetcher = Debug_js_1.debug(`puppeteer:fetcher`); | ||
const debugFetcher = Debug_js_1.debug('puppeteer:fetcher'); | ||
const downloadURLs = { | ||
@@ -112,6 +112,6 @@ chrome: { | ||
if (stats === undefined) { | ||
console.error(`The chromium binary is not available for arm64.`); | ||
console.error(`If you are on Ubuntu, you can install with: `); | ||
console.error(`\n sudo apt install chromium\n`); | ||
console.error(`\n sudo apt install chromium-browser\n`); | ||
console.error('The chromium binary is not available for arm64.' + | ||
'\nIf you are on Ubuntu, you can install with: ' + | ||
'\n\n sudo apt install chromium\n' + | ||
'\n\n sudo apt install chromium-browser\n'); | ||
throw new Error(); | ||
@@ -182,3 +182,3 @@ } | ||
else | ||
assert_js_1.assert(this._platform, 'Unsupported platform: ' + os.platform()); | ||
assert_js_1.assert(this._platform, 'Unsupported platform: ' + platform); | ||
} | ||
@@ -317,5 +317,4 @@ /** | ||
} | ||
else { | ||
else | ||
throw new Error('Unsupported product: ' + this._product); | ||
} | ||
const url = downloadURL(this._product, this._platform, this._downloadHost, revision); | ||
@@ -344,3 +343,3 @@ const local = fs.existsSync(folderPath); | ||
_getFolderPath(revision) { | ||
return path.join(this._downloadsFolder, this._platform + '-' + revision); | ||
return path.join(this._downloadsFolder, `${this._platform}-${revision}`); | ||
} | ||
@@ -438,3 +437,3 @@ } | ||
.then((fileNames) => { | ||
const appName = fileNames.filter((item) => typeof item === 'string' && item.endsWith('.app'))[0]; | ||
const appName = fileNames.find((item) => typeof item === 'string' && item.endsWith('.app')); | ||
if (!appName) | ||
@@ -441,0 +440,0 @@ return reject(new Error(`Cannot find app in ${mountPath}`)); |
@@ -25,4 +25,7 @@ "use strict"; | ||
const progress_1 = __importDefault(require("progress")); | ||
const url_1 = __importDefault(require("url")); | ||
const node_js_1 = __importDefault(require("../node.js")); | ||
const revisions_js_1 = require("../revisions.js"); | ||
const https_proxy_agent_1 = __importDefault(require("https-proxy-agent")); | ||
const proxy_from_env_1 = require("proxy-from-env"); | ||
const supportedProducts = { | ||
@@ -126,8 +129,19 @@ chrome: 'Chromium', | ||
function getFirefoxNightlyVersion() { | ||
const firefoxVersions = 'https://product-details.mozilla.org/1.0/firefox_versions.json'; | ||
const firefoxVersionsUrl = 'https://product-details.mozilla.org/1.0/firefox_versions.json'; | ||
const proxyURL = proxy_from_env_1.getProxyForUrl(firefoxVersionsUrl); | ||
const requestOptions = {}; | ||
if (proxyURL) { | ||
const parsedProxyURL = url_1.default.parse(proxyURL); | ||
const proxyOptions = { | ||
...parsedProxyURL, | ||
secureProxy: parsedProxyURL.protocol === 'https:', | ||
}; | ||
requestOptions.agent = https_proxy_agent_1.default(proxyOptions); | ||
requestOptions.rejectUnauthorized = false; | ||
} | ||
const promise = new Promise((resolve, reject) => { | ||
let data = ''; | ||
logPolitely(`Requesting latest Firefox Nightly version from ${firefoxVersions}`); | ||
logPolitely(`Requesting latest Firefox Nightly version from ${firefoxVersionsUrl}`); | ||
https_1.default | ||
.get(firefoxVersions, (r) => { | ||
.get(firefoxVersionsUrl, requestOptions, (r) => { | ||
if (r.statusCode >= 400) | ||
@@ -134,0 +148,0 @@ return reject(new Error(`Got status code ${r.statusCode}`)); |
@@ -31,3 +31,3 @@ /** | ||
* Path to a user data directory. | ||
* {@link https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md | see the Chromium docs} | ||
* {@link https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/user_data_dir.md | see the Chromium docs} | ||
* for more info. | ||
@@ -116,3 +116,3 @@ */ | ||
/** | ||
* {@link https://developer.mozilla.org/en-US/docs/Mozilla/Preferences/Preference_reference | Additional preferences } that can be passed when launching with Firefox. | ||
* {@link https://searchfox.org/mozilla-release/source/modules/libpref/init/all.js | Additional preferences } that can be passed when launching with Firefox. | ||
*/ | ||
@@ -119,0 +119,0 @@ extraPrefsFirefox?: Record<string, unknown>; |
@@ -25,6 +25,12 @@ "use strict"; | ||
static create(url) { | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
const pkg = require('../../../../package.json'); | ||
return new Promise((resolve, reject) => { | ||
const ws = new ws_1.default(url, [], { | ||
followRedirects: true, | ||
perMessageDeflate: false, | ||
maxPayload: 256 * 1024 * 1024, // 256Mb | ||
maxPayload: 256 * 1024 * 1024, | ||
headers: { | ||
'User-Agent': `Puppeteer ${pkg.version}`, | ||
}, | ||
}); | ||
@@ -31,0 +37,0 @@ ws.addEventListener('open', () => resolve(new NodeWebSocketTransport(ws))); |
@@ -25,7 +25,7 @@ /** | ||
} | ||
const normalizeValue = (value) => value.replace(/ +/g, ' ').trim(); | ||
const knownAttributes = new Set(['name', 'role']); | ||
const attributeRegexp = /\[\s*(?<attribute>\w+)\s*=\s*"(?<value>\\.|[^"\\]*)"\s*\]/g; | ||
function parseAriaSelector(selector) { | ||
const normalize = (value) => value.replace(/ +/g, ' ').trim(); | ||
const knownAttributes = new Set(['name', 'role']); | ||
const queryOptions = {}; | ||
const attributeRegexp = /\[\s*(?<attribute>\w+)\s*=\s*"(?<value>\\.|[^"\\]*)"\s*\]/g; | ||
const defaultName = selector.replace(attributeRegexp, (_, attribute, value) => { | ||
@@ -35,7 +35,7 @@ attribute = attribute.trim(); | ||
throw new Error(`Unknown aria attribute "${attribute}" in selector`); | ||
queryOptions[attribute] = normalize(value); | ||
queryOptions[attribute] = normalizeValue(value); | ||
return ''; | ||
}); | ||
if (defaultName && !queryOptions.name) | ||
queryOptions.name = normalize(defaultName); | ||
queryOptions.name = normalizeValue(defaultName); | ||
return queryOptions; | ||
@@ -42,0 +42,0 @@ } |
@@ -22,2 +22,3 @@ /** | ||
export declare const assert: (value: unknown, message?: string) => void; | ||
export declare const assertNever: (value: never, message?: string) => void; | ||
//# sourceMappingURL=assert.d.ts.map |
@@ -25,2 +25,6 @@ /** | ||
}; | ||
export const assertNever = (value, message) => { | ||
if (value) | ||
throw new Error(message); | ||
}; | ||
//# sourceMappingURL=assert.js.map |
@@ -25,2 +25,18 @@ /** | ||
/** | ||
* BrowserContext options. | ||
* | ||
* @public | ||
*/ | ||
export interface BrowserContextOptions { | ||
/** | ||
* Proxy server with optional port to use for all requests. | ||
* Username and password can be set in `Page.authenticate`. | ||
*/ | ||
proxyServer?: string; | ||
/** | ||
* Bypass the proxy for the given semi-colon-separated list of hosts. | ||
*/ | ||
proxyBypassList?: string[]; | ||
} | ||
/** | ||
* @internal | ||
@@ -36,3 +52,3 @@ */ | ||
*/ | ||
export declare type Permission = 'geolocation' | 'midi' | 'notifications' | 'camera' | 'microphone' | 'background-sync' | 'ambient-light-sensor' | 'accelerometer' | 'gyroscope' | 'magnetometer' | 'accessibility-events' | 'clipboard-read' | 'clipboard-write' | 'payment-handler' | 'idle-detection' | 'midi-sysex'; | ||
export declare type Permission = 'geolocation' | 'midi' | 'notifications' | 'camera' | 'microphone' | 'background-sync' | 'ambient-light-sensor' | 'accelerometer' | 'gyroscope' | 'magnetometer' | 'accessibility-events' | 'clipboard-read' | 'clipboard-write' | 'payment-handler' | 'persistent-storage' | 'idle-detection' | 'midi-sysex'; | ||
/** | ||
@@ -182,3 +198,3 @@ * @public | ||
*/ | ||
createIncognitoBrowserContext(): Promise<BrowserContext>; | ||
createIncognitoBrowserContext(options?: BrowserContextOptions): Promise<BrowserContext>; | ||
/** | ||
@@ -185,0 +201,0 @@ * Returns an array of all open browser contexts. In a newly created browser, this will |
@@ -38,2 +38,3 @@ /** | ||
['payment-handler', 'paymentHandler'], | ||
['persistent-storage', 'durableStorage'], | ||
['idle-detection', 'idleDetection'], | ||
@@ -142,4 +143,8 @@ // chrome-specific permissions we have. | ||
*/ | ||
async createIncognitoBrowserContext() { | ||
const { browserContextId } = await this._connection.send('Target.createBrowserContext'); | ||
async createIncognitoBrowserContext(options = {}) { | ||
const { proxyServer = '', proxyBypassList = [] } = options; | ||
const { browserContextId } = await this._connection.send('Target.createBrowserContext', { | ||
proxyServer, | ||
proxyBypassList: proxyBypassList && proxyBypassList.join(','), | ||
}); | ||
const context = new BrowserContext(this._connection, this, browserContextId); | ||
@@ -146,0 +151,0 @@ this._contexts.set(browserContextId, context); |
@@ -86,3 +86,3 @@ import { Protocol } from 'devtools-protocol'; | ||
* Useful links: {@link https://chromedevtools.github.io/devtools-protocol/ | DevTools Protocol Viewer} | ||
* and {@link https://github.com/aslushnikov/getting-started-with-cdp/blob/master/README.md | Getting Started with DevTools Protocol}. | ||
* and {@link https://github.com/aslushnikov/getting-started-with-cdp/blob/HEAD/README.md | Getting Started with DevTools Protocol}. | ||
* | ||
@@ -89,0 +89,0 @@ * @example |
@@ -172,3 +172,3 @@ /** | ||
* Useful links: {@link https://chromedevtools.github.io/devtools-protocol/ | DevTools Protocol Viewer} | ||
* and {@link https://github.com/aslushnikov/getting-started-with-cdp/blob/master/README.md | Getting Started with DevTools Protocol}. | ||
* and {@link https://github.com/aslushnikov/getting-started-with-cdp/blob/HEAD/README.md | Getting Started with DevTools Protocol}. | ||
* | ||
@@ -175,0 +175,0 @@ * @example |
@@ -45,2 +45,12 @@ /** | ||
/** | ||
* The CoverageEntry class for JavaScript | ||
* @public | ||
*/ | ||
export interface JSCoverageEntry extends CoverageEntry { | ||
/** | ||
* Raw V8 script coverage entry. | ||
*/ | ||
rawScriptCoverage?: Protocol.Profiler.ScriptCoverage; | ||
} | ||
/** | ||
* Set of configurable options for JS coverage. | ||
@@ -58,2 +68,6 @@ * @public | ||
reportAnonymousScripts?: boolean; | ||
/** | ||
* Whether the result includes raw V8 script coverage entries. | ||
*/ | ||
includeRawScriptCoverage?: boolean; | ||
} | ||
@@ -136,3 +150,3 @@ /** | ||
*/ | ||
stopJSCoverage(): Promise<CoverageEntry[]>; | ||
stopJSCoverage(): Promise<JSCoverageEntry[]>; | ||
/** | ||
@@ -164,2 +178,3 @@ * @param options - Set of configurable options for coverage, defaults to | ||
_reportAnonymousScripts: boolean; | ||
_includeRawScriptCoverage: boolean; | ||
constructor(client: CDPSession); | ||
@@ -169,6 +184,7 @@ start(options?: { | ||
reportAnonymousScripts?: boolean; | ||
includeRawScriptCoverage?: boolean; | ||
}): Promise<void>; | ||
_onExecutionContextsCleared(): void; | ||
_onScriptParsed(event: Protocol.Debugger.ScriptParsedEvent): Promise<void>; | ||
stop(): Promise<CoverageEntry[]>; | ||
stop(): Promise<JSCoverageEntry[]>; | ||
} | ||
@@ -175,0 +191,0 @@ /** |
@@ -115,2 +115,3 @@ /** | ||
this._reportAnonymousScripts = false; | ||
this._includeRawScriptCoverage = false; | ||
this._client = client; | ||
@@ -120,5 +121,6 @@ } | ||
assert(!this._enabled, 'JSCoverage is already enabled'); | ||
const { resetOnNavigation = true, reportAnonymousScripts = false } = options; | ||
const { resetOnNavigation = true, reportAnonymousScripts = false, includeRawScriptCoverage = false, } = options; | ||
this._resetOnNavigation = resetOnNavigation; | ||
this._reportAnonymousScripts = reportAnonymousScripts; | ||
this._includeRawScriptCoverage = includeRawScriptCoverage; | ||
this._enabled = true; | ||
@@ -134,3 +136,3 @@ this._scriptURLs.clear(); | ||
this._client.send('Profiler.startPreciseCoverage', { | ||
callCount: false, | ||
callCount: this._includeRawScriptCoverage, | ||
detailed: true, | ||
@@ -190,3 +192,8 @@ }), | ||
const ranges = convertToDisjointRanges(flattenRanges); | ||
coverage.push({ url, ranges, text }); | ||
if (!this._includeRawScriptCoverage) { | ||
coverage.push({ url, ranges, text }); | ||
} | ||
else { | ||
coverage.push({ url, ranges, text, rawScriptCoverage: entry }); | ||
} | ||
} | ||
@@ -193,0 +200,0 @@ return coverage; |
@@ -162,2 +162,74 @@ /** | ||
{ | ||
name: 'Galaxy S8', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36', | ||
viewport: { | ||
width: 360, | ||
height: 740, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
name: 'Galaxy S8 landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 7.0; SM-G950U Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.84 Mobile Safari/537.36', | ||
viewport: { | ||
width: 740, | ||
height: 360, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
name: 'Galaxy S9+', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36', | ||
viewport: { | ||
width: 320, | ||
height: 658, | ||
deviceScaleFactor: 4.5, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
name: 'Galaxy S9+ landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; SM-G965U Build/R16NW) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.111 Mobile Safari/537.36', | ||
viewport: { | ||
width: 658, | ||
height: 320, | ||
deviceScaleFactor: 4.5, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
name: 'Galaxy Tab S4', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Safari/537.36', | ||
viewport: { | ||
width: 712, | ||
height: 1138, | ||
deviceScaleFactor: 2.25, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
name: 'Galaxy Tab S4 landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 8.1.0; SM-T837A) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.80 Safari/537.36', | ||
viewport: { | ||
width: 1138, | ||
height: 712, | ||
deviceScaleFactor: 2.25, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
name: 'iPad', | ||
@@ -942,2 +1014,50 @@ userAgent: 'Mozilla/5.0 (iPad; CPU OS 11_0 like Mac OS X) AppleWebKit/604.1.34 (KHTML, like Gecko) Version/11.0 Mobile/15A5341f Safari/604.1', | ||
}, | ||
{ | ||
name: 'Pixel 3', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.158 Mobile Safari/537.36', | ||
viewport: { | ||
width: 393, | ||
height: 786, | ||
deviceScaleFactor: 2.75, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
name: 'Pixel 3 landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 9; Pixel 3 Build/PQ1A.181105.017.A1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.158 Mobile Safari/537.36', | ||
viewport: { | ||
width: 786, | ||
height: 393, | ||
deviceScaleFactor: 2.75, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
name: 'Pixel 4', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36', | ||
viewport: { | ||
width: 353, | ||
height: 745, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
name: 'Pixel 4 landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 10; Pixel 4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Mobile Safari/537.36', | ||
viewport: { | ||
width: 745, | ||
height: 353, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
]; | ||
@@ -944,0 +1064,0 @@ /** |
@@ -93,2 +93,3 @@ /** | ||
content?: string; | ||
id?: string; | ||
type?: string; | ||
@@ -95,0 +96,0 @@ }): Promise<ElementHandle>; |
@@ -161,7 +161,7 @@ /** | ||
async addScriptTag(options) { | ||
const { url = null, path = null, content = null, type = '' } = options; | ||
const { url = null, path = null, content = null, id = '', type = '', } = options; | ||
if (url !== null) { | ||
try { | ||
const context = await this.executionContext(); | ||
return (await context.evaluateHandle(addScriptUrl, url, type)).asElement(); | ||
return (await context.evaluateHandle(addScriptUrl, url, id, type)).asElement(); | ||
} | ||
@@ -180,12 +180,14 @@ catch (error) { | ||
const context = await this.executionContext(); | ||
return (await context.evaluateHandle(addScriptContent, contents, type)).asElement(); | ||
return (await context.evaluateHandle(addScriptContent, contents, id, type)).asElement(); | ||
} | ||
if (content !== null) { | ||
const context = await this.executionContext(); | ||
return (await context.evaluateHandle(addScriptContent, content, type)).asElement(); | ||
return (await context.evaluateHandle(addScriptContent, content, id, type)).asElement(); | ||
} | ||
throw new Error('Provide an object with a `url`, `path` or `content` property'); | ||
async function addScriptUrl(url, type) { | ||
async function addScriptUrl(url, id, type) { | ||
const script = document.createElement('script'); | ||
script.src = url; | ||
if (id) | ||
script.id = id; | ||
if (type) | ||
@@ -201,6 +203,8 @@ script.type = type; | ||
} | ||
function addScriptContent(content, type = 'text/javascript') { | ||
function addScriptContent(content, id, type = 'text/javascript') { | ||
const script = document.createElement('script'); | ||
script.type = type; | ||
script.text = content; | ||
if (id) | ||
script.id = id; | ||
let error = null; | ||
@@ -207,0 +211,0 @@ script.onerror = (e) => (error = e); |
@@ -40,3 +40,3 @@ /** | ||
*/ | ||
export declare type JSONArray = Serializable[]; | ||
export declare type JSONArray = readonly Serializable[]; | ||
/** | ||
@@ -43,0 +43,0 @@ * @public |
@@ -25,2 +25,3 @@ /** | ||
const UTILITY_WORLD_NAME = '__puppeteer_utility_world__'; | ||
const xPathPattern = /^\(\/\/[^\)]+\)|^\/\//; | ||
/** | ||
@@ -765,7 +766,6 @@ * We use symbols to prevent external parties listening to these events. | ||
waitFor(selectorOrFunctionOrTimeout, options = {}, ...args) { | ||
const xPathPattern = '//'; | ||
console.warn('waitFor is deprecated and will be removed in a future release. See https://github.com/puppeteer/puppeteer/issues/6214 for details and how to migrate your code.'); | ||
if (helper.isString(selectorOrFunctionOrTimeout)) { | ||
const string = selectorOrFunctionOrTimeout; | ||
if (string.startsWith(xPathPattern)) | ||
if (xPathPattern.test(string)) | ||
return this.waitForXPath(string, options); | ||
@@ -772,0 +772,0 @@ return this.waitForSelector(string, options); |
@@ -238,3 +238,6 @@ /** | ||
private _scrollIntoViewIfNeeded; | ||
clickablePoint(): Promise<Point>; | ||
/** | ||
* Returns the middle point within an element unless a specific offset is provided. | ||
*/ | ||
clickablePoint(offset?: Offset): Promise<Point>; | ||
private _getBoxModel; | ||
@@ -429,3 +432,5 @@ private _fromProtocolQuad; | ||
*/ | ||
isIntersectingViewport(): Promise<boolean>; | ||
isIntersectingViewport(options?: { | ||
threshold?: number; | ||
}): Promise<boolean>; | ||
} | ||
@@ -435,2 +440,15 @@ /** | ||
*/ | ||
export interface Offset { | ||
/** | ||
* x-offset for the clickable point relative to the top-left corder of the border box. | ||
*/ | ||
x: number; | ||
/** | ||
* y-offset for the clickable point relative to the top-left corder of the border box. | ||
*/ | ||
y: number; | ||
} | ||
/** | ||
* @public | ||
*/ | ||
export interface ClickOptions { | ||
@@ -451,2 +469,6 @@ /** | ||
clickCount?: number; | ||
/** | ||
* Offset for the clickable point relative to the top-left corder of the border box. | ||
*/ | ||
offset?: Offset; | ||
} | ||
@@ -453,0 +475,0 @@ /** |
@@ -296,3 +296,6 @@ /** | ||
} | ||
async clickablePoint() { | ||
/** | ||
* Returns the middle point within an element unless a specific offset is provided. | ||
*/ | ||
async clickablePoint(offset) { | ||
const [result, layoutMetrics] = await Promise.all([ | ||
@@ -307,3 +310,3 @@ this._client | ||
if (!result || !result.quads.length) | ||
throw new Error('Node is either not visible or not an HTMLElement'); | ||
throw new Error('Node is either not clickable or not an HTMLElement'); | ||
// Filter out quads that have too small area to click into. | ||
@@ -317,5 +320,25 @@ // Fallback to `layoutViewport` in case of using Firefox. | ||
if (!quads.length) | ||
throw new Error('Node is either not visible or not an HTMLElement'); | ||
throw new Error('Node is either not clickable or not an HTMLElement'); | ||
const quad = quads[0]; | ||
if (offset) { | ||
// Return the point of the first quad identified by offset. | ||
let minX = Number.MAX_SAFE_INTEGER; | ||
let minY = Number.MAX_SAFE_INTEGER; | ||
for (const point of quad) { | ||
if (point.x < minX) { | ||
minX = point.x; | ||
} | ||
if (point.y < minY) { | ||
minY = point.y; | ||
} | ||
} | ||
if (minX !== Number.MAX_SAFE_INTEGER && | ||
minY !== Number.MAX_SAFE_INTEGER) { | ||
return { | ||
x: minX + offset.x, | ||
y: minY + offset.y, | ||
}; | ||
} | ||
} | ||
// Return the middle point of the first quad. | ||
const quad = quads[0]; | ||
let x = 0; | ||
@@ -371,3 +394,3 @@ let y = 0; | ||
await this._scrollIntoViewIfNeeded(); | ||
const { x, y } = await this.clickablePoint(); | ||
const { x, y } = await this.clickablePoint(options.offset); | ||
await this._page.mouse.click(x, y, options); | ||
@@ -757,4 +780,5 @@ } | ||
*/ | ||
async isIntersectingViewport() { | ||
return await this.evaluate(async (element) => { | ||
async isIntersectingViewport(options) { | ||
const { threshold = 0 } = options || {}; | ||
return await this.evaluate(async (element, threshold) => { | ||
const visibleRatio = await new Promise((resolve) => { | ||
@@ -767,4 +791,4 @@ const observer = new IntersectionObserver((entries) => { | ||
}); | ||
return visibleRatio > 0; | ||
}); | ||
return threshold === 1 ? visibleRatio === 1 : visibleRatio > threshold; | ||
}, threshold); | ||
} | ||
@@ -771,0 +795,0 @@ } |
@@ -77,2 +77,3 @@ /** | ||
extraHTTPHeaders(): Record<string, string>; | ||
numRequestsInProgress(): number; | ||
setOfflineMode(value: boolean): Promise<void>; | ||
@@ -79,0 +80,0 @@ emulateNetworkConditions(networkConditions: NetworkConditions | null): Promise<void>; |
@@ -121,2 +121,7 @@ /** | ||
} | ||
numRequestsInProgress() { | ||
return [...this._requestIdToRequest].filter(([, request]) => { | ||
return !request.response(); | ||
}).length; | ||
} | ||
async setOfflineMode(value) { | ||
@@ -123,0 +128,0 @@ this._emulatedNetworkConditions.offline = value; |
@@ -145,2 +145,7 @@ /** | ||
omitBackground?: boolean; | ||
/** | ||
* Timeout in milliseconds | ||
* @defaultValue 30000 | ||
*/ | ||
timeout?: number; | ||
} | ||
@@ -147,0 +152,0 @@ /** |
@@ -62,3 +62,2 @@ /** | ||
'disabled-by-default-v8.cpu_profiler', | ||
'disabled-by-default-v8.cpu_profiler.hires', | ||
]; | ||
@@ -68,2 +67,6 @@ const { path = null, screenshots = false, categories = defaultCategories, } = options; | ||
categories.push('disabled-by-default-devtools.screenshot'); | ||
const excludedCategories = categories | ||
.filter((cat) => cat.startsWith('-')) | ||
.map((cat) => cat.slice(1)); | ||
const includedCategories = categories.filter((cat) => !cat.startsWith('-')); | ||
this._path = path; | ||
@@ -73,3 +76,6 @@ this._recording = true; | ||
transferMode: 'ReturnAsStream', | ||
categories: categories.join(','), | ||
traceConfig: { | ||
excludedCategories, | ||
includedCategories, | ||
}, | ||
}); | ||
@@ -76,0 +82,0 @@ } |
@@ -31,3 +31,3 @@ /** | ||
import { assert } from '../common/assert.js'; | ||
const debugFetcher = debug(`puppeteer:fetcher`); | ||
const debugFetcher = debug('puppeteer:fetcher'); | ||
const downloadURLs = { | ||
@@ -87,6 +87,6 @@ chrome: { | ||
if (stats === undefined) { | ||
console.error(`The chromium binary is not available for arm64.`); | ||
console.error(`If you are on Ubuntu, you can install with: `); | ||
console.error(`\n sudo apt install chromium\n`); | ||
console.error(`\n sudo apt install chromium-browser\n`); | ||
console.error('The chromium binary is not available for arm64.' + | ||
'\nIf you are on Ubuntu, you can install with: ' + | ||
'\n\n sudo apt install chromium\n' + | ||
'\n\n sudo apt install chromium-browser\n'); | ||
throw new Error(); | ||
@@ -157,3 +157,3 @@ } | ||
else | ||
assert(this._platform, 'Unsupported platform: ' + os.platform()); | ||
assert(this._platform, 'Unsupported platform: ' + platform); | ||
} | ||
@@ -292,5 +292,4 @@ /** | ||
} | ||
else { | ||
else | ||
throw new Error('Unsupported product: ' + this._product); | ||
} | ||
const url = downloadURL(this._product, this._platform, this._downloadHost, revision); | ||
@@ -319,3 +318,3 @@ const local = fs.existsSync(folderPath); | ||
_getFolderPath(revision) { | ||
return path.join(this._downloadsFolder, this._platform + '-' + revision); | ||
return path.join(this._downloadsFolder, `${this._platform}-${revision}`); | ||
} | ||
@@ -412,3 +411,3 @@ } | ||
.then((fileNames) => { | ||
const appName = fileNames.filter((item) => typeof item === 'string' && item.endsWith('.app'))[0]; | ||
const appName = fileNames.find((item) => typeof item === 'string' && item.endsWith('.app')); | ||
if (!appName) | ||
@@ -415,0 +414,0 @@ return reject(new Error(`Cannot find app in ${mountPath}`)); |
@@ -19,4 +19,7 @@ /** | ||
import ProgressBar from 'progress'; | ||
import URL from 'url'; | ||
import puppeteer from '../node.js'; | ||
import { PUPPETEER_REVISIONS } from '../revisions.js'; | ||
import createHttpsProxyAgent from 'https-proxy-agent'; | ||
import { getProxyForUrl } from 'proxy-from-env'; | ||
const supportedProducts = { | ||
@@ -120,8 +123,19 @@ chrome: 'Chromium', | ||
function getFirefoxNightlyVersion() { | ||
const firefoxVersions = 'https://product-details.mozilla.org/1.0/firefox_versions.json'; | ||
const firefoxVersionsUrl = 'https://product-details.mozilla.org/1.0/firefox_versions.json'; | ||
const proxyURL = getProxyForUrl(firefoxVersionsUrl); | ||
const requestOptions = {}; | ||
if (proxyURL) { | ||
const parsedProxyURL = URL.parse(proxyURL); | ||
const proxyOptions = { | ||
...parsedProxyURL, | ||
secureProxy: parsedProxyURL.protocol === 'https:', | ||
}; | ||
requestOptions.agent = createHttpsProxyAgent(proxyOptions); | ||
requestOptions.rejectUnauthorized = false; | ||
} | ||
const promise = new Promise((resolve, reject) => { | ||
let data = ''; | ||
logPolitely(`Requesting latest Firefox Nightly version from ${firefoxVersions}`); | ||
logPolitely(`Requesting latest Firefox Nightly version from ${firefoxVersionsUrl}`); | ||
https | ||
.get(firefoxVersions, (r) => { | ||
.get(firefoxVersionsUrl, requestOptions, (r) => { | ||
if (r.statusCode >= 400) | ||
@@ -128,0 +142,0 @@ return reject(new Error(`Got status code ${r.statusCode}`)); |
@@ -31,3 +31,3 @@ /** | ||
* Path to a user data directory. | ||
* {@link https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md | see the Chromium docs} | ||
* {@link https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/user_data_dir.md | see the Chromium docs} | ||
* for more info. | ||
@@ -116,3 +116,3 @@ */ | ||
/** | ||
* {@link https://developer.mozilla.org/en-US/docs/Mozilla/Preferences/Preference_reference | Additional preferences } that can be passed when launching with Firefox. | ||
* {@link https://searchfox.org/mozilla-release/source/modules/libpref/init/all.js | Additional preferences } that can be passed when launching with Firefox. | ||
*/ | ||
@@ -119,0 +119,0 @@ extraPrefsFirefox?: Record<string, unknown>; |
@@ -19,6 +19,12 @@ import NodeWebSocket from 'ws'; | ||
static create(url) { | ||
// eslint-disable-next-line @typescript-eslint/no-var-requires | ||
const pkg = require('../../../../package.json'); | ||
return new Promise((resolve, reject) => { | ||
const ws = new NodeWebSocket(url, [], { | ||
followRedirects: true, | ||
perMessageDeflate: false, | ||
maxPayload: 256 * 1024 * 1024, // 256Mb | ||
maxPayload: 256 * 1024 * 1024, | ||
headers: { | ||
'User-Agent': `Puppeteer ${pkg.version}`, | ||
}, | ||
}); | ||
@@ -25,0 +31,0 @@ ws.addEventListener('open', () => resolve(new NodeWebSocketTransport(ws))); |
{ | ||
"name": "puppeteer-core", | ||
"version": "10.2.0", | ||
"version": "10.4.0", | ||
"description": "A high-level API to control headless Chrome over the DevTools Protocol", | ||
@@ -37,4 +37,4 @@ "main": "./cjs-entry-core.js", | ||
"test-install": "scripts/test-install.sh", | ||
"clean-docs": "rimraf new-docs && rimraf docs-api-json", | ||
"generate-d-ts": "npm run clean-docs && api-extractor run --local --verbose", | ||
"clean-docs": "rimraf website/docs && rimraf docs-api-json", | ||
"generate-d-ts": "npm run clean-docs && api-extractor run --local --verbose && node inject-global-type-stubs.js", | ||
"generate-docs": "npm run generate-d-ts && api-documenter markdown -i docs-api-json -o website/docs && node utils/remove-tag.js", | ||
@@ -119,6 +119,7 @@ "ensure-correct-devtools-protocol-revision": "ts-node -s scripts/ensure-correct-devtools-protocol-package", | ||
"hooks": { | ||
"pre-commit": "npm run eslint", | ||
"commit-msg": "commitlint --env HUSKY_GIT_PARAMS", | ||
"pre-push": "npm run ensure-pinned-deps" | ||
"pre-push": "npm run tsc && npm run eslint && npm run doc && npm run ensure-pinned-deps" | ||
} | ||
} | ||
} |
@@ -11,3 +11,3 @@ # Puppeteer | ||
###### [API](https://github.com/puppeteer/puppeteer/blob/v10.2.0/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING.md) | [Troubleshooting](https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md) | ||
###### [API](https://github.com/puppeteer/puppeteer/blob/v10.4.0/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/puppeteer/puppeteer/blob/main/CONTRIBUTING.md) | [Troubleshooting](https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md) | ||
@@ -30,3 +30,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. | ||
Give it a spin: https://try-puppeteer.appspot.com/ | ||
Give it a spin: [https://try-puppeteer.appspot.com/](https://try-puppeteer.appspot.com/) | ||
@@ -46,3 +46,3 @@ <!-- [START getstarted] --> | ||
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, download into another path, or download a different browser, see [Environment variables](https://github.com/puppeteer/puppeteer/blob/v10.2.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, download into another path, or download a different browser, see [Environment variables](https://github.com/puppeteer/puppeteer/blob/v10.4.0/docs/api.md#environment-variables). | ||
@@ -72,3 +72,3 @@ ### puppeteer-core | ||
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/v10.2.0/docs/api.md#). | ||
of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/puppeteer/puppeteer/blob/v10.4.0/docs/api.md#). | ||
@@ -98,3 +98,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/v10.2.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/v10.4.0/docs/api.md#pagesetviewportviewport). | ||
@@ -126,3 +126,3 @@ **Example** - create a PDF. | ||
See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v10.2.0/docs/api.md#pagepdfoptions) for more information about creating pdfs. | ||
See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v10.4.0/docs/api.md#pagepdfoptions) for more information about creating pdfs. | ||
@@ -162,3 +162,3 @@ **Example** - evaluate script in the context of the page | ||
See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v10.2.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/v10.4.0/docs/api.md#pageevaluatepagefunction-args) for more information on `evaluate` and related methods like `evaluateOnNewDocument` and `exposeFunction`. | ||
@@ -173,3 +173,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/v10.2.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/v10.4.0/docs/api.md#puppeteerlaunchoptions) when launching a browser: | ||
@@ -190,5 +190,5 @@ ```js | ||
You can also use Puppeteer with Firefox Nightly (experimental support). See [`Puppeteer.launch()`](https://github.com/puppeteer/puppeteer/blob/v10.2.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/v10.4.0/docs/api.md#puppeteerlaunchoptions) for more information. | ||
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. | ||
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/+/refs/heads/main/docs/chromium_browser_vs_google_chrome.md) describes some differences for Linux users. | ||
@@ -203,3 +203,3 @@ **3. Creates a fresh user profile** | ||
- [API Documentation](https://github.com/puppeteer/puppeteer/blob/v10.2.0/docs/api.md) | ||
- [API Documentation](https://github.com/puppeteer/puppeteer/blob/v10.4.0/docs/api.md) | ||
- [Examples](https://github.com/puppeteer/puppeteer/tree/main/examples/) | ||
@@ -346,3 +346,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/v10.2.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/v10.4.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. | ||
@@ -447,3 +447,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/v10.2.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/v10.4.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). | ||
@@ -450,0 +450,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2794500
497
51307
21