puppeteer-core
Advanced tools
Comparing version 3.0.4 to 3.1.0
19
index.js
@@ -17,5 +17,5 @@ /** | ||
const {helper} = require('./lib/helper'); | ||
const { helper } = require('./lib/helper'); | ||
const api = require('./lib/api'); | ||
const {Page} = require('./lib/Page'); | ||
const { Page } = require('./lib/Page'); | ||
for (const className in api) { | ||
@@ -29,3 +29,3 @@ if (typeof api[className] === 'function') | ||
const {Puppeteer} = require('./lib/Puppeteer'); | ||
const { Puppeteer } = require('./lib/Puppeteer'); | ||
const packageJson = require('./package.json'); | ||
@@ -35,7 +35,16 @@ let preferredRevision = packageJson.puppeteer.chromium_revision; | ||
// puppeteer-core ignores environment variables | ||
const product = isPuppeteerCore ? undefined : process.env.PUPPETEER_PRODUCT || process.env.npm_config_puppeteer_product || process.env.npm_package_config_puppeteer_product; | ||
const product = isPuppeteerCore | ||
? undefined | ||
: process.env.PUPPETEER_PRODUCT || | ||
process.env.npm_config_puppeteer_product || | ||
process.env.npm_package_config_puppeteer_product; | ||
if (!isPuppeteerCore && product === 'firefox') | ||
preferredRevision = packageJson.puppeteer.firefox_revision; | ||
const puppeteer = new Puppeteer(__dirname, preferredRevision, isPuppeteerCore, product); | ||
const puppeteer = new Puppeteer( | ||
__dirname, | ||
preferredRevision, | ||
isPuppeteerCore, | ||
product | ||
); | ||
@@ -42,0 +51,0 @@ // The introspection in `Helper.installAsyncStackHooks` references `Puppeteer._launcher` |
183
install.js
@@ -29,5 +29,7 @@ /** | ||
const firefoxVersions = | ||
'https://product-details.mozilla.org/1.0/firefox_versions.json'; | ||
const supportedProducts = { | ||
'chrome': 'Chromium', | ||
'firefox': 'Firefox Nightly' | ||
chrome: 'Chromium', | ||
firefox: 'Firefox Nightly', | ||
}; | ||
@@ -38,6 +40,16 @@ | ||
const downloadHost = process.env.PUPPETEER_DOWNLOAD_HOST || process.env.npm_config_puppeteer_download_host || process.env.npm_package_config_puppeteer_download_host; | ||
const downloadHost = | ||
process.env.PUPPETEER_DOWNLOAD_HOST || | ||
process.env.npm_config_puppeteer_download_host || | ||
process.env.npm_package_config_puppeteer_download_host; | ||
const puppeteer = require('./index'); | ||
const product = process.env.PUPPETEER_PRODUCT || process.env.npm_config_puppeteer_product || process.env.npm_package_config_puppeteer_product || 'chrome'; | ||
const browserFetcher = puppeteer.createBrowserFetcher({product, host: downloadHost}); | ||
const product = | ||
process.env.PUPPETEER_PRODUCT || | ||
process.env.npm_config_puppeteer_product || | ||
process.env.npm_package_config_puppeteer_product || | ||
'chrome'; | ||
const browserFetcher = puppeteer.createBrowserFetcher({ | ||
product, | ||
host: downloadHost, | ||
}); | ||
const revision = await getRevision(); | ||
@@ -48,7 +60,14 @@ await fetchBinary(revision); | ||
if (product === 'chrome') { | ||
return process.env.PUPPETEER_CHROMIUM_REVISION || process.env.npm_config_puppeteer_chromium_revision || process.env.npm_package_config_puppeteer_chromium_revision | ||
|| require('./package.json').puppeteer.chromium_revision; | ||
return ( | ||
process.env.PUPPETEER_CHROMIUM_REVISION || | ||
process.env.npm_config_puppeteer_chromium_revision || | ||
process.env.npm_package_config_puppeteer_chromium_revision || | ||
require('./package.json').puppeteer.chromium_revision | ||
); | ||
} else if (product === 'firefox') { | ||
puppeteer._preferredRevision = require('./package.json').puppeteer.firefox_revision; | ||
return getFirefoxNightlyVersion(browserFetcher.host()).catch(error => { console.error(error); process.exit(1); }); | ||
return getFirefoxNightlyVersion(browserFetcher.host()).catch((error) => { | ||
console.error(error); | ||
process.exit(1); | ||
}); | ||
} else { | ||
@@ -64,3 +83,5 @@ throw new Error(`Unsupported product ${product}`); | ||
if (revisionInfo.local) { | ||
logPolitely(`${supportedProducts[product]} is already in ${revisionInfo.folderPath}; skipping download.`); | ||
logPolitely( | ||
`${supportedProducts[product]} is already in ${revisionInfo.folderPath}; skipping download.` | ||
); | ||
return; | ||
@@ -70,12 +91,11 @@ } | ||
// Override current environment proxy settings with npm configuration, if any. | ||
const NPM_HTTPS_PROXY = process.env.npm_config_https_proxy || process.env.npm_config_proxy; | ||
const NPM_HTTP_PROXY = process.env.npm_config_http_proxy || process.env.npm_config_proxy; | ||
const NPM_HTTPS_PROXY = | ||
process.env.npm_config_https_proxy || process.env.npm_config_proxy; | ||
const NPM_HTTP_PROXY = | ||
process.env.npm_config_http_proxy || process.env.npm_config_proxy; | ||
const NPM_NO_PROXY = process.env.npm_config_no_proxy; | ||
if (NPM_HTTPS_PROXY) | ||
process.env.HTTPS_PROXY = NPM_HTTPS_PROXY; | ||
if (NPM_HTTP_PROXY) | ||
process.env.HTTP_PROXY = NPM_HTTP_PROXY; | ||
if (NPM_NO_PROXY) | ||
process.env.NO_PROXY = NPM_NO_PROXY; | ||
if (NPM_HTTPS_PROXY) process.env.HTTPS_PROXY = NPM_HTTPS_PROXY; | ||
if (NPM_HTTP_PROXY) process.env.HTTP_PROXY = NPM_HTTP_PROXY; | ||
if (NPM_NO_PROXY) process.env.NO_PROXY = NPM_NO_PROXY; | ||
@@ -87,5 +107,11 @@ /** | ||
function onSuccess(localRevisions) { | ||
logPolitely(`${supportedProducts[product]} (${revisionInfo.revision}) downloaded to ${revisionInfo.folderPath}`); | ||
localRevisions = localRevisions.filter(revision => revision !== revisionInfo.revision); | ||
const cleanupOldVersions = localRevisions.map(revision => browserFetcher.remove(revision)); | ||
logPolitely( | ||
`${supportedProducts[product]} (${revisionInfo.revision}) downloaded to ${revisionInfo.folderPath}` | ||
); | ||
localRevisions = localRevisions.filter( | ||
(revision) => revision !== revisionInfo.revision | ||
); | ||
const cleanupOldVersions = localRevisions.map((revision) => | ||
browserFetcher.remove(revision) | ||
); | ||
Promise.all([...cleanupOldVersions]); | ||
@@ -98,3 +124,5 @@ } | ||
function onError(error) { | ||
console.error(`ERROR: Failed to set up ${supportedProducts[product]} r${revision}! Set "PUPPETEER_SKIP_DOWNLOAD" env variable to skip download.`); | ||
console.error( | ||
`ERROR: Failed to set up ${supportedProducts[product]} r${revision}! Set "PUPPETEER_SKIP_DOWNLOAD" env variable to skip download.` | ||
); | ||
console.error(error); | ||
@@ -109,8 +137,13 @@ process.exit(1); | ||
const ProgressBar = require('progress'); | ||
progressBar = new ProgressBar(`Downloading ${supportedProducts[product]} r${revision} - ${toMegabytes(totalBytes)} [:bar] :percent :etas `, { | ||
complete: '=', | ||
incomplete: ' ', | ||
width: 20, | ||
total: totalBytes, | ||
}); | ||
progressBar = new ProgressBar( | ||
`Downloading ${ | ||
supportedProducts[product] | ||
} r${revision} - ${toMegabytes(totalBytes)} [:bar] :percent :etas `, | ||
{ | ||
complete: '=', | ||
incomplete: ' ', | ||
width: 20, | ||
total: totalBytes, | ||
} | ||
); | ||
} | ||
@@ -122,6 +155,7 @@ const delta = downloadedBytes - lastDownloadedBytes; | ||
return browserFetcher.download(revisionInfo.revision, onProgress) | ||
.then(() => browserFetcher.localRevisions()) | ||
.then(onSuccess) | ||
.catch(onError); | ||
return browserFetcher | ||
.download(revisionInfo.revision, onProgress) | ||
.then(() => browserFetcher.localRevisions()) | ||
.then(onSuccess) | ||
.catch(onError); | ||
} | ||
@@ -139,24 +173,19 @@ | ||
logPolitely(`Requesting latest Firefox Nightly version from ${host}`); | ||
https.get(host + '/', r => { | ||
if (r.statusCode >= 400) | ||
return reject(new Error(`Got status code ${r.statusCode}`)); | ||
r.on('data', chunk => { | ||
data += chunk; | ||
}); | ||
r.on('end', parseVersion); | ||
}).on('error', reject); | ||
function parseVersion() { | ||
const regex = /firefox\-(?<version>\d\d)\..*/gm; | ||
let result = 0; | ||
let match; | ||
while ((match = regex.exec(data)) !== null) { | ||
const version = parseInt(match.groups.version, 10); | ||
if (version > result) | ||
result = version; | ||
} | ||
if (result) | ||
resolve(result.toString()); | ||
else reject(new Error('Firefox version not found')); | ||
} | ||
https | ||
.get(firefoxVersions, (r) => { | ||
if (r.statusCode >= 400) | ||
return reject(new Error(`Got status code ${r.statusCode}`)); | ||
r.on('data', (chunk) => { | ||
data += chunk; | ||
}); | ||
r.on('end', () => { | ||
try { | ||
const versions = JSON.parse(data); | ||
return resolve(versions.FIREFOX_NIGHTLY); | ||
} catch { | ||
return reject(new Error('Firefox version not found')); | ||
} | ||
}); | ||
}) | ||
.on('error', reject); | ||
}); | ||
@@ -171,28 +200,51 @@ return promise; | ||
if (!logLevelDisplay) | ||
console.log(toBeLogged); | ||
if (!logLevelDisplay) console.log(toBeLogged); | ||
} | ||
if (process.env.PUPPETEER_SKIP_DOWNLOAD) { | ||
logPolitely('**INFO** Skipping browser download. "PUPPETEER_SKIP_DOWNLOAD" environment variable was found.'); | ||
logPolitely( | ||
'**INFO** Skipping browser download. "PUPPETEER_SKIP_DOWNLOAD" environment variable was found.' | ||
); | ||
return; | ||
} | ||
if (process.env.NPM_CONFIG_PUPPETEER_SKIP_DOWNLOAD || process.env.npm_config_puppeteer_skip_download) { | ||
logPolitely('**INFO** Skipping browser download. "PUPPETEER_SKIP_DOWNLOAD" was set in npm config.'); | ||
if ( | ||
process.env.NPM_CONFIG_PUPPETEER_SKIP_DOWNLOAD || | ||
process.env.npm_config_puppeteer_skip_download | ||
) { | ||
logPolitely( | ||
'**INFO** Skipping browser download. "PUPPETEER_SKIP_DOWNLOAD" was set in npm config.' | ||
); | ||
return; | ||
} | ||
if (process.env.NPM_PACKAGE_CONFIG_PUPPETEER_SKIP_DOWNLOAD || process.env.npm_package_config_puppeteer_skip_download) { | ||
logPolitely('**INFO** Skipping browser download. "PUPPETEER_SKIP_DOWNLOAD" was set in project config.'); | ||
if ( | ||
process.env.NPM_PACKAGE_CONFIG_PUPPETEER_SKIP_DOWNLOAD || | ||
process.env.npm_package_config_puppeteer_skip_download | ||
) { | ||
logPolitely( | ||
'**INFO** Skipping browser download. "PUPPETEER_SKIP_DOWNLOAD" was set in project config.' | ||
); | ||
return; | ||
} | ||
if (process.env.PUPPETEER_SKIP_CHROMIUM_DOWNLOAD) { | ||
logPolitely('**INFO** Skipping browser download. "PUPPETEER_SKIP_CHROMIUM_DOWNLOAD" environment variable was found.'); | ||
logPolitely( | ||
'**INFO** Skipping browser download. "PUPPETEER_SKIP_CHROMIUM_DOWNLOAD" environment variable was found.' | ||
); | ||
return; | ||
} | ||
if (process.env.NPM_CONFIG_PUPPETEER_SKIP_CHROMIUM_DOWNLOAD || process.env.npm_config_puppeteer_skip_chromium_download) { | ||
logPolitely('**INFO** Skipping browser download. "PUPPETEER_SKIP_CHROMIUM_DOWNLOAD" was set in npm config.'); | ||
if ( | ||
process.env.NPM_CONFIG_PUPPETEER_SKIP_CHROMIUM_DOWNLOAD || | ||
process.env.npm_config_puppeteer_skip_chromium_download | ||
) { | ||
logPolitely( | ||
'**INFO** Skipping browser download. "PUPPETEER_SKIP_CHROMIUM_DOWNLOAD" was set in npm config.' | ||
); | ||
return; | ||
} | ||
if (process.env.NPM_PACKAGE_CONFIG_PUPPETEER_SKIP_CHROMIUM_DOWNLOAD || process.env.npm_package_config_puppeteer_skip_chromium_download) { | ||
logPolitely('**INFO** Skipping browser download. "PUPPETEER_SKIP_CHROMIUM_DOWNLOAD" was set in project config.'); | ||
if ( | ||
process.env.NPM_PACKAGE_CONFIG_PUPPETEER_SKIP_CHROMIUM_DOWNLOAD || | ||
process.env.npm_package_config_puppeteer_skip_chromium_download | ||
) { | ||
logPolitely( | ||
'**INFO** Skipping browser download. "PUPPETEER_SKIP_CHROMIUM_DOWNLOAD" was set in project config.' | ||
); | ||
return; | ||
@@ -202,2 +254,1 @@ } | ||
download(); | ||
@@ -18,2 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Accessibility = void 0; | ||
class Accessibility { | ||
@@ -24,7 +25,9 @@ constructor(client) { | ||
async snapshot(options = {}) { | ||
const { interestingOnly = true, root = null, } = options; | ||
const { interestingOnly = true, root = null } = options; | ||
const { nodes } = await this._client.send('Accessibility.getFullAXTree'); | ||
let backendNodeId = null; | ||
if (root) { | ||
const { node } = await this._client.send('DOM.describeNode', { objectId: root._remoteObject.objectId }); | ||
const { node } = await this._client.send('DOM.describeNode', { | ||
objectId: root._remoteObject.objectId, | ||
}); | ||
backendNodeId = node.backendNodeId; | ||
@@ -35,3 +38,3 @@ } | ||
if (backendNodeId) { | ||
needle = defaultRoot.find(node => node._payload.backendDOMNodeId === backendNodeId); | ||
needle = defaultRoot.find((node) => node.payload.backendDOMNodeId === backendNodeId); | ||
if (!needle) | ||
@@ -41,48 +44,42 @@ return null; | ||
if (!interestingOnly) | ||
return serializeTree(needle)[0]; | ||
return this.serializeTree(needle)[0]; | ||
const interestingNodes = new Set(); | ||
collectInterestingNodes(interestingNodes, defaultRoot, false); | ||
this.collectInterestingNodes(interestingNodes, defaultRoot, false); | ||
if (!interestingNodes.has(needle)) | ||
return null; | ||
return serializeTree(needle, interestingNodes)[0]; | ||
return this.serializeTree(needle, interestingNodes)[0]; | ||
} | ||
serializeTree(node, whitelistedNodes) { | ||
const children = []; | ||
for (const child of node.children) | ||
children.push(...this.serializeTree(child, whitelistedNodes)); | ||
if (whitelistedNodes && !whitelistedNodes.has(node)) | ||
return children; | ||
const serializedNode = node.serialize(); | ||
if (children.length) | ||
serializedNode.children = children; | ||
return [serializedNode]; | ||
} | ||
collectInterestingNodes(collection, node, insideControl) { | ||
if (node.isInteresting(insideControl)) | ||
collection.add(node); | ||
if (node.isLeafNode()) | ||
return; | ||
insideControl = insideControl || node.isControl(); | ||
for (const child of node.children) | ||
this.collectInterestingNodes(collection, child, insideControl); | ||
} | ||
} | ||
exports.Accessibility = Accessibility; | ||
/** | ||
* @param {!Set<!AXNode>} collection | ||
* @param {!AXNode} node | ||
* @param {boolean} insideControl | ||
*/ | ||
function collectInterestingNodes(collection, node, insideControl) { | ||
if (node.isInteresting(insideControl)) | ||
collection.add(node); | ||
if (node.isLeafNode()) | ||
return; | ||
insideControl = insideControl || node.isControl(); | ||
for (const child of node._children) | ||
collectInterestingNodes(collection, child, insideControl); | ||
} | ||
function serializeTree(node, whitelistedNodes) { | ||
const children = []; | ||
for (const child of node._children) | ||
children.push(...serializeTree(child, whitelistedNodes)); | ||
if (whitelistedNodes && !whitelistedNodes.has(node)) | ||
return children; | ||
const serializedNode = node.serialize(); | ||
if (children.length) | ||
serializedNode.children = children; | ||
return [serializedNode]; | ||
} | ||
class AXNode { | ||
constructor(payload) { | ||
this._children = []; | ||
this.children = []; | ||
this._richlyEditable = false; | ||
this._editable = false; | ||
this._focusable = false; | ||
this._expanded = false; | ||
this._hidden = false; | ||
this._payload = payload; | ||
this._name = this._payload.name ? this._payload.name.value : ''; | ||
this._role = this._payload.role ? this._payload.role.value : 'Unknown'; | ||
for (const property of this._payload.properties || []) { | ||
this.payload = payload; | ||
this._name = this.payload.name ? this.payload.name.value : ''; | ||
this._role = this.payload.role ? this.payload.role.value : 'Unknown'; | ||
for (const property of this.payload.properties || []) { | ||
if (property.name === 'editable') { | ||
@@ -94,4 +91,2 @@ this._richlyEditable = property.value.value === 'richtext'; | ||
this._focusable = property.value.value; | ||
if (property.name === 'expanded') | ||
this._expanded = property.value.value; | ||
if (property.name === 'hidden') | ||
@@ -106,8 +101,9 @@ this._hidden = property.value.value; | ||
return true; | ||
return this._role === 'textbox' || this._role === 'ComboBox' || this._role === 'searchbox'; | ||
return (this._role === 'textbox' || | ||
this._role === 'ComboBox' || | ||
this._role === 'searchbox'); | ||
} | ||
_isTextOnlyObject() { | ||
const role = this._role; | ||
return (role === 'LineBreak' || role === 'text' || | ||
role === 'InlineTextBox'); | ||
return role === 'LineBreak' || role === 'text' || role === 'InlineTextBox'; | ||
} | ||
@@ -117,3 +113,3 @@ _hasFocusableChild() { | ||
this._cachedHasFocusableChild = false; | ||
for (const child of this._children) { | ||
for (const child of this.children) { | ||
if (child._focusable || child._hasFocusableChild()) { | ||
@@ -130,3 +126,3 @@ this._cachedHasFocusableChild = true; | ||
return this; | ||
for (const child of this._children) { | ||
for (const child of this.children) { | ||
const result = child.find(predicate); | ||
@@ -139,3 +135,3 @@ if (result) | ||
isLeafNode() { | ||
if (!this._children.length) | ||
if (!this.children.length) | ||
return true; | ||
@@ -201,6 +197,2 @@ // These types of objects may have children that we use as internal | ||
} | ||
/** | ||
* @param {boolean} insideControl | ||
* @return {boolean} | ||
*/ | ||
isInteresting(insideControl) { | ||
@@ -222,12 +214,12 @@ const role = this._role; | ||
const properties = new Map(); | ||
for (const property of this._payload.properties || []) | ||
for (const property of this.payload.properties || []) | ||
properties.set(property.name.toLowerCase(), property.value.value); | ||
if (this._payload.name) | ||
properties.set('name', this._payload.name.value); | ||
if (this._payload.value) | ||
properties.set('value', this._payload.value.value); | ||
if (this._payload.description) | ||
properties.set('description', this._payload.description.value); | ||
if (this.payload.name) | ||
properties.set('name', this.payload.name.value); | ||
if (this.payload.value) | ||
properties.set('value', this.payload.value.value); | ||
if (this.payload.description) | ||
properties.set('description', this.payload.description.value); | ||
const node = { | ||
role: this._role | ||
role: this._role, | ||
}; | ||
@@ -270,6 +262,3 @@ const userStringProperties = [ | ||
} | ||
const tristateProperties = [ | ||
'checked', | ||
'pressed', | ||
]; | ||
const tristateProperties = ['checked', 'pressed']; | ||
for (const tristateProperty of tristateProperties) { | ||
@@ -279,3 +268,4 @@ if (!properties.has(tristateProperty)) | ||
const value = properties.get(tristateProperty); | ||
node[tristateProperty] = value === 'mixed' ? 'mixed' : value === 'true' ? true : false; | ||
node[tristateProperty] = | ||
value === 'mixed' ? 'mixed' : value === 'true' ? true : false; | ||
} | ||
@@ -309,3 +299,2 @@ const numericalProperties = [ | ||
static createTree(payloads) { | ||
/** @type {!Map<string, !AXNode>} */ | ||
const nodeById = new Map(); | ||
@@ -315,4 +304,4 @@ for (const payload of payloads) | ||
for (const node of nodeById.values()) { | ||
for (const childId of node._payload.childIds || []) | ||
node._children.push(nodeById.get(childId)); | ||
for (const childId of node.payload.childIds || []) | ||
node.children.push(nodeById.get(childId)); | ||
} | ||
@@ -319,0 +308,0 @@ return nodeById.values().next().value; |
@@ -26,3 +26,3 @@ /** | ||
CDPSession: require('./Connection').CDPSession, | ||
ConsoleMessage: require('./Page').ConsoleMessage, | ||
ConsoleMessage: require('./ConsoleMessage').ConsoleMessage, | ||
Coverage: require('./Coverage').Coverage, | ||
@@ -32,3 +32,3 @@ Dialog: require('./Dialog').Dialog, | ||
ExecutionContext: require('./ExecutionContext').ExecutionContext, | ||
FileChooser: require('./Page').FileChooser, | ||
FileChooser: require('./FileChooser').FileChooser, | ||
Frame: require('./FrameManager').Frame, | ||
@@ -40,5 +40,5 @@ JSHandle: require('./JSHandle').JSHandle, | ||
Puppeteer: require('./Puppeteer').Puppeteer, | ||
Request: require('./NetworkManager').Request, | ||
Response: require('./NetworkManager').Response, | ||
SecurityDetails: require('./NetworkManager').SecurityDetails, | ||
Request: require('./Request').Request, | ||
Response: require('./Response').Response, | ||
SecurityDetails: require('./SecurityDetails').SecurityDetails, | ||
Target: require('./Target').Target, | ||
@@ -45,0 +45,0 @@ TimeoutError: require('./Errors').TimeoutError, |
@@ -18,6 +18,6 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.BrowserContext = exports.Browser = void 0; | ||
const helper_1 = require("./helper"); | ||
const Target_1 = require("./Target"); | ||
const EventEmitter = require("events"); | ||
const TaskQueue_1 = require("./TaskQueue"); | ||
const Events_1 = require("./Events"); | ||
@@ -27,7 +27,5 @@ class Browser extends EventEmitter { | ||
super(); | ||
this._screenshotTaskQueue = new TaskQueue_1.TaskQueue(); | ||
this._ignoreHTTPSErrors = ignoreHTTPSErrors; | ||
this._defaultViewport = defaultViewport; | ||
this._process = process; | ||
this._screenshotTaskQueue = new TaskQueue_1.TaskQueue(); | ||
this._connection = connection; | ||
@@ -66,6 +64,8 @@ this._closeCallback = closeCallback || function () { }; | ||
/** | ||
* @param {?string} contextId | ||
*/ | ||
* @param {?string} contextId | ||
*/ | ||
async _disposeContext(contextId) { | ||
await this._connection.send('Target.disposeBrowserContext', { browserContextId: contextId || undefined }); | ||
await this._connection.send('Target.disposeBrowserContext', { | ||
browserContextId: contextId || undefined, | ||
}); | ||
this._contexts.delete(contextId); | ||
@@ -76,4 +76,6 @@ } | ||
const { browserContextId } = targetInfo; | ||
const context = (browserContextId && this._contexts.has(browserContextId)) ? this._contexts.get(browserContextId) : this._defaultContext; | ||
const target = new Target_1.Target(targetInfo, context, () => this._connection.createSession(targetInfo), this._ignoreHTTPSErrors, this._defaultViewport, this._screenshotTaskQueue); | ||
const context = browserContextId && this._contexts.has(browserContextId) | ||
? this._contexts.get(browserContextId) | ||
: this._defaultContext; | ||
const target = new Target_1.Target(targetInfo, context, () => this._connection.createSession(targetInfo), this._ignoreHTTPSErrors, this._defaultViewport); | ||
helper_1.assert(!this._targets.has(event.targetInfo.targetId), 'Target should not exist before targetCreated'); | ||
@@ -87,4 +89,4 @@ this._targets.set(event.targetInfo.targetId, target); | ||
/** | ||
* @param {{targetId: string}} event | ||
*/ | ||
* @param {{targetId: string}} event | ||
*/ | ||
async _targetDestroyed(event) { | ||
@@ -97,8 +99,10 @@ const target = this._targets.get(event.targetId); | ||
this.emit(Events_1.Events.Browser.TargetDestroyed, target); | ||
target.browserContext().emit(Events_1.Events.BrowserContext.TargetDestroyed, target); | ||
target | ||
.browserContext() | ||
.emit(Events_1.Events.BrowserContext.TargetDestroyed, target); | ||
} | ||
} | ||
/** | ||
* @param {!Protocol.Target.targetInfoChangedPayload} event | ||
*/ | ||
* @param {!Protocol.Target.targetInfoChangedPayload} event | ||
*/ | ||
_targetInfoChanged(event) { | ||
@@ -122,3 +126,6 @@ const target = this._targets.get(event.targetInfo.targetId); | ||
async _createPageInContext(contextId) { | ||
const { targetId } = await this._connection.send('Target.createTarget', { url: 'about:blank', browserContextId: contextId || undefined }); | ||
const { targetId } = await this._connection.send('Target.createTarget', { | ||
url: 'about:blank', | ||
browserContextId: contextId || undefined, | ||
}); | ||
const target = await this._targets.get(targetId); | ||
@@ -130,12 +137,12 @@ helper_1.assert(await target._initializedPromise, 'Failed to create target for page'); | ||
targets() { | ||
return Array.from(this._targets.values()).filter(target => target._isInitialized); | ||
return Array.from(this._targets.values()).filter((target) => target._isInitialized); | ||
} | ||
target() { | ||
return this.targets().find(target => target.type() === 'browser'); | ||
return this.targets().find((target) => target.type() === 'browser'); | ||
} | ||
/** | ||
* @param {function(!Target):boolean} predicate | ||
* @param {{timeout?: number}=} options | ||
* @return {!Promise<!Target>} | ||
*/ | ||
* @param {function(!Target):boolean} predicate | ||
* @param {{timeout?: number}=} options | ||
* @return {!Promise<!Target>} | ||
*/ | ||
async waitForTarget(predicate, options = {}) { | ||
@@ -147,3 +154,3 @@ const { timeout = 30000 } = options; | ||
let resolve; | ||
const targetPromise = new Promise(x => resolve = x); | ||
const targetPromise = new Promise((x) => (resolve = x)); | ||
this.on(Events_1.Events.Browser.TargetCreated, check); | ||
@@ -166,3 +173,3 @@ this.on(Events_1.Events.Browser.TargetChanged, check); | ||
async pages() { | ||
const contextPages = await Promise.all(this.browserContexts().map(context => context.pages())); | ||
const contextPages = await Promise.all(this.browserContexts().map((context) => context.pages())); | ||
// Flatten array. | ||
@@ -202,12 +209,14 @@ return contextPages.reduce((acc, x) => acc.concat(x), []); | ||
targets() { | ||
return this._browser.targets().filter(target => target.browserContext() === this); | ||
return this._browser | ||
.targets() | ||
.filter((target) => target.browserContext() === this); | ||
} | ||
waitForTarget(predicate, options) { | ||
return this._browser.waitForTarget(target => target.browserContext() === this && predicate(target), options); | ||
return this._browser.waitForTarget((target) => target.browserContext() === this && predicate(target), options); | ||
} | ||
async pages() { | ||
const pages = await Promise.all(this.targets() | ||
.filter(target => target.type() === 'page') | ||
.map(target => target.page())); | ||
return pages.filter(page => !!page); | ||
.filter((target) => target.type() === 'page') | ||
.map((target) => target.page())); | ||
return pages.filter((page) => !!page); | ||
} | ||
@@ -238,3 +247,3 @@ isIncognito() { | ||
]); | ||
permissions = permissions.map(permission => { | ||
permissions = permissions.map((permission) => { | ||
const protocolPermission = webPermissionToProtocol.get(permission); | ||
@@ -245,6 +254,12 @@ if (!protocolPermission) | ||
}); | ||
await this._connection.send('Browser.grantPermissions', { origin, browserContextId: this._id || undefined, permissions }); | ||
await this._connection.send('Browser.grantPermissions', { | ||
origin, | ||
browserContextId: this._id || undefined, | ||
permissions, | ||
}); | ||
} | ||
async clearPermissionOverrides() { | ||
await this._connection.send('Browser.resetPermissions', { browserContextId: this._id || undefined }); | ||
await this._connection.send('Browser.resetPermissions', { | ||
browserContextId: this._id || undefined, | ||
}); | ||
} | ||
@@ -251,0 +266,0 @@ newPage() { |
@@ -18,2 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.BrowserFetcher = void 0; | ||
const os = require("os"); | ||
@@ -42,6 +43,6 @@ const fs = require("fs"); | ||
firefox: { | ||
linux: '%s/firefox-%s.0a1.en-US.%s-x86_64.tar.bz2', | ||
mac: '%s/firefox-%s.0a1.en-US.%s.dmg', | ||
win32: '%s/firefox-%s.0a1.en-US.%s.zip', | ||
win64: '%s/firefox-%s.0a1.en-US.%s.zip', | ||
linux: '%s/firefox-%s.en-US.%s-x86_64.tar.bz2', | ||
mac: '%s/firefox-%s.en-US.%s.dmg', | ||
win32: '%s/firefox-%s.en-US.%s.zip', | ||
win64: '%s/firefox-%s.en-US.%s.zip', | ||
}, | ||
@@ -57,3 +58,3 @@ }; | ||
destination: '.local-firefox', | ||
} | ||
}, | ||
}; | ||
@@ -91,4 +92,4 @@ function archiveName(product, platform, revision) { | ||
function existsAsync(filePath) { | ||
return new Promise(resolve => { | ||
fs.access(filePath, err => resolve(!err)); | ||
return new Promise((resolve) => { | ||
fs.access(filePath, (err) => resolve(!err)); | ||
}); | ||
@@ -102,3 +103,5 @@ } | ||
helper_1.assert(this._product === 'chrome' || this._product === 'firefox', `Unknown product: "${options.product}"`); | ||
this._downloadsFolder = options.path || path.join(projectRoot, browserConfig[this._product].destination); | ||
this._downloadsFolder = | ||
options.path || | ||
path.join(projectRoot, browserConfig[this._product].destination); | ||
this._downloadHost = options.host || browserConfig[this._product].host; | ||
@@ -134,7 +137,7 @@ this.setPlatform(options.platform); | ||
const url = downloadURL(this._product, this._platform, this._downloadHost, revision); | ||
return new Promise(resolve => { | ||
const request = httpRequest(url, 'HEAD', response => { | ||
return new Promise((resolve) => { | ||
const request = httpRequest(url, 'HEAD', (response) => { | ||
resolve(response.statusCode === 200); | ||
}); | ||
request.on('error', error => { | ||
request.on('error', (error) => { | ||
console.error(error); | ||
@@ -173,6 +176,9 @@ resolve(false); | ||
async localRevisions() { | ||
if (!await existsAsync(this._downloadsFolder)) | ||
if (!(await existsAsync(this._downloadsFolder))) | ||
return []; | ||
const fileNames = await readdirAsync(this._downloadsFolder); | ||
return fileNames.map(fileName => parseFolderPath(this._product, fileName)).filter(entry => entry && entry.platform === this._platform).map(entry => entry.revision); | ||
return fileNames | ||
.map((fileName) => parseFolderPath(this._product, fileName)) | ||
.filter((entry) => entry && entry.platform === this._platform) | ||
.map((entry) => entry.revision); | ||
} | ||
@@ -182,3 +188,3 @@ async remove(revision) { | ||
helper_1.assert(await existsAsync(folderPath), `Failed to remove: revision ${revision} is not downloaded`); | ||
await new Promise(fulfill => removeRecursive(folderPath, fulfill)); | ||
await new Promise((fulfill) => removeRecursive(folderPath, fulfill)); | ||
} | ||
@@ -213,4 +219,18 @@ revisionInfo(revision) { | ||
const local = fs.existsSync(folderPath); | ||
debugFetcher({ revision, executablePath, folderPath, local, url, product: this._product }); | ||
return { revision, executablePath, folderPath, local, url, product: this._product }; | ||
debugFetcher({ | ||
revision, | ||
executablePath, | ||
folderPath, | ||
local, | ||
url, | ||
product: this._product, | ||
}); | ||
return { | ||
revision, | ||
executablePath, | ||
folderPath, | ||
local, | ||
url, | ||
product: this._product, | ||
}; | ||
} | ||
@@ -247,4 +267,7 @@ /** | ||
let totalBytes = 0; | ||
const promise = new Promise((x, y) => { fulfill = x; reject = y; }); | ||
const request = httpRequest(url, 'GET', response => { | ||
const promise = new Promise((x, y) => { | ||
fulfill = x; | ||
reject = y; | ||
}); | ||
const request = httpRequest(url, 'GET', (response) => { | ||
if (response.statusCode !== 200) { | ||
@@ -259,9 +282,10 @@ const error = new Error(`Download failed: server returned code ${response.statusCode}. URL: ${url}`); | ||
file.on('finish', () => fulfill()); | ||
file.on('error', error => reject(error)); | ||
file.on('error', (error) => reject(error)); | ||
response.pipe(file); | ||
totalBytes = parseInt(/** @type {string} */ (response.headers['content-length']), 10); | ||
totalBytes = parseInt( | ||
/** @type {string} */ response.headers['content-length'], 10); | ||
if (progressCallback) | ||
response.on('data', onData); | ||
}); | ||
request.on('error', error => reject(error)); | ||
request.on('error', (error) => reject(error)); | ||
return promise; | ||
@@ -299,3 +323,5 @@ function onData(chunk) { | ||
const readStream = fs.createReadStream(tarPath); | ||
readStream.on('data', () => { process.stdout.write('\rExtracting...'); }); | ||
readStream.on('data', () => { | ||
process.stdout.write('\rExtracting...'); | ||
}); | ||
readStream.pipe(bzip()).pipe(tarStream); | ||
@@ -322,4 +348,5 @@ }); | ||
mountPath = volumes[0]; | ||
readdirAsync(mountPath).then(fileNames => { | ||
const appName = fileNames.filter(item => typeof item === 'string' && item.endsWith('.app'))[0]; | ||
readdirAsync(mountPath) | ||
.then((fileNames) => { | ||
const appName = fileNames.filter((item) => typeof item === 'string' && item.endsWith('.app'))[0]; | ||
if (!appName) | ||
@@ -329,3 +356,3 @@ return reject(new Error(`Cannot find app in ${mountPath}`)); | ||
debugFetcher(`Copying ${copyPath} to ${folderPath}`); | ||
childProcess.exec(`cp -R "${copyPath}" "${folderPath}"`, err => { | ||
childProcess.exec(`cp -R "${copyPath}" "${folderPath}"`, (err) => { | ||
if (err) | ||
@@ -336,3 +363,4 @@ reject(err); | ||
}); | ||
}).catch(reject); | ||
}) | ||
.catch(reject); | ||
}); | ||
@@ -345,3 +373,3 @@ } | ||
debugFetcher(`Unmounting ${mountPath}`); | ||
childProcess.exec(unmountCommand, err => { | ||
childProcess.exec(unmountCommand, (err) => { | ||
if (err) | ||
@@ -351,3 +379,7 @@ console.error(`Error unmounting dmg: ${err}`); | ||
} | ||
return new Promise(mountAndCopy).catch(error => { console.error(error); }).finally(unmount); | ||
return new Promise(mountAndCopy) | ||
.catch((error) => { | ||
console.error(error); | ||
}) | ||
.finally(unmount); | ||
} | ||
@@ -386,7 +418,7 @@ function httpRequest(url, method, response) { | ||
}; | ||
const request = options.protocol === 'https:' ? | ||
https.request(options, requestCallback) : | ||
http.request(options, requestCallback); | ||
const request = options.protocol === 'https:' | ||
? https.request(options, requestCallback) | ||
: http.request(options, requestCallback); | ||
request.end(); | ||
return request; | ||
} |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.CDPSession = exports.Connection = void 0; | ||
/** | ||
@@ -64,3 +65,3 @@ * Copyright 2017 Google Inc. All rights reserved. | ||
if (this._delay) | ||
await new Promise(f => setTimeout(f, this._delay)); | ||
await new Promise((f) => setTimeout(f, this._delay)); | ||
debugProtocol('◀ RECV ' + message); | ||
@@ -123,3 +124,6 @@ const object = JSON.parse(message); | ||
async createSession(targetInfo) { | ||
const { sessionId } = await this.send('Target.attachToTarget', { targetId: targetInfo.targetId, flatten: true }); | ||
const { sessionId } = await this.send('Target.attachToTarget', { | ||
targetId: targetInfo.targetId, | ||
flatten: true, | ||
}); | ||
return this._sessions.get(sessionId); | ||
@@ -147,3 +151,3 @@ } | ||
*/ | ||
params: params || {} | ||
params: params || {}, | ||
}); | ||
@@ -171,3 +175,5 @@ return new Promise((resolve, reject) => { | ||
throw new Error(`Session already detached. Most likely the ${this._targetType} has been closed.`); | ||
await this._connection.send('Target.detachFromTarget', { sessionId: this._sessionId }); | ||
await this._connection.send('Target.detachFromTarget', { | ||
sessionId: this._sessionId, | ||
}); | ||
} | ||
@@ -174,0 +180,0 @@ _onClosed() { |
@@ -18,2 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Coverage = void 0; | ||
const helper_1 = require("./helper"); | ||
@@ -52,3 +53,3 @@ const ExecutionContext_1 = require("./ExecutionContext"); | ||
helper_1.assert(!this._enabled, 'JSCoverage is already enabled'); | ||
const { resetOnNavigation = true, reportAnonymousScripts = false } = options; | ||
const { resetOnNavigation = true, reportAnonymousScripts = false, } = options; | ||
this._resetOnNavigation = resetOnNavigation; | ||
@@ -65,5 +66,8 @@ this._reportAnonymousScripts = reportAnonymousScripts; | ||
this._client.send('Profiler.enable'), | ||
this._client.send('Profiler.startPreciseCoverage', { callCount: false, detailed: true }), | ||
this._client.send('Profiler.startPreciseCoverage', { | ||
callCount: false, | ||
detailed: true, | ||
}), | ||
this._client.send('Debugger.enable'), | ||
this._client.send('Debugger.setSkipAllPauses', { skip: true }) | ||
this._client.send('Debugger.setSkipAllPauses', { skip: true }), | ||
]); | ||
@@ -85,3 +89,5 @@ } | ||
try { | ||
const response = await this._client.send('Debugger.getScriptSource', { scriptId: event.scriptId }); | ||
const response = await this._client.send('Debugger.getScriptSource', { | ||
scriptId: event.scriptId, | ||
}); | ||
this._scriptURLs.set(event.scriptId, event.url); | ||
@@ -162,3 +168,5 @@ this._scriptSources.set(event.scriptId, response.scriptSource); | ||
try { | ||
const response = await this._client.send('CSS.getStyleSheetText', { styleSheetId: header.styleSheetId }); | ||
const response = await this._client.send('CSS.getStyleSheetText', { | ||
styleSheetId: header.styleSheetId, | ||
}); | ||
this._stylesheetURLs.set(header.styleSheetId, header.sourceURL); | ||
@@ -232,3 +240,5 @@ this._stylesheetSources.set(header.styleSheetId, response.text); | ||
for (const point of points) { | ||
if (hitCountStack.length && lastOffset < point.offset && hitCountStack[hitCountStack.length - 1] > 0) { | ||
if (hitCountStack.length && | ||
lastOffset < point.offset && | ||
hitCountStack[hitCountStack.length - 1] > 0) { | ||
const lastResult = results.length ? results[results.length - 1] : null; | ||
@@ -247,3 +257,3 @@ if (lastResult && lastResult.end === lastOffset) | ||
// Filter out empty ranges. | ||
return results.filter(range => range.end - range.start > 1); | ||
return results.filter((range) => range.end - range.start > 1); | ||
} |
@@ -18,855 +18,856 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.devicesMap = void 0; | ||
const devices = [ | ||
{ | ||
'name': 'Blackberry PlayBook', | ||
'userAgent': 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+', | ||
'viewport': { | ||
'width': 600, | ||
'height': 1024, | ||
'deviceScaleFactor': 1, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Blackberry PlayBook', | ||
userAgent: 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+', | ||
viewport: { | ||
width: 600, | ||
height: 1024, | ||
deviceScaleFactor: 1, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Blackberry PlayBook landscape', | ||
'userAgent': 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+', | ||
'viewport': { | ||
'width': 1024, | ||
'height': 600, | ||
'deviceScaleFactor': 1, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'Blackberry PlayBook landscape', | ||
userAgent: 'Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML like Gecko) Version/7.2.1.0 Safari/536.2+', | ||
viewport: { | ||
width: 1024, | ||
height: 600, | ||
deviceScaleFactor: 1, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'BlackBerry Z30', | ||
'userAgent': 'Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile Safari/537.10+', | ||
'viewport': { | ||
'width': 360, | ||
'height': 640, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'BlackBerry Z30', | ||
userAgent: 'Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile Safari/537.10+', | ||
viewport: { | ||
width: 360, | ||
height: 640, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'BlackBerry Z30 landscape', | ||
'userAgent': 'Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile Safari/537.10+', | ||
'viewport': { | ||
'width': 640, | ||
'height': 360, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'BlackBerry Z30 landscape', | ||
userAgent: 'Mozilla/5.0 (BB10; Touch) AppleWebKit/537.10+ (KHTML, like Gecko) Version/10.0.9.2372 Mobile Safari/537.10+', | ||
viewport: { | ||
width: 640, | ||
height: 360, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'Galaxy Note 3', | ||
'userAgent': 'Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', | ||
'viewport': { | ||
'width': 360, | ||
'height': 640, | ||
'deviceScaleFactor': 3, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Galaxy Note 3', | ||
userAgent: 'Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', | ||
viewport: { | ||
width: 360, | ||
height: 640, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Galaxy Note 3 landscape', | ||
'userAgent': 'Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', | ||
'viewport': { | ||
'width': 640, | ||
'height': 360, | ||
'deviceScaleFactor': 3, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'Galaxy Note 3 landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; U; Android 4.3; en-us; SM-N900T Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', | ||
viewport: { | ||
width: 640, | ||
height: 360, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'Galaxy Note II', | ||
'userAgent': 'Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', | ||
'viewport': { | ||
'width': 360, | ||
'height': 640, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Galaxy Note II', | ||
userAgent: 'Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', | ||
viewport: { | ||
width: 360, | ||
height: 640, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Galaxy Note II landscape', | ||
'userAgent': 'Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', | ||
'viewport': { | ||
'width': 640, | ||
'height': 360, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'Galaxy Note II landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; U; Android 4.1; en-us; GT-N7100 Build/JRO03C) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', | ||
viewport: { | ||
width: 640, | ||
height: 360, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'Galaxy S III', | ||
'userAgent': 'Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', | ||
'viewport': { | ||
'width': 360, | ||
'height': 640, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Galaxy S III', | ||
userAgent: 'Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', | ||
viewport: { | ||
width: 360, | ||
height: 640, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Galaxy S III landscape', | ||
'userAgent': 'Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', | ||
'viewport': { | ||
'width': 640, | ||
'height': 360, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'Galaxy S III landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30', | ||
viewport: { | ||
width: 640, | ||
height: 360, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'Galaxy S5', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 360, | ||
'height': 640, | ||
'deviceScaleFactor': 3, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Galaxy S5', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 360, | ||
height: 640, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Galaxy S5 landscape', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 640, | ||
'height': 360, | ||
'deviceScaleFactor': 3, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'Galaxy S5 landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 640, | ||
height: 360, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPad', | ||
'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', | ||
'viewport': { | ||
'width': 768, | ||
'height': 1024, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'iPad', | ||
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', | ||
viewport: { | ||
width: 768, | ||
height: 1024, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPad landscape', | ||
'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', | ||
'viewport': { | ||
'width': 1024, | ||
'height': 768, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'iPad landscape', | ||
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', | ||
viewport: { | ||
width: 1024, | ||
height: 768, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPad Mini', | ||
'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', | ||
'viewport': { | ||
'width': 768, | ||
'height': 1024, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'iPad Mini', | ||
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', | ||
viewport: { | ||
width: 768, | ||
height: 1024, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPad Mini landscape', | ||
'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', | ||
'viewport': { | ||
'width': 1024, | ||
'height': 768, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'iPad Mini landscape', | ||
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', | ||
viewport: { | ||
width: 1024, | ||
height: 768, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPad Pro', | ||
'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', | ||
'viewport': { | ||
'width': 1024, | ||
'height': 1366, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'iPad Pro', | ||
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', | ||
viewport: { | ||
width: 1024, | ||
height: 1366, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPad Pro landscape', | ||
'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', | ||
'viewport': { | ||
'width': 1366, | ||
'height': 1024, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'iPad Pro landscape', | ||
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', | ||
viewport: { | ||
width: 1366, | ||
height: 1024, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone 4', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53', | ||
'viewport': { | ||
'width': 320, | ||
'height': 480, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'iPhone 4', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53', | ||
viewport: { | ||
width: 320, | ||
height: 480, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone 4 landscape', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53', | ||
'viewport': { | ||
'width': 480, | ||
'height': 320, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'iPhone 4 landscape', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 7_1_2 like Mac OS X) AppleWebKit/537.51.2 (KHTML, like Gecko) Version/7.0 Mobile/11D257 Safari/9537.53', | ||
viewport: { | ||
width: 480, | ||
height: 320, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone 5', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1', | ||
'viewport': { | ||
'width': 320, | ||
'height': 568, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'iPhone 5', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1', | ||
viewport: { | ||
width: 320, | ||
height: 568, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone 5 landscape', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1', | ||
'viewport': { | ||
'width': 568, | ||
'height': 320, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'iPhone 5 landscape', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1', | ||
viewport: { | ||
width: 568, | ||
height: 320, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone 6', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
'viewport': { | ||
'width': 375, | ||
'height': 667, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'iPhone 6', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
viewport: { | ||
width: 375, | ||
height: 667, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone 6 landscape', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
'viewport': { | ||
'width': 667, | ||
'height': 375, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'iPhone 6 landscape', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
viewport: { | ||
width: 667, | ||
height: 375, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone 6 Plus', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
'viewport': { | ||
'width': 414, | ||
'height': 736, | ||
'deviceScaleFactor': 3, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'iPhone 6 Plus', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
viewport: { | ||
width: 414, | ||
height: 736, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone 6 Plus landscape', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
'viewport': { | ||
'width': 736, | ||
'height': 414, | ||
'deviceScaleFactor': 3, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'iPhone 6 Plus landscape', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
viewport: { | ||
width: 736, | ||
height: 414, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone 7', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
'viewport': { | ||
'width': 375, | ||
'height': 667, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'iPhone 7', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
viewport: { | ||
width: 375, | ||
height: 667, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone 7 landscape', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
'viewport': { | ||
'width': 667, | ||
'height': 375, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'iPhone 7 landscape', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
viewport: { | ||
width: 667, | ||
height: 375, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone 7 Plus', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
'viewport': { | ||
'width': 414, | ||
'height': 736, | ||
'deviceScaleFactor': 3, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'iPhone 7 Plus', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
viewport: { | ||
width: 414, | ||
height: 736, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone 7 Plus landscape', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
'viewport': { | ||
'width': 736, | ||
'height': 414, | ||
'deviceScaleFactor': 3, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'iPhone 7 Plus landscape', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
viewport: { | ||
width: 736, | ||
height: 414, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone 8', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
'viewport': { | ||
'width': 375, | ||
'height': 667, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'iPhone 8', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
viewport: { | ||
width: 375, | ||
height: 667, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone 8 landscape', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
'viewport': { | ||
'width': 667, | ||
'height': 375, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'iPhone 8 landscape', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
viewport: { | ||
width: 667, | ||
height: 375, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone 8 Plus', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
'viewport': { | ||
'width': 414, | ||
'height': 736, | ||
'deviceScaleFactor': 3, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'iPhone 8 Plus', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
viewport: { | ||
width: 414, | ||
height: 736, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone 8 Plus landscape', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
'viewport': { | ||
'width': 736, | ||
'height': 414, | ||
'deviceScaleFactor': 3, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'iPhone 8 Plus landscape', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
viewport: { | ||
width: 736, | ||
height: 414, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone SE', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1', | ||
'viewport': { | ||
'width': 320, | ||
'height': 568, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'iPhone SE', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1', | ||
viewport: { | ||
width: 320, | ||
height: 568, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone SE landscape', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1', | ||
'viewport': { | ||
'width': 568, | ||
'height': 320, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'iPhone SE landscape', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_1 like Mac OS X) AppleWebKit/603.1.30 (KHTML, like Gecko) Version/10.0 Mobile/14E304 Safari/602.1', | ||
viewport: { | ||
width: 568, | ||
height: 320, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone X', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
'viewport': { | ||
'width': 375, | ||
'height': 812, | ||
'deviceScaleFactor': 3, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'iPhone X', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
viewport: { | ||
width: 375, | ||
height: 812, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'iPhone X landscape', | ||
'userAgent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
'viewport': { | ||
'width': 812, | ||
'height': 375, | ||
'deviceScaleFactor': 3, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'iPhone X landscape', | ||
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1', | ||
viewport: { | ||
width: 812, | ||
height: 375, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'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', | ||
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: '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', | ||
'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', | ||
'viewport': { | ||
'width': 240, | ||
'height': 320, | ||
'deviceScaleFactor': 1, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'JioPhone 2', | ||
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', | ||
viewport: { | ||
width: 240, | ||
height: 320, | ||
deviceScaleFactor: 1, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'JioPhone 2 landscape', | ||
'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', | ||
'viewport': { | ||
'width': 320, | ||
'height': 240, | ||
'deviceScaleFactor': 1, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'JioPhone 2 landscape', | ||
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', | ||
viewport: { | ||
width: 320, | ||
height: 240, | ||
deviceScaleFactor: 1, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'Kindle Fire HDX', | ||
'userAgent': 'Mozilla/5.0 (Linux; U; en-us; KFAPWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true', | ||
'viewport': { | ||
'width': 800, | ||
'height': 1280, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Kindle Fire HDX', | ||
userAgent: 'Mozilla/5.0 (Linux; U; en-us; KFAPWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true', | ||
viewport: { | ||
width: 800, | ||
height: 1280, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Kindle Fire HDX landscape', | ||
'userAgent': 'Mozilla/5.0 (Linux; U; en-us; KFAPWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true', | ||
'viewport': { | ||
'width': 1280, | ||
'height': 800, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'Kindle Fire HDX landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; U; en-us; KFAPWI Build/JDQ39) AppleWebKit/535.19 (KHTML, like Gecko) Silk/3.13 Safari/535.19 Silk-Accelerated=true', | ||
viewport: { | ||
width: 1280, | ||
height: 800, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'LG Optimus L70', | ||
'userAgent': 'Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 384, | ||
'height': 640, | ||
'deviceScaleFactor': 1.25, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'LG Optimus L70', | ||
userAgent: 'Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 384, | ||
height: 640, | ||
deviceScaleFactor: 1.25, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'LG Optimus L70 landscape', | ||
'userAgent': 'Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 640, | ||
'height': 384, | ||
'deviceScaleFactor': 1.25, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'LG Optimus L70 landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; U; Android 4.4.2; en-us; LGMS323 Build/KOT49I.MS32310c) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 640, | ||
height: 384, | ||
deviceScaleFactor: 1.25, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'Microsoft Lumia 550', | ||
'userAgent': 'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/14.14263', | ||
'viewport': { | ||
'width': 640, | ||
'height': 360, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Microsoft Lumia 550', | ||
userAgent: 'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 550) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/14.14263', | ||
viewport: { | ||
width: 640, | ||
height: 360, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Microsoft Lumia 950', | ||
'userAgent': 'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/14.14263', | ||
'viewport': { | ||
'width': 360, | ||
'height': 640, | ||
'deviceScaleFactor': 4, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Microsoft Lumia 950', | ||
userAgent: 'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/14.14263', | ||
viewport: { | ||
width: 360, | ||
height: 640, | ||
deviceScaleFactor: 4, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Microsoft Lumia 950 landscape', | ||
'userAgent': 'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/14.14263', | ||
'viewport': { | ||
'width': 640, | ||
'height': 360, | ||
'deviceScaleFactor': 4, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'Microsoft Lumia 950 landscape', | ||
userAgent: 'Mozilla/5.0 (Windows Phone 10.0; Android 4.2.1; Microsoft; Lumia 950) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2486.0 Mobile Safari/537.36 Edge/14.14263', | ||
viewport: { | ||
width: 640, | ||
height: 360, | ||
deviceScaleFactor: 4, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nexus 10', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Safari/537.36', | ||
'viewport': { | ||
'width': 800, | ||
'height': 1280, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Nexus 10', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Safari/537.36', | ||
viewport: { | ||
width: 800, | ||
height: 1280, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nexus 10 landscape', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Safari/537.36', | ||
'viewport': { | ||
'width': 1280, | ||
'height': 800, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'Nexus 10 landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 10 Build/MOB31T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Safari/537.36', | ||
viewport: { | ||
width: 1280, | ||
height: 800, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nexus 4', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 384, | ||
'height': 640, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Nexus 4', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 384, | ||
height: 640, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nexus 4 landscape', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 640, | ||
'height': 384, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'Nexus 4 landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 4.4.2; Nexus 4 Build/KOT49H) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 640, | ||
height: 384, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nexus 5', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 360, | ||
'height': 640, | ||
'deviceScaleFactor': 3, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Nexus 5', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 360, | ||
height: 640, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nexus 5 landscape', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 640, | ||
'height': 360, | ||
'deviceScaleFactor': 3, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'Nexus 5 landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 640, | ||
height: 360, | ||
deviceScaleFactor: 3, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nexus 5X', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 412, | ||
'height': 732, | ||
'deviceScaleFactor': 2.625, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Nexus 5X', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 412, | ||
height: 732, | ||
deviceScaleFactor: 2.625, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nexus 5X landscape', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 732, | ||
'height': 412, | ||
'deviceScaleFactor': 2.625, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'Nexus 5X landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 5X Build/OPR4.170623.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 732, | ||
height: 412, | ||
deviceScaleFactor: 2.625, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nexus 6', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 412, | ||
'height': 732, | ||
'deviceScaleFactor': 3.5, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Nexus 6', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 412, | ||
height: 732, | ||
deviceScaleFactor: 3.5, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nexus 6 landscape', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 732, | ||
'height': 412, | ||
'deviceScaleFactor': 3.5, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'Nexus 6 landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 7.1.1; Nexus 6 Build/N6F26U) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 732, | ||
height: 412, | ||
deviceScaleFactor: 3.5, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nexus 6P', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 412, | ||
'height': 732, | ||
'deviceScaleFactor': 3.5, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Nexus 6P', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 412, | ||
height: 732, | ||
deviceScaleFactor: 3.5, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nexus 6P landscape', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 732, | ||
'height': 412, | ||
'deviceScaleFactor': 3.5, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'Nexus 6P landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; Nexus 6P Build/OPP3.170518.006) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 732, | ||
height: 412, | ||
deviceScaleFactor: 3.5, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nexus 7', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Safari/537.36', | ||
'viewport': { | ||
'width': 600, | ||
'height': 960, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Nexus 7', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Safari/537.36', | ||
viewport: { | ||
width: 600, | ||
height: 960, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nexus 7 landscape', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Safari/537.36', | ||
'viewport': { | ||
'width': 960, | ||
'height': 600, | ||
'deviceScaleFactor': 2, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'Nexus 7 landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 6.0.1; Nexus 7 Build/MOB30X) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Safari/537.36', | ||
viewport: { | ||
width: 960, | ||
height: 600, | ||
deviceScaleFactor: 2, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nokia Lumia 520', | ||
'userAgent': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 520)', | ||
'viewport': { | ||
'width': 320, | ||
'height': 533, | ||
'deviceScaleFactor': 1.5, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Nokia Lumia 520', | ||
userAgent: 'Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 520)', | ||
viewport: { | ||
width: 320, | ||
height: 533, | ||
deviceScaleFactor: 1.5, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nokia Lumia 520 landscape', | ||
'userAgent': 'Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 520)', | ||
'viewport': { | ||
'width': 533, | ||
'height': 320, | ||
'deviceScaleFactor': 1.5, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'Nokia Lumia 520 landscape', | ||
userAgent: 'Mozilla/5.0 (compatible; MSIE 10.0; Windows Phone 8.0; Trident/6.0; IEMobile/10.0; ARM; Touch; NOKIA; Lumia 520)', | ||
viewport: { | ||
width: 533, | ||
height: 320, | ||
deviceScaleFactor: 1.5, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nokia N9', | ||
'userAgent': 'Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13', | ||
'viewport': { | ||
'width': 480, | ||
'height': 854, | ||
'deviceScaleFactor': 1, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Nokia N9', | ||
userAgent: 'Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13', | ||
viewport: { | ||
width: 480, | ||
height: 854, | ||
deviceScaleFactor: 1, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Nokia N9 landscape', | ||
'userAgent': 'Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13', | ||
'viewport': { | ||
'width': 854, | ||
'height': 480, | ||
'deviceScaleFactor': 1, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'Nokia N9 landscape', | ||
userAgent: 'Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13', | ||
viewport: { | ||
width: 854, | ||
height: 480, | ||
deviceScaleFactor: 1, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'Pixel 2', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 411, | ||
'height': 731, | ||
'deviceScaleFactor': 2.625, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Pixel 2', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 411, | ||
height: 731, | ||
deviceScaleFactor: 2.625, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Pixel 2 landscape', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 731, | ||
'height': 411, | ||
'deviceScaleFactor': 2.625, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
name: 'Pixel 2 landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 8.0; Pixel 2 Build/OPD3.170816.012) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 731, | ||
height: 411, | ||
deviceScaleFactor: 2.625, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
{ | ||
'name': 'Pixel 2 XL', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 411, | ||
'height': 823, | ||
'deviceScaleFactor': 3.5, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': false | ||
} | ||
name: 'Pixel 2 XL', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 411, | ||
height: 823, | ||
deviceScaleFactor: 3.5, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: false, | ||
}, | ||
}, | ||
{ | ||
'name': 'Pixel 2 XL landscape', | ||
'userAgent': 'Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
'viewport': { | ||
'width': 823, | ||
'height': 411, | ||
'deviceScaleFactor': 3.5, | ||
'isMobile': true, | ||
'hasTouch': true, | ||
'isLandscape': true | ||
} | ||
} | ||
name: 'Pixel 2 XL landscape', | ||
userAgent: 'Mozilla/5.0 (Linux; Android 8.0.0; Pixel 2 XL Build/OPD1.170816.004) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3765.0 Mobile Safari/537.36', | ||
viewport: { | ||
width: 823, | ||
height: 411, | ||
deviceScaleFactor: 3.5, | ||
isMobile: true, | ||
hasTouch: true, | ||
isLandscape: true, | ||
}, | ||
}, | ||
]; | ||
@@ -873,0 +874,0 @@ const devicesMap = {}; |
@@ -18,2 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Dialog = exports.DialogType = void 0; | ||
const helper_1 = require("./helper"); | ||
@@ -30,36 +31,39 @@ /* TODO(jacktfranklin): protocol.d.ts defines this | ||
})(DialogType = exports.DialogType || (exports.DialogType = {})); | ||
class Dialog { | ||
constructor(client, type, message, defaultValue = '') { | ||
this._handled = false; | ||
this._client = client; | ||
this._type = type; | ||
this._message = message; | ||
this._defaultValue = defaultValue; | ||
let Dialog = /** @class */ (() => { | ||
class Dialog { | ||
constructor(client, type, message, defaultValue = '') { | ||
this._handled = false; | ||
this._client = client; | ||
this._type = type; | ||
this._message = message; | ||
this._defaultValue = defaultValue; | ||
} | ||
type() { | ||
return this._type; | ||
} | ||
message() { | ||
return this._message; | ||
} | ||
defaultValue() { | ||
return this._defaultValue; | ||
} | ||
async accept(promptText) { | ||
helper_1.assert(!this._handled, 'Cannot accept dialog which is already handled!'); | ||
this._handled = true; | ||
await this._client.send('Page.handleJavaScriptDialog', { | ||
accept: true, | ||
promptText: promptText, | ||
}); | ||
} | ||
async dismiss() { | ||
helper_1.assert(!this._handled, 'Cannot dismiss dialog which is already handled!'); | ||
this._handled = true; | ||
await this._client.send('Page.handleJavaScriptDialog', { | ||
accept: false, | ||
}); | ||
} | ||
} | ||
type() { | ||
return this._type; | ||
} | ||
message() { | ||
return this._message; | ||
} | ||
defaultValue() { | ||
return this._defaultValue; | ||
} | ||
async accept(promptText) { | ||
helper_1.assert(!this._handled, 'Cannot accept dialog which is already handled!'); | ||
this._handled = true; | ||
await this._client.send('Page.handleJavaScriptDialog', { | ||
accept: true, | ||
promptText: promptText | ||
}); | ||
} | ||
async dismiss() { | ||
helper_1.assert(!this._handled, 'Cannot dismiss dialog which is already handled!'); | ||
this._handled = true; | ||
await this._client.send('Page.handleJavaScriptDialog', { | ||
accept: false | ||
}); | ||
} | ||
} | ||
Dialog.Type = DialogType; | ||
return Dialog; | ||
})(); | ||
exports.Dialog = Dialog; | ||
Dialog.Type = DialogType; |
@@ -18,2 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.DOMWorld = void 0; | ||
const fs = require("fs"); | ||
@@ -52,3 +53,3 @@ const helper_1 = require("./helper"); | ||
this._documentPromise = null; | ||
this._contextPromise = new Promise(fulfill => { | ||
this._contextPromise = new Promise((fulfill) => { | ||
this._contextResolveCallback = fulfill; | ||
@@ -147,3 +148,3 @@ }); | ||
// lifecycle event. @see https://crrev.com/608658 | ||
await this.evaluate(html => { | ||
await this.evaluate((html) => { | ||
document.open(); | ||
@@ -206,3 +207,3 @@ document.write(html); | ||
let error = null; | ||
script.onerror = e => error = e; | ||
script.onerror = (e) => (error = e); | ||
document.head.appendChild(script); | ||
@@ -315,3 +316,3 @@ if (error) | ||
const title = `${isXPath ? 'XPath' : 'selector'} "${selectorOrXPath}"${waitForHidden ? ' to be hidden' : ''}`; | ||
const { updatedSelector, queryHandler } = QueryHandler_1.getQueryHandlerAndSelector(selectorOrXPath, (element, selector) => document.querySelector(selector)); | ||
const { updatedSelector, queryHandler, } = QueryHandler_1.getQueryHandlerAndSelector(selectorOrXPath, (element, selector) => document.querySelector(selector)); | ||
const waitTask = new WaitTask(this, predicate, queryHandler, title, polling, timeout, updatedSelector, isXPath, waitForVisible, waitForHidden); | ||
@@ -334,3 +335,5 @@ const handle = await waitTask.promise; | ||
? document.evaluate(selectorOrXPath, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue | ||
: predicateQueryHandler ? predicateQueryHandler(document, selectorOrXPath) : document.querySelector(selectorOrXPath); | ||
: predicateQueryHandler | ||
? predicateQueryHandler(document, selectorOrXPath) | ||
: document.querySelector(selectorOrXPath); | ||
if (!node) | ||
@@ -340,6 +343,8 @@ return waitForHidden; | ||
return node; | ||
const element = (node.nodeType === Node.TEXT_NODE ? node.parentElement : node); | ||
const element = node.nodeType === Node.TEXT_NODE | ||
? node.parentElement | ||
: node; | ||
const style = window.getComputedStyle(element); | ||
const isVisible = style && style.visibility !== 'hidden' && hasVisibleBoundingBox(); | ||
const success = (waitForVisible === isVisible || waitForHidden === !isVisible); | ||
const success = waitForVisible === isVisible || waitForHidden === !isVisible; | ||
return success ? node : null; | ||
@@ -419,3 +424,4 @@ function hasVisibleBoundingBox() { | ||
// throw an error - ignore this predicate run altogether. | ||
if (!error && await this._domWorld.evaluate(s => !s, success).catch(() => true)) { | ||
if (!error && | ||
(await this._domWorld.evaluate((s) => !s, success).catch(() => true))) { | ||
await success.dispose(); | ||
@@ -430,3 +436,4 @@ return; | ||
// destroyed. | ||
if (error && error.message.includes('Cannot find context with specified id')) | ||
if (error && | ||
error.message.includes('Cannot find context with specified id')) | ||
return; | ||
@@ -448,3 +455,3 @@ if (error) | ||
if (timeout) | ||
setTimeout(() => timedOut = true, timeout); | ||
setTimeout(() => (timedOut = true), timeout); | ||
if (polling === 'raf') | ||
@@ -464,3 +471,3 @@ return await pollRaf(); | ||
let fulfill; | ||
const result = new Promise(x => fulfill = x); | ||
const result = new Promise((x) => (fulfill = x)); | ||
const observer = new MutationObserver(() => { | ||
@@ -480,3 +487,3 @@ if (timedOut) { | ||
subtree: true, | ||
attributes: true | ||
attributes: true, | ||
}); | ||
@@ -487,3 +494,3 @@ return result; | ||
let fulfill; | ||
const result = new Promise(x => fulfill = x); | ||
const result = new Promise((x) => (fulfill = x)); | ||
onRaf(); | ||
@@ -505,3 +512,3 @@ return result; | ||
let fulfill; | ||
const result = new Promise(x => fulfill = x); | ||
const result = new Promise((x) => (fulfill = x)); | ||
onTimeout(); | ||
@@ -508,0 +515,0 @@ return result; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.EmulationManager = void 0; | ||
class EmulationManager { | ||
@@ -14,9 +15,17 @@ constructor(client) { | ||
const deviceScaleFactor = viewport.deviceScaleFactor || 1; | ||
const screenOrientation = viewport.isLandscape ? { angle: 90, type: 'landscapePrimary' } : { angle: 0, type: 'portraitPrimary' }; | ||
const screenOrientation = viewport.isLandscape | ||
? { angle: 90, type: 'landscapePrimary' } | ||
: { angle: 0, type: 'portraitPrimary' }; | ||
const hasTouch = viewport.hasTouch || false; | ||
await Promise.all([ | ||
this._client.send('Emulation.setDeviceMetricsOverride', { mobile, width, height, deviceScaleFactor, screenOrientation }), | ||
this._client.send('Emulation.setDeviceMetricsOverride', { | ||
mobile, | ||
width, | ||
height, | ||
deviceScaleFactor, | ||
screenOrientation, | ||
}), | ||
this._client.send('Emulation.setTouchEmulationEnabled', { | ||
enabled: hasTouch | ||
}) | ||
enabled: hasTouch, | ||
}), | ||
]); | ||
@@ -23,0 +32,0 @@ const reloadNeeded = this._emulatingMobile !== mobile || this._hasTouch !== hasTouch; |
@@ -18,2 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.puppeteerErrors = exports.TimeoutError = void 0; | ||
class CustomError extends Error { | ||
@@ -20,0 +21,0 @@ constructor(message) { |
@@ -18,2 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Events = void 0; | ||
exports.Events = { | ||
@@ -46,3 +47,3 @@ Page: { | ||
TargetChanged: 'targetchanged', | ||
Disconnected: 'disconnected' | ||
Disconnected: 'disconnected', | ||
}, | ||
@@ -49,0 +50,0 @@ BrowserContext: { |
@@ -18,2 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ExecutionContext = exports.EVALUATION_SCRIPT_URL = void 0; | ||
const helper_1 = require("./helper"); | ||
@@ -43,4 +44,7 @@ const JSHandle_1 = require("./JSHandle"); | ||
const expression = pageFunction; | ||
const expressionWithSourceUrl = SOURCE_URL_REGEX.test(expression) ? expression : expression + '\n' + suffix; | ||
const { exceptionDetails, result: remoteObject } = await this._client.send('Runtime.evaluate', { | ||
const expressionWithSourceUrl = SOURCE_URL_REGEX.test(expression) | ||
? expression | ||
: expression + '\n' + suffix; | ||
const { exceptionDetails, result: remoteObject } = await this._client | ||
.send('Runtime.evaluate', { | ||
expression: expressionWithSourceUrl, | ||
@@ -50,7 +54,10 @@ contextId, | ||
awaitPromise: true, | ||
userGesture: true | ||
}).catch(rewriteError); | ||
userGesture: true, | ||
}) | ||
.catch(rewriteError); | ||
if (exceptionDetails) | ||
throw new Error('Evaluation failed: ' + helper_1.helper.getExceptionMessage(exceptionDetails)); | ||
return returnByValue ? helper_1.helper.valueFromRemoteObject(remoteObject) : JSHandle_1.createJSHandle(this, remoteObject); | ||
return returnByValue | ||
? helper_1.helper.valueFromRemoteObject(remoteObject) | ||
: JSHandle_1.createJSHandle(this, remoteObject); | ||
} | ||
@@ -67,3 +74,4 @@ if (typeof pageFunction !== 'function') | ||
if (functionText.startsWith('async ')) | ||
functionText = 'async function ' + functionText.substring('async '.length); | ||
functionText = | ||
'async function ' + functionText.substring('async '.length); | ||
else | ||
@@ -87,14 +95,17 @@ functionText = 'function ' + functionText; | ||
awaitPromise: true, | ||
userGesture: true | ||
userGesture: true, | ||
}); | ||
} | ||
catch (error) { | ||
if (error instanceof TypeError && error.message.startsWith('Converting circular structure to JSON')) | ||
if (error instanceof TypeError && | ||
error.message.startsWith('Converting circular structure to JSON')) | ||
error.message += ' Are you passing a nested JSHandle?'; | ||
throw error; | ||
} | ||
const { exceptionDetails, result: remoteObject } = await callFunctionOnPromise.catch(rewriteError); | ||
const { exceptionDetails, result: remoteObject, } = await callFunctionOnPromise.catch(rewriteError); | ||
if (exceptionDetails) | ||
throw new Error('Evaluation failed: ' + helper_1.helper.getExceptionMessage(exceptionDetails)); | ||
return returnByValue ? helper_1.helper.valueFromRemoteObject(remoteObject) : JSHandle_1.createJSHandle(this, remoteObject); | ||
return returnByValue | ||
? helper_1.helper.valueFromRemoteObject(remoteObject) | ||
: JSHandle_1.createJSHandle(this, remoteObject); | ||
/** | ||
@@ -106,3 +117,4 @@ * @param {*} arg | ||
function convertArgument(arg) { | ||
if (typeof arg === 'bigint') // eslint-disable-line valid-typeof | ||
if (typeof arg === 'bigint') | ||
// eslint-disable-line valid-typeof | ||
return { unserializableValue: `${arg.toString()}n` }; | ||
@@ -117,3 +129,3 @@ if (Object.is(arg, -0)) | ||
return { unserializableValue: 'NaN' }; | ||
const objectHandle = arg && (arg instanceof JSHandle_1.JSHandle) ? arg : null; | ||
const objectHandle = arg && arg instanceof JSHandle_1.JSHandle ? arg : null; | ||
if (objectHandle) { | ||
@@ -125,3 +137,5 @@ if (objectHandle._context !== this) | ||
if (objectHandle._remoteObject.unserializableValue) | ||
return { unserializableValue: objectHandle._remoteObject.unserializableValue }; | ||
return { | ||
unserializableValue: objectHandle._remoteObject.unserializableValue, | ||
}; | ||
if (!objectHandle._remoteObject.objectId) | ||
@@ -136,5 +150,6 @@ return { value: objectHandle._remoteObject.value }; | ||
return { result: { type: 'undefined' } }; | ||
if (error.message.includes('Object couldn\'t be returned by value')) | ||
if (error.message.includes("Object couldn't be returned by value")) | ||
return { result: { type: 'undefined' } }; | ||
if (error.message.endsWith('Cannot find context with specified id') || error.message.endsWith('Inspected target navigated or closed')) | ||
if (error.message.endsWith('Cannot find context with specified id') || | ||
error.message.endsWith('Inspected target navigated or closed')) | ||
throw new Error('Execution context was destroyed, most likely because of a navigation.'); | ||
@@ -148,3 +163,3 @@ throw error; | ||
const response = await this._client.send('Runtime.queryObjects', { | ||
prototypeObjectId: prototypeHandle._remoteObject.objectId | ||
prototypeObjectId: prototypeHandle._remoteObject.objectId, | ||
}); | ||
@@ -151,0 +166,0 @@ return JSHandle_1.createJSHandle(this, response.objects); |
@@ -18,2 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Frame = exports.FrameManager = void 0; | ||
const EventEmitter = require("events"); | ||
@@ -37,11 +38,11 @@ const helper_1 = require("./helper"); | ||
this._timeoutSettings = timeoutSettings; | ||
this._client.on('Page.frameAttached', event => this._onFrameAttached(event.frameId, event.parentFrameId)); | ||
this._client.on('Page.frameNavigated', event => this._onFrameNavigated(event.frame)); | ||
this._client.on('Page.navigatedWithinDocument', event => this._onFrameNavigatedWithinDocument(event.frameId, event.url)); | ||
this._client.on('Page.frameDetached', event => this._onFrameDetached(event.frameId)); | ||
this._client.on('Page.frameStoppedLoading', event => this._onFrameStoppedLoading(event.frameId)); | ||
this._client.on('Runtime.executionContextCreated', event => this._onExecutionContextCreated(event.context)); | ||
this._client.on('Runtime.executionContextDestroyed', event => this._onExecutionContextDestroyed(event.executionContextId)); | ||
this._client.on('Page.frameAttached', (event) => this._onFrameAttached(event.frameId, event.parentFrameId)); | ||
this._client.on('Page.frameNavigated', (event) => this._onFrameNavigated(event.frame)); | ||
this._client.on('Page.navigatedWithinDocument', (event) => this._onFrameNavigatedWithinDocument(event.frameId, event.url)); | ||
this._client.on('Page.frameDetached', (event) => this._onFrameDetached(event.frameId)); | ||
this._client.on('Page.frameStoppedLoading', (event) => this._onFrameStoppedLoading(event.frameId)); | ||
this._client.on('Runtime.executionContextCreated', (event) => this._onExecutionContextCreated(event.context)); | ||
this._client.on('Runtime.executionContextDestroyed', (event) => this._onExecutionContextDestroyed(event.executionContextId)); | ||
this._client.on('Runtime.executionContextsCleared', () => this._onExecutionContextsCleared()); | ||
this._client.on('Page.lifecycleEvent', event => this._onLifecycleEvent(event)); | ||
this._client.on('Page.lifecycleEvent', (event) => this._onLifecycleEvent(event)); | ||
} | ||
@@ -57,3 +58,5 @@ async initialize() { | ||
this._client.send('Page.setLifecycleEventsEnabled', { enabled: true }), | ||
this._client.send('Runtime.enable', {}).then(() => this._ensureIsolatedWorld(UTILITY_WORLD_NAME)), | ||
this._client | ||
.send('Runtime.enable', {}) | ||
.then(() => this._ensureIsolatedWorld(UTILITY_WORLD_NAME)), | ||
this._networkManager.initialize(), | ||
@@ -77,3 +80,5 @@ ]); | ||
watcher.timeoutOrTerminationPromise(), | ||
ensureNewDocumentNavigation ? watcher.newDocumentNavigationPromise() : watcher.sameDocumentNavigationPromise(), | ||
ensureNewDocumentNavigation | ||
? watcher.newDocumentNavigationPromise() | ||
: watcher.sameDocumentNavigationPromise(), | ||
]); | ||
@@ -87,5 +92,11 @@ } | ||
try { | ||
const response = await client.send('Page.navigate', { url, referrer, frameId }); | ||
const response = await client.send('Page.navigate', { | ||
url, | ||
referrer, | ||
frameId, | ||
}); | ||
ensureNewDocumentNavigation = !!response.loaderId; | ||
return response.errorText ? new Error(`${response.errorText} at ${url}`) : null; | ||
return response.errorText | ||
? new Error(`${response.errorText} at ${url}`) | ||
: null; | ||
} | ||
@@ -104,3 +115,3 @@ catch (error) { | ||
watcher.sameDocumentNavigationPromise(), | ||
watcher.newDocumentNavigationPromise() | ||
watcher.newDocumentNavigationPromise(), | ||
]); | ||
@@ -158,3 +169,5 @@ watcher.dispose(); | ||
const isMainFrame = !framePayload.parentId; | ||
let frame = isMainFrame ? this._mainFrame : this._frames.get(framePayload.id); | ||
let frame = isMainFrame | ||
? this._mainFrame | ||
: this._frames.get(framePayload.id); | ||
helper_1.assert(isMainFrame || frame, 'We either navigate top level or have old version of the navigated frame'); | ||
@@ -192,7 +205,9 @@ // Detach all child frames first. | ||
}), | ||
await Promise.all(this.frames().map(frame => this._client.send('Page.createIsolatedWorld', { | ||
await Promise.all(this.frames().map((frame) => this._client | ||
.send('Page.createIsolatedWorld', { | ||
frameId: frame._id, | ||
grantUniveralAccess: true, | ||
worldName: name, | ||
}).catch(helper_1.debugError))); // frames might be removed before we send this | ||
}) | ||
.catch(helper_1.debugError))); // frames might be removed before we send this | ||
} | ||
@@ -221,3 +236,4 @@ _onFrameNavigatedWithinDocument(frameId, url) { | ||
} | ||
else if (contextPayload.name === UTILITY_WORLD_NAME && !frame._secondaryWorld._hasContext()) { | ||
else if (contextPayload.name === UTILITY_WORLD_NAME && | ||
!frame._secondaryWorld._hasContext()) { | ||
// In case of multiple sessions to the same target, there's a race between | ||
@@ -371,6 +387,6 @@ // connections so we might end up creating multiple isolated worlds. | ||
if (helper_1.helper.isNumber(selectorOrFunctionOrTimeout)) | ||
return new Promise(fulfill => setTimeout(fulfill, selectorOrFunctionOrTimeout)); | ||
return new Promise((fulfill) => setTimeout(fulfill, selectorOrFunctionOrTimeout)); | ||
if (typeof selectorOrFunctionOrTimeout === 'function') | ||
return this.waitForFunction(selectorOrFunctionOrTimeout, options, ...args); | ||
return Promise.reject(new Error('Unsupported target type: ' + (typeof selectorOrFunctionOrTimeout))); | ||
return Promise.reject(new Error('Unsupported target type: ' + typeof selectorOrFunctionOrTimeout)); | ||
} | ||
@@ -377,0 +393,0 @@ async waitForSelector(selector, options) { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.helper = exports.assert = exports.debugError = void 0; | ||
/** | ||
@@ -33,7 +34,11 @@ * Copyright 2017 Google Inc. All rights reserved. | ||
if (exceptionDetails.exception) | ||
return exceptionDetails.exception.description || exceptionDetails.exception.value; | ||
return (exceptionDetails.exception.description || exceptionDetails.exception.value); | ||
let message = exceptionDetails.text; | ||
if (exceptionDetails.stackTrace) { | ||
for (const callframe of exceptionDetails.stackTrace.callFrames) { | ||
const location = callframe.url + ':' + callframe.lineNumber + ':' + callframe.columnNumber; | ||
const location = callframe.url + | ||
':' + | ||
callframe.lineNumber + | ||
':' + | ||
callframe.columnNumber; | ||
const functionName = callframe.functionName || '<anonymous>'; | ||
@@ -60,3 +65,4 @@ message += `\n at ${functionName} (${location})`; | ||
default: | ||
throw new Error('Unsupported unserializable value: ' + remoteObject.unserializableValue); | ||
throw new Error('Unsupported unserializable value: ' + | ||
remoteObject.unserializableValue); | ||
} | ||
@@ -69,3 +75,5 @@ } | ||
return; | ||
await client.send('Runtime.releaseObject', { objectId: remoteObject.objectId }).catch(error => { | ||
await client | ||
.send('Runtime.releaseObject', { objectId: remoteObject.objectId }) | ||
.catch((error) => { | ||
// Exceptions might happen in case of a page been navigated or closed. | ||
@@ -79,13 +87,19 @@ // Swallow these since they are harmless and we don't leak anything in this case. | ||
const method = Reflect.get(classType.prototype, methodName); | ||
if (methodName === 'constructor' || typeof methodName !== 'string' || methodName.startsWith('_') || typeof method !== 'function' || method.constructor.name !== 'AsyncFunction') | ||
if (methodName === 'constructor' || | ||
typeof methodName !== 'string' || | ||
methodName.startsWith('_') || | ||
typeof method !== 'function' || | ||
method.constructor.name !== 'AsyncFunction') | ||
continue; | ||
Reflect.set(classType.prototype, methodName, function (...args) { | ||
const syncStack = { | ||
stack: '' | ||
stack: '', | ||
}; | ||
Error.captureStackTrace(syncStack); | ||
return method.call(this, ...args).catch(error => { | ||
return method.call(this, ...args).catch((error) => { | ||
const stack = syncStack.stack.substring(syncStack.stack.indexOf('\n') + 1); | ||
const clientStack = stack.substring(stack.indexOf('\n')); | ||
if (error instanceof Error && error.stack && !error.stack.includes(clientStack)) | ||
if (error instanceof Error && | ||
error.stack && | ||
!error.stack.includes(clientStack)) | ||
error.stack += '\n -- ASYNC --\n' + stack; | ||
@@ -118,3 +132,3 @@ throw error; | ||
}); | ||
const listener = addEventListener(emitter, eventName, event => { | ||
const listener = addEventListener(emitter, eventName, (event) => { | ||
if (!predicate(event)) | ||
@@ -133,6 +147,6 @@ return; | ||
} | ||
const result = await Promise.race([promise, abortPromise]).then(r => { | ||
const result = await Promise.race([promise, abortPromise]).then((r) => { | ||
cleanup(); | ||
return r; | ||
}, error => { | ||
}, (error) => { | ||
cleanup(); | ||
@@ -160,3 +174,3 @@ throw error; | ||
const timeoutError = new Errors_1.TimeoutError(`waiting for ${taskName} failed: timeout ${timeout}ms exceeded`); | ||
const timeoutPromise = new Promise((resolve, x) => reject = x); | ||
const timeoutPromise = new Promise((resolve, x) => (reject = x)); | ||
let timeoutTimer = null; | ||
@@ -163,0 +177,0 @@ if (timeout) |
@@ -18,2 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Touchscreen = exports.Mouse = exports.Keyboard = void 0; | ||
const helper_1 = require("./helper"); | ||
@@ -43,3 +44,3 @@ const USKeyboardLayout_1 = require("./USKeyboardLayout"); | ||
location: description.location, | ||
isKeypad: description.location === 3 | ||
isKeypad: description.location === 3, | ||
}); | ||
@@ -65,3 +66,3 @@ } | ||
text: '', | ||
location: 0 | ||
location: 0, | ||
}; | ||
@@ -103,3 +104,3 @@ const definition = USKeyboardLayout_1.keyDefinitions[keyString]; | ||
code: description.code, | ||
location: description.location | ||
location: description.location, | ||
}); | ||
@@ -121,3 +122,3 @@ } | ||
if (delay) | ||
await new Promise(f => setTimeout(f, delay)); | ||
await new Promise((f) => setTimeout(f, delay)); | ||
await this.sendCharacter(char); | ||
@@ -131,3 +132,3 @@ } | ||
if (delay) | ||
await new Promise(f => setTimeout(f, options.delay)); | ||
await new Promise((f) => setTimeout(f, options.delay)); | ||
await this.up(key); | ||
@@ -160,3 +161,3 @@ } | ||
y: fromY + (this._y - fromY) * (i / steps), | ||
modifiers: this._keyboard._modifiers | ||
modifiers: this._keyboard._modifiers, | ||
}); | ||
@@ -168,7 +169,4 @@ } | ||
if (delay !== null) { | ||
await Promise.all([ | ||
this.move(x, y), | ||
this.down(options), | ||
]); | ||
await new Promise(f => setTimeout(f, delay)); | ||
await Promise.all([this.move(x, y), this.down(options)]); | ||
await new Promise((f) => setTimeout(f, delay)); | ||
await this.up(options); | ||
@@ -193,3 +191,3 @@ } | ||
modifiers: this._keyboard._modifiers, | ||
clickCount | ||
clickCount, | ||
}); | ||
@@ -209,3 +207,3 @@ } | ||
modifiers: this._keyboard._modifiers, | ||
clickCount | ||
clickCount, | ||
}); | ||
@@ -230,3 +228,3 @@ } | ||
expression: 'new Promise(x => requestAnimationFrame(() => requestAnimationFrame(x)))', | ||
awaitPromise: true | ||
awaitPromise: true, | ||
}); | ||
@@ -237,3 +235,3 @@ const touchPoints = [{ x: Math.round(x), y: Math.round(y) }]; | ||
touchPoints, | ||
modifiers: this._keyboard._modifiers | ||
modifiers: this._keyboard._modifiers, | ||
}); | ||
@@ -243,3 +241,3 @@ await this._client.send('Input.dispatchTouchEvent', { | ||
touchPoints: [], | ||
modifiers: this._keyboard._modifiers | ||
modifiers: this._keyboard._modifiers, | ||
}); | ||
@@ -246,0 +244,0 @@ } |
@@ -18,2 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.ElementHandle = exports.JSHandle = exports.createJSHandle = void 0; | ||
const helper_1 = require("./helper"); | ||
@@ -60,3 +61,3 @@ const QueryHandler_1 = require("./QueryHandler"); | ||
objectId: this._remoteObject.objectId, | ||
ownProperties: true | ||
ownProperties: true, | ||
}); | ||
@@ -115,3 +116,3 @@ const result = new Map(); | ||
const nodeInfo = await this._client.send('DOM.describeNode', { | ||
objectId: this._remoteObject.objectId | ||
objectId: this._remoteObject.objectId, | ||
}); | ||
@@ -130,10 +131,14 @@ if (typeof nodeInfo.node.frameId !== 'string') | ||
if (!pageJavascriptEnabled) { | ||
// Chrome still supports behavior: instant but it's not in the spec so TS shouts | ||
// We don't want to make this breaking change in Puppeteer yet so we'll ignore the line. | ||
// @ts-ignore | ||
element.scrollIntoView({ block: 'center', inline: 'center', behavior: 'instant' }); | ||
element.scrollIntoView({ | ||
block: 'center', | ||
inline: 'center', | ||
// Chrome still supports behavior: instant but it's not in the spec so TS shouts | ||
// We don't want to make this breaking change in Puppeteer yet so we'll ignore the line. | ||
// @ts-ignore | ||
behavior: 'instant', | ||
}); | ||
return false; | ||
} | ||
const visibleRatio = await new Promise(resolve => { | ||
const observer = new IntersectionObserver(entries => { | ||
const visibleRatio = await new Promise((resolve) => { | ||
const observer = new IntersectionObserver((entries) => { | ||
resolve(entries[0].intersectionRatio); | ||
@@ -145,6 +150,10 @@ observer.disconnect(); | ||
if (visibleRatio !== 1.0) { | ||
// Chrome still supports behavior: instant but it's not in the spec so TS shouts | ||
// We don't want to make this breaking change in Puppeteer yet so we'll ignore the line. | ||
// @ts-ignore | ||
element.scrollIntoView({ block: 'center', inline: 'center', behavior: 'instant' }); | ||
element.scrollIntoView({ | ||
block: 'center', | ||
inline: 'center', | ||
// Chrome still supports behavior: instant but it's not in the spec so TS shouts | ||
// We don't want to make this breaking change in Puppeteer yet so we'll ignore the line. | ||
// @ts-ignore | ||
behavior: 'instant', | ||
}); | ||
} | ||
@@ -158,5 +167,7 @@ return false; | ||
const [result, layoutMetrics] = await Promise.all([ | ||
this._client.send('DOM.getContentQuads', { | ||
objectId: this._remoteObject.objectId | ||
}).catch(helper_1.debugError), | ||
this._client | ||
.send('DOM.getContentQuads', { | ||
objectId: this._remoteObject.objectId, | ||
}) | ||
.catch(helper_1.debugError), | ||
this._client.send('Page.getLayoutMetrics'), | ||
@@ -168,3 +179,6 @@ ]); | ||
const { clientWidth, clientHeight } = layoutMetrics.layoutViewport; | ||
const quads = result.quads.map(quad => this._fromProtocolQuad(quad)).map(quad => this._intersectQuadWithViewport(quad, clientWidth, clientHeight)).filter(quad => computeQuadArea(quad) > 1); | ||
const quads = result.quads | ||
.map((quad) => this._fromProtocolQuad(quad)) | ||
.map((quad) => this._intersectQuadWithViewport(quad, clientWidth, clientHeight)) | ||
.filter((quad) => computeQuadArea(quad) > 1); | ||
if (!quads.length) | ||
@@ -182,9 +196,11 @@ throw new Error('Node is either not visible or not an HTMLElement'); | ||
x: x / 4, | ||
y: y / 4 | ||
y: y / 4, | ||
}; | ||
} | ||
_getBoxModel() { | ||
return this._client.send('DOM.getBoxModel', { | ||
objectId: this._remoteObject.objectId | ||
}).catch(error => helper_1.debugError(error)); | ||
return this._client | ||
.send('DOM.getBoxModel', { | ||
objectId: this._remoteObject.objectId, | ||
}) | ||
.catch((error) => helper_1.debugError(error)); | ||
} | ||
@@ -196,7 +212,7 @@ _fromProtocolQuad(quad) { | ||
{ x: quad[4], y: quad[5] }, | ||
{ x: quad[6], y: quad[7] } | ||
{ x: quad[6], y: quad[7] }, | ||
]; | ||
} | ||
_intersectQuadWithViewport(quad, width, height) { | ||
return quad.map(point => ({ | ||
return quad.map((point) => ({ | ||
x: Math.min(Math.max(point.x, 0), width), | ||
@@ -218,7 +234,11 @@ y: Math.min(Math.max(point.y, 0), height), | ||
for (const value of values) | ||
helper_1.assert(helper_1.helper.isString(value), 'Values must be strings. Found value "' + value + '" of type "' + (typeof value) + '"'); | ||
helper_1.assert(helper_1.helper.isString(value), 'Values must be strings. Found value "' + | ||
value + | ||
'" of type "' + | ||
typeof value + | ||
'"'); | ||
/* TODO(jacktfranklin@): once ExecutionContext is TypeScript, and | ||
* its evaluate function is properly typed with generics we can | ||
* return here and remove the typecasting | ||
*/ | ||
* its evaluate function is properly typed with generics we can | ||
* return here and remove the typecasting | ||
*/ | ||
return this.evaluate((element, values) => { | ||
@@ -236,3 +256,5 @@ if (element.nodeName.toLowerCase() !== 'select') | ||
element.dispatchEvent(new Event('change', { bubbles: true })); | ||
return options.filter(option => option.selected).map(option => option.value); | ||
return options | ||
.filter((option) => option.selected) | ||
.map((option) => option.value); | ||
}, values); | ||
@@ -279,3 +301,7 @@ } | ||
else { | ||
await this._client.send('DOM.setFileInputFiles', { objectId, files, backendNodeId }); | ||
await this._client.send('DOM.setFileInputFiles', { | ||
objectId, | ||
files, | ||
backendNodeId, | ||
}); | ||
} | ||
@@ -289,3 +315,3 @@ } | ||
async focus() { | ||
await this.evaluate(element => element.focus()); | ||
await this.evaluate((element) => element.focus()); | ||
} | ||
@@ -325,3 +351,3 @@ async type(text, options) { | ||
width, | ||
height | ||
height, | ||
}; | ||
@@ -334,3 +360,5 @@ } | ||
const viewport = this._page.viewport(); | ||
if (viewport && (boundingBox.width > viewport.width || boundingBox.height > viewport.height)) { | ||
if (viewport && | ||
(boundingBox.width > viewport.width || | ||
boundingBox.height > viewport.height)) { | ||
const newViewport = { | ||
@@ -348,3 +376,3 @@ width: Math.max(viewport.width, Math.ceil(boundingBox.width)), | ||
helper_1.assert(boundingBox.height !== 0, 'Node has 0 height.'); | ||
const { layoutViewport: { pageX, pageY } } = await this._client.send('Page.getLayoutMetrics'); | ||
const { layoutViewport: { pageX, pageY }, } = await this._client.send('Page.getLayoutMetrics'); | ||
const clip = Object.assign({}, boundingBox); | ||
@@ -354,3 +382,3 @@ clip.x += pageX; | ||
const imageData = await this._page.screenshot(Object.assign({}, { | ||
clip | ||
clip, | ||
}, options)); | ||
@@ -423,4 +451,4 @@ if (needsViewportReset) | ||
return await this.evaluate(async (element) => { | ||
const visibleRatio = await new Promise(resolve => { | ||
const observer = new IntersectionObserver(entries => { | ||
const visibleRatio = await new Promise((resolve) => { | ||
const observer = new IntersectionObserver((entries) => { | ||
resolve(entries[0].intersectionRatio); | ||
@@ -427,0 +455,0 @@ observer.disconnect(); |
@@ -24,6 +24,2 @@ "use strict"; | ||
const fs = require("fs"); | ||
const readline = require("readline"); | ||
const debug = require("debug"); | ||
const removeFolder = require("rimraf"); | ||
const childProcess = require("child_process"); | ||
const BrowserFetcher_1 = require("./BrowserFetcher"); | ||
@@ -33,121 +29,6 @@ const Connection_1 = require("./Connection"); | ||
const helper_1 = require("./helper"); | ||
const Errors_1 = require("./Errors"); | ||
const WebSocketTransport_1 = require("./WebSocketTransport"); | ||
const PipeTransport_1 = require("./PipeTransport"); | ||
const BrowserRunner_1 = require("./launcher/BrowserRunner"); | ||
const mkdtempAsync = helper_1.helper.promisify(fs.mkdtemp); | ||
const removeFolderAsync = helper_1.helper.promisify(removeFolder); | ||
const writeFileAsync = helper_1.helper.promisify(fs.writeFile); | ||
const debugLauncher = debug('puppeteer:launcher'); | ||
class BrowserRunner { | ||
constructor(executablePath, processArguments, tempDirectory) { | ||
this.proc = null; | ||
this.connection = null; | ||
this._closed = true; | ||
this._listeners = []; | ||
this._executablePath = executablePath; | ||
this._processArguments = processArguments; | ||
this._tempDirectory = tempDirectory; | ||
} | ||
start(options = {}) { | ||
const { handleSIGINT, handleSIGTERM, handleSIGHUP, dumpio, env, pipe } = options; | ||
let stdio = ['pipe', 'pipe', 'pipe']; | ||
if (pipe) { | ||
if (dumpio) | ||
stdio = ['ignore', 'pipe', 'pipe', 'pipe', 'pipe']; | ||
else | ||
stdio = ['ignore', 'ignore', 'ignore', 'pipe', 'pipe']; | ||
} | ||
helper_1.assert(!this.proc, 'This process has previously been started.'); | ||
debugLauncher(`Calling ${this._executablePath} ${this._processArguments.join(' ')}`); | ||
this.proc = childProcess.spawn(this._executablePath, this._processArguments, { | ||
// On non-windows platforms, `detached: true` makes child process a leader of a new | ||
// process group, making it possible to kill child process tree with `.kill(-pid)` command. | ||
// @see https://nodejs.org/api/child_process.html#child_process_options_detached | ||
detached: process.platform !== 'win32', | ||
env, | ||
stdio | ||
}); | ||
if (dumpio) { | ||
this.proc.stderr.pipe(process.stderr); | ||
this.proc.stdout.pipe(process.stdout); | ||
} | ||
this._closed = false; | ||
this._processClosing = new Promise(fulfill => { | ||
this.proc.once('exit', () => { | ||
this._closed = true; | ||
// Cleanup as processes exit. | ||
if (this._tempDirectory) { | ||
removeFolderAsync(this._tempDirectory) | ||
.then(() => fulfill()) | ||
.catch(error => console.error(error)); | ||
} | ||
else { | ||
fulfill(); | ||
} | ||
}); | ||
}); | ||
this._listeners = [helper_1.helper.addEventListener(process, 'exit', this.kill.bind(this))]; | ||
if (handleSIGINT) | ||
this._listeners.push(helper_1.helper.addEventListener(process, 'SIGINT', () => { this.kill(); process.exit(130); })); | ||
if (handleSIGTERM) | ||
this._listeners.push(helper_1.helper.addEventListener(process, 'SIGTERM', this.close.bind(this))); | ||
if (handleSIGHUP) | ||
this._listeners.push(helper_1.helper.addEventListener(process, 'SIGHUP', this.close.bind(this))); | ||
} | ||
close() { | ||
if (this._closed) | ||
return Promise.resolve(); | ||
helper_1.helper.removeEventListeners(this._listeners); | ||
if (this._tempDirectory) { | ||
this.kill(); | ||
} | ||
else if (this.connection) { | ||
// Attempt to close the browser gracefully | ||
this.connection.send('Browser.close').catch(error => { | ||
helper_1.debugError(error); | ||
this.kill(); | ||
}); | ||
} | ||
return this._processClosing; | ||
} | ||
kill() { | ||
helper_1.helper.removeEventListeners(this._listeners); | ||
if (this.proc && this.proc.pid && !this.proc.killed && !this._closed) { | ||
try { | ||
if (process.platform === 'win32') | ||
childProcess.execSync(`taskkill /pid ${this.proc.pid} /T /F`); | ||
else | ||
process.kill(-this.proc.pid, 'SIGKILL'); | ||
} | ||
catch (error) { | ||
// the process might have already stopped | ||
} | ||
} | ||
// Attempt to remove temporary profile directory to avoid littering. | ||
try { | ||
removeFolder.sync(this._tempDirectory); | ||
} | ||
catch (error) { } | ||
} | ||
/** | ||
* @param {!({usePipe?: boolean, timeout: number, slowMo: number, preferredRevision: string})} options | ||
* | ||
* @return {!Promise<!Connection>} | ||
*/ | ||
async setupConnection(options) { | ||
const { usePipe, timeout, slowMo, preferredRevision } = options; | ||
if (!usePipe) { | ||
const browserWSEndpoint = await waitForWSEndpoint(this.proc, timeout, preferredRevision); | ||
const transport = await WebSocketTransport_1.WebSocketTransport.create(browserWSEndpoint); | ||
this.connection = new Connection_1.Connection(browserWSEndpoint, transport, slowMo); | ||
} | ||
else { | ||
// stdio was assigned during start(), and the 'pipe' option there adds the 4th and 5th items to stdio array | ||
const { 3: pipeWrite, 4: pipeRead } = this.proc.stdio; | ||
const transport = new PipeTransport_1.PipeTransport(pipeWrite, pipeRead); | ||
this.connection = new Connection_1.Connection('', transport, slowMo); | ||
} | ||
return this.connection; | ||
} | ||
} | ||
class ChromeLauncher { | ||
@@ -160,3 +41,3 @@ constructor(projectRoot, preferredRevision, isPuppeteerCore) { | ||
async launch(options = {}) { | ||
const { ignoreDefaultArgs = false, args = [], dumpio = false, executablePath = null, pipe = false, env = process.env, handleSIGINT = true, handleSIGTERM = true, handleSIGHUP = true, ignoreHTTPSErrors = false, defaultViewport = { width: 800, height: 600 }, slowMo = 0, timeout = 30000 } = options; | ||
const { ignoreDefaultArgs = false, args = [], dumpio = false, executablePath = null, pipe = false, env = process.env, handleSIGINT = true, handleSIGTERM = true, handleSIGHUP = true, ignoreHTTPSErrors = false, defaultViewport = { width: 800, height: 600 }, slowMo = 0, timeout = 30000, } = options; | ||
const profilePath = path.join(os.tmpdir(), 'puppeteer_dev_chrome_profile-'); | ||
@@ -167,9 +48,9 @@ const chromeArguments = []; | ||
else if (Array.isArray(ignoreDefaultArgs)) | ||
chromeArguments.push(...this.defaultArgs(options).filter(arg => !ignoreDefaultArgs.includes(arg))); | ||
chromeArguments.push(...this.defaultArgs(options).filter((arg) => !ignoreDefaultArgs.includes(arg))); | ||
else | ||
chromeArguments.push(...args); | ||
let temporaryUserDataDir = null; | ||
if (!chromeArguments.some(argument => argument.startsWith('--remote-debugging-'))) | ||
if (!chromeArguments.some((argument) => argument.startsWith('--remote-debugging-'))) | ||
chromeArguments.push(pipe ? '--remote-debugging-pipe' : '--remote-debugging-port=0'); | ||
if (!chromeArguments.some(arg => arg.startsWith('--user-data-dir'))) { | ||
if (!chromeArguments.some((arg) => arg.startsWith('--user-data-dir'))) { | ||
temporaryUserDataDir = await mkdtempAsync(profilePath); | ||
@@ -186,8 +67,20 @@ chromeArguments.push(`--user-data-dir=${temporaryUserDataDir}`); | ||
const usePipe = chromeArguments.includes('--remote-debugging-pipe'); | ||
const runner = new BrowserRunner(chromeExecutable, chromeArguments, temporaryUserDataDir); | ||
runner.start({ handleSIGHUP, handleSIGTERM, handleSIGINT, dumpio, env, pipe: usePipe }); | ||
const runner = new BrowserRunner_1.BrowserRunner(chromeExecutable, chromeArguments, temporaryUserDataDir); | ||
runner.start({ | ||
handleSIGHUP, | ||
handleSIGTERM, | ||
handleSIGINT, | ||
dumpio, | ||
env, | ||
pipe: usePipe, | ||
}); | ||
try { | ||
const connection = await runner.setupConnection({ usePipe, timeout, slowMo, preferredRevision: this._preferredRevision }); | ||
const connection = await runner.setupConnection({ | ||
usePipe, | ||
timeout, | ||
slowMo, | ||
preferredRevision: this._preferredRevision, | ||
}); | ||
const browser = await Browser_1.Browser.create(connection, [], ignoreHTTPSErrors, defaultViewport, runner.proc, runner.close.bind(runner)); | ||
await browser.waitForTarget(t => t.type() === 'page'); | ||
await browser.waitForTarget((t) => t.type() === 'page'); | ||
return browser; | ||
@@ -230,3 +123,3 @@ } | ||
]; | ||
const { devtools = false, headless = !devtools, args = [], userDataDir = null } = options; | ||
const { devtools = false, headless = !devtools, args = [], userDataDir = null, } = options; | ||
if (userDataDir) | ||
@@ -239,3 +132,3 @@ chromeArguments.push(`--user-data-dir=${userDataDir}`); | ||
} | ||
if (args.every(arg => arg.startsWith('-'))) | ||
if (args.every((arg) => arg.startsWith('-'))) | ||
chromeArguments.push('about:blank'); | ||
@@ -253,3 +146,6 @@ chromeArguments.push(...args); | ||
const { browserWSEndpoint, browserURL, ignoreHTTPSErrors = false, defaultViewport = { width: 800, height: 600 }, transport, slowMo = 0, } = options; | ||
helper_1.assert(Number(!!browserWSEndpoint) + Number(!!browserURL) + Number(!!transport) === 1, 'Exactly one of browserWSEndpoint, browserURL or transport must be passed to puppeteer.connect'); | ||
helper_1.assert(Number(!!browserWSEndpoint) + | ||
Number(!!browserURL) + | ||
Number(!!transport) === | ||
1, 'Exactly one of browserWSEndpoint, browserURL or transport must be passed to puppeteer.connect'); | ||
let connection = null; | ||
@@ -279,3 +175,3 @@ if (transport) { | ||
async launch(options = {}) { | ||
const { ignoreDefaultArgs = false, args = [], dumpio = false, executablePath = null, pipe = false, env = process.env, handleSIGINT = true, handleSIGTERM = true, handleSIGHUP = true, ignoreHTTPSErrors = false, defaultViewport = { width: 800, height: 600 }, slowMo = 0, timeout = 30000, extraPrefsFirefox = {} } = options; | ||
const { ignoreDefaultArgs = false, args = [], dumpio = false, executablePath = null, pipe = false, env = process.env, handleSIGINT = true, handleSIGTERM = true, handleSIGHUP = true, ignoreHTTPSErrors = false, defaultViewport = { width: 800, height: 600 }, slowMo = 0, timeout = 30000, extraPrefsFirefox = {}, } = options; | ||
const firefoxArguments = []; | ||
@@ -285,9 +181,10 @@ if (!ignoreDefaultArgs) | ||
else if (Array.isArray(ignoreDefaultArgs)) | ||
firefoxArguments.push(...this.defaultArgs(options).filter(arg => !ignoreDefaultArgs.includes(arg))); | ||
firefoxArguments.push(...this.defaultArgs(options).filter((arg) => !ignoreDefaultArgs.includes(arg))); | ||
else | ||
firefoxArguments.push(...args); | ||
if (!firefoxArguments.some(argument => argument.startsWith('--remote-debugging-'))) | ||
if (!firefoxArguments.some((argument) => argument.startsWith('--remote-debugging-'))) | ||
firefoxArguments.push('--remote-debugging-port=0'); | ||
let temporaryUserDataDir = null; | ||
if (!firefoxArguments.includes('-profile') && !firefoxArguments.includes('--profile')) { | ||
if (!firefoxArguments.includes('-profile') && | ||
!firefoxArguments.includes('--profile')) { | ||
temporaryUserDataDir = await this._createProfile(extraPrefsFirefox); | ||
@@ -305,8 +202,20 @@ firefoxArguments.push('--profile'); | ||
} | ||
const runner = new BrowserRunner(firefoxExecutable, firefoxArguments, temporaryUserDataDir); | ||
runner.start({ handleSIGHUP, handleSIGTERM, handleSIGINT, dumpio, env, pipe }); | ||
const runner = new BrowserRunner_1.BrowserRunner(firefoxExecutable, firefoxArguments, temporaryUserDataDir); | ||
runner.start({ | ||
handleSIGHUP, | ||
handleSIGTERM, | ||
handleSIGINT, | ||
dumpio, | ||
env, | ||
pipe, | ||
}); | ||
try { | ||
const connection = await runner.setupConnection({ usePipe: pipe, timeout, slowMo, preferredRevision: this._preferredRevision }); | ||
const connection = await runner.setupConnection({ | ||
usePipe: pipe, | ||
timeout, | ||
slowMo, | ||
preferredRevision: this._preferredRevision, | ||
}); | ||
const browser = await Browser_1.Browser.create(connection, [], ignoreHTTPSErrors, defaultViewport, runner.proc, runner.close.bind(runner)); | ||
await browser.waitForTarget(t => t.type() === 'page'); | ||
await browser.waitForTarget((t) => t.type() === 'page'); | ||
return browser; | ||
@@ -321,3 +230,6 @@ } | ||
const { browserWSEndpoint, browserURL, ignoreHTTPSErrors = false, defaultViewport = { width: 800, height: 600 }, transport, slowMo = 0, } = options; | ||
helper_1.assert(Number(!!browserWSEndpoint) + Number(!!browserURL) + Number(!!transport) === 1, 'Exactly one of browserWSEndpoint, browserURL or transport must be passed to puppeteer.connect'); | ||
helper_1.assert(Number(!!browserWSEndpoint) + | ||
Number(!!browserURL) + | ||
Number(!!transport) === | ||
1, 'Exactly one of browserWSEndpoint, browserURL or transport must be passed to puppeteer.connect'); | ||
let connection = null; | ||
@@ -345,3 +257,5 @@ if (transport) { | ||
if (this._preferredRevision === 'latest') { | ||
const browserFetcher = new BrowserFetcher_1.BrowserFetcher(this._projectRoot, { product: this.product }); | ||
const browserFetcher = new BrowserFetcher_1.BrowserFetcher(this._projectRoot, { | ||
product: this.product, | ||
}); | ||
const localRevisions = await browserFetcher.localRevisions(); | ||
@@ -356,7 +270,4 @@ if (localRevisions[0]) | ||
defaultArgs(options = {}) { | ||
const firefoxArguments = [ | ||
'--no-remote', | ||
'--foreground', | ||
]; | ||
const { devtools = false, headless = !devtools, args = [], userDataDir = null } = options; | ||
const firefoxArguments = ['--no-remote', '--foreground']; | ||
const { devtools = false, headless = !devtools, args = [], userDataDir = null, } = options; | ||
if (userDataDir) { | ||
@@ -370,3 +281,3 @@ firefoxArguments.push('--profile'); | ||
firefoxArguments.push('--devtools'); | ||
if (args.every(arg => arg.startsWith('-'))) | ||
if (args.every((arg) => arg.startsWith('-'))) | ||
firefoxArguments.push('about:blank'); | ||
@@ -546,52 +457,14 @@ firefoxArguments.push(...args); | ||
} | ||
function waitForWSEndpoint(browserProcess, timeout, preferredRevision) { | ||
return new Promise((resolve, reject) => { | ||
const rl = readline.createInterface({ input: browserProcess.stderr }); | ||
let stderr = ''; | ||
const listeners = [ | ||
helper_1.helper.addEventListener(rl, 'line', onLine), | ||
helper_1.helper.addEventListener(rl, 'close', () => onClose()), | ||
helper_1.helper.addEventListener(browserProcess, 'exit', () => onClose()), | ||
helper_1.helper.addEventListener(browserProcess, 'error', error => onClose(error)) | ||
]; | ||
const timeoutId = timeout ? setTimeout(onTimeout, timeout) : 0; | ||
/** | ||
* @param {!Error=} error | ||
*/ | ||
function onClose(error) { | ||
cleanup(); | ||
reject(new Error([ | ||
'Failed to launch the browser process!' + (error ? ' ' + error.message : ''), | ||
stderr, | ||
'', | ||
'TROUBLESHOOTING: https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md', | ||
'', | ||
].join('\n'))); | ||
} | ||
function onTimeout() { | ||
cleanup(); | ||
reject(new Errors_1.TimeoutError(`Timed out after ${timeout} ms while trying to connect to the browser! Only Chrome at revision r${preferredRevision} is guaranteed to work.`)); | ||
} | ||
function onLine(line) { | ||
stderr += line + '\n'; | ||
const match = line.match(/^DevTools listening on (ws:\/\/.*)$/); | ||
if (!match) | ||
return; | ||
cleanup(); | ||
resolve(match[1]); | ||
} | ||
function cleanup() { | ||
if (timeoutId) | ||
clearTimeout(timeoutId); | ||
helper_1.helper.removeEventListeners(listeners); | ||
} | ||
}); | ||
} | ||
function getWSEndpoint(browserURL) { | ||
let resolve, reject; | ||
const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); | ||
const promise = new Promise((res, rej) => { | ||
resolve = res; | ||
reject = rej; | ||
}); | ||
const endpointURL = URL.resolve(browserURL, '/json/version'); | ||
const protocol = endpointURL.startsWith('https') ? https : http; | ||
const requestOptions = Object.assign(URL.parse(endpointURL), { method: 'GET' }); | ||
const request = protocol.request(requestOptions, res => { | ||
const requestOptions = Object.assign(URL.parse(endpointURL), { | ||
method: 'GET', | ||
}); | ||
const request = protocol.request(requestOptions, (res) => { | ||
let data = ''; | ||
@@ -605,3 +478,3 @@ if (res.statusCode !== 200) { | ||
res.setEncoding('utf8'); | ||
res.on('data', chunk => data += chunk); | ||
res.on('data', (chunk) => (data += chunk)); | ||
res.on('end', () => resolve(JSON.parse(data).webSocketDebuggerUrl)); | ||
@@ -611,4 +484,6 @@ }); | ||
request.end(); | ||
return promise.catch(error => { | ||
error.message = `Failed to fetch browser webSocket url from ${endpointURL}: ` + error.message; | ||
return promise.catch((error) => { | ||
error.message = | ||
`Failed to fetch browser webSocket url from ${endpointURL}: ` + | ||
error.message; | ||
throw error; | ||
@@ -620,9 +495,16 @@ }); | ||
if (!launcher._isPuppeteerCore) { | ||
const executablePath = process.env.PUPPETEER_EXECUTABLE_PATH || process.env.npm_config_puppeteer_executable_path || process.env.npm_package_config_puppeteer_executable_path; | ||
const executablePath = process.env.PUPPETEER_EXECUTABLE_PATH || | ||
process.env.npm_config_puppeteer_executable_path || | ||
process.env.npm_package_config_puppeteer_executable_path; | ||
if (executablePath) { | ||
const missingText = !fs.existsSync(executablePath) ? 'Tried to use PUPPETEER_EXECUTABLE_PATH env variable to launch browser but did not find any executable at: ' + executablePath : null; | ||
const missingText = !fs.existsSync(executablePath) | ||
? 'Tried to use PUPPETEER_EXECUTABLE_PATH env variable to launch browser but did not find any executable at: ' + | ||
executablePath | ||
: null; | ||
return { executablePath, missingText }; | ||
} | ||
} | ||
const browserFetcher = new BrowserFetcher_1.BrowserFetcher(launcher._projectRoot, { product: launcher.product }); | ||
const browserFetcher = new BrowserFetcher_1.BrowserFetcher(launcher._projectRoot, { | ||
product: launcher.product, | ||
}); | ||
if (!launcher._isPuppeteerCore && launcher.product === 'chrome') { | ||
@@ -632,3 +514,6 @@ const revision = process.env['PUPPETEER_CHROMIUM_REVISION']; | ||
const revisionInfo = browserFetcher.revisionInfo(revision); | ||
const missingText = !revisionInfo.local ? 'Tried to use PUPPETEER_CHROMIUM_REVISION env variable to launch browser but did not find executable at: ' + revisionInfo.executablePath : null; | ||
const missingText = !revisionInfo.local | ||
? 'Tried to use PUPPETEER_CHROMIUM_REVISION env variable to launch browser but did not find executable at: ' + | ||
revisionInfo.executablePath | ||
: null; | ||
return { executablePath: revisionInfo.executablePath, missingText }; | ||
@@ -638,3 +523,5 @@ } | ||
const revisionInfo = browserFetcher.revisionInfo(launcher._preferredRevision); | ||
const missingText = !revisionInfo.local ? `Could not find browser revision ${launcher._preferredRevision}. Run "npm install" or "yarn install" to download a browser binary.` : null; | ||
const missingText = !revisionInfo.local | ||
? `Could not find browser revision ${launcher._preferredRevision}. Run "npm install" or "yarn install" to download a browser binary.` | ||
: null; | ||
return { executablePath: revisionInfo.executablePath, missingText }; | ||
@@ -645,3 +532,6 @@ } | ||
if (!product && !isPuppeteerCore) | ||
product = process.env.PUPPETEER_PRODUCT || process.env.npm_config_puppeteer_product || process.env.npm_package_config_puppeteer_product; | ||
product = | ||
process.env.PUPPETEER_PRODUCT || | ||
process.env.npm_config_puppeteer_product || | ||
process.env.npm_package_config_puppeteer_product; | ||
switch (product) { | ||
@@ -652,2 +542,9 @@ case 'firefox': | ||
default: | ||
if (typeof product !== 'undefined' && product !== 'chrome') { | ||
/* The user gave us an incorrect product name | ||
* we'll default to launching Chrome, but log to the console | ||
* to let the user know (they've probably typoed). | ||
*/ | ||
console.warn(`Warning: unknown product name ${product}. Falling back to chrome.`); | ||
} | ||
return new ChromeLauncher(projectRoot, preferredRevision, isPuppeteerCore); | ||
@@ -654,0 +551,0 @@ } |
@@ -18,2 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.LifecycleWatcher = void 0; | ||
const helper_1 = require("./helper"); | ||
@@ -34,3 +35,3 @@ const Events_1 = require("./Events"); | ||
waitUntil = [waitUntil]; | ||
this._expectedLifecycle = waitUntil.map(value => { | ||
this._expectedLifecycle = waitUntil.map((value) => { | ||
const protocolEvent = puppeteerToProtocolLifecycle.get(value); | ||
@@ -52,13 +53,13 @@ helper_1.assert(protocolEvent, 'Unknown value for options.waitUntil: ' + value); | ||
]; | ||
this._sameDocumentNavigationPromise = new Promise(fulfill => { | ||
this._sameDocumentNavigationPromise = new Promise((fulfill) => { | ||
this._sameDocumentNavigationCompleteCallback = fulfill; | ||
}); | ||
this._lifecyclePromise = new Promise(fulfill => { | ||
this._lifecyclePromise = new Promise((fulfill) => { | ||
this._lifecycleCallback = fulfill; | ||
}); | ||
this._newDocumentNavigationPromise = new Promise(fulfill => { | ||
this._newDocumentNavigationPromise = new Promise((fulfill) => { | ||
this._newDocumentNavigationCompleteCallback = fulfill; | ||
}); | ||
this._timeoutPromise = this._createTimeoutPromise(); | ||
this._terminationPromise = new Promise(fulfill => { | ||
this._terminationPromise = new Promise((fulfill) => { | ||
this._terminationCallback = fulfill; | ||
@@ -102,4 +103,3 @@ }); | ||
const errorMessage = 'Navigation timeout of ' + this._timeout + ' ms exceeded'; | ||
return new Promise(fulfill => this._maximumTimer = setTimeout(fulfill, this._timeout)) | ||
.then(() => new Errors_1.TimeoutError(errorMessage)); | ||
return new Promise((fulfill) => (this._maximumTimer = setTimeout(fulfill, this._timeout))).then(() => new Errors_1.TimeoutError(errorMessage)); | ||
} | ||
@@ -117,3 +117,4 @@ _navigatedWithinDocument(frame) { | ||
this._lifecycleCallback(); | ||
if (this._frame._loaderId === this._initialLoaderId && !this._hasSameDocumentNavigation) | ||
if (this._frame._loaderId === this._initialLoaderId && | ||
!this._hasSameDocumentNavigation) | ||
return; | ||
@@ -120,0 +121,0 @@ if (this._hasSameDocumentNavigation) |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.NetworkManager = void 0; | ||
/** | ||
@@ -21,2 +22,4 @@ * Copyright 2017 Google Inc. All rights reserved. | ||
const Events_1 = require("./Events"); | ||
const Request_1 = require("./Request"); | ||
const Response_1 = require("./Response"); | ||
class NetworkManager extends EventEmitter { | ||
@@ -49,3 +52,5 @@ constructor(client, ignoreHTTPSErrors, frameManager) { | ||
if (this._ignoreHTTPSErrors) | ||
await this._client.send('Security.setIgnoreCertificateErrors', { ignore: true }); | ||
await this._client.send('Security.setIgnoreCertificateErrors', { | ||
ignore: true, | ||
}); | ||
} | ||
@@ -63,3 +68,5 @@ async authenticate(credentials) { | ||
} | ||
await this._client.send('Network.setExtraHTTPHeaders', { headers: this._extraHTTPHeaders }); | ||
await this._client.send('Network.setExtraHTTPHeaders', { | ||
headers: this._extraHTTPHeaders, | ||
}); | ||
} | ||
@@ -78,3 +85,3 @@ extraHTTPHeaders() { | ||
downloadThroughput: -1, | ||
uploadThroughput: -1 | ||
uploadThroughput: -1, | ||
}); | ||
@@ -110,3 +117,3 @@ } | ||
this._updateProtocolCacheDisabled(), | ||
this._client.send('Fetch.disable') | ||
this._client.send('Fetch.disable'), | ||
]); | ||
@@ -117,3 +124,3 @@ } | ||
await this._client.send('Network.setCacheDisabled', { | ||
cacheDisabled: this._userCacheDisabled || this._protocolRequestInterceptionEnabled | ||
cacheDisabled: this._userCacheDisabled || this._protocolRequestInterceptionEnabled, | ||
}); | ||
@@ -123,3 +130,4 @@ } | ||
// Request interception doesn't happen for data URLs with Network Service. | ||
if (this._protocolRequestInterceptionEnabled && !event.request.url.startsWith('data:')) { | ||
if (this._protocolRequestInterceptionEnabled && | ||
!event.request.url.startsWith('data:')) { | ||
const requestId = event.requestId; | ||
@@ -150,13 +158,21 @@ const interceptionId = this._requestIdToInterceptionId.get(requestId); | ||
} | ||
const { username, password } = this._credentials || { username: undefined, password: undefined }; | ||
this._client.send('Fetch.continueWithAuth', { | ||
const { username, password } = this._credentials || { | ||
username: undefined, | ||
password: undefined, | ||
}; | ||
this._client | ||
.send('Fetch.continueWithAuth', { | ||
requestId: event.requestId, | ||
authChallengeResponse: { response, username, password }, | ||
}).catch(helper_1.debugError); | ||
}) | ||
.catch(helper_1.debugError); | ||
} | ||
_onRequestPaused(event) { | ||
if (!this._userRequestInterceptionEnabled && this._protocolRequestInterceptionEnabled) { | ||
this._client.send('Fetch.continueRequest', { | ||
requestId: event.requestId | ||
}).catch(helper_1.debugError); | ||
if (!this._userRequestInterceptionEnabled && | ||
this._protocolRequestInterceptionEnabled) { | ||
this._client | ||
.send('Fetch.continueRequest', { | ||
requestId: event.requestId, | ||
}) | ||
.catch(helper_1.debugError); | ||
} | ||
@@ -184,4 +200,6 @@ const requestId = event.networkId; | ||
} | ||
const frame = event.frameId ? this._frameManager.frame(event.frameId) : null; | ||
const request = new Request(this._client, frame, interceptionId, this._userRequestInterceptionEnabled, event, redirectChain); | ||
const frame = event.frameId | ||
? this._frameManager.frame(event.frameId) | ||
: null; | ||
const request = new Request_1.Request(this._client, frame, interceptionId, this._userRequestInterceptionEnabled, event, redirectChain); | ||
this._requestIdToRequest.set(event.requestId, request); | ||
@@ -196,6 +214,6 @@ this.emit(Events_1.Events.NetworkManager.Request, request); | ||
_handleRequestRedirect(request, responsePayload) { | ||
const response = new Response(this._client, request, responsePayload); | ||
const response = new Response_1.Response(this._client, request, responsePayload); | ||
request._response = response; | ||
request._redirectChain.push(request); | ||
response._bodyLoadedPromiseFulfill.call(null, new Error('Response body is unavailable for redirect responses')); | ||
response._resolveBody(new Error('Response body is unavailable for redirect responses')); | ||
this._requestIdToRequest.delete(request._requestId); | ||
@@ -211,3 +229,3 @@ this._attemptedAuthentications.delete(request._interceptionId); | ||
return; | ||
const response = new Response(this._client, request, event.response); | ||
const response = new Response_1.Response(this._client, request, event.response); | ||
request._response = response; | ||
@@ -225,3 +243,3 @@ this.emit(Events_1.Events.NetworkManager.Response, response); | ||
if (request.response()) | ||
request.response()._bodyLoadedPromiseFulfill.call(null); | ||
request.response()._resolveBody(null); | ||
this._requestIdToRequest.delete(request._requestId); | ||
@@ -240,3 +258,3 @@ this._attemptedAuthentications.delete(request._interceptionId); | ||
if (response) | ||
response._bodyLoadedPromiseFulfill.call(null); | ||
response._resolveBody(null); | ||
this._requestIdToRequest.delete(request._requestId); | ||
@@ -248,321 +266,1 @@ this._attemptedAuthentications.delete(request._interceptionId); | ||
exports.NetworkManager = NetworkManager; | ||
class Request { | ||
constructor(client, frame, interceptionId, allowInterception, event, redirectChain) { | ||
this._interceptionHandled = false; | ||
this._response = null; | ||
this._failureText = null; | ||
this._headers = {}; | ||
this._fromMemoryCache = false; | ||
this._client = client; | ||
this._requestId = event.requestId; | ||
this._isNavigationRequest = event.requestId === event.loaderId && event.type === 'Document'; | ||
this._interceptionId = interceptionId; | ||
this._allowInterception = allowInterception; | ||
this._url = event.request.url; | ||
this._resourceType = event.type.toLowerCase(); | ||
this._method = event.request.method; | ||
this._postData = event.request.postData; | ||
this._frame = frame; | ||
this._redirectChain = redirectChain; | ||
for (const key of Object.keys(event.request.headers)) | ||
this._headers[key.toLowerCase()] = event.request.headers[key]; | ||
} | ||
url() { | ||
return this._url; | ||
} | ||
resourceType() { | ||
return this._resourceType; | ||
} | ||
method() { | ||
return this._method; | ||
} | ||
postData() { | ||
return this._postData; | ||
} | ||
headers() { | ||
return this._headers; | ||
} | ||
response() { | ||
return this._response; | ||
} | ||
frame() { | ||
return this._frame; | ||
} | ||
isNavigationRequest() { | ||
return this._isNavigationRequest; | ||
} | ||
redirectChain() { | ||
return this._redirectChain.slice(); | ||
} | ||
/** | ||
* @return {?{errorText: string}} | ||
*/ | ||
failure() { | ||
if (!this._failureText) | ||
return null; | ||
return { | ||
errorText: this._failureText | ||
}; | ||
} | ||
async continue(overrides = {}) { | ||
// Request interception is not supported for data: urls. | ||
if (this._url.startsWith('data:')) | ||
return; | ||
helper_1.assert(this._allowInterception, 'Request Interception is not enabled!'); | ||
helper_1.assert(!this._interceptionHandled, 'Request is already handled!'); | ||
const { url, method, postData, headers } = overrides; | ||
this._interceptionHandled = true; | ||
await this._client.send('Fetch.continueRequest', { | ||
requestId: this._interceptionId, | ||
url, | ||
method, | ||
postData, | ||
headers: headers ? headersArray(headers) : undefined, | ||
}).catch(error => { | ||
// In certain cases, protocol will return error if the request was already canceled | ||
// or the page was closed. We should tolerate these errors. | ||
helper_1.debugError(error); | ||
}); | ||
} | ||
async respond(response) { | ||
// Mocking responses for dataURL requests is not currently supported. | ||
if (this._url.startsWith('data:')) | ||
return; | ||
helper_1.assert(this._allowInterception, 'Request Interception is not enabled!'); | ||
helper_1.assert(!this._interceptionHandled, 'Request is already handled!'); | ||
this._interceptionHandled = true; | ||
const responseBody = response.body && helper_1.helper.isString(response.body) ? Buffer.from(response.body) : response.body || null; | ||
const responseHeaders = {}; | ||
if (response.headers) { | ||
for (const header of Object.keys(response.headers)) | ||
responseHeaders[header.toLowerCase()] = response.headers[header]; | ||
} | ||
if (response.contentType) | ||
responseHeaders['content-type'] = response.contentType; | ||
if (responseBody && !('content-length' in responseHeaders)) | ||
responseHeaders['content-length'] = String(Buffer.byteLength(responseBody)); | ||
await this._client.send('Fetch.fulfillRequest', { | ||
requestId: this._interceptionId, | ||
responseCode: response.status || 200, | ||
responsePhrase: STATUS_TEXTS[response.status || 200], | ||
responseHeaders: headersArray(responseHeaders), | ||
body: responseBody ? responseBody.toString('base64') : undefined, | ||
}).catch(error => { | ||
// In certain cases, protocol will return error if the request was already canceled | ||
// or the page was closed. We should tolerate these errors. | ||
helper_1.debugError(error); | ||
}); | ||
} | ||
async abort(errorCode = 'failed') { | ||
// Request interception is not supported for data: urls. | ||
if (this._url.startsWith('data:')) | ||
return; | ||
const errorReason = errorReasons[errorCode]; | ||
helper_1.assert(errorReason, 'Unknown error code: ' + errorCode); | ||
helper_1.assert(this._allowInterception, 'Request Interception is not enabled!'); | ||
helper_1.assert(!this._interceptionHandled, 'Request is already handled!'); | ||
this._interceptionHandled = true; | ||
await this._client.send('Fetch.failRequest', { | ||
requestId: this._interceptionId, | ||
errorReason | ||
}).catch(error => { | ||
// In certain cases, protocol will return error if the request was already canceled | ||
// or the page was closed. We should tolerate these errors. | ||
helper_1.debugError(error); | ||
}); | ||
} | ||
} | ||
exports.Request = Request; | ||
const errorReasons = { | ||
'aborted': 'Aborted', | ||
'accessdenied': 'AccessDenied', | ||
'addressunreachable': 'AddressUnreachable', | ||
'blockedbyclient': 'BlockedByClient', | ||
'blockedbyresponse': 'BlockedByResponse', | ||
'connectionaborted': 'ConnectionAborted', | ||
'connectionclosed': 'ConnectionClosed', | ||
'connectionfailed': 'ConnectionFailed', | ||
'connectionrefused': 'ConnectionRefused', | ||
'connectionreset': 'ConnectionReset', | ||
'internetdisconnected': 'InternetDisconnected', | ||
'namenotresolved': 'NameNotResolved', | ||
'timedout': 'TimedOut', | ||
'failed': 'Failed', | ||
}; | ||
class Response { | ||
constructor(client, request, responsePayload) { | ||
this._contentPromise = null; | ||
this._headers = {}; | ||
this._client = client; | ||
this._request = request; | ||
this._bodyLoadedPromise = new Promise(fulfill => { | ||
this._bodyLoadedPromiseFulfill = fulfill; | ||
}); | ||
this._remoteAddress = { | ||
ip: responsePayload.remoteIPAddress, | ||
port: responsePayload.remotePort, | ||
}; | ||
this._status = responsePayload.status; | ||
this._statusText = responsePayload.statusText; | ||
this._url = request.url(); | ||
this._fromDiskCache = !!responsePayload.fromDiskCache; | ||
this._fromServiceWorker = !!responsePayload.fromServiceWorker; | ||
for (const key of Object.keys(responsePayload.headers)) | ||
this._headers[key.toLowerCase()] = responsePayload.headers[key]; | ||
this._securityDetails = responsePayload.securityDetails ? new SecurityDetails(responsePayload.securityDetails) : null; | ||
} | ||
remoteAddress() { | ||
return this._remoteAddress; | ||
} | ||
url() { | ||
return this._url; | ||
} | ||
ok() { | ||
return this._status === 0 || (this._status >= 200 && this._status <= 299); | ||
} | ||
status() { | ||
return this._status; | ||
} | ||
statusText() { | ||
return this._statusText; | ||
} | ||
headers() { | ||
return this._headers; | ||
} | ||
securityDetails() { | ||
return this._securityDetails; | ||
} | ||
buffer() { | ||
if (!this._contentPromise) { | ||
this._contentPromise = this._bodyLoadedPromise.then(async (error) => { | ||
if (error) | ||
throw error; | ||
const response = await this._client.send('Network.getResponseBody', { | ||
requestId: this._request._requestId | ||
}); | ||
return Buffer.from(response.body, response.base64Encoded ? 'base64' : 'utf8'); | ||
}); | ||
} | ||
return this._contentPromise; | ||
} | ||
async text() { | ||
const content = await this.buffer(); | ||
return content.toString('utf8'); | ||
} | ||
async json() { | ||
const content = await this.text(); | ||
return JSON.parse(content); | ||
} | ||
request() { | ||
return this._request; | ||
} | ||
fromCache() { | ||
return this._fromDiskCache || this._request._fromMemoryCache; | ||
} | ||
fromServiceWorker() { | ||
return this._fromServiceWorker; | ||
} | ||
frame() { | ||
return this._request.frame(); | ||
} | ||
} | ||
exports.Response = Response; | ||
class SecurityDetails { | ||
constructor(securityPayload) { | ||
this._subjectName = securityPayload.subjectName; | ||
this._issuer = securityPayload.issuer; | ||
this._validFrom = securityPayload.validFrom; | ||
this._validTo = securityPayload.validTo; | ||
this._protocol = securityPayload.protocol; | ||
} | ||
subjectName() { | ||
return this._subjectName; | ||
} | ||
issuer() { | ||
return this._issuer; | ||
} | ||
validFrom() { | ||
return this._validFrom; | ||
} | ||
validTo() { | ||
return this._validTo; | ||
} | ||
protocol() { | ||
return this._protocol; | ||
} | ||
} | ||
exports.SecurityDetails = SecurityDetails; | ||
function headersArray(headers) { | ||
const result = []; | ||
for (const name in headers) { | ||
if (!Object.is(headers[name], undefined)) | ||
result.push({ name, value: headers[name] + '' }); | ||
} | ||
return result; | ||
} | ||
// List taken from https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml with extra 306 and 418 codes. | ||
const STATUS_TEXTS = { | ||
'100': 'Continue', | ||
'101': 'Switching Protocols', | ||
'102': 'Processing', | ||
'103': 'Early Hints', | ||
'200': 'OK', | ||
'201': 'Created', | ||
'202': 'Accepted', | ||
'203': 'Non-Authoritative Information', | ||
'204': 'No Content', | ||
'205': 'Reset Content', | ||
'206': 'Partial Content', | ||
'207': 'Multi-Status', | ||
'208': 'Already Reported', | ||
'226': 'IM Used', | ||
'300': 'Multiple Choices', | ||
'301': 'Moved Permanently', | ||
'302': 'Found', | ||
'303': 'See Other', | ||
'304': 'Not Modified', | ||
'305': 'Use Proxy', | ||
'306': 'Switch Proxy', | ||
'307': 'Temporary Redirect', | ||
'308': 'Permanent Redirect', | ||
'400': 'Bad Request', | ||
'401': 'Unauthorized', | ||
'402': 'Payment Required', | ||
'403': 'Forbidden', | ||
'404': 'Not Found', | ||
'405': 'Method Not Allowed', | ||
'406': 'Not Acceptable', | ||
'407': 'Proxy Authentication Required', | ||
'408': 'Request Timeout', | ||
'409': 'Conflict', | ||
'410': 'Gone', | ||
'411': 'Length Required', | ||
'412': 'Precondition Failed', | ||
'413': 'Payload Too Large', | ||
'414': 'URI Too Long', | ||
'415': 'Unsupported Media Type', | ||
'416': 'Range Not Satisfiable', | ||
'417': 'Expectation Failed', | ||
'418': 'I\'m a teapot', | ||
'421': 'Misdirected Request', | ||
'422': 'Unprocessable Entity', | ||
'423': 'Locked', | ||
'424': 'Failed Dependency', | ||
'425': 'Too Early', | ||
'426': 'Upgrade Required', | ||
'428': 'Precondition Required', | ||
'429': 'Too Many Requests', | ||
'431': 'Request Header Fields Too Large', | ||
'451': 'Unavailable For Legal Reasons', | ||
'500': 'Internal Server Error', | ||
'501': 'Not Implemented', | ||
'502': 'Bad Gateway', | ||
'503': 'Service Unavailable', | ||
'504': 'Gateway Timeout', | ||
'505': 'HTTP Version Not Supported', | ||
'506': 'Variant Also Negotiates', | ||
'507': 'Insufficient Storage', | ||
'508': 'Loop Detected', | ||
'510': 'Not Extended', | ||
'511': 'Network Authentication Required', | ||
}; |
300
lib/Page.js
@@ -18,2 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Page = void 0; | ||
const fs = require("fs"); | ||
@@ -35,2 +36,4 @@ const EventEmitter = require("events"); | ||
const TimeoutSettings_1 = require("./TimeoutSettings"); | ||
const FileChooser_1 = require("./FileChooser"); | ||
const ConsoleMessage_1 = require("./ConsoleMessage"); | ||
const writeFileAsync = helper_1.helper.promisify(fs.writeFile); | ||
@@ -50,4 +53,14 @@ const paperFormats = { | ||
}; | ||
class ScreenshotTaskQueue { | ||
constructor() { | ||
this._chain = Promise.resolve(undefined); | ||
} | ||
postTask(task) { | ||
const result = this._chain.then(task); | ||
this._chain = result.catch(() => { }); | ||
return result; | ||
} | ||
} | ||
class Page extends EventEmitter { | ||
constructor(client, target, ignoreHTTPSErrors, screenshotTaskQueue) { | ||
constructor(client, target, ignoreHTTPSErrors) { | ||
super(); | ||
@@ -71,10 +84,12 @@ this._closed = false; | ||
this._coverage = new Coverage_1.Coverage(client); | ||
this._screenshotTaskQueue = screenshotTaskQueue; | ||
this._screenshotTaskQueue = new ScreenshotTaskQueue(); | ||
this._viewport = null; | ||
client.on('Target.attachedToTarget', event => { | ||
client.on('Target.attachedToTarget', (event) => { | ||
if (event.targetInfo.type !== 'worker') { | ||
// If we don't detach from service workers, they will never die. | ||
client.send('Target.detachFromTarget', { | ||
sessionId: event.sessionId | ||
}).catch(helper_1.debugError); | ||
client | ||
.send('Target.detachFromTarget', { | ||
sessionId: event.sessionId, | ||
}) | ||
.catch(helper_1.debugError); | ||
return; | ||
@@ -87,3 +102,3 @@ } | ||
}); | ||
client.on('Target.detachedFromTarget', event => { | ||
client.on('Target.detachedFromTarget', (event) => { | ||
const worker = this._workers.get(event.sessionId); | ||
@@ -95,21 +110,21 @@ if (!worker) | ||
}); | ||
this._frameManager.on(Events_1.Events.FrameManager.FrameAttached, event => this.emit(Events_1.Events.Page.FrameAttached, event)); | ||
this._frameManager.on(Events_1.Events.FrameManager.FrameDetached, event => this.emit(Events_1.Events.Page.FrameDetached, event)); | ||
this._frameManager.on(Events_1.Events.FrameManager.FrameNavigated, event => this.emit(Events_1.Events.Page.FrameNavigated, event)); | ||
this._frameManager.on(Events_1.Events.FrameManager.FrameAttached, (event) => this.emit(Events_1.Events.Page.FrameAttached, event)); | ||
this._frameManager.on(Events_1.Events.FrameManager.FrameDetached, (event) => this.emit(Events_1.Events.Page.FrameDetached, event)); | ||
this._frameManager.on(Events_1.Events.FrameManager.FrameNavigated, (event) => this.emit(Events_1.Events.Page.FrameNavigated, event)); | ||
const networkManager = this._frameManager.networkManager(); | ||
networkManager.on(Events_1.Events.NetworkManager.Request, event => this.emit(Events_1.Events.Page.Request, event)); | ||
networkManager.on(Events_1.Events.NetworkManager.Response, event => this.emit(Events_1.Events.Page.Response, event)); | ||
networkManager.on(Events_1.Events.NetworkManager.RequestFailed, event => this.emit(Events_1.Events.Page.RequestFailed, event)); | ||
networkManager.on(Events_1.Events.NetworkManager.RequestFinished, event => this.emit(Events_1.Events.Page.RequestFinished, event)); | ||
networkManager.on(Events_1.Events.NetworkManager.Request, (event) => this.emit(Events_1.Events.Page.Request, event)); | ||
networkManager.on(Events_1.Events.NetworkManager.Response, (event) => this.emit(Events_1.Events.Page.Response, event)); | ||
networkManager.on(Events_1.Events.NetworkManager.RequestFailed, (event) => this.emit(Events_1.Events.Page.RequestFailed, event)); | ||
networkManager.on(Events_1.Events.NetworkManager.RequestFinished, (event) => this.emit(Events_1.Events.Page.RequestFinished, event)); | ||
this._fileChooserInterceptors = new Set(); | ||
client.on('Page.domContentEventFired', () => this.emit(Events_1.Events.Page.DOMContentLoaded)); | ||
client.on('Page.loadEventFired', () => this.emit(Events_1.Events.Page.Load)); | ||
client.on('Runtime.consoleAPICalled', event => this._onConsoleAPI(event)); | ||
client.on('Runtime.bindingCalled', event => this._onBindingCalled(event)); | ||
client.on('Page.javascriptDialogOpening', event => this._onDialog(event)); | ||
client.on('Runtime.exceptionThrown', exception => this._handleException(exception.exceptionDetails)); | ||
client.on('Runtime.consoleAPICalled', (event) => this._onConsoleAPI(event)); | ||
client.on('Runtime.bindingCalled', (event) => this._onBindingCalled(event)); | ||
client.on('Page.javascriptDialogOpening', (event) => this._onDialog(event)); | ||
client.on('Runtime.exceptionThrown', (exception) => this._handleException(exception.exceptionDetails)); | ||
client.on('Inspector.targetCrashed', () => this._onTargetCrashed()); | ||
client.on('Performance.metrics', event => this._emitMetrics(event)); | ||
client.on('Log.entryAdded', event => this._onLogEntryAdded(event)); | ||
client.on('Page.fileChooserOpened', event => this._onFileChooser(event)); | ||
client.on('Performance.metrics', (event) => this._emitMetrics(event)); | ||
client.on('Log.entryAdded', (event) => this._onLogEntryAdded(event)); | ||
client.on('Page.fileChooserOpened', (event) => this._onFileChooser(event)); | ||
this._target._isClosedPromise.then(() => { | ||
@@ -120,4 +135,4 @@ this.emit(Events_1.Events.Page.Close); | ||
} | ||
static async create(client, target, ignoreHTTPSErrors, defaultViewport, screenshotTaskQueue) { | ||
const page = new Page(client, target, ignoreHTTPSErrors, screenshotTaskQueue); | ||
static async create(client, target, ignoreHTTPSErrors, defaultViewport) { | ||
const page = new Page(client, target, ignoreHTTPSErrors); | ||
await page._initialize(); | ||
@@ -131,3 +146,7 @@ if (defaultViewport) | ||
this._frameManager.initialize(), | ||
this._client.send('Target.setAutoAttach', { autoAttach: true, waitForDebuggerOnStart: false, flatten: true }), | ||
this._client.send('Target.setAutoAttach', { | ||
autoAttach: true, | ||
waitForDebuggerOnStart: false, | ||
flatten: true, | ||
}), | ||
this._client.send('Performance.enable', {}), | ||
@@ -145,3 +164,3 @@ this._client.send('Log.enable', {}), | ||
this._fileChooserInterceptors.clear(); | ||
const fileChooser = new FileChooser(this._client, element, event); | ||
const fileChooser = new FileChooser_1.FileChooser(element, event); | ||
for (const interceptor of interceptors) | ||
@@ -152,8 +171,12 @@ interceptor.call(null, fileChooser); | ||
if (!this._fileChooserInterceptors.size) | ||
await this._client.send('Page.setInterceptFileChooserDialog', { enabled: true }); | ||
const { timeout = this._timeoutSettings.timeout(), } = options; | ||
await this._client.send('Page.setInterceptFileChooserDialog', { | ||
enabled: true, | ||
}); | ||
const { timeout = this._timeoutSettings.timeout() } = options; | ||
let callback; | ||
const promise = new Promise(x => callback = x); | ||
const promise = new Promise((x) => (callback = x)); | ||
this._fileChooserInterceptors.add(callback); | ||
return helper_1.helper.waitWithTimeout(promise, 'waiting for file chooser', timeout).catch(error => { | ||
return helper_1.helper | ||
.waitWithTimeout(promise, 'waiting for file chooser', timeout) | ||
.catch((error) => { | ||
this._fileChooserInterceptors.delete(callback); | ||
@@ -171,3 +194,7 @@ throw error; | ||
throw new Error(`Invalid accuracy "${accuracy}": precondition 0 <= ACCURACY failed.`); | ||
await this._client.send('Emulation.setGeolocationOverride', { longitude, latitude, accuracy }); | ||
await this._client.send('Emulation.setGeolocationOverride', { | ||
longitude, | ||
latitude, | ||
accuracy, | ||
}); | ||
} | ||
@@ -189,5 +216,5 @@ target() { | ||
if (args) | ||
args.map(arg => helper_1.helper.releaseObject(this._client, arg)); | ||
args.map((arg) => helper_1.helper.releaseObject(this._client, arg)); | ||
if (source !== 'worker') | ||
this.emit(Events_1.Events.Page.Console, new ConsoleMessage(level, text, [], { url, lineNumber })); | ||
this.emit(Events_1.Events.Page.Console, new ConsoleMessage_1.ConsoleMessage(level, text, [], { url, lineNumber })); | ||
} | ||
@@ -255,3 +282,3 @@ mainFrame() { | ||
const originalCookies = (await this._client.send('Network.getCookies', { | ||
urls: urls.length ? urls : [this.url()] | ||
urls: urls.length ? urls : [this.url()], | ||
})).cookies; | ||
@@ -278,3 +305,3 @@ const unsupportedCookieAttributes = ['priority']; | ||
const startsWithHTTP = pageURL.startsWith('http'); | ||
const items = cookies.map(cookie => { | ||
const items = cookies.map((cookie) => { | ||
const item = Object.assign({}, cookie); | ||
@@ -303,4 +330,6 @@ if (!item.url && startsWithHTTP) | ||
await this._client.send('Runtime.addBinding', { name: name }); | ||
await this._client.send('Page.addScriptToEvaluateOnNewDocument', { source: expression }); | ||
await Promise.all(this.frames().map(frame => frame.evaluate(expression).catch(helper_1.debugError))); | ||
await this._client.send('Page.addScriptToEvaluateOnNewDocument', { | ||
source: expression, | ||
}); | ||
await Promise.all(this.frames().map((frame) => frame.evaluate(expression).catch(helper_1.debugError))); | ||
function addPageBinding(bindingName) { | ||
@@ -343,3 +372,3 @@ /* Cast window to any here as we're about to add properties to it | ||
title: event.title, | ||
metrics: this._buildMetricsObject(event.metrics) | ||
metrics: this._buildMetricsObject(event.metrics), | ||
}); | ||
@@ -379,3 +408,3 @@ } | ||
const context = this._frameManager.executionContextById(event.executionContextId); | ||
const values = event.args.map(arg => JSHandle_1.createJSHandle(context, arg)); | ||
const values = event.args.map((arg) => JSHandle_1.createJSHandle(context, arg)); | ||
this._addConsoleMessage(event.type, values, event.stackTrace); | ||
@@ -396,3 +425,8 @@ } | ||
} | ||
this._client.send('Runtime.evaluate', { expression, contextId: event.executionContextId }).catch(helper_1.debugError); | ||
this._client | ||
.send('Runtime.evaluate', { | ||
expression, | ||
contextId: event.executionContextId, | ||
}) | ||
.catch(helper_1.debugError); | ||
function deliverResult(name, seq, result) { | ||
@@ -415,3 +449,3 @@ window[name]['callbacks'].get(seq).resolve(result); | ||
if (!this.listenerCount(Events_1.Events.Page.Console)) { | ||
args.forEach(arg => arg.dispose()); | ||
args.forEach((arg) => arg.dispose()); | ||
return; | ||
@@ -427,8 +461,10 @@ } | ||
} | ||
const location = stackTrace && stackTrace.callFrames.length ? { | ||
url: stackTrace.callFrames[0].url, | ||
lineNumber: stackTrace.callFrames[0].lineNumber, | ||
columnNumber: stackTrace.callFrames[0].columnNumber, | ||
} : {}; | ||
const message = new ConsoleMessage(type, textTokens.join(' '), args, location); | ||
const location = stackTrace && stackTrace.callFrames.length | ||
? { | ||
url: stackTrace.callFrames[0].url, | ||
lineNumber: stackTrace.callFrames[0].lineNumber, | ||
columnNumber: stackTrace.callFrames[0].columnNumber, | ||
} | ||
: {}; | ||
const message = new ConsoleMessage_1.ConsoleMessage(type, textTokens.join(' '), args, location); | ||
this.emit(Events_1.Events.Page.Console, message); | ||
@@ -463,6 +499,3 @@ } | ||
async reload(options) { | ||
const result = await Promise.all([ | ||
this.waitForNavigation(options), | ||
this._client.send('Page.reload') | ||
]); | ||
const result = await Promise.all([this.waitForNavigation(options), this._client.send('Page.reload')]); | ||
return result[0]; | ||
@@ -475,12 +508,12 @@ } | ||
if (!this._disconnectPromise) | ||
this._disconnectPromise = new Promise(fulfill => this._client.once(Events_1.Events.CDPSession.Disconnected, () => fulfill(new Error('Target closed')))); | ||
this._disconnectPromise = new Promise((fulfill) => this._client.once(Events_1.Events.CDPSession.Disconnected, () => fulfill(new Error('Target closed')))); | ||
return this._disconnectPromise; | ||
} | ||
async waitForRequest(urlOrPredicate, options = {}) { | ||
const { timeout = this._timeoutSettings.timeout(), } = options; | ||
return helper_1.helper.waitForEvent(this._frameManager.networkManager(), Events_1.Events.NetworkManager.Request, request => { | ||
const { timeout = this._timeoutSettings.timeout() } = options; | ||
return helper_1.helper.waitForEvent(this._frameManager.networkManager(), Events_1.Events.NetworkManager.Request, (request) => { | ||
if (helper_1.helper.isString(urlOrPredicate)) | ||
return (urlOrPredicate === request.url()); | ||
return urlOrPredicate === request.url(); | ||
if (typeof urlOrPredicate === 'function') | ||
return !!(urlOrPredicate(request)); | ||
return !!urlOrPredicate(request); | ||
return false; | ||
@@ -490,8 +523,8 @@ }, timeout, this._sessionClosePromise()); | ||
async waitForResponse(urlOrPredicate, options = {}) { | ||
const { timeout = this._timeoutSettings.timeout(), } = options; | ||
return helper_1.helper.waitForEvent(this._frameManager.networkManager(), Events_1.Events.NetworkManager.Response, response => { | ||
const { timeout = this._timeoutSettings.timeout() } = options; | ||
return helper_1.helper.waitForEvent(this._frameManager.networkManager(), Events_1.Events.NetworkManager.Response, (response) => { | ||
if (helper_1.helper.isString(urlOrPredicate)) | ||
return (urlOrPredicate === response.url()); | ||
return urlOrPredicate === response.url(); | ||
if (typeof urlOrPredicate === 'function') | ||
return !!(urlOrPredicate(response)); | ||
return !!urlOrPredicate(response); | ||
return false; | ||
@@ -523,3 +556,3 @@ }, timeout, this._sessionClosePromise()); | ||
this.setViewport(options.viewport), | ||
this.setUserAgent(options.userAgent) | ||
this.setUserAgent(options.userAgent), | ||
]); | ||
@@ -531,3 +564,5 @@ } | ||
this._javascriptEnabled = enabled; | ||
await this._client.send('Emulation.setScriptExecutionDisabled', { value: !enabled }); | ||
await this._client.send('Emulation.setScriptExecutionDisabled', { | ||
value: !enabled, | ||
}); | ||
} | ||
@@ -539,3 +574,5 @@ async setBypassCSP(enabled) { | ||
helper_1.assert(type === 'screen' || type === 'print' || type === null, 'Unsupported media type: ' + type); | ||
await this._client.send('Emulation.setEmulatedMedia', { media: type || '' }); | ||
await this._client.send('Emulation.setEmulatedMedia', { | ||
media: type || '', | ||
}); | ||
} | ||
@@ -546,3 +583,3 @@ async emulateMediaFeatures(features) { | ||
if (Array.isArray(features)) { | ||
features.every(mediaFeature => { | ||
features.every((mediaFeature) => { | ||
const name = mediaFeature.name; | ||
@@ -552,3 +589,5 @@ helper_1.assert(/^prefers-(?:color-scheme|reduced-motion)$/.test(name), 'Unsupported media feature: ' + name); | ||
}); | ||
await this._client.send('Emulation.setEmulatedMedia', { features: features }); | ||
await this._client.send('Emulation.setEmulatedMedia', { | ||
features: features, | ||
}); | ||
} | ||
@@ -558,3 +597,5 @@ } | ||
try { | ||
await this._client.send('Emulation.setTimezoneOverride', { timezoneId: timezoneId || '' }); | ||
await this._client.send('Emulation.setTimezoneOverride', { | ||
timezoneId: timezoneId || '', | ||
}); | ||
} | ||
@@ -577,7 +618,11 @@ catch (error) { | ||
async evaluate(pageFunction, ...args) { | ||
return this._frameManager.mainFrame().evaluate(pageFunction, ...args); | ||
return this._frameManager | ||
.mainFrame() | ||
.evaluate(pageFunction, ...args); | ||
} | ||
async evaluateOnNewDocument(pageFunction, ...args) { | ||
const source = helper_1.helper.evaluationString(pageFunction, ...args); | ||
await this._client.send('Page.addScriptToEvaluateOnNewDocument', { source }); | ||
await this._client.send('Page.addScriptToEvaluateOnNewDocument', { | ||
source, | ||
}); | ||
} | ||
@@ -606,20 +651,30 @@ async setCacheEnabled(enabled = true) { | ||
if (options.quality) { | ||
helper_1.assert(screenshotType === 'jpeg', 'options.quality is unsupported for the ' + screenshotType + ' screenshots'); | ||
helper_1.assert(typeof options.quality === 'number', 'Expected options.quality to be a number but found ' + (typeof options.quality)); | ||
helper_1.assert(screenshotType === 'jpeg', 'options.quality is unsupported for the ' + | ||
screenshotType + | ||
' screenshots'); | ||
helper_1.assert(typeof options.quality === 'number', 'Expected options.quality to be a number but found ' + | ||
typeof options.quality); | ||
helper_1.assert(Number.isInteger(options.quality), 'Expected options.quality to be an integer'); | ||
helper_1.assert(options.quality >= 0 && options.quality <= 100, 'Expected options.quality to be between 0 and 100 (inclusive), got ' + options.quality); | ||
helper_1.assert(options.quality >= 0 && options.quality <= 100, 'Expected options.quality to be between 0 and 100 (inclusive), got ' + | ||
options.quality); | ||
} | ||
helper_1.assert(!options.clip || !options.fullPage, 'options.clip and options.fullPage are exclusive'); | ||
if (options.clip) { | ||
helper_1.assert(typeof options.clip.x === 'number', 'Expected options.clip.x to be a number but found ' + (typeof options.clip.x)); | ||
helper_1.assert(typeof options.clip.y === 'number', 'Expected options.clip.y to be a number but found ' + (typeof options.clip.y)); | ||
helper_1.assert(typeof options.clip.width === 'number', 'Expected options.clip.width to be a number but found ' + (typeof options.clip.width)); | ||
helper_1.assert(typeof options.clip.height === 'number', 'Expected options.clip.height to be a number but found ' + (typeof options.clip.height)); | ||
helper_1.assert(typeof options.clip.x === 'number', 'Expected options.clip.x to be a number but found ' + | ||
typeof options.clip.x); | ||
helper_1.assert(typeof options.clip.y === 'number', 'Expected options.clip.y to be a number but found ' + | ||
typeof options.clip.y); | ||
helper_1.assert(typeof options.clip.width === 'number', 'Expected options.clip.width to be a number but found ' + | ||
typeof options.clip.width); | ||
helper_1.assert(typeof options.clip.height === 'number', 'Expected options.clip.height to be a number but found ' + | ||
typeof options.clip.height); | ||
helper_1.assert(options.clip.width !== 0, 'Expected options.clip.width not to be 0.'); | ||
helper_1.assert(options.clip.height !== 0, 'Expected options.clip.height not to be 0.'); | ||
} | ||
return this._screenshotTaskQueue.postTask(this._screenshotTask.bind(this, screenshotType, options)); | ||
return this._screenshotTaskQueue.postTask(() => this._screenshotTask(screenshotType, options)); | ||
} | ||
async _screenshotTask(format, options) { | ||
await this._client.send('Target.activateTarget', { targetId: this._target._targetId }); | ||
await this._client.send('Target.activateTarget', { | ||
targetId: this._target._targetId, | ||
}); | ||
let clip = options.clip ? processClip(options.clip) : undefined; | ||
@@ -633,9 +688,23 @@ if (options.fullPage) { | ||
const { isMobile = false, deviceScaleFactor = 1, isLandscape = false } = this._viewport || {}; | ||
const screenOrientation = isLandscape ? { angle: 90, type: 'landscapePrimary' } : { angle: 0, type: 'portraitPrimary' }; | ||
await this._client.send('Emulation.setDeviceMetricsOverride', { mobile: isMobile, width, height, deviceScaleFactor, screenOrientation }); | ||
const screenOrientation = isLandscape | ||
? { angle: 90, type: 'landscapePrimary' } | ||
: { angle: 0, type: 'portraitPrimary' }; | ||
await this._client.send('Emulation.setDeviceMetricsOverride', { | ||
mobile: isMobile, | ||
width, | ||
height, | ||
deviceScaleFactor, | ||
screenOrientation, | ||
}); | ||
} | ||
const shouldSetDefaultBackground = options.omitBackground && format === 'png'; | ||
if (shouldSetDefaultBackground) | ||
await this._client.send('Emulation.setDefaultBackgroundColorOverride', { color: { r: 0, g: 0, b: 0, a: 0 } }); | ||
const result = await this._client.send('Page.captureScreenshot', { format, quality: options.quality, clip }); | ||
await this._client.send('Emulation.setDefaultBackgroundColorOverride', { | ||
color: { r: 0, g: 0, b: 0, a: 0 }, | ||
}); | ||
const result = await this._client.send('Page.captureScreenshot', { | ||
format, | ||
quality: options.quality, | ||
clip, | ||
}); | ||
if (shouldSetDefaultBackground) | ||
@@ -645,3 +714,5 @@ await this._client.send('Emulation.setDefaultBackgroundColorOverride'); | ||
await this.setViewport(this._viewport); | ||
const buffer = options.encoding === 'base64' ? result.data : Buffer.from(result.data, 'base64'); | ||
const buffer = options.encoding === 'base64' | ||
? result.data | ||
: Buffer.from(result.data, 'base64'); | ||
if (options.path) | ||
@@ -659,3 +730,3 @@ await writeFileAsync(options.path, buffer); | ||
async pdf(options = {}) { | ||
const { scale = 1, displayHeaderFooter = false, headerTemplate = '', footerTemplate = '', printBackground = false, landscape = false, pageRanges = '', preferCSSPageSize = false, margin = {}, path = null } = options; | ||
const { scale = 1, displayHeaderFooter = false, headerTemplate = '', footerTemplate = '', printBackground = false, landscape = false, pageRanges = '', preferCSSPageSize = false, margin = {}, path = null, } = options; | ||
let paperWidth = 8.5; | ||
@@ -671,3 +742,4 @@ let paperHeight = 11; | ||
paperWidth = convertPrintParameterToInches(options.width) || paperWidth; | ||
paperHeight = convertPrintParameterToInches(options.height) || paperHeight; | ||
paperHeight = | ||
convertPrintParameterToInches(options.height) || paperHeight; | ||
} | ||
@@ -693,3 +765,3 @@ const marginTop = convertPrintParameterToInches(margin.top) || 0; | ||
pageRanges, | ||
preferCSSPageSize | ||
preferCSSPageSize, | ||
}); | ||
@@ -708,3 +780,5 @@ return await helper_1.helper.readProtocolStream(this._client, result.stream, path); | ||
else { | ||
await this._client._connection.send('Target.closeTarget', { targetId: this._target._targetId }); | ||
await this._client._connection.send('Target.closeTarget', { | ||
targetId: this._target._targetId, | ||
}); | ||
await this._target._isClosedPromise; | ||
@@ -767,6 +841,6 @@ } | ||
const unitToPixels = { | ||
'px': 1, | ||
'in': 96, | ||
'cm': 37.8, | ||
'mm': 3.78 | ||
px: 1, | ||
in: 96, | ||
cm: 37.8, | ||
mm: 3.78, | ||
}; | ||
@@ -779,6 +853,6 @@ function convertPrintParameterToInches(parameter) { | ||
// Treat numbers as pixel values to be aligned with phantom's paperSize. | ||
pixels = /** @type {number} */ (parameter); | ||
pixels = /** @type {number} */ parameter; | ||
} | ||
else if (helper_1.helper.isString(parameter)) { | ||
const text = /** @type {string} */ (parameter); | ||
const text = /** @type {string} */ parameter; | ||
let unit = text.substring(text.length - 2).toLowerCase(); | ||
@@ -800,47 +874,5 @@ let valueText = ''; | ||
else { | ||
throw new Error('page.pdf() Cannot handle parameter type: ' + (typeof parameter)); | ||
throw new Error('page.pdf() Cannot handle parameter type: ' + typeof parameter); | ||
} | ||
return pixels / 96; | ||
} | ||
class ConsoleMessage { | ||
constructor(type, text, args, location = {}) { | ||
this._type = type; | ||
this._text = text; | ||
this._args = args; | ||
this._location = location; | ||
} | ||
type() { | ||
return this._type; | ||
} | ||
text() { | ||
return this._text; | ||
} | ||
args() { | ||
return this._args; | ||
} | ||
location() { | ||
return this._location; | ||
} | ||
} | ||
exports.ConsoleMessage = ConsoleMessage; | ||
class FileChooser { | ||
constructor(client, element, event) { | ||
this._handled = false; | ||
this._client = client; | ||
this._element = element; | ||
this._multiple = event.mode !== 'selectSingle'; | ||
} | ||
isMultiple() { | ||
return this._multiple; | ||
} | ||
async accept(filePaths) { | ||
helper_1.assert(!this._handled, 'Cannot accept FileChooser which is already handled!'); | ||
this._handled = true; | ||
await this._element.uploadFile(...filePaths); | ||
} | ||
async cancel() { | ||
helper_1.assert(!this._handled, 'Cannot cancel FileChooser which is already handled!'); | ||
this._handled = true; | ||
} | ||
} | ||
exports.FileChooser = FileChooser; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.PipeTransport = void 0; | ||
/** | ||
@@ -24,3 +25,3 @@ * Copyright 2018 Google Inc. All rights reserved. | ||
this._eventListeners = [ | ||
helper_1.helper.addEventListener(pipeRead, 'data', buffer => this._dispatch(buffer)), | ||
helper_1.helper.addEventListener(pipeRead, 'data', (buffer) => this._dispatch(buffer)), | ||
helper_1.helper.addEventListener(pipeRead, 'close', () => { | ||
@@ -27,0 +28,0 @@ if (this.onclose) |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Puppeteer = void 0; | ||
/** | ||
@@ -54,3 +55,5 @@ * Copyright 2017 Google Inc. All rights reserved. | ||
get _launcher() { | ||
if (!this._lazyLauncher || this._lazyLauncher.product !== this._productName || this._changedProduct) { | ||
if (!this._lazyLauncher || | ||
this._lazyLauncher.product !== this._productName || | ||
this._changedProduct) { | ||
// @ts-ignore | ||
@@ -57,0 +60,0 @@ // eslint-disable-next-line @typescript-eslint/no-var-requires |
@@ -18,2 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getQueryHandlerAndSelector = exports.clearQueryHandlers = exports.customQueryHandlers = exports.unregisterCustomQueryHandler = exports.registerCustomQueryHandler = void 0; | ||
const _customQueryHandlers = new Map(); | ||
@@ -56,3 +57,3 @@ function registerCustomQueryHandler(name, handler) { | ||
updatedSelector, | ||
queryHandler | ||
queryHandler, | ||
}; | ||
@@ -66,3 +67,3 @@ } | ||
getQueryHandlerAndSelector, | ||
clearQueryHandlers | ||
clearQueryHandlers, | ||
}; |
@@ -18,2 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Target = void 0; | ||
const Events_1 = require("./Events"); | ||
@@ -23,3 +24,3 @@ const Page_1 = require("./Page"); | ||
class Target { | ||
constructor(targetInfo, browserContext, sessionFactory, ignoreHTTPSErrors, defaultViewport, screenshotTaskQueue) { | ||
constructor(targetInfo, browserContext, sessionFactory, ignoreHTTPSErrors, defaultViewport) { | ||
this._targetInfo = targetInfo; | ||
@@ -31,3 +32,2 @@ this._browserContext = browserContext; | ||
this._defaultViewport = defaultViewport; | ||
this._screenshotTaskQueue = screenshotTaskQueue; | ||
/** @type {?Promise<!Puppeteer.Page>} */ | ||
@@ -37,3 +37,3 @@ this._pagePromise = null; | ||
this._workerPromise = null; | ||
this._initializedPromise = new Promise(fulfill => this._initializedCallback = fulfill).then(async (success) => { | ||
this._initializedPromise = new Promise((fulfill) => (this._initializedCallback = fulfill)).then(async (success) => { | ||
if (!success) | ||
@@ -51,4 +51,5 @@ return false; | ||
}); | ||
this._isClosedPromise = new Promise(fulfill => this._closedCallback = fulfill); | ||
this._isInitialized = this._targetInfo.type !== 'page' || this._targetInfo.url !== ''; | ||
this._isClosedPromise = new Promise((fulfill) => (this._closedCallback = fulfill)); | ||
this._isInitialized = | ||
this._targetInfo.type !== 'page' || this._targetInfo.url !== ''; | ||
if (this._isInitialized) | ||
@@ -61,5 +62,6 @@ this._initializedCallback(true); | ||
async page() { | ||
if ((this._targetInfo.type === 'page' || this._targetInfo.type === 'background_page') && !this._pagePromise) { | ||
this._pagePromise = this._sessionFactory() | ||
.then(client => Page_1.Page.create(client, this, this._ignoreHTTPSErrors, this._defaultViewport, this._screenshotTaskQueue)); | ||
if ((this._targetInfo.type === 'page' || | ||
this._targetInfo.type === 'background_page') && | ||
!this._pagePromise) { | ||
this._pagePromise = this._sessionFactory().then((client) => Page_1.Page.create(client, this, this._ignoreHTTPSErrors, this._defaultViewport)); | ||
} | ||
@@ -69,8 +71,8 @@ return this._pagePromise; | ||
async worker() { | ||
if (this._targetInfo.type !== 'service_worker' && this._targetInfo.type !== 'shared_worker') | ||
if (this._targetInfo.type !== 'service_worker' && | ||
this._targetInfo.type !== 'shared_worker') | ||
return null; | ||
if (!this._workerPromise) { | ||
// TODO(einbinder): Make workers send their console logs. | ||
this._workerPromise = this._sessionFactory() | ||
.then(client => new Worker_1.Worker(client, this._targetInfo.url, () => { } /* consoleAPICalled */, () => { } /* exceptionThrown */)); | ||
this._workerPromise = this._sessionFactory().then((client) => new Worker_1.Worker(client, this._targetInfo.url, () => { } /* consoleAPICalled */, () => { } /* exceptionThrown */)); | ||
} | ||
@@ -84,3 +86,7 @@ return this._workerPromise; | ||
const type = this._targetInfo.type; | ||
if (type === 'page' || type === 'background_page' || type === 'service_worker' || type === 'shared_worker' || type === 'browser') | ||
if (type === 'page' || | ||
type === 'background_page' || | ||
type === 'service_worker' || | ||
type === 'shared_worker' || | ||
type === 'browser') | ||
return type; | ||
@@ -103,3 +109,4 @@ return 'other'; | ||
this._targetInfo = targetInfo; | ||
if (!this._isInitialized && (this._targetInfo.type !== 'page' || this._targetInfo.url !== '')) { | ||
if (!this._isInitialized && | ||
(this._targetInfo.type !== 'page' || this._targetInfo.url !== '')) { | ||
this._isInitialized = true; | ||
@@ -106,0 +113,0 @@ this._initializedCallback(true); |
@@ -18,2 +18,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.TimeoutSettings = void 0; | ||
const DEFAULT_TIMEOUT = 30000; | ||
@@ -20,0 +21,0 @@ class TimeoutSettings { |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Tracing = void 0; | ||
/** | ||
@@ -28,6 +29,14 @@ * Copyright 2017 Google Inc. All rights reserved. | ||
const defaultCategories = [ | ||
'-*', 'devtools.timeline', 'v8.execute', 'disabled-by-default-devtools.timeline', | ||
'disabled-by-default-devtools.timeline.frame', 'toplevel', | ||
'blink.console', 'blink.user_timing', 'latencyInfo', 'disabled-by-default-devtools.timeline.stack', | ||
'disabled-by-default-v8.cpu_profiler', 'disabled-by-default-v8.cpu_profiler.hires' | ||
'-*', | ||
'devtools.timeline', | ||
'v8.execute', | ||
'disabled-by-default-devtools.timeline', | ||
'disabled-by-default-devtools.timeline.frame', | ||
'toplevel', | ||
'blink.console', | ||
'blink.user_timing', | ||
'latencyInfo', | ||
'disabled-by-default-devtools.timeline.stack', | ||
'disabled-by-default-v8.cpu_profiler', | ||
'disabled-by-default-v8.cpu_profiler.hires', | ||
]; | ||
@@ -41,3 +50,3 @@ const { path = null, screenshots = false, categories = defaultCategories, } = options; | ||
transferMode: 'ReturnAsStream', | ||
categories: categories.join(',') | ||
categories: categories.join(','), | ||
}); | ||
@@ -47,5 +56,7 @@ } | ||
let fulfill; | ||
const contentPromise = new Promise(x => fulfill = x); | ||
this._client.once('Tracing.tracingComplete', event => { | ||
helper_1.helper.readProtocolStream(this._client, event.stream, this._path).then(fulfill); | ||
const contentPromise = new Promise((x) => (fulfill = x)); | ||
this._client.once('Tracing.tracingComplete', (event) => { | ||
helper_1.helper | ||
.readProtocolStream(this._client, event.stream, this._path) | ||
.then(fulfill); | ||
}); | ||
@@ -52,0 +63,0 @@ await this._client.send('Tracing.end'); |
@@ -18,258 +18,387 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.keyDefinitions = void 0; | ||
exports.keyDefinitions = { | ||
'0': { 'keyCode': 48, 'key': '0', 'code': 'Digit0' }, | ||
'1': { 'keyCode': 49, 'key': '1', 'code': 'Digit1' }, | ||
'2': { 'keyCode': 50, 'key': '2', 'code': 'Digit2' }, | ||
'3': { 'keyCode': 51, 'key': '3', 'code': 'Digit3' }, | ||
'4': { 'keyCode': 52, 'key': '4', 'code': 'Digit4' }, | ||
'5': { 'keyCode': 53, 'key': '5', 'code': 'Digit5' }, | ||
'6': { 'keyCode': 54, 'key': '6', 'code': 'Digit6' }, | ||
'7': { 'keyCode': 55, 'key': '7', 'code': 'Digit7' }, | ||
'8': { 'keyCode': 56, 'key': '8', 'code': 'Digit8' }, | ||
'9': { 'keyCode': 57, 'key': '9', 'code': 'Digit9' }, | ||
'Power': { 'key': 'Power', 'code': 'Power' }, | ||
'Eject': { 'key': 'Eject', 'code': 'Eject' }, | ||
'Abort': { 'keyCode': 3, 'code': 'Abort', 'key': 'Cancel' }, | ||
'Help': { 'keyCode': 6, 'code': 'Help', 'key': 'Help' }, | ||
'Backspace': { 'keyCode': 8, 'code': 'Backspace', 'key': 'Backspace' }, | ||
'Tab': { 'keyCode': 9, 'code': 'Tab', 'key': 'Tab' }, | ||
'Numpad5': { 'keyCode': 12, 'shiftKeyCode': 101, 'key': 'Clear', 'code': 'Numpad5', 'shiftKey': '5', 'location': 3 }, | ||
'NumpadEnter': { 'keyCode': 13, 'code': 'NumpadEnter', 'key': 'Enter', 'text': '\r', 'location': 3 }, | ||
'Enter': { 'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': '\r' }, | ||
'\r': { 'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': '\r' }, | ||
'\n': { 'keyCode': 13, 'code': 'Enter', 'key': 'Enter', 'text': '\r' }, | ||
'ShiftLeft': { 'keyCode': 16, 'code': 'ShiftLeft', 'key': 'Shift', 'location': 1 }, | ||
'ShiftRight': { 'keyCode': 16, 'code': 'ShiftRight', 'key': 'Shift', 'location': 2 }, | ||
'ControlLeft': { 'keyCode': 17, 'code': 'ControlLeft', 'key': 'Control', 'location': 1 }, | ||
'ControlRight': { 'keyCode': 17, 'code': 'ControlRight', 'key': 'Control', 'location': 2 }, | ||
'AltLeft': { 'keyCode': 18, 'code': 'AltLeft', 'key': 'Alt', 'location': 1 }, | ||
'AltRight': { 'keyCode': 18, 'code': 'AltRight', 'key': 'Alt', 'location': 2 }, | ||
'Pause': { 'keyCode': 19, 'code': 'Pause', 'key': 'Pause' }, | ||
'CapsLock': { 'keyCode': 20, 'code': 'CapsLock', 'key': 'CapsLock' }, | ||
'Escape': { 'keyCode': 27, 'code': 'Escape', 'key': 'Escape' }, | ||
'Convert': { 'keyCode': 28, 'code': 'Convert', 'key': 'Convert' }, | ||
'NonConvert': { 'keyCode': 29, 'code': 'NonConvert', 'key': 'NonConvert' }, | ||
'Space': { 'keyCode': 32, 'code': 'Space', 'key': ' ' }, | ||
'Numpad9': { 'keyCode': 33, 'shiftKeyCode': 105, 'key': 'PageUp', 'code': 'Numpad9', 'shiftKey': '9', 'location': 3 }, | ||
'PageUp': { 'keyCode': 33, 'code': 'PageUp', 'key': 'PageUp' }, | ||
'Numpad3': { 'keyCode': 34, 'shiftKeyCode': 99, 'key': 'PageDown', 'code': 'Numpad3', 'shiftKey': '3', 'location': 3 }, | ||
'PageDown': { 'keyCode': 34, 'code': 'PageDown', 'key': 'PageDown' }, | ||
'End': { 'keyCode': 35, 'code': 'End', 'key': 'End' }, | ||
'Numpad1': { 'keyCode': 35, 'shiftKeyCode': 97, 'key': 'End', 'code': 'Numpad1', 'shiftKey': '1', 'location': 3 }, | ||
'Home': { 'keyCode': 36, 'code': 'Home', 'key': 'Home' }, | ||
'Numpad7': { 'keyCode': 36, 'shiftKeyCode': 103, 'key': 'Home', 'code': 'Numpad7', 'shiftKey': '7', 'location': 3 }, | ||
'ArrowLeft': { 'keyCode': 37, 'code': 'ArrowLeft', 'key': 'ArrowLeft' }, | ||
'Numpad4': { 'keyCode': 37, 'shiftKeyCode': 100, 'key': 'ArrowLeft', 'code': 'Numpad4', 'shiftKey': '4', 'location': 3 }, | ||
'Numpad8': { 'keyCode': 38, 'shiftKeyCode': 104, 'key': 'ArrowUp', 'code': 'Numpad8', 'shiftKey': '8', 'location': 3 }, | ||
'ArrowUp': { 'keyCode': 38, 'code': 'ArrowUp', 'key': 'ArrowUp' }, | ||
'ArrowRight': { 'keyCode': 39, 'code': 'ArrowRight', 'key': 'ArrowRight' }, | ||
'Numpad6': { 'keyCode': 39, 'shiftKeyCode': 102, 'key': 'ArrowRight', 'code': 'Numpad6', 'shiftKey': '6', 'location': 3 }, | ||
'Numpad2': { 'keyCode': 40, 'shiftKeyCode': 98, 'key': 'ArrowDown', 'code': 'Numpad2', 'shiftKey': '2', 'location': 3 }, | ||
'ArrowDown': { 'keyCode': 40, 'code': 'ArrowDown', 'key': 'ArrowDown' }, | ||
'Select': { 'keyCode': 41, 'code': 'Select', 'key': 'Select' }, | ||
'Open': { 'keyCode': 43, 'code': 'Open', 'key': 'Execute' }, | ||
'PrintScreen': { 'keyCode': 44, 'code': 'PrintScreen', 'key': 'PrintScreen' }, | ||
'Insert': { 'keyCode': 45, 'code': 'Insert', 'key': 'Insert' }, | ||
'Numpad0': { 'keyCode': 45, 'shiftKeyCode': 96, 'key': 'Insert', 'code': 'Numpad0', 'shiftKey': '0', 'location': 3 }, | ||
'Delete': { 'keyCode': 46, 'code': 'Delete', 'key': 'Delete' }, | ||
'NumpadDecimal': { 'keyCode': 46, 'shiftKeyCode': 110, 'code': 'NumpadDecimal', 'key': '\u0000', 'shiftKey': '.', 'location': 3 }, | ||
'Digit0': { 'keyCode': 48, 'code': 'Digit0', 'shiftKey': ')', 'key': '0' }, | ||
'Digit1': { 'keyCode': 49, 'code': 'Digit1', 'shiftKey': '!', 'key': '1' }, | ||
'Digit2': { 'keyCode': 50, 'code': 'Digit2', 'shiftKey': '@', 'key': '2' }, | ||
'Digit3': { 'keyCode': 51, 'code': 'Digit3', 'shiftKey': '#', 'key': '3' }, | ||
'Digit4': { 'keyCode': 52, 'code': 'Digit4', 'shiftKey': '$', 'key': '4' }, | ||
'Digit5': { 'keyCode': 53, 'code': 'Digit5', 'shiftKey': '%', 'key': '5' }, | ||
'Digit6': { 'keyCode': 54, 'code': 'Digit6', 'shiftKey': '^', 'key': '6' }, | ||
'Digit7': { 'keyCode': 55, 'code': 'Digit7', 'shiftKey': '&', 'key': '7' }, | ||
'Digit8': { 'keyCode': 56, 'code': 'Digit8', 'shiftKey': '*', 'key': '8' }, | ||
'Digit9': { 'keyCode': 57, 'code': 'Digit9', 'shiftKey': '\(', 'key': '9' }, | ||
'KeyA': { 'keyCode': 65, 'code': 'KeyA', 'shiftKey': 'A', 'key': 'a' }, | ||
'KeyB': { 'keyCode': 66, 'code': 'KeyB', 'shiftKey': 'B', 'key': 'b' }, | ||
'KeyC': { 'keyCode': 67, 'code': 'KeyC', 'shiftKey': 'C', 'key': 'c' }, | ||
'KeyD': { 'keyCode': 68, 'code': 'KeyD', 'shiftKey': 'D', 'key': 'd' }, | ||
'KeyE': { 'keyCode': 69, 'code': 'KeyE', 'shiftKey': 'E', 'key': 'e' }, | ||
'KeyF': { 'keyCode': 70, 'code': 'KeyF', 'shiftKey': 'F', 'key': 'f' }, | ||
'KeyG': { 'keyCode': 71, 'code': 'KeyG', 'shiftKey': 'G', 'key': 'g' }, | ||
'KeyH': { 'keyCode': 72, 'code': 'KeyH', 'shiftKey': 'H', 'key': 'h' }, | ||
'KeyI': { 'keyCode': 73, 'code': 'KeyI', 'shiftKey': 'I', 'key': 'i' }, | ||
'KeyJ': { 'keyCode': 74, 'code': 'KeyJ', 'shiftKey': 'J', 'key': 'j' }, | ||
'KeyK': { 'keyCode': 75, 'code': 'KeyK', 'shiftKey': 'K', 'key': 'k' }, | ||
'KeyL': { 'keyCode': 76, 'code': 'KeyL', 'shiftKey': 'L', 'key': 'l' }, | ||
'KeyM': { 'keyCode': 77, 'code': 'KeyM', 'shiftKey': 'M', 'key': 'm' }, | ||
'KeyN': { 'keyCode': 78, 'code': 'KeyN', 'shiftKey': 'N', 'key': 'n' }, | ||
'KeyO': { 'keyCode': 79, 'code': 'KeyO', 'shiftKey': 'O', 'key': 'o' }, | ||
'KeyP': { 'keyCode': 80, 'code': 'KeyP', 'shiftKey': 'P', 'key': 'p' }, | ||
'KeyQ': { 'keyCode': 81, 'code': 'KeyQ', 'shiftKey': 'Q', 'key': 'q' }, | ||
'KeyR': { 'keyCode': 82, 'code': 'KeyR', 'shiftKey': 'R', 'key': 'r' }, | ||
'KeyS': { 'keyCode': 83, 'code': 'KeyS', 'shiftKey': 'S', 'key': 's' }, | ||
'KeyT': { 'keyCode': 84, 'code': 'KeyT', 'shiftKey': 'T', 'key': 't' }, | ||
'KeyU': { 'keyCode': 85, 'code': 'KeyU', 'shiftKey': 'U', 'key': 'u' }, | ||
'KeyV': { 'keyCode': 86, 'code': 'KeyV', 'shiftKey': 'V', 'key': 'v' }, | ||
'KeyW': { 'keyCode': 87, 'code': 'KeyW', 'shiftKey': 'W', 'key': 'w' }, | ||
'KeyX': { 'keyCode': 88, 'code': 'KeyX', 'shiftKey': 'X', 'key': 'x' }, | ||
'KeyY': { 'keyCode': 89, 'code': 'KeyY', 'shiftKey': 'Y', 'key': 'y' }, | ||
'KeyZ': { 'keyCode': 90, 'code': 'KeyZ', 'shiftKey': 'Z', 'key': 'z' }, | ||
'MetaLeft': { 'keyCode': 91, 'code': 'MetaLeft', 'key': 'Meta', 'location': 1 }, | ||
'MetaRight': { 'keyCode': 92, 'code': 'MetaRight', 'key': 'Meta', 'location': 2 }, | ||
'ContextMenu': { 'keyCode': 93, 'code': 'ContextMenu', 'key': 'ContextMenu' }, | ||
'NumpadMultiply': { 'keyCode': 106, 'code': 'NumpadMultiply', 'key': '*', 'location': 3 }, | ||
'NumpadAdd': { 'keyCode': 107, 'code': 'NumpadAdd', 'key': '+', 'location': 3 }, | ||
'NumpadSubtract': { 'keyCode': 109, 'code': 'NumpadSubtract', 'key': '-', 'location': 3 }, | ||
'NumpadDivide': { 'keyCode': 111, 'code': 'NumpadDivide', 'key': '/', 'location': 3 }, | ||
'F1': { 'keyCode': 112, 'code': 'F1', 'key': 'F1' }, | ||
'F2': { 'keyCode': 113, 'code': 'F2', 'key': 'F2' }, | ||
'F3': { 'keyCode': 114, 'code': 'F3', 'key': 'F3' }, | ||
'F4': { 'keyCode': 115, 'code': 'F4', 'key': 'F4' }, | ||
'F5': { 'keyCode': 116, 'code': 'F5', 'key': 'F5' }, | ||
'F6': { 'keyCode': 117, 'code': 'F6', 'key': 'F6' }, | ||
'F7': { 'keyCode': 118, 'code': 'F7', 'key': 'F7' }, | ||
'F8': { 'keyCode': 119, 'code': 'F8', 'key': 'F8' }, | ||
'F9': { 'keyCode': 120, 'code': 'F9', 'key': 'F9' }, | ||
'F10': { 'keyCode': 121, 'code': 'F10', 'key': 'F10' }, | ||
'F11': { 'keyCode': 122, 'code': 'F11', 'key': 'F11' }, | ||
'F12': { 'keyCode': 123, 'code': 'F12', 'key': 'F12' }, | ||
'F13': { 'keyCode': 124, 'code': 'F13', 'key': 'F13' }, | ||
'F14': { 'keyCode': 125, 'code': 'F14', 'key': 'F14' }, | ||
'F15': { 'keyCode': 126, 'code': 'F15', 'key': 'F15' }, | ||
'F16': { 'keyCode': 127, 'code': 'F16', 'key': 'F16' }, | ||
'F17': { 'keyCode': 128, 'code': 'F17', 'key': 'F17' }, | ||
'F18': { 'keyCode': 129, 'code': 'F18', 'key': 'F18' }, | ||
'F19': { 'keyCode': 130, 'code': 'F19', 'key': 'F19' }, | ||
'F20': { 'keyCode': 131, 'code': 'F20', 'key': 'F20' }, | ||
'F21': { 'keyCode': 132, 'code': 'F21', 'key': 'F21' }, | ||
'F22': { 'keyCode': 133, 'code': 'F22', 'key': 'F22' }, | ||
'F23': { 'keyCode': 134, 'code': 'F23', 'key': 'F23' }, | ||
'F24': { 'keyCode': 135, 'code': 'F24', 'key': 'F24' }, | ||
'NumLock': { 'keyCode': 144, 'code': 'NumLock', 'key': 'NumLock' }, | ||
'ScrollLock': { 'keyCode': 145, 'code': 'ScrollLock', 'key': 'ScrollLock' }, | ||
'AudioVolumeMute': { 'keyCode': 173, 'code': 'AudioVolumeMute', 'key': 'AudioVolumeMute' }, | ||
'AudioVolumeDown': { 'keyCode': 174, 'code': 'AudioVolumeDown', 'key': 'AudioVolumeDown' }, | ||
'AudioVolumeUp': { 'keyCode': 175, 'code': 'AudioVolumeUp', 'key': 'AudioVolumeUp' }, | ||
'MediaTrackNext': { 'keyCode': 176, 'code': 'MediaTrackNext', 'key': 'MediaTrackNext' }, | ||
'MediaTrackPrevious': { 'keyCode': 177, 'code': 'MediaTrackPrevious', 'key': 'MediaTrackPrevious' }, | ||
'MediaStop': { 'keyCode': 178, 'code': 'MediaStop', 'key': 'MediaStop' }, | ||
'MediaPlayPause': { 'keyCode': 179, 'code': 'MediaPlayPause', 'key': 'MediaPlayPause' }, | ||
'Semicolon': { 'keyCode': 186, 'code': 'Semicolon', 'shiftKey': ':', 'key': ';' }, | ||
'Equal': { 'keyCode': 187, 'code': 'Equal', 'shiftKey': '+', 'key': '=' }, | ||
'NumpadEqual': { 'keyCode': 187, 'code': 'NumpadEqual', 'key': '=', 'location': 3 }, | ||
'Comma': { 'keyCode': 188, 'code': 'Comma', 'shiftKey': '\<', 'key': ',' }, | ||
'Minus': { 'keyCode': 189, 'code': 'Minus', 'shiftKey': '_', 'key': '-' }, | ||
'Period': { 'keyCode': 190, 'code': 'Period', 'shiftKey': '>', 'key': '.' }, | ||
'Slash': { 'keyCode': 191, 'code': 'Slash', 'shiftKey': '?', 'key': '/' }, | ||
'Backquote': { 'keyCode': 192, 'code': 'Backquote', 'shiftKey': '~', 'key': '`' }, | ||
'BracketLeft': { 'keyCode': 219, 'code': 'BracketLeft', 'shiftKey': '{', 'key': '[' }, | ||
'Backslash': { 'keyCode': 220, 'code': 'Backslash', 'shiftKey': '|', 'key': '\\' }, | ||
'BracketRight': { 'keyCode': 221, 'code': 'BracketRight', 'shiftKey': '}', 'key': ']' }, | ||
'Quote': { 'keyCode': 222, 'code': 'Quote', 'shiftKey': '"', 'key': '\'' }, | ||
'AltGraph': { 'keyCode': 225, 'code': 'AltGraph', 'key': 'AltGraph' }, | ||
'Props': { 'keyCode': 247, 'code': 'Props', 'key': 'CrSel' }, | ||
'Cancel': { 'keyCode': 3, 'key': 'Cancel', 'code': 'Abort' }, | ||
'Clear': { 'keyCode': 12, 'key': 'Clear', 'code': 'Numpad5', 'location': 3 }, | ||
'Shift': { 'keyCode': 16, 'key': 'Shift', 'code': 'ShiftLeft', 'location': 1 }, | ||
'Control': { 'keyCode': 17, 'key': 'Control', 'code': 'ControlLeft', 'location': 1 }, | ||
'Alt': { 'keyCode': 18, 'key': 'Alt', 'code': 'AltLeft', 'location': 1 }, | ||
'Accept': { 'keyCode': 30, 'key': 'Accept' }, | ||
'ModeChange': { 'keyCode': 31, 'key': 'ModeChange' }, | ||
' ': { 'keyCode': 32, 'key': ' ', 'code': 'Space' }, | ||
'Print': { 'keyCode': 42, 'key': 'Print' }, | ||
'Execute': { 'keyCode': 43, 'key': 'Execute', 'code': 'Open' }, | ||
'\u0000': { 'keyCode': 46, 'key': '\u0000', 'code': 'NumpadDecimal', 'location': 3 }, | ||
'a': { 'keyCode': 65, 'key': 'a', 'code': 'KeyA' }, | ||
'b': { 'keyCode': 66, 'key': 'b', 'code': 'KeyB' }, | ||
'c': { 'keyCode': 67, 'key': 'c', 'code': 'KeyC' }, | ||
'd': { 'keyCode': 68, 'key': 'd', 'code': 'KeyD' }, | ||
'e': { 'keyCode': 69, 'key': 'e', 'code': 'KeyE' }, | ||
'f': { 'keyCode': 70, 'key': 'f', 'code': 'KeyF' }, | ||
'g': { 'keyCode': 71, 'key': 'g', 'code': 'KeyG' }, | ||
'h': { 'keyCode': 72, 'key': 'h', 'code': 'KeyH' }, | ||
'i': { 'keyCode': 73, 'key': 'i', 'code': 'KeyI' }, | ||
'j': { 'keyCode': 74, 'key': 'j', 'code': 'KeyJ' }, | ||
'k': { 'keyCode': 75, 'key': 'k', 'code': 'KeyK' }, | ||
'l': { 'keyCode': 76, 'key': 'l', 'code': 'KeyL' }, | ||
'm': { 'keyCode': 77, 'key': 'm', 'code': 'KeyM' }, | ||
'n': { 'keyCode': 78, 'key': 'n', 'code': 'KeyN' }, | ||
'o': { 'keyCode': 79, 'key': 'o', 'code': 'KeyO' }, | ||
'p': { 'keyCode': 80, 'key': 'p', 'code': 'KeyP' }, | ||
'q': { 'keyCode': 81, 'key': 'q', 'code': 'KeyQ' }, | ||
'r': { 'keyCode': 82, 'key': 'r', 'code': 'KeyR' }, | ||
's': { 'keyCode': 83, 'key': 's', 'code': 'KeyS' }, | ||
't': { 'keyCode': 84, 'key': 't', 'code': 'KeyT' }, | ||
'u': { 'keyCode': 85, 'key': 'u', 'code': 'KeyU' }, | ||
'v': { 'keyCode': 86, 'key': 'v', 'code': 'KeyV' }, | ||
'w': { 'keyCode': 87, 'key': 'w', 'code': 'KeyW' }, | ||
'x': { 'keyCode': 88, 'key': 'x', 'code': 'KeyX' }, | ||
'y': { 'keyCode': 89, 'key': 'y', 'code': 'KeyY' }, | ||
'z': { 'keyCode': 90, 'key': 'z', 'code': 'KeyZ' }, | ||
'Meta': { 'keyCode': 91, 'key': 'Meta', 'code': 'MetaLeft', 'location': 1 }, | ||
'*': { 'keyCode': 106, 'key': '*', 'code': 'NumpadMultiply', 'location': 3 }, | ||
'+': { 'keyCode': 107, 'key': '+', 'code': 'NumpadAdd', 'location': 3 }, | ||
'-': { 'keyCode': 109, 'key': '-', 'code': 'NumpadSubtract', 'location': 3 }, | ||
'/': { 'keyCode': 111, 'key': '/', 'code': 'NumpadDivide', 'location': 3 }, | ||
';': { 'keyCode': 186, 'key': ';', 'code': 'Semicolon' }, | ||
'=': { 'keyCode': 187, 'key': '=', 'code': 'Equal' }, | ||
',': { 'keyCode': 188, 'key': ',', 'code': 'Comma' }, | ||
'.': { 'keyCode': 190, 'key': '.', 'code': 'Period' }, | ||
'`': { 'keyCode': 192, 'key': '`', 'code': 'Backquote' }, | ||
'[': { 'keyCode': 219, 'key': '[', 'code': 'BracketLeft' }, | ||
'\\': { 'keyCode': 220, 'key': '\\', 'code': 'Backslash' }, | ||
']': { 'keyCode': 221, 'key': ']', 'code': 'BracketRight' }, | ||
'\'': { 'keyCode': 222, 'key': '\'', 'code': 'Quote' }, | ||
'Attn': { 'keyCode': 246, 'key': 'Attn' }, | ||
'CrSel': { 'keyCode': 247, 'key': 'CrSel', 'code': 'Props' }, | ||
'ExSel': { 'keyCode': 248, 'key': 'ExSel' }, | ||
'EraseEof': { 'keyCode': 249, 'key': 'EraseEof' }, | ||
'Play': { 'keyCode': 250, 'key': 'Play' }, | ||
'ZoomOut': { 'keyCode': 251, 'key': 'ZoomOut' }, | ||
')': { 'keyCode': 48, 'key': ')', 'code': 'Digit0' }, | ||
'!': { 'keyCode': 49, 'key': '!', 'code': 'Digit1' }, | ||
'@': { 'keyCode': 50, 'key': '@', 'code': 'Digit2' }, | ||
'#': { 'keyCode': 51, 'key': '#', 'code': 'Digit3' }, | ||
'$': { 'keyCode': 52, 'key': '$', 'code': 'Digit4' }, | ||
'%': { 'keyCode': 53, 'key': '%', 'code': 'Digit5' }, | ||
'^': { 'keyCode': 54, 'key': '^', 'code': 'Digit6' }, | ||
'&': { 'keyCode': 55, 'key': '&', 'code': 'Digit7' }, | ||
'(': { 'keyCode': 57, 'key': '\(', 'code': 'Digit9' }, | ||
'A': { 'keyCode': 65, 'key': 'A', 'code': 'KeyA' }, | ||
'B': { 'keyCode': 66, 'key': 'B', 'code': 'KeyB' }, | ||
'C': { 'keyCode': 67, 'key': 'C', 'code': 'KeyC' }, | ||
'D': { 'keyCode': 68, 'key': 'D', 'code': 'KeyD' }, | ||
'E': { 'keyCode': 69, 'key': 'E', 'code': 'KeyE' }, | ||
'F': { 'keyCode': 70, 'key': 'F', 'code': 'KeyF' }, | ||
'G': { 'keyCode': 71, 'key': 'G', 'code': 'KeyG' }, | ||
'H': { 'keyCode': 72, 'key': 'H', 'code': 'KeyH' }, | ||
'I': { 'keyCode': 73, 'key': 'I', 'code': 'KeyI' }, | ||
'J': { 'keyCode': 74, 'key': 'J', 'code': 'KeyJ' }, | ||
'K': { 'keyCode': 75, 'key': 'K', 'code': 'KeyK' }, | ||
'L': { 'keyCode': 76, 'key': 'L', 'code': 'KeyL' }, | ||
'M': { 'keyCode': 77, 'key': 'M', 'code': 'KeyM' }, | ||
'N': { 'keyCode': 78, 'key': 'N', 'code': 'KeyN' }, | ||
'O': { 'keyCode': 79, 'key': 'O', 'code': 'KeyO' }, | ||
'P': { 'keyCode': 80, 'key': 'P', 'code': 'KeyP' }, | ||
'Q': { 'keyCode': 81, 'key': 'Q', 'code': 'KeyQ' }, | ||
'R': { 'keyCode': 82, 'key': 'R', 'code': 'KeyR' }, | ||
'S': { 'keyCode': 83, 'key': 'S', 'code': 'KeyS' }, | ||
'T': { 'keyCode': 84, 'key': 'T', 'code': 'KeyT' }, | ||
'U': { 'keyCode': 85, 'key': 'U', 'code': 'KeyU' }, | ||
'V': { 'keyCode': 86, 'key': 'V', 'code': 'KeyV' }, | ||
'W': { 'keyCode': 87, 'key': 'W', 'code': 'KeyW' }, | ||
'X': { 'keyCode': 88, 'key': 'X', 'code': 'KeyX' }, | ||
'Y': { 'keyCode': 89, 'key': 'Y', 'code': 'KeyY' }, | ||
'Z': { 'keyCode': 90, 'key': 'Z', 'code': 'KeyZ' }, | ||
':': { 'keyCode': 186, 'key': ':', 'code': 'Semicolon' }, | ||
'<': { 'keyCode': 188, 'key': '\<', 'code': 'Comma' }, | ||
'_': { 'keyCode': 189, 'key': '_', 'code': 'Minus' }, | ||
'>': { 'keyCode': 190, 'key': '>', 'code': 'Period' }, | ||
'?': { 'keyCode': 191, 'key': '?', 'code': 'Slash' }, | ||
'~': { 'keyCode': 192, 'key': '~', 'code': 'Backquote' }, | ||
'{': { 'keyCode': 219, 'key': '{', 'code': 'BracketLeft' }, | ||
'|': { 'keyCode': 220, 'key': '|', 'code': 'Backslash' }, | ||
'}': { 'keyCode': 221, 'key': '}', 'code': 'BracketRight' }, | ||
'"': { 'keyCode': 222, 'key': '"', 'code': 'Quote' }, | ||
'SoftLeft': { 'key': 'SoftLeft', 'code': 'SoftLeft', 'location': 4 }, | ||
'SoftRight': { 'key': 'SoftRight', 'code': 'SoftRight', 'location': 4 }, | ||
'Camera': { 'keyCode': 44, 'key': 'Camera', 'code': 'Camera', 'location': 4 }, | ||
'Call': { 'key': 'Call', 'code': 'Call', 'location': 4 }, | ||
'EndCall': { 'keyCode': 95, 'key': 'EndCall', 'code': 'EndCall', 'location': 4 }, | ||
'VolumeDown': { 'keyCode': 182, 'key': 'VolumeDown', 'code': 'VolumeDown', 'location': 4 }, | ||
'VolumeUp': { 'keyCode': 183, 'key': 'VolumeUp', 'code': 'VolumeUp', 'location': 4 }, | ||
'0': { keyCode: 48, key: '0', code: 'Digit0' }, | ||
'1': { keyCode: 49, key: '1', code: 'Digit1' }, | ||
'2': { keyCode: 50, key: '2', code: 'Digit2' }, | ||
'3': { keyCode: 51, key: '3', code: 'Digit3' }, | ||
'4': { keyCode: 52, key: '4', code: 'Digit4' }, | ||
'5': { keyCode: 53, key: '5', code: 'Digit5' }, | ||
'6': { keyCode: 54, key: '6', code: 'Digit6' }, | ||
'7': { keyCode: 55, key: '7', code: 'Digit7' }, | ||
'8': { keyCode: 56, key: '8', code: 'Digit8' }, | ||
'9': { keyCode: 57, key: '9', code: 'Digit9' }, | ||
Power: { key: 'Power', code: 'Power' }, | ||
Eject: { key: 'Eject', code: 'Eject' }, | ||
Abort: { keyCode: 3, code: 'Abort', key: 'Cancel' }, | ||
Help: { keyCode: 6, code: 'Help', key: 'Help' }, | ||
Backspace: { keyCode: 8, code: 'Backspace', key: 'Backspace' }, | ||
Tab: { keyCode: 9, code: 'Tab', key: 'Tab' }, | ||
Numpad5: { | ||
keyCode: 12, | ||
shiftKeyCode: 101, | ||
key: 'Clear', | ||
code: 'Numpad5', | ||
shiftKey: '5', | ||
location: 3, | ||
}, | ||
NumpadEnter: { | ||
keyCode: 13, | ||
code: 'NumpadEnter', | ||
key: 'Enter', | ||
text: '\r', | ||
location: 3, | ||
}, | ||
Enter: { keyCode: 13, code: 'Enter', key: 'Enter', text: '\r' }, | ||
'\r': { keyCode: 13, code: 'Enter', key: 'Enter', text: '\r' }, | ||
'\n': { keyCode: 13, code: 'Enter', key: 'Enter', text: '\r' }, | ||
ShiftLeft: { keyCode: 16, code: 'ShiftLeft', key: 'Shift', location: 1 }, | ||
ShiftRight: { keyCode: 16, code: 'ShiftRight', key: 'Shift', location: 2 }, | ||
ControlLeft: { | ||
keyCode: 17, | ||
code: 'ControlLeft', | ||
key: 'Control', | ||
location: 1, | ||
}, | ||
ControlRight: { | ||
keyCode: 17, | ||
code: 'ControlRight', | ||
key: 'Control', | ||
location: 2, | ||
}, | ||
AltLeft: { keyCode: 18, code: 'AltLeft', key: 'Alt', location: 1 }, | ||
AltRight: { keyCode: 18, code: 'AltRight', key: 'Alt', location: 2 }, | ||
Pause: { keyCode: 19, code: 'Pause', key: 'Pause' }, | ||
CapsLock: { keyCode: 20, code: 'CapsLock', key: 'CapsLock' }, | ||
Escape: { keyCode: 27, code: 'Escape', key: 'Escape' }, | ||
Convert: { keyCode: 28, code: 'Convert', key: 'Convert' }, | ||
NonConvert: { keyCode: 29, code: 'NonConvert', key: 'NonConvert' }, | ||
Space: { keyCode: 32, code: 'Space', key: ' ' }, | ||
Numpad9: { | ||
keyCode: 33, | ||
shiftKeyCode: 105, | ||
key: 'PageUp', | ||
code: 'Numpad9', | ||
shiftKey: '9', | ||
location: 3, | ||
}, | ||
PageUp: { keyCode: 33, code: 'PageUp', key: 'PageUp' }, | ||
Numpad3: { | ||
keyCode: 34, | ||
shiftKeyCode: 99, | ||
key: 'PageDown', | ||
code: 'Numpad3', | ||
shiftKey: '3', | ||
location: 3, | ||
}, | ||
PageDown: { keyCode: 34, code: 'PageDown', key: 'PageDown' }, | ||
End: { keyCode: 35, code: 'End', key: 'End' }, | ||
Numpad1: { | ||
keyCode: 35, | ||
shiftKeyCode: 97, | ||
key: 'End', | ||
code: 'Numpad1', | ||
shiftKey: '1', | ||
location: 3, | ||
}, | ||
Home: { keyCode: 36, code: 'Home', key: 'Home' }, | ||
Numpad7: { | ||
keyCode: 36, | ||
shiftKeyCode: 103, | ||
key: 'Home', | ||
code: 'Numpad7', | ||
shiftKey: '7', | ||
location: 3, | ||
}, | ||
ArrowLeft: { keyCode: 37, code: 'ArrowLeft', key: 'ArrowLeft' }, | ||
Numpad4: { | ||
keyCode: 37, | ||
shiftKeyCode: 100, | ||
key: 'ArrowLeft', | ||
code: 'Numpad4', | ||
shiftKey: '4', | ||
location: 3, | ||
}, | ||
Numpad8: { | ||
keyCode: 38, | ||
shiftKeyCode: 104, | ||
key: 'ArrowUp', | ||
code: 'Numpad8', | ||
shiftKey: '8', | ||
location: 3, | ||
}, | ||
ArrowUp: { keyCode: 38, code: 'ArrowUp', key: 'ArrowUp' }, | ||
ArrowRight: { keyCode: 39, code: 'ArrowRight', key: 'ArrowRight' }, | ||
Numpad6: { | ||
keyCode: 39, | ||
shiftKeyCode: 102, | ||
key: 'ArrowRight', | ||
code: 'Numpad6', | ||
shiftKey: '6', | ||
location: 3, | ||
}, | ||
Numpad2: { | ||
keyCode: 40, | ||
shiftKeyCode: 98, | ||
key: 'ArrowDown', | ||
code: 'Numpad2', | ||
shiftKey: '2', | ||
location: 3, | ||
}, | ||
ArrowDown: { keyCode: 40, code: 'ArrowDown', key: 'ArrowDown' }, | ||
Select: { keyCode: 41, code: 'Select', key: 'Select' }, | ||
Open: { keyCode: 43, code: 'Open', key: 'Execute' }, | ||
PrintScreen: { keyCode: 44, code: 'PrintScreen', key: 'PrintScreen' }, | ||
Insert: { keyCode: 45, code: 'Insert', key: 'Insert' }, | ||
Numpad0: { | ||
keyCode: 45, | ||
shiftKeyCode: 96, | ||
key: 'Insert', | ||
code: 'Numpad0', | ||
shiftKey: '0', | ||
location: 3, | ||
}, | ||
Delete: { keyCode: 46, code: 'Delete', key: 'Delete' }, | ||
NumpadDecimal: { | ||
keyCode: 46, | ||
shiftKeyCode: 110, | ||
code: 'NumpadDecimal', | ||
key: '\u0000', | ||
shiftKey: '.', | ||
location: 3, | ||
}, | ||
Digit0: { keyCode: 48, code: 'Digit0', shiftKey: ')', key: '0' }, | ||
Digit1: { keyCode: 49, code: 'Digit1', shiftKey: '!', key: '1' }, | ||
Digit2: { keyCode: 50, code: 'Digit2', shiftKey: '@', key: '2' }, | ||
Digit3: { keyCode: 51, code: 'Digit3', shiftKey: '#', key: '3' }, | ||
Digit4: { keyCode: 52, code: 'Digit4', shiftKey: '$', key: '4' }, | ||
Digit5: { keyCode: 53, code: 'Digit5', shiftKey: '%', key: '5' }, | ||
Digit6: { keyCode: 54, code: 'Digit6', shiftKey: '^', key: '6' }, | ||
Digit7: { keyCode: 55, code: 'Digit7', shiftKey: '&', key: '7' }, | ||
Digit8: { keyCode: 56, code: 'Digit8', shiftKey: '*', key: '8' }, | ||
Digit9: { keyCode: 57, code: 'Digit9', shiftKey: '(', key: '9' }, | ||
KeyA: { keyCode: 65, code: 'KeyA', shiftKey: 'A', key: 'a' }, | ||
KeyB: { keyCode: 66, code: 'KeyB', shiftKey: 'B', key: 'b' }, | ||
KeyC: { keyCode: 67, code: 'KeyC', shiftKey: 'C', key: 'c' }, | ||
KeyD: { keyCode: 68, code: 'KeyD', shiftKey: 'D', key: 'd' }, | ||
KeyE: { keyCode: 69, code: 'KeyE', shiftKey: 'E', key: 'e' }, | ||
KeyF: { keyCode: 70, code: 'KeyF', shiftKey: 'F', key: 'f' }, | ||
KeyG: { keyCode: 71, code: 'KeyG', shiftKey: 'G', key: 'g' }, | ||
KeyH: { keyCode: 72, code: 'KeyH', shiftKey: 'H', key: 'h' }, | ||
KeyI: { keyCode: 73, code: 'KeyI', shiftKey: 'I', key: 'i' }, | ||
KeyJ: { keyCode: 74, code: 'KeyJ', shiftKey: 'J', key: 'j' }, | ||
KeyK: { keyCode: 75, code: 'KeyK', shiftKey: 'K', key: 'k' }, | ||
KeyL: { keyCode: 76, code: 'KeyL', shiftKey: 'L', key: 'l' }, | ||
KeyM: { keyCode: 77, code: 'KeyM', shiftKey: 'M', key: 'm' }, | ||
KeyN: { keyCode: 78, code: 'KeyN', shiftKey: 'N', key: 'n' }, | ||
KeyO: { keyCode: 79, code: 'KeyO', shiftKey: 'O', key: 'o' }, | ||
KeyP: { keyCode: 80, code: 'KeyP', shiftKey: 'P', key: 'p' }, | ||
KeyQ: { keyCode: 81, code: 'KeyQ', shiftKey: 'Q', key: 'q' }, | ||
KeyR: { keyCode: 82, code: 'KeyR', shiftKey: 'R', key: 'r' }, | ||
KeyS: { keyCode: 83, code: 'KeyS', shiftKey: 'S', key: 's' }, | ||
KeyT: { keyCode: 84, code: 'KeyT', shiftKey: 'T', key: 't' }, | ||
KeyU: { keyCode: 85, code: 'KeyU', shiftKey: 'U', key: 'u' }, | ||
KeyV: { keyCode: 86, code: 'KeyV', shiftKey: 'V', key: 'v' }, | ||
KeyW: { keyCode: 87, code: 'KeyW', shiftKey: 'W', key: 'w' }, | ||
KeyX: { keyCode: 88, code: 'KeyX', shiftKey: 'X', key: 'x' }, | ||
KeyY: { keyCode: 89, code: 'KeyY', shiftKey: 'Y', key: 'y' }, | ||
KeyZ: { keyCode: 90, code: 'KeyZ', shiftKey: 'Z', key: 'z' }, | ||
MetaLeft: { keyCode: 91, code: 'MetaLeft', key: 'Meta', location: 1 }, | ||
MetaRight: { keyCode: 92, code: 'MetaRight', key: 'Meta', location: 2 }, | ||
ContextMenu: { keyCode: 93, code: 'ContextMenu', key: 'ContextMenu' }, | ||
NumpadMultiply: { | ||
keyCode: 106, | ||
code: 'NumpadMultiply', | ||
key: '*', | ||
location: 3, | ||
}, | ||
NumpadAdd: { keyCode: 107, code: 'NumpadAdd', key: '+', location: 3 }, | ||
NumpadSubtract: { | ||
keyCode: 109, | ||
code: 'NumpadSubtract', | ||
key: '-', | ||
location: 3, | ||
}, | ||
NumpadDivide: { keyCode: 111, code: 'NumpadDivide', key: '/', location: 3 }, | ||
F1: { keyCode: 112, code: 'F1', key: 'F1' }, | ||
F2: { keyCode: 113, code: 'F2', key: 'F2' }, | ||
F3: { keyCode: 114, code: 'F3', key: 'F3' }, | ||
F4: { keyCode: 115, code: 'F4', key: 'F4' }, | ||
F5: { keyCode: 116, code: 'F5', key: 'F5' }, | ||
F6: { keyCode: 117, code: 'F6', key: 'F6' }, | ||
F7: { keyCode: 118, code: 'F7', key: 'F7' }, | ||
F8: { keyCode: 119, code: 'F8', key: 'F8' }, | ||
F9: { keyCode: 120, code: 'F9', key: 'F9' }, | ||
F10: { keyCode: 121, code: 'F10', key: 'F10' }, | ||
F11: { keyCode: 122, code: 'F11', key: 'F11' }, | ||
F12: { keyCode: 123, code: 'F12', key: 'F12' }, | ||
F13: { keyCode: 124, code: 'F13', key: 'F13' }, | ||
F14: { keyCode: 125, code: 'F14', key: 'F14' }, | ||
F15: { keyCode: 126, code: 'F15', key: 'F15' }, | ||
F16: { keyCode: 127, code: 'F16', key: 'F16' }, | ||
F17: { keyCode: 128, code: 'F17', key: 'F17' }, | ||
F18: { keyCode: 129, code: 'F18', key: 'F18' }, | ||
F19: { keyCode: 130, code: 'F19', key: 'F19' }, | ||
F20: { keyCode: 131, code: 'F20', key: 'F20' }, | ||
F21: { keyCode: 132, code: 'F21', key: 'F21' }, | ||
F22: { keyCode: 133, code: 'F22', key: 'F22' }, | ||
F23: { keyCode: 134, code: 'F23', key: 'F23' }, | ||
F24: { keyCode: 135, code: 'F24', key: 'F24' }, | ||
NumLock: { keyCode: 144, code: 'NumLock', key: 'NumLock' }, | ||
ScrollLock: { keyCode: 145, code: 'ScrollLock', key: 'ScrollLock' }, | ||
AudioVolumeMute: { | ||
keyCode: 173, | ||
code: 'AudioVolumeMute', | ||
key: 'AudioVolumeMute', | ||
}, | ||
AudioVolumeDown: { | ||
keyCode: 174, | ||
code: 'AudioVolumeDown', | ||
key: 'AudioVolumeDown', | ||
}, | ||
AudioVolumeUp: { keyCode: 175, code: 'AudioVolumeUp', key: 'AudioVolumeUp' }, | ||
MediaTrackNext: { | ||
keyCode: 176, | ||
code: 'MediaTrackNext', | ||
key: 'MediaTrackNext', | ||
}, | ||
MediaTrackPrevious: { | ||
keyCode: 177, | ||
code: 'MediaTrackPrevious', | ||
key: 'MediaTrackPrevious', | ||
}, | ||
MediaStop: { keyCode: 178, code: 'MediaStop', key: 'MediaStop' }, | ||
MediaPlayPause: { | ||
keyCode: 179, | ||
code: 'MediaPlayPause', | ||
key: 'MediaPlayPause', | ||
}, | ||
Semicolon: { keyCode: 186, code: 'Semicolon', shiftKey: ':', key: ';' }, | ||
Equal: { keyCode: 187, code: 'Equal', shiftKey: '+', key: '=' }, | ||
NumpadEqual: { keyCode: 187, code: 'NumpadEqual', key: '=', location: 3 }, | ||
Comma: { keyCode: 188, code: 'Comma', shiftKey: '<', key: ',' }, | ||
Minus: { keyCode: 189, code: 'Minus', shiftKey: '_', key: '-' }, | ||
Period: { keyCode: 190, code: 'Period', shiftKey: '>', key: '.' }, | ||
Slash: { keyCode: 191, code: 'Slash', shiftKey: '?', key: '/' }, | ||
Backquote: { keyCode: 192, code: 'Backquote', shiftKey: '~', key: '`' }, | ||
BracketLeft: { keyCode: 219, code: 'BracketLeft', shiftKey: '{', key: '[' }, | ||
Backslash: { keyCode: 220, code: 'Backslash', shiftKey: '|', key: '\\' }, | ||
BracketRight: { keyCode: 221, code: 'BracketRight', shiftKey: '}', key: ']' }, | ||
Quote: { keyCode: 222, code: 'Quote', shiftKey: '"', key: "'" }, | ||
AltGraph: { keyCode: 225, code: 'AltGraph', key: 'AltGraph' }, | ||
Props: { keyCode: 247, code: 'Props', key: 'CrSel' }, | ||
Cancel: { keyCode: 3, key: 'Cancel', code: 'Abort' }, | ||
Clear: { keyCode: 12, key: 'Clear', code: 'Numpad5', location: 3 }, | ||
Shift: { keyCode: 16, key: 'Shift', code: 'ShiftLeft', location: 1 }, | ||
Control: { keyCode: 17, key: 'Control', code: 'ControlLeft', location: 1 }, | ||
Alt: { keyCode: 18, key: 'Alt', code: 'AltLeft', location: 1 }, | ||
Accept: { keyCode: 30, key: 'Accept' }, | ||
ModeChange: { keyCode: 31, key: 'ModeChange' }, | ||
' ': { keyCode: 32, key: ' ', code: 'Space' }, | ||
Print: { keyCode: 42, key: 'Print' }, | ||
Execute: { keyCode: 43, key: 'Execute', code: 'Open' }, | ||
'\u0000': { keyCode: 46, key: '\u0000', code: 'NumpadDecimal', location: 3 }, | ||
a: { keyCode: 65, key: 'a', code: 'KeyA' }, | ||
b: { keyCode: 66, key: 'b', code: 'KeyB' }, | ||
c: { keyCode: 67, key: 'c', code: 'KeyC' }, | ||
d: { keyCode: 68, key: 'd', code: 'KeyD' }, | ||
e: { keyCode: 69, key: 'e', code: 'KeyE' }, | ||
f: { keyCode: 70, key: 'f', code: 'KeyF' }, | ||
g: { keyCode: 71, key: 'g', code: 'KeyG' }, | ||
h: { keyCode: 72, key: 'h', code: 'KeyH' }, | ||
i: { keyCode: 73, key: 'i', code: 'KeyI' }, | ||
j: { keyCode: 74, key: 'j', code: 'KeyJ' }, | ||
k: { keyCode: 75, key: 'k', code: 'KeyK' }, | ||
l: { keyCode: 76, key: 'l', code: 'KeyL' }, | ||
m: { keyCode: 77, key: 'm', code: 'KeyM' }, | ||
n: { keyCode: 78, key: 'n', code: 'KeyN' }, | ||
o: { keyCode: 79, key: 'o', code: 'KeyO' }, | ||
p: { keyCode: 80, key: 'p', code: 'KeyP' }, | ||
q: { keyCode: 81, key: 'q', code: 'KeyQ' }, | ||
r: { keyCode: 82, key: 'r', code: 'KeyR' }, | ||
s: { keyCode: 83, key: 's', code: 'KeyS' }, | ||
t: { keyCode: 84, key: 't', code: 'KeyT' }, | ||
u: { keyCode: 85, key: 'u', code: 'KeyU' }, | ||
v: { keyCode: 86, key: 'v', code: 'KeyV' }, | ||
w: { keyCode: 87, key: 'w', code: 'KeyW' }, | ||
x: { keyCode: 88, key: 'x', code: 'KeyX' }, | ||
y: { keyCode: 89, key: 'y', code: 'KeyY' }, | ||
z: { keyCode: 90, key: 'z', code: 'KeyZ' }, | ||
Meta: { keyCode: 91, key: 'Meta', code: 'MetaLeft', location: 1 }, | ||
'*': { keyCode: 106, key: '*', code: 'NumpadMultiply', location: 3 }, | ||
'+': { keyCode: 107, key: '+', code: 'NumpadAdd', location: 3 }, | ||
'-': { keyCode: 109, key: '-', code: 'NumpadSubtract', location: 3 }, | ||
'/': { keyCode: 111, key: '/', code: 'NumpadDivide', location: 3 }, | ||
';': { keyCode: 186, key: ';', code: 'Semicolon' }, | ||
'=': { keyCode: 187, key: '=', code: 'Equal' }, | ||
',': { keyCode: 188, key: ',', code: 'Comma' }, | ||
'.': { keyCode: 190, key: '.', code: 'Period' }, | ||
'`': { keyCode: 192, key: '`', code: 'Backquote' }, | ||
'[': { keyCode: 219, key: '[', code: 'BracketLeft' }, | ||
'\\': { keyCode: 220, key: '\\', code: 'Backslash' }, | ||
']': { keyCode: 221, key: ']', code: 'BracketRight' }, | ||
"'": { keyCode: 222, key: "'", code: 'Quote' }, | ||
Attn: { keyCode: 246, key: 'Attn' }, | ||
CrSel: { keyCode: 247, key: 'CrSel', code: 'Props' }, | ||
ExSel: { keyCode: 248, key: 'ExSel' }, | ||
EraseEof: { keyCode: 249, key: 'EraseEof' }, | ||
Play: { keyCode: 250, key: 'Play' }, | ||
ZoomOut: { keyCode: 251, key: 'ZoomOut' }, | ||
')': { keyCode: 48, key: ')', code: 'Digit0' }, | ||
'!': { keyCode: 49, key: '!', code: 'Digit1' }, | ||
'@': { keyCode: 50, key: '@', code: 'Digit2' }, | ||
'#': { keyCode: 51, key: '#', code: 'Digit3' }, | ||
$: { keyCode: 52, key: '$', code: 'Digit4' }, | ||
'%': { keyCode: 53, key: '%', code: 'Digit5' }, | ||
'^': { keyCode: 54, key: '^', code: 'Digit6' }, | ||
'&': { keyCode: 55, key: '&', code: 'Digit7' }, | ||
'(': { keyCode: 57, key: '(', code: 'Digit9' }, | ||
A: { keyCode: 65, key: 'A', code: 'KeyA' }, | ||
B: { keyCode: 66, key: 'B', code: 'KeyB' }, | ||
C: { keyCode: 67, key: 'C', code: 'KeyC' }, | ||
D: { keyCode: 68, key: 'D', code: 'KeyD' }, | ||
E: { keyCode: 69, key: 'E', code: 'KeyE' }, | ||
F: { keyCode: 70, key: 'F', code: 'KeyF' }, | ||
G: { keyCode: 71, key: 'G', code: 'KeyG' }, | ||
H: { keyCode: 72, key: 'H', code: 'KeyH' }, | ||
I: { keyCode: 73, key: 'I', code: 'KeyI' }, | ||
J: { keyCode: 74, key: 'J', code: 'KeyJ' }, | ||
K: { keyCode: 75, key: 'K', code: 'KeyK' }, | ||
L: { keyCode: 76, key: 'L', code: 'KeyL' }, | ||
M: { keyCode: 77, key: 'M', code: 'KeyM' }, | ||
N: { keyCode: 78, key: 'N', code: 'KeyN' }, | ||
O: { keyCode: 79, key: 'O', code: 'KeyO' }, | ||
P: { keyCode: 80, key: 'P', code: 'KeyP' }, | ||
Q: { keyCode: 81, key: 'Q', code: 'KeyQ' }, | ||
R: { keyCode: 82, key: 'R', code: 'KeyR' }, | ||
S: { keyCode: 83, key: 'S', code: 'KeyS' }, | ||
T: { keyCode: 84, key: 'T', code: 'KeyT' }, | ||
U: { keyCode: 85, key: 'U', code: 'KeyU' }, | ||
V: { keyCode: 86, key: 'V', code: 'KeyV' }, | ||
W: { keyCode: 87, key: 'W', code: 'KeyW' }, | ||
X: { keyCode: 88, key: 'X', code: 'KeyX' }, | ||
Y: { keyCode: 89, key: 'Y', code: 'KeyY' }, | ||
Z: { keyCode: 90, key: 'Z', code: 'KeyZ' }, | ||
':': { keyCode: 186, key: ':', code: 'Semicolon' }, | ||
'<': { keyCode: 188, key: '<', code: 'Comma' }, | ||
_: { keyCode: 189, key: '_', code: 'Minus' }, | ||
'>': { keyCode: 190, key: '>', code: 'Period' }, | ||
'?': { keyCode: 191, key: '?', code: 'Slash' }, | ||
'~': { keyCode: 192, key: '~', code: 'Backquote' }, | ||
'{': { keyCode: 219, key: '{', code: 'BracketLeft' }, | ||
'|': { keyCode: 220, key: '|', code: 'Backslash' }, | ||
'}': { keyCode: 221, key: '}', code: 'BracketRight' }, | ||
'"': { keyCode: 222, key: '"', code: 'Quote' }, | ||
SoftLeft: { key: 'SoftLeft', code: 'SoftLeft', location: 4 }, | ||
SoftRight: { key: 'SoftRight', code: 'SoftRight', location: 4 }, | ||
Camera: { keyCode: 44, key: 'Camera', code: 'Camera', location: 4 }, | ||
Call: { key: 'Call', code: 'Call', location: 4 }, | ||
EndCall: { keyCode: 95, key: 'EndCall', code: 'EndCall', location: 4 }, | ||
VolumeDown: { | ||
keyCode: 182, | ||
key: 'VolumeDown', | ||
code: 'VolumeDown', | ||
location: 4, | ||
}, | ||
VolumeUp: { keyCode: 183, key: 'VolumeUp', code: 'VolumeUp', location: 4 }, | ||
}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.WebSocketTransport = void 0; | ||
/** | ||
@@ -22,3 +23,3 @@ * Copyright 2018 Google Inc. All rights reserved. | ||
this._ws = ws; | ||
this._ws.addEventListener('message', event => { | ||
this._ws.addEventListener('message', (event) => { | ||
if (this.onmessage) | ||
@@ -25,0 +26,0 @@ this.onmessage.call(null, event.data); |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Worker = void 0; | ||
/** | ||
@@ -27,7 +28,7 @@ * Copyright 2018 Google Inc. All rights reserved. | ||
this._url = url; | ||
this._executionContextPromise = new Promise(x => this._executionContextCallback = x); | ||
this._executionContextPromise = new Promise((x) => (this._executionContextCallback = x)); | ||
let jsHandleFactory; | ||
this._client.once('Runtime.executionContextCreated', async (event) => { | ||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type | ||
jsHandleFactory = remoteObject => new JSHandle_1.JSHandle(executionContext, client, remoteObject); | ||
jsHandleFactory = (remoteObject) => new JSHandle_1.JSHandle(executionContext, client, remoteObject); | ||
const executionContext = new ExecutionContext_1.ExecutionContext(client, event.context, null); | ||
@@ -38,4 +39,4 @@ this._executionContextCallback(executionContext); | ||
this._client.send('Runtime.enable', {}).catch(helper_1.debugError); | ||
this._client.on('Runtime.consoleAPICalled', event => consoleAPICalled(event.type, event.args.map(jsHandleFactory), event.stackTrace)); | ||
this._client.on('Runtime.exceptionThrown', exception => exceptionThrown(exception.exceptionDetails)); | ||
this._client.on('Runtime.consoleAPICalled', (event) => consoleAPICalled(event.type, event.args.map(jsHandleFactory), event.stackTrace)); | ||
this._client.on('Runtime.exceptionThrown', (exception) => exceptionThrown(exception.exceptionDetails)); | ||
} | ||
@@ -42,0 +43,0 @@ url() { |
{ | ||
"name": "puppeteer-core", | ||
"version": "3.0.4", | ||
"version": "3.1.0", | ||
"description": "A high-level API to control headless Chrome over the DevTools Protocol", | ||
@@ -11,3 +11,3 @@ "main": "index.js", | ||
"puppeteer": { | ||
"chromium_revision": "737027", | ||
"chromium_revision": "756035", | ||
"firefox_revision": "latest" | ||
@@ -27,2 +27,3 @@ }, | ||
"eslint": "([ \"$CI\" = true ] && eslint --ext js --ext ts --quiet -f codeframe . || eslint --ext js --ext ts .)", | ||
"eslint-fix": "eslint --ext js --ext ts --fix .", | ||
"lint": "npm run eslint && npm run tsc && npm run doc", | ||
@@ -63,2 +64,3 @@ "doc": "node utils/doclint/cli.js", | ||
"@types/node": "^10.17.14", | ||
"@types/proxy-from-env": "^1.0.1", | ||
"@types/rimraf": "^2.0.2", | ||
@@ -72,3 +74,5 @@ "@types/tar-fs": "^1.16.2", | ||
"eslint": "^6.8.0", | ||
"eslint-config-prettier": "^6.11.0", | ||
"eslint-plugin-mocha": "^6.3.0", | ||
"eslint-plugin-prettier": "^3.1.3", | ||
"eslint-plugin-unicorn": "^19.0.1", | ||
@@ -83,4 +87,6 @@ "esprima": "^4.0.0", | ||
"pngjs": "^5.0.0", | ||
"prettier": "^2.0.5", | ||
"sinon": "^9.0.2", | ||
"text-diff": "^1.0.1", | ||
"typescript": "3.8.3" | ||
"typescript": "3.9.2" | ||
}, | ||
@@ -87,0 +93,0 @@ "browser": { |
@@ -9,3 +9,3 @@ # Puppeteer | ||
###### [API](https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/puppeteer/puppeteer/blob/master/CONTRIBUTING.md) | [Troubleshooting](https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md) | ||
###### [API](https://github.com/puppeteer/puppeteer/blob/v3.1.0/docs/api.md) | [FAQ](#faq) | [Contributing](https://github.com/puppeteer/puppeteer/blob/master/CONTRIBUTING.md) | [Troubleshooting](https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md) | ||
@@ -41,3 +41,3 @@ > Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the [DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/). Puppeteer runs [headless](https://developers.google.com/web/updates/2017/04/headless-chrome) by default, but can be configured to run full (non-headless) Chrome or Chromium. | ||
Note: When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API. To skip the download, or to download a different browser, see [Environment variables](https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#environment-variables). | ||
Note: When you install Puppeteer, it downloads a recent version of Chromium (~170MB Mac, ~282MB Linux, ~280MB Win) that is guaranteed to work with the API. To skip the download, or to download a different browser, see [Environment variables](https://github.com/puppeteer/puppeteer/blob/v3.1.0/docs/api.md#environment-variables). | ||
@@ -68,3 +68,3 @@ | ||
Puppeteer will be familiar to people using other browser testing frameworks. You create an instance | ||
of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#). | ||
of `Browser`, open pages, and then manipulate them with [Puppeteer's API](https://github.com/puppeteer/puppeteer/blob/v3.1.0/docs/api.md#). | ||
@@ -94,3 +94,3 @@ **Example** - navigating to https://example.com and saving a screenshot as *example.png*: | ||
Puppeteer sets an initial page size to 800×600px, which defines the screenshot size. The page size can be customized with [`Page.setViewport()`](https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#pagesetviewportviewport). | ||
Puppeteer sets an initial page size to 800×600px, which defines the screenshot size. The page size can be customized with [`Page.setViewport()`](https://github.com/puppeteer/puppeteer/blob/v3.1.0/docs/api.md#pagesetviewportviewport). | ||
@@ -120,3 +120,3 @@ **Example** - create a PDF. | ||
See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#pagepdfoptions) for more information about creating pdfs. | ||
See [`Page.pdf()`](https://github.com/puppeteer/puppeteer/blob/v3.1.0/docs/api.md#pagepdfoptions) for more information about creating pdfs. | ||
@@ -156,3 +156,3 @@ **Example** - evaluate script in the context of the page | ||
See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#pageevaluatepagefunction-args) for more information on `evaluate` and related methods like `evaluateOnNewDocument` and `exposeFunction`. | ||
See [`Page.evaluate()`](https://github.com/puppeteer/puppeteer/blob/v3.1.0/docs/api.md#pageevaluatepagefunction-args) for more information on `evaluate` and related methods like `evaluateOnNewDocument` and `exposeFunction`. | ||
@@ -166,3 +166,3 @@ <!-- [END getstarted] --> | ||
Puppeteer launches Chromium in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). To launch a full version of Chromium, set the [`headless` option](https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#puppeteerlaunchoptions) when launching a browser: | ||
Puppeteer launches Chromium in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). To launch a full version of Chromium, set the [`headless` option](https://github.com/puppeteer/puppeteer/blob/v3.1.0/docs/api.md#puppeteerlaunchoptions) when launching a browser: | ||
@@ -183,3 +183,3 @@ ```js | ||
You can also use Puppeteer with Firefox Nightly (experimental support). See [`Puppeteer.launch()`](https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#puppeteerlaunchoptions) for more information. | ||
You can also use Puppeteer with Firefox Nightly (experimental support). See [`Puppeteer.launch()`](https://github.com/puppeteer/puppeteer/blob/v3.1.0/docs/api.md#puppeteerlaunchoptions) for more information. | ||
@@ -196,3 +196,3 @@ See [`this article`](https://www.howtogeek.com/202825/what%E2%80%99s-the-difference-between-chromium-and-chrome/) for a description of the differences between Chromium and Chrome. [`This article`](https://chromium.googlesource.com/chromium/src/+/master/docs/chromium_browser_vs_google_chrome.md) describes some differences for Linux users. | ||
- [API Documentation](https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md) | ||
- [API Documentation](https://github.com/puppeteer/puppeteer/blob/v3.1.0/docs/api.md) | ||
- [Examples](https://github.com/puppeteer/puppeteer/tree/master/examples/) | ||
@@ -324,3 +324,3 @@ - [Community list of Puppeteer resources](https://github.com/transitive-bullshit/awesome-puppeteer) | ||
From Puppeteer v2.1.0 onwards you can specify [`puppeteer.launch({product: 'firefox'})`](https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#puppeteerlaunchoptions) to run your Puppeteer scripts in Firefox Nightly, without any additional custom patches. While [an older experiment](https://www.npmjs.com/package/puppeteer-firefox) required a patched version of Firefox, [the current approach](https://wiki.mozilla.org/Remote) works with “stock” Firefox. | ||
From Puppeteer v2.1.0 onwards you can specify [`puppeteer.launch({product: 'firefox'})`](https://github.com/puppeteer/puppeteer/blob/v3.1.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. | ||
@@ -421,3 +421,3 @@ We will continue to collaborate with other browser vendors to bring Puppeteer support to browsers such as Safari. | ||
* Puppeteer is bundled with Chromium — not Chrome — and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://github.com/puppeteer/puppeteer/blob/v3.0.4/docs/api.md#puppeteerlaunchoptions). You should only use this configuration if you need an official release of Chrome that supports these media formats.) | ||
* Puppeteer is bundled with Chromium — not Chrome — and so by default, it inherits all of [Chromium's media-related limitations](https://www.chromium.org/audio-video). This means that Puppeteer does not support licensed formats such as AAC or H.264. (However, it is possible to force Puppeteer to use a separately-installed version Chrome instead of Chromium via the [`executablePath` option to `puppeteer.launch`](https://github.com/puppeteer/puppeteer/blob/v3.1.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). | ||
@@ -424,0 +424,0 @@ |
@@ -20,3 +20,3 @@ /** | ||
const fs = require('fs'); | ||
const {promisify} = require('util'); | ||
const { promisify } = require('util'); | ||
@@ -26,3 +26,6 @@ const exec = promisify(child_process.exec); | ||
const fileExists = async filePath => fsAccess(filePath).then(() => true).catch(() => false); | ||
const fileExists = async (filePath) => | ||
fsAccess(filePath) | ||
.then(() => true) | ||
.catch(() => false); | ||
/* | ||
@@ -42,3 +45,3 @@ | ||
async function compileTypeScript() { | ||
return exec('npm run tsc').catch(error => { | ||
return exec('npm run tsc').catch((error) => { | ||
console.error('Error running TypeScript', error); | ||
@@ -59,5 +62,4 @@ process.exit(1); | ||
// It's being run as node typescript-if-required.js, not require('..') | ||
if (require.main === module) | ||
compileTypeScriptIfRequired(); | ||
if (require.main === module) compileTypeScriptIfRequired(); | ||
module.exports = compileTypeScriptIfRequired; |
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
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
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
903806
48
23707
28