Change let into const (#457)

This patch:
- changes `let` into `const` throughout codebase
- adds eslint check to prefer const over let
This commit is contained in:
Eric Bidelman 2017-08-21 16:39:04 -07:00 committed by Andrey Lushnikov
parent 5d6d3e0a81
commit 1f9b4fb4c8
37 changed files with 495 additions and 494 deletions

View File

@ -47,6 +47,7 @@ module.exports = {
"new-parens": 2, "new-parens": 2,
"func-call-spacing": 2, "func-call-spacing": 2,
"arrow-parens": [2, "as-needed"], "arrow-parens": [2, "as-needed"],
"prefer-const": 2,
// anti-patterns // anti-patterns
"no-var": 2, "no-var": 2,

View File

@ -628,5 +628,5 @@ module.exports = [
} }
} }
]; ];
for (let device of module.exports) for (const device of module.exports)
module.exports[device.name] = device; module.exports[device.name] = device;

View File

@ -24,7 +24,7 @@ const revisionInfo = Downloader.revisionInfo(platform, revision);
if (revisionInfo.downloaded) if (revisionInfo.downloaded)
return; return;
let allRevisions = Downloader.downloadedRevisions(); const allRevisions = Downloader.downloadedRevisions();
Downloader.downloadRevision(platform, revision, onProgress) Downloader.downloadRevision(platform, revision, onProgress)
// Remove previous chromium revisions. // Remove previous chromium revisions.
.then(() => Promise.all(allRevisions.map(({platform, revision}) => Downloader.removeRevision(platform, revision)))) .then(() => Promise.all(allRevisions.map(({platform, revision}) => Downloader.removeRevision(platform, revision))))
@ -52,7 +52,7 @@ function onProgress(bytesTotal, delta) {
} }
function toMegabytes(bytes) { function toMegabytes(bytes) {
let mb = bytes / 1024 / 1024; const mb = bytes / 1024 / 1024;
return `${Math.round(mb * 10) / 10} Mb`; return `${Math.round(mb * 10) / 10} Mb`;
} }

View File

@ -50,7 +50,7 @@ class Browser {
* @return {!Promise<string>} * @return {!Promise<string>}
*/ */
async version() { async version() {
let version = await this._connection.send('Browser.getVersion'); const version = await this._connection.send('Browser.getVersion');
return version.product; return version.product;
} }

View File

@ -27,7 +27,7 @@ class Connection extends EventEmitter {
*/ */
static async create(url, delay = 0) { static async create(url, delay = 0) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let ws = new WebSocket(url, { perMessageDeflate: false }); const ws = new WebSocket(url, { perMessageDeflate: false });
ws.on('open', () => resolve(new Connection(url, ws, delay))); ws.on('open', () => resolve(new Connection(url, ws, delay)));
ws.on('error', reject); ws.on('error', reject);
}); });
@ -66,8 +66,8 @@ class Connection extends EventEmitter {
* @return {!Promise<?Object>} * @return {!Promise<?Object>}
*/ */
send(method, params = {}) { send(method, params = {}) {
let id = ++this._lastId; const id = ++this._lastId;
let message = JSON.stringify({id, method, params}); const message = JSON.stringify({id, method, params});
debugProtocol('SEND ► ' + message); debugProtocol('SEND ► ' + message);
this._ws.send(message); this._ws.send(message);
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -82,9 +82,9 @@ class Connection extends EventEmitter {
if (this._delay) if (this._delay)
await new Promise(f => setTimeout(f, this._delay)); await new Promise(f => setTimeout(f, this._delay));
debugProtocol('◀ RECV ' + message); debugProtocol('◀ RECV ' + message);
let object = JSON.parse(message); const object = JSON.parse(message);
if (object.id && this._callbacks.has(object.id)) { if (object.id && this._callbacks.has(object.id)) {
let callback = this._callbacks.get(object.id); const callback = this._callbacks.get(object.id);
this._callbacks.delete(object.id); this._callbacks.delete(object.id);
if (object.error) if (object.error)
callback.reject(new Error(`Protocol error (${callback.method}): ${object.error.message} ${object.error.data}`)); callback.reject(new Error(`Protocol error (${callback.method}): ${object.error.message} ${object.error.data}`));
@ -109,10 +109,10 @@ class Connection extends EventEmitter {
_onClose() { _onClose() {
this._ws.removeAllListeners(); this._ws.removeAllListeners();
for (let callback of this._callbacks.values()) for (const callback of this._callbacks.values())
callback.reject(new Error(`Protocol error (${callback.method}): Target closed.`)); callback.reject(new Error(`Protocol error (${callback.method}): Target closed.`));
this._callbacks.clear(); this._callbacks.clear();
for (let session of this._sessions.values()) for (const session of this._sessions.values())
session._onClosed(); session._onClosed();
this._sessions.clear(); this._sessions.clear();
} }
@ -168,14 +168,14 @@ class Session extends EventEmitter {
send(method, params = {}) { send(method, params = {}) {
if (!this._connection) if (!this._connection)
return Promise.reject(new Error(`Protocol error (${method}): Session closed. Most likely the page has been closed.`)); return Promise.reject(new Error(`Protocol error (${method}): Session closed. Most likely the page has been closed.`));
let id = ++this._lastId; const id = ++this._lastId;
let message = JSON.stringify({id, method, params}); const message = JSON.stringify({id, method, params});
debugSession('SEND ► ' + message); debugSession('SEND ► ' + message);
this._connection.send('Target.sendMessageToTarget', {sessionId: this._sessionId, message}).catch(e => { this._connection.send('Target.sendMessageToTarget', {sessionId: this._sessionId, message}).catch(e => {
// The response from target might have been already dispatched. // The response from target might have been already dispatched.
if (!this._callbacks.has(id)) if (!this._callbacks.has(id))
return; return;
let callback = this._callbacks.get(id); const callback = this._callbacks.get(id);
this._callbacks.delete(object.id); this._callbacks.delete(object.id);
callback.reject(e); callback.reject(e);
}); });
@ -189,9 +189,9 @@ class Session extends EventEmitter {
*/ */
_onMessage(message) { _onMessage(message) {
debugSession('◀ RECV ' + message); debugSession('◀ RECV ' + message);
let object = JSON.parse(message); const object = JSON.parse(message);
if (object.id && this._callbacks.has(object.id)) { if (object.id && this._callbacks.has(object.id)) {
let callback = this._callbacks.get(object.id); const callback = this._callbacks.get(object.id);
this._callbacks.delete(object.id); this._callbacks.delete(object.id);
if (object.error) if (object.error)
callback.reject(new Error(`Protocol error (${callback.method}): ${object.error.message} ${object.error.data}`)); callback.reject(new Error(`Protocol error (${callback.method}): ${object.error.message} ${object.error.data}`));
@ -211,7 +211,7 @@ class Session extends EventEmitter {
} }
_onClosed() { _onClosed() {
for (let callback of this._callbacks.values()) for (const callback of this._callbacks.values())
callback.reject(new Error(`Protocol error (${callback.method}): Target closed.`)); callback.reject(new Error(`Protocol error (${callback.method}): Target closed.`));
this._callbacks.clear(); this._callbacks.clear();
this._connection = null; this._connection = null;

View File

@ -48,11 +48,11 @@ class ElementHandle {
console.assert(!this._disposed, 'ElementHandle is disposed!'); console.assert(!this._disposed, 'ElementHandle is disposed!');
console.assert(typeof pageFunction === 'function', 'First argument to ElementHandle.evaluate must be a function!'); console.assert(typeof pageFunction === 'function', 'First argument to ElementHandle.evaluate must be a function!');
let stringifiedArgs = ['this']; const stringifiedArgs = ['this'];
stringifiedArgs.push(...args.map(x => JSON.stringify(x))); stringifiedArgs.push(...args.map(x => JSON.stringify(x)));
let functionDeclaration = `function() { return (${pageFunction})(${stringifiedArgs.join(',')}) }`; const functionDeclaration = `function() { return (${pageFunction})(${stringifiedArgs.join(',')}) }`;
const objectId = this._remoteObject.objectId; const objectId = this._remoteObject.objectId;
let { exceptionDetails, result: remoteObject } = await this._client.send('Runtime.callFunctionOn', { objectId, functionDeclaration, returnByValue: false, awaitPromise: true}); const { exceptionDetails, result: remoteObject } = await this._client.send('Runtime.callFunctionOn', { objectId, functionDeclaration, returnByValue: false, awaitPromise: true});
if (exceptionDetails) if (exceptionDetails)
throw new Error('Evaluation failed: ' + helper.getExceptionMessage(exceptionDetails)); throw new Error('Evaluation failed: ' + helper.getExceptionMessage(exceptionDetails));
return await helper.serializeRemoteObject(this._client, remoteObject); return await helper.serializeRemoteObject(this._client, remoteObject);
@ -62,11 +62,11 @@ class ElementHandle {
* @return {!Promise<{x: number, y: number}>} * @return {!Promise<{x: number, y: number}>}
*/ */
async _visibleCenter() { async _visibleCenter() {
let center = await this.evaluate(element => { const center = await this.evaluate(element => {
if (!element.ownerDocument.contains(element)) if (!element.ownerDocument.contains(element))
return null; return null;
element.scrollIntoViewIfNeeded(); element.scrollIntoViewIfNeeded();
let rect = element.getBoundingClientRect(); const rect = element.getBoundingClientRect();
return { return {
x: (Math.max(rect.left, 0) + Math.min(rect.right, window.innerWidth)) / 2, x: (Math.max(rect.left, 0) + Math.min(rect.right, window.innerWidth)) / 2,
y: (Math.max(rect.top, 0) + Math.min(rect.bottom, window.innerHeight)) / 2 y: (Math.max(rect.top, 0) + Math.min(rect.bottom, window.innerHeight)) / 2
@ -81,7 +81,7 @@ class ElementHandle {
* @return {!Promise} * @return {!Promise}
*/ */
async hover() { async hover() {
let {x, y} = await this._visibleCenter(); const {x, y} = await this._visibleCenter();
await this._mouse.move(x, y); await this._mouse.move(x, y);
} }
@ -90,7 +90,7 @@ class ElementHandle {
* @return {!Promise} * @return {!Promise}
*/ */
async click(options) { async click(options) {
let {x, y} = await this._visibleCenter(); const {x, y} = await this._visibleCenter();
await this._mouse.click(x, y, options); await this._mouse.click(x, y, options);
} }
@ -99,7 +99,7 @@ class ElementHandle {
* @return {!Promise} * @return {!Promise}
*/ */
async uploadFile(...filePaths) { async uploadFile(...filePaths) {
let files = filePaths.map(filePath => path.resolve(filePath)); const files = filePaths.map(filePath => path.resolve(filePath));
const objectId = this._remoteObject.objectId; const objectId = this._remoteObject.objectId;
return this._client.send('DOM.setFileInputFiles', { objectId, files }); return this._client.send('DOM.setFileInputFiles', { objectId, files });
} }

View File

@ -61,8 +61,8 @@ class FrameManager extends EventEmitter {
if (this._frames.has(frameId)) if (this._frames.has(frameId))
return; return;
console.assert(parentFrameId); console.assert(parentFrameId);
let parentFrame = this._frames.get(parentFrameId); const parentFrame = this._frames.get(parentFrameId);
let frame = new Frame(this._client, this._mouse, parentFrame, frameId); const frame = new Frame(this._client, this._mouse, parentFrame, frameId);
this._frames.set(frame._id, frame); this._frames.set(frame._id, frame);
this.emit(FrameManager.Events.FrameAttached, frame); this.emit(FrameManager.Events.FrameAttached, frame);
} }
@ -77,7 +77,7 @@ class FrameManager extends EventEmitter {
// Detach all child frames first. // Detach all child frames first.
if (frame) { if (frame) {
for (let child of frame.childFrames()) for (const child of frame.childFrames())
this._removeFramesRecursively(child); this._removeFramesRecursively(child);
} }
@ -105,7 +105,7 @@ class FrameManager extends EventEmitter {
* @param {string} frameId * @param {string} frameId
*/ */
_onFrameDetached(frameId) { _onFrameDetached(frameId) {
let frame = this._frames.get(frameId); const frame = this._frames.get(frameId);
if (frame) if (frame)
this._removeFramesRecursively(frame); this._removeFramesRecursively(frame);
} }
@ -116,7 +116,7 @@ class FrameManager extends EventEmitter {
if (!frame) if (!frame)
return; return;
frame._defaultContextId = context.id; frame._defaultContextId = context.id;
for (let waitTask of frame._waitTasks) for (const waitTask of frame._waitTasks)
waitTask.rerun(); waitTask.rerun();
} }
@ -124,7 +124,7 @@ class FrameManager extends EventEmitter {
* @param {!Frame} frame * @param {!Frame} frame
*/ */
_removeFramesRecursively(frame) { _removeFramesRecursively(frame) {
for (let child of frame.childFrames()) for (const child of frame.childFrames())
this._removeFramesRecursively(child); this._removeFramesRecursively(child);
frame._detach(); frame._detach();
this._frames.delete(frame._id); this._frames.delete(frame._id);
@ -179,7 +179,7 @@ class Frame {
* @return {!Promise<(!Object|undefined)>} * @return {!Promise<(!Object|undefined)>}
*/ */
async evaluate(pageFunction, ...args) { async evaluate(pageFunction, ...args) {
let remoteObject = await this._rawEvaluate(pageFunction, ...args); const remoteObject = await this._rawEvaluate(pageFunction, ...args);
return await helper.serializeRemoteObject(this._client, remoteObject); return await helper.serializeRemoteObject(this._client, remoteObject);
} }
@ -188,7 +188,7 @@ class Frame {
* @return {!Promise<?ElementHandle>} * @return {!Promise<?ElementHandle>}
*/ */
async $(selector) { async $(selector) {
let remoteObject = await this._rawEvaluate(selector => document.querySelector(selector), selector); const remoteObject = await this._rawEvaluate(selector => document.querySelector(selector), selector);
if (remoteObject.subtype === 'node') if (remoteObject.subtype === 'node')
return new ElementHandle(this._client, remoteObject, this._mouse); return new ElementHandle(this._client, remoteObject, this._mouse);
helper.releaseObject(this._client, remoteObject); helper.releaseObject(this._client, remoteObject);
@ -201,9 +201,9 @@ class Frame {
* @return {!Promise<(!Object|undefined)>} * @return {!Promise<(!Object|undefined)>}
*/ */
async _rawEvaluate(pageFunction, ...args) { async _rawEvaluate(pageFunction, ...args) {
let expression = helper.evaluationString(pageFunction, ...args); const expression = helper.evaluationString(pageFunction, ...args);
const contextId = this._defaultContextId; const contextId = this._defaultContextId;
let { exceptionDetails, result: remoteObject } = await this._client.send('Runtime.evaluate', { expression, contextId, returnByValue: false, awaitPromise: true}); const { exceptionDetails, result: remoteObject } = await this._client.send('Runtime.evaluate', { expression, contextId, returnByValue: false, awaitPromise: true});
if (exceptionDetails) if (exceptionDetails)
throw new Error('Evaluation failed: ' + helper.getExceptionMessage(exceptionDetails)); throw new Error('Evaluation failed: ' + helper.getExceptionMessage(exceptionDetails));
return remoteObject; return remoteObject;
@ -270,9 +270,9 @@ class Frame {
* @param {string} url * @param {string} url
*/ */
function addScriptTag(url) { function addScriptTag(url) {
let script = document.createElement('script'); const script = document.createElement('script');
script.src = url; script.src = url;
let promise = new Promise(x => script.onload = x); const promise = new Promise(x => script.onload = x);
document.head.appendChild(script); document.head.appendChild(script);
return promise; return promise;
} }
@ -349,7 +349,7 @@ class Frame {
} }
_detach() { _detach() {
for (let waitTask of this._waitTasks) for (const waitTask of this._waitTasks)
waitTask.terminate(new Error('waitForSelector failed: frame got detached.')); waitTask.terminate(new Error('waitForSelector failed: frame got detached.'));
this._detached = true; this._detached = true;
if (this._parentFrame) if (this._parentFrame)

View File

@ -166,7 +166,7 @@ class Mouse {
} }
} }
let keys = { const keys = {
'Cancel': 3, 'Cancel': 3,
'Help': 6, 'Help': 6,
'Backspace': 8, 'Backspace': 8,

View File

@ -113,7 +113,7 @@ class Launcher {
* @return {!Promise<!Browser>} * @return {!Promise<!Browser>}
*/ */
static async connect({browserWSEndpoint, ignoreHTTPSErrors = false}) { static async connect({browserWSEndpoint, ignoreHTTPSErrors = false}) {
let connection = await Connection.create(browserWSEndpoint); const connection = await Connection.create(browserWSEndpoint);
return new Browser(connection, !!ignoreHTTPSErrors); return new Browser(connection, !!ignoreHTTPSErrors);
} }
} }
@ -127,12 +127,12 @@ function waitForWSEndpoint(chromeProcess, timeout) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const rl = readline.createInterface({ input: chromeProcess.stderr }); const rl = readline.createInterface({ input: chromeProcess.stderr });
let stderr = ''; let stderr = '';
let listeners = [ const listeners = [
helper.addEventListener(rl, 'line', onLine), helper.addEventListener(rl, 'line', onLine),
helper.addEventListener(rl, 'close', onClose), helper.addEventListener(rl, 'close', onClose),
helper.addEventListener(chromeProcess, 'exit', onClose) helper.addEventListener(chromeProcess, 'exit', onClose)
]; ];
let timeoutId = timeout ? setTimeout(onTimeout, timeout) : 0; const timeoutId = timeout ? setTimeout(onTimeout, timeout) : 0;
function onClose() { function onClose() {
cleanup(); cleanup();

View File

@ -61,7 +61,7 @@ class Multimap {
* @return {boolean} * @return {boolean}
*/ */
hasValue(key, value) { hasValue(key, value) {
let set = this._map.get(key); const set = this._map.get(key);
if (!set) if (!set)
return false; return false;
return set.has(value); return set.has(value);
@ -80,8 +80,8 @@ class Multimap {
* @return {boolean} * @return {boolean}
*/ */
delete(key, value) { delete(key, value) {
let values = this.get(key); const values = this.get(key);
let result = values.delete(value); const result = values.delete(value);
if (!values.size) if (!values.size)
this._map.delete(key); this._map.delete(key);
return result; return result;
@ -99,7 +99,7 @@ class Multimap {
* @return {?V} value * @return {?V} value
*/ */
firstValue(key) { firstValue(key) {
let set = this._map.get(key); const set = this._map.get(key);
if (!set) if (!set)
return null; return null;
return set.values().next().value; return set.values().next().value;
@ -116,8 +116,8 @@ class Multimap {
* @return {!Array<!V>} * @return {!Array<!V>}
*/ */
valuesArray() { valuesArray() {
let result = []; const result = [];
for (let key of this._map.keys()) for (const key of this._map.keys())
result.push(...Array.from(this._map.get(key).values())); result.push(...Array.from(this._map.get(key).values()));
return result; return result;
} }

View File

@ -40,19 +40,19 @@ class NavigatorWatcher {
this._eventListeners = []; this._eventListeners = [];
let watchdog = new Promise(fulfill => this._maximumTimer = setTimeout(fulfill, this._timeout)) const watchdog = new Promise(fulfill => this._maximumTimer = setTimeout(fulfill, this._timeout))
.then(() => 'Navigation Timeout Exceeded: ' + this._timeout + 'ms exceeded'); .then(() => 'Navigation Timeout Exceeded: ' + this._timeout + 'ms exceeded');
let navigationPromises = [watchdog]; const navigationPromises = [watchdog];
if (!this._ignoreHTTPSErrors) { if (!this._ignoreHTTPSErrors) {
let certificateError = new Promise(fulfill => { const certificateError = new Promise(fulfill => {
this._eventListeners.push(helper.addEventListener(this._client, 'Security.certificateError', fulfill)); this._eventListeners.push(helper.addEventListener(this._client, 'Security.certificateError', fulfill));
}).then(error => 'SSL Certificate error: ' + error.errorType); }).then(error => 'SSL Certificate error: ' + error.errorType);
navigationPromises.push(certificateError); navigationPromises.push(certificateError);
} }
if (this._waitUntil === 'load') { if (this._waitUntil === 'load') {
let loadEventFired = new Promise(fulfill => { const loadEventFired = new Promise(fulfill => {
this._eventListeners.push(helper.addEventListener(this._client, 'Page.loadEventFired', fulfill)); this._eventListeners.push(helper.addEventListener(this._client, 'Page.loadEventFired', fulfill));
}).then(() => null); }).then(() => null);
navigationPromises.push(loadEventFired); navigationPromises.push(loadEventFired);
@ -64,7 +64,7 @@ class NavigatorWatcher {
helper.addEventListener(this._client, 'Network.webSocketCreated', this._onLoadingStarted.bind(this)), helper.addEventListener(this._client, 'Network.webSocketCreated', this._onLoadingStarted.bind(this)),
helper.addEventListener(this._client, 'Network.webSocketClosed', this._onLoadingCompleted.bind(this)), helper.addEventListener(this._client, 'Network.webSocketClosed', this._onLoadingCompleted.bind(this)),
]); ]);
let networkIdle = new Promise(fulfill => this._networkIdleCallback = fulfill).then(() => null); const networkIdle = new Promise(fulfill => this._networkIdleCallback = fulfill).then(() => null);
navigationPromises.push(networkIdle); navigationPromises.push(networkIdle);
} }

View File

@ -51,8 +51,8 @@ class NetworkManager extends EventEmitter {
*/ */
async setExtraHTTPHeaders(extraHTTPHeaders) { async setExtraHTTPHeaders(extraHTTPHeaders) {
this._extraHTTPHeaders = new Map(extraHTTPHeaders); this._extraHTTPHeaders = new Map(extraHTTPHeaders);
let headers = {}; const headers = {};
for (let entry of extraHTTPHeaders.entries()) for (const entry of extraHTTPHeaders.entries())
headers[entry[0]] = entry[1]; headers[entry[0]] = entry[1];
await this._client.send('Network.setExtraHTTPHeaders', { headers }); await this._client.send('Network.setExtraHTTPHeaders', { headers });
} }
@ -89,13 +89,13 @@ class NetworkManager extends EventEmitter {
event.request.url = removeURLHash(event.request.url); event.request.url = removeURLHash(event.request.url);
if (event.redirectStatusCode) { if (event.redirectStatusCode) {
let request = this._interceptionIdToRequest.get(event.interceptionId); const request = this._interceptionIdToRequest.get(event.interceptionId);
console.assert(request, 'INTERNAL ERROR: failed to find request for interception redirect.'); console.assert(request, 'INTERNAL ERROR: failed to find request for interception redirect.');
this._handleRequestRedirect(request, event.redirectStatusCode, event.redirectHeaders); this._handleRequestRedirect(request, event.redirectStatusCode, event.redirectHeaders);
this._handleRequestStart(request._requestId, event.interceptionId, event.redirectUrl, event.request); this._handleRequestStart(request._requestId, event.interceptionId, event.redirectUrl, event.request);
return; return;
} }
let requestHash = generateRequestHash(event.request); const requestHash = generateRequestHash(event.request);
this._requestHashToInterceptions.set(requestHash, event); this._requestHashToInterceptions.set(requestHash, event);
this._maybeResolveInterception(requestHash); this._maybeResolveInterception(requestHash);
} }
@ -106,7 +106,7 @@ class NetworkManager extends EventEmitter {
* @param {!Object} redirectHeaders * @param {!Object} redirectHeaders
*/ */
_handleRequestRedirect(request, redirectStatus, redirectHeaders) { _handleRequestRedirect(request, redirectStatus, redirectHeaders) {
let response = new Response(this._client, request, redirectStatus, redirectHeaders); const response = new Response(this._client, request, redirectStatus, redirectHeaders);
request._response = response; request._response = response;
this._requestIdToRequest.delete(request._requestId); this._requestIdToRequest.delete(request._requestId);
this._interceptionIdToRequest.delete(request._interceptionId); this._interceptionIdToRequest.delete(request._interceptionId);
@ -121,7 +121,7 @@ class NetworkManager extends EventEmitter {
* @param {!Object} requestPayload * @param {!Object} requestPayload
*/ */
_handleRequestStart(requestId, interceptionId, url, requestPayload) { _handleRequestStart(requestId, interceptionId, url, requestPayload) {
let request = new Request(this._client, requestId, interceptionId, url, requestPayload); const request = new Request(this._client, requestId, interceptionId, url, requestPayload);
this._requestIdToRequest.set(requestId, request); this._requestIdToRequest.set(requestId, request);
this._interceptionIdToRequest.set(interceptionId, request); this._interceptionIdToRequest.set(interceptionId, request);
this.emit(NetworkManager.Events.Request, request); this.emit(NetworkManager.Events.Request, request);
@ -135,13 +135,13 @@ class NetworkManager extends EventEmitter {
// All redirects are handled in requestIntercepted. // All redirects are handled in requestIntercepted.
if (event.redirectResponse) if (event.redirectResponse)
return; return;
let requestHash = generateRequestHash(event.request); const requestHash = generateRequestHash(event.request);
this._requestHashToRequestIds.set(requestHash, event.requestId); this._requestHashToRequestIds.set(requestHash, event.requestId);
this._maybeResolveInterception(requestHash); this._maybeResolveInterception(requestHash);
return; return;
} }
if (event.redirectResponse) { if (event.redirectResponse) {
let request = this._requestIdToRequest.get(event.requestId); const request = this._requestIdToRequest.get(event.requestId);
this._handleRequestRedirect(request, event.redirectResponse.status, event.redirectResponse.headers); this._handleRequestRedirect(request, event.redirectResponse.status, event.redirectResponse.headers);
} }
this._handleRequestStart(event.requestId, null, event.request.url, event.request); this._handleRequestStart(event.requestId, null, event.request.url, event.request);
@ -165,11 +165,11 @@ class NetworkManager extends EventEmitter {
* @param {!Object} event * @param {!Object} event
*/ */
_onResponseReceived(event) { _onResponseReceived(event) {
let request = this._requestIdToRequest.get(event.requestId); const request = this._requestIdToRequest.get(event.requestId);
// FileUpload sends a response without a matching request. // FileUpload sends a response without a matching request.
if (!request) if (!request)
return; return;
let response = new Response(this._client, request, event.response.status, event.response.headers); const response = new Response(this._client, request, event.response.status, event.response.headers);
request._response = response; request._response = response;
this.emit(NetworkManager.Events.Response, response); this.emit(NetworkManager.Events.Response, response);
} }
@ -178,7 +178,7 @@ class NetworkManager extends EventEmitter {
* @param {!Object} event * @param {!Object} event
*/ */
_onLoadingFinished(event) { _onLoadingFinished(event) {
let request = this._requestIdToRequest.get(event.requestId); const request = this._requestIdToRequest.get(event.requestId);
// For certain requestIds we never receive requestWillBeSent event. // For certain requestIds we never receive requestWillBeSent event.
// @see https://crbug.com/750469 // @see https://crbug.com/750469
if (!request) if (!request)
@ -193,7 +193,7 @@ class NetworkManager extends EventEmitter {
* @param {!Object} event * @param {!Object} event
*/ */
_onLoadingFailed(event) { _onLoadingFailed(event) {
let request = this._requestIdToRequest.get(event.requestId); const request = this._requestIdToRequest.get(event.requestId);
// For certain requestIds we never receive requestWillBeSent event. // For certain requestIds we never receive requestWillBeSent event.
// @see https://crbug.com/750469 // @see https://crbug.com/750469
if (!request) if (!request)
@ -249,7 +249,7 @@ class Request {
let headers = undefined; let headers = undefined;
if (overrides.headers) { if (overrides.headers) {
headers = {}; headers = {};
for (let entry of overrides.headers) for (const entry of overrides.headers)
headers[entry[0]] = entry[1]; headers[entry[0]] = entry[1];
} }
this._client.send('Network.continueInterceptedRequest', { this._client.send('Network.continueInterceptedRequest', {
@ -300,7 +300,7 @@ class Response {
buffer() { buffer() {
if (!this._contentPromise) { if (!this._contentPromise) {
this._contentPromise = this._request._completePromise.then(async() => { this._contentPromise = this._request._completePromise.then(async() => {
let response = await this._client.send('Network.getResponseBody', { const response = await this._client.send('Network.getResponseBody', {
requestId: this._request._requestId requestId: this._request._requestId
}); });
return Buffer.from(response.body, response.base64Encoded ? 'base64' : 'utf8'); return Buffer.from(response.body, response.base64Encoded ? 'base64' : 'utf8');
@ -313,7 +313,7 @@ class Response {
* @return {!Promise<string>} * @return {!Promise<string>}
*/ */
async text() { async text() {
let content = await this.buffer(); const content = await this.buffer();
return content.toString('utf8'); return content.toString('utf8');
} }
@ -321,7 +321,7 @@ class Response {
* @return {!Promise<!Object>} * @return {!Promise<!Object>}
*/ */
async json() { async json() {
let content = await this.text(); const content = await this.text();
return JSON.parse(content); return JSON.parse(content);
} }
@ -339,15 +339,15 @@ helper.tracePublicAPI(Response);
* @return {string} * @return {string}
*/ */
function generateRequestHash(request) { function generateRequestHash(request) {
let hash = { const hash = {
url: request.url, url: request.url,
method: request.method, method: request.method,
postData: request.postData, postData: request.postData,
headers: {}, headers: {},
}; };
let headers = Object.keys(request.headers); const headers = Object.keys(request.headers);
headers.sort(); headers.sort();
for (let header of headers) { for (const header of headers) {
if (header === 'Accept' || header === 'Referer' || header === 'X-DevTools-Emulate-Network-Conditions-Client-Id') if (header === 'Accept' || header === 'Referer' || header === 'X-DevTools-Emulate-Network-Conditions-Client-Id')
continue; continue;
hash.headers[header] = request.headers[header]; hash.headers[header] = request.headers[header];
@ -360,7 +360,7 @@ function generateRequestHash(request) {
* @return {string} * @return {string}
*/ */
function removeURLHash(url) { function removeURLHash(url) {
let urlObject = new URL(url); const urlObject = new URL(url);
urlObject.hash = ''; urlObject.hash = '';
return urlObject.toString(); return urlObject.toString();
} }

View File

@ -171,7 +171,7 @@ class Page extends EventEmitter {
throw new Error(`Failed to add page binding with name ${name}: window['${name}'] already exists!`); throw new Error(`Failed to add page binding with name ${name}: window['${name}'] already exists!`);
this._pageBindings[name] = puppeteerFunction; this._pageBindings[name] = puppeteerFunction;
let expression = helper.evaluationString(addPageBinding, name); const expression = helper.evaluationString(addPageBinding, name);
await this._client.send('Page.addScriptToEvaluateOnNewDocument', { source: expression }); await this._client.send('Page.addScriptToEvaluateOnNewDocument', { source: expression });
await this._client.send('Runtime.evaluate', { expression, returnByValue: true }); await this._client.send('Runtime.evaluate', { expression, returnByValue: true });
@ -213,15 +213,15 @@ class Page extends EventEmitter {
* @param {!Object} exceptionDetails * @param {!Object} exceptionDetails
*/ */
_handleException(exceptionDetails) { _handleException(exceptionDetails) {
let message = helper.getExceptionMessage(exceptionDetails); const message = helper.getExceptionMessage(exceptionDetails);
this.emit(Page.Events.PageError, new Error(message)); this.emit(Page.Events.PageError, new Error(message));
} }
async _onConsoleAPI(event) { async _onConsoleAPI(event) {
if (event.type === 'debug' && event.args.length && event.args[0].value === 'driver:page-binding') { if (event.type === 'debug' && event.args.length && event.args[0].value === 'driver:page-binding') {
let {name, seq, args} = JSON.parse(event.args[1].value); const {name, seq, args} = JSON.parse(event.args[1].value);
let result = await this._pageBindings[name](...args); const result = await this._pageBindings[name](...args);
let expression = helper.evaluationString(deliverResult, name, seq, result); const expression = helper.evaluationString(deliverResult, name, seq, result);
this._client.send('Runtime.evaluate', { expression }); this._client.send('Runtime.evaluate', { expression });
function deliverResult(name, seq, result) { function deliverResult(name, seq, result) {
@ -234,7 +234,7 @@ class Page extends EventEmitter {
event.args.map(arg => helper.releaseObject(this._client, arg)); event.args.map(arg => helper.releaseObject(this._client, arg));
return; return;
} }
let values = await Promise.all(event.args.map(arg => helper.serializeRemoteObject(this._client, arg))); const values = await Promise.all(event.args.map(arg => helper.serializeRemoteObject(this._client, arg)));
this.emit(Page.Events.Console, ...values); this.emit(Page.Events.Console, ...values);
} }
@ -249,7 +249,7 @@ class Page extends EventEmitter {
else if (event.type === 'beforeunload') else if (event.type === 'beforeunload')
dialogType = Dialog.Type.BeforeUnload; dialogType = Dialog.Type.BeforeUnload;
console.assert(dialogType, 'Unknown javascript dialog type: ' + event.type); console.assert(dialogType, 'Unknown javascript dialog type: ' + event.type);
let dialog = new Dialog(this._client, dialogType, event.message, event.defaultPrompt); const dialog = new Dialog(this._client, dialogType, event.message, event.defaultPrompt);
this.emit(Page.Events.Dialog, dialog); this.emit(Page.Events.Dialog, dialog);
} }
@ -419,7 +419,7 @@ class Page extends EventEmitter {
* @return {!Promise} * @return {!Promise}
*/ */
async evaluateOnNewDocument(pageFunction, ...args) { async evaluateOnNewDocument(pageFunction, ...args) {
let source = helper.evaluationString(pageFunction, ...args); const source = helper.evaluationString(pageFunction, ...args);
await this._client.send('Page.addScriptToEvaluateOnNewDocument', { source }); await this._client.send('Page.addScriptToEvaluateOnNewDocument', { source });
} }
@ -430,7 +430,7 @@ class Page extends EventEmitter {
async screenshot(options = {}) { async screenshot(options = {}) {
let screenshotType = null; let screenshotType = null;
if (options.path) { if (options.path) {
let mimeType = mime.lookup(options.path); const mimeType = mime.lookup(options.path);
if (mimeType === 'image/png') if (mimeType === 'image/png')
screenshotType = 'png'; screenshotType = 'png';
else if (mimeType === 'image/jpeg') else if (mimeType === 'image/jpeg')
@ -488,14 +488,14 @@ class Page extends EventEmitter {
if (options.omitBackground) if (options.omitBackground)
await this._client.send('Emulation.setDefaultBackgroundColorOverride', { color: { r: 0, g: 0, b: 0, a: 0 } }); await this._client.send('Emulation.setDefaultBackgroundColorOverride', { color: { r: 0, g: 0, b: 0, a: 0 } });
let result = await this._client.send('Page.captureScreenshot', { format, quality: options.quality, clip }); const result = await this._client.send('Page.captureScreenshot', { format, quality: options.quality, clip });
if (options.omitBackground) if (options.omitBackground)
await this._client.send('Emulation.setDefaultBackgroundColorOverride'); await this._client.send('Emulation.setDefaultBackgroundColorOverride');
if (options.fullPage) if (options.fullPage)
await this.setViewport(this._viewport); await this.setViewport(this._viewport);
let buffer = new Buffer(result.data, 'base64'); const buffer = new Buffer(result.data, 'base64');
if (options.path) if (options.path)
fs.writeFileSync(options.path, buffer); fs.writeFileSync(options.path, buffer);
return buffer; return buffer;
@ -506,16 +506,16 @@ class Page extends EventEmitter {
* @return {!Promise<!Buffer>} * @return {!Promise<!Buffer>}
*/ */
async pdf(options = {}) { async pdf(options = {}) {
let scale = options.scale || 1; const scale = options.scale || 1;
let displayHeaderFooter = !!options.displayHeaderFooter; const displayHeaderFooter = !!options.displayHeaderFooter;
let printBackground = !!options.printBackground; const printBackground = !!options.printBackground;
let landscape = !!options.landscape; const landscape = !!options.landscape;
let pageRanges = options.pageRanges || ''; const pageRanges = options.pageRanges || '';
let paperWidth = 8.5; let paperWidth = 8.5;
let paperHeight = 11; let paperHeight = 11;
if (options.format) { if (options.format) {
let format = Page.PaperFormats[options.format.toLowerCase()]; const format = Page.PaperFormats[options.format.toLowerCase()];
console.assert(format, 'Unknown paper format: ' + options.format); console.assert(format, 'Unknown paper format: ' + options.format);
paperWidth = format.width; paperWidth = format.width;
paperHeight = format.height; paperHeight = format.height;
@ -524,13 +524,13 @@ class Page extends EventEmitter {
paperHeight = convertPrintParameterToInches(options.height) || paperHeight; paperHeight = convertPrintParameterToInches(options.height) || paperHeight;
} }
let marginOptions = options.margin || {}; const marginOptions = options.margin || {};
let marginTop = convertPrintParameterToInches(marginOptions.top) || 0; const marginTop = convertPrintParameterToInches(marginOptions.top) || 0;
let marginLeft = convertPrintParameterToInches(marginOptions.left) || 0; const marginLeft = convertPrintParameterToInches(marginOptions.left) || 0;
let marginBottom = convertPrintParameterToInches(marginOptions.bottom) || 0; const marginBottom = convertPrintParameterToInches(marginOptions.bottom) || 0;
let marginRight = convertPrintParameterToInches(marginOptions.right) || 0; const marginRight = convertPrintParameterToInches(marginOptions.right) || 0;
let result = await this._client.send('Page.printToPDF', { const result = await this._client.send('Page.printToPDF', {
landscape: landscape, landscape: landscape,
displayHeaderFooter: displayHeaderFooter, displayHeaderFooter: displayHeaderFooter,
printBackground: printBackground, printBackground: printBackground,
@ -543,7 +543,7 @@ class Page extends EventEmitter {
marginRight: marginRight, marginRight: marginRight,
pageRanges: pageRanges pageRanges: pageRanges
}); });
let buffer = new Buffer(result.data, 'base64'); const buffer = new Buffer(result.data, 'base64');
if (options.path) if (options.path)
fs.writeFileSync(options.path, buffer); fs.writeFileSync(options.path, buffer);
return buffer; return buffer;
@ -583,7 +583,7 @@ class Page extends EventEmitter {
* @return {!Promise} * @return {!Promise}
*/ */
async click(selector, options) { async click(selector, options) {
let handle = await this.$(selector); const handle = await this.$(selector);
console.assert(handle, 'No node found for selector: ' + selector); console.assert(handle, 'No node found for selector: ' + selector);
await handle.click(options); await handle.click(options);
await handle.dispose(); await handle.dispose();
@ -594,7 +594,7 @@ class Page extends EventEmitter {
* @param {!Promise} * @param {!Promise}
*/ */
async hover(selector) { async hover(selector) {
let handle = await this.$(selector); const handle = await this.$(selector);
console.assert(handle, 'No node found for selector: ' + selector); console.assert(handle, 'No node found for selector: ' + selector);
await handle.hover(); await handle.hover();
await handle.dispose(); await handle.dispose();
@ -605,7 +605,7 @@ class Page extends EventEmitter {
* @return {!Promise} * @return {!Promise}
*/ */
async focus(selector) { async focus(selector) {
let handle = await this.$(selector); const handle = await this.$(selector);
console.assert(handle, 'No node found for selector: ' + selector); console.assert(handle, 'No node found for selector: ' + selector);
await handle.evaluate(element => element.focus()); await handle.evaluate(element => element.focus());
await handle.dispose(); await handle.dispose();
@ -621,7 +621,7 @@ class Page extends EventEmitter {
if (options && options.delay) if (options && options.delay)
delay = options.delay; delay = options.delay;
let last; let last;
for (let char of text) { for (const char of text) {
last = this.press(char, {text: char, delay}); last = this.press(char, {text: char, delay});
if (delay) if (delay)
await new Promise(f => setTimeout(f, delay)); await new Promise(f => setTimeout(f, delay));
@ -684,7 +684,7 @@ Page.PaperFormats = {
a5: {width: 5.83, height: 8.27 }, a5: {width: 5.83, height: 8.27 },
}; };
let unitToPixels = { const unitToPixels = {
'px': 1, 'px': 1,
'in': 96, 'in': 96,
'cm': 37.8, 'cm': 37.8,
@ -703,7 +703,7 @@ function convertPrintParameterToInches(parameter) {
// Treat numbers as pixel values to be aligned with phantom's paperSize. // Treat numbers as pixel values to be aligned with phantom's paperSize.
pixels = /** @type {number} */ (parameter); pixels = /** @type {number} */ (parameter);
} else if (helper.isString(parameter)) { } else if (helper.isString(parameter)) {
let text = parameter; const text = parameter;
let unit = text.substring(text.length - 2).toLowerCase(); let unit = text.substring(text.length - 2).toLowerCase();
let valueText = ''; let valueText = '';
if (unitToPixels.hasOwnProperty(unit)) { if (unitToPixels.hasOwnProperty(unit)) {
@ -714,7 +714,7 @@ function convertPrintParameterToInches(parameter) {
unit = 'px'; unit = 'px';
valueText = text; valueText = text;
} }
let value = Number(valueText); const value = Number(valueText);
console.assert(!isNaN(value), 'Failed to parse parameter value: ' + text); console.assert(!isNaN(value), 'Failed to parse parameter value: ' + text);
pixels = value * unitToPixels[unit]; pixels = value * unitToPixels[unit];
} else { } else {

View File

@ -57,7 +57,7 @@ class Tracing {
*/ */
async stop() { async stop() {
let fulfill; let fulfill;
let contentPromise = new Promise(x => fulfill = x); const contentPromise = new Promise(x => fulfill = x);
this._client.once('Tracing.tracingComplete', event => { this._client.once('Tracing.tracingComplete', event => {
this._readStream(event.stream, this._path).then(fulfill); this._readStream(event.stream, this._path).then(fulfill);
}); });
@ -73,9 +73,9 @@ class Tracing {
*/ */
async _readStream(handle, path) { async _readStream(handle, path) {
let eof = false; let eof = false;
let file = fs.openSync(path, 'w'); const file = fs.openSync(path, 'w');
while (!eof) { while (!eof) {
let response = await this._client.send('IO.read', {handle}); const response = await this._client.send('IO.read', {handle});
eof = response.eof; eof = response.eof;
if (path) if (path)
fs.writeSync(file, response.data); fs.writeSync(file, response.data);

View File

@ -39,9 +39,9 @@ class Helper {
return exceptionDetails.exception.description; return exceptionDetails.exception.description;
let message = exceptionDetails.text; let message = exceptionDetails.text;
if (exceptionDetails.stackTrace) { if (exceptionDetails.stackTrace) {
for (let callframe of exceptionDetails.stackTrace.callFrames) { for (const callframe of exceptionDetails.stackTrace.callFrames) {
let location = callframe.url + ':' + callframe.lineNumber + ':' + callframe.columnNumber; const location = callframe.url + ':' + callframe.lineNumber + ':' + callframe.columnNumber;
let functionName = callframe.functionName || '<anonymous>'; const functionName = callframe.functionName || '<anonymous>';
message += `\n at ${functionName} (${location})`; message += `\n at ${functionName} (${location})`;
} }
} }
@ -73,7 +73,7 @@ class Helper {
if (remoteObject.subtype === 'promise') if (remoteObject.subtype === 'promise')
return remoteObject.description; return remoteObject.description;
try { try {
let response = await client.send('Runtime.callFunctionOn', { const response = await client.send('Runtime.callFunctionOn', {
objectId: remoteObject.objectId, objectId: remoteObject.objectId,
functionDeclaration: 'function() { return this; }', functionDeclaration: 'function() { return this; }',
returnByValue: true, returnByValue: true,
@ -112,15 +112,15 @@ class Helper {
const debug = require('debug')(`puppeteer:${className}`); const debug = require('debug')(`puppeteer:${className}`);
if (!debug.enabled && !apiCoverage) if (!debug.enabled && !apiCoverage)
return; return;
for (let methodName of Reflect.ownKeys(classType.prototype)) { for (const methodName of Reflect.ownKeys(classType.prototype)) {
const method = Reflect.get(classType.prototype, methodName); const method = Reflect.get(classType.prototype, methodName);
if (methodName === 'constructor' || typeof methodName !== 'string' || methodName.startsWith('_') || typeof method !== 'function') if (methodName === 'constructor' || typeof methodName !== 'string' || methodName.startsWith('_') || typeof method !== 'function')
continue; continue;
if (apiCoverage) if (apiCoverage)
apiCoverage.set(`${className}.${methodName}`, false); apiCoverage.set(`${className}.${methodName}`, false);
Reflect.set(classType.prototype, methodName, function(...args) { Reflect.set(classType.prototype, methodName, function(...args) {
let argsText = args.map(stringifyArgument).join(', '); const argsText = args.map(stringifyArgument).join(', ');
let callsite = `${className}.${methodName}(${argsText})`; const callsite = `${className}.${methodName}(${argsText})`;
if (debug.enabled) if (debug.enabled)
debug(callsite); debug(callsite);
if (apiCoverage) if (apiCoverage)
@ -131,12 +131,12 @@ class Helper {
if (classType.Events) { if (classType.Events) {
if (apiCoverage) { if (apiCoverage) {
for (let event of Object.values(classType.Events)) for (const event of Object.values(classType.Events))
apiCoverage.set(`${className}.emit(${JSON.stringify(event)})`, false); apiCoverage.set(`${className}.emit(${JSON.stringify(event)})`, false);
} }
const method = Reflect.get(classType.prototype, 'emit'); const method = Reflect.get(classType.prototype, 'emit');
Reflect.set(classType.prototype, 'emit', function(event, ...args) { Reflect.set(classType.prototype, 'emit', function(event, ...args) {
let argsText = [JSON.stringify(event)].concat(args.map(stringifyArgument)).join(', '); const argsText = [JSON.stringify(event)].concat(args.map(stringifyArgument)).join(', ');
if (debug.enabled && this.listenerCount(event)) if (debug.enabled && this.listenerCount(event))
debug(`${className}.emit(${argsText})`); debug(`${className}.emit(${argsText})`);
if (apiCoverage && this.listenerCount(event)) if (apiCoverage && this.listenerCount(event))
@ -160,7 +160,7 @@ class Helper {
} }
const state = {}; const state = {};
const keys = Object.keys(arg); const keys = Object.keys(arg);
for (let key of keys) { for (const key of keys) {
const value = arg[key]; const value = arg[key];
if (Helper.isString(value) || Helper.isNumber(value)) if (Helper.isString(value) || Helper.isNumber(value))
state[key] = JSON.stringify(value); state[key] = JSON.stringify(value);
@ -185,7 +185,7 @@ class Helper {
* @param {!Array<{emitter: !EventEmitter, eventName: string, handler: function(?)}>} * @param {!Array<{emitter: !EventEmitter, eventName: string, handler: function(?)}>}
*/ */
static removeEventListeners(listeners) { static removeEventListeners(listeners) {
for (let listener of listeners) for (const listener of listeners)
listener.emitter.removeListener(listener.eventName, listener.handler); listener.emitter.removeListener(listener.eventName, listener.handler);
listeners.splice(0, listeners.length); listeners.splice(0, listeners.length);
} }

View File

@ -68,7 +68,7 @@ class FileSystem {
* @param {string} toPath * @param {string} toPath
*/ */
copy(fromPath, toPath) { copy(fromPath, toPath) {
let content = fs.readFileSync(fromPath); const content = fs.readFileSync(fromPath);
fs.writeFileSync(toPath, content); fs.writeFileSync(toPath, content);
} }
@ -77,7 +77,7 @@ class FileSystem {
* @param {string} toPath * @param {string} toPath
*/ */
move(fromPath, toPath) { move(fromPath, toPath) {
let content = fs.readFileSync(fromPath); const content = fs.readFileSync(fromPath);
fs.writeFileSync(toPath, content); fs.writeFileSync(toPath, content);
fs.unlinkSync(fromPath); fs.unlinkSync(fromPath);
} }
@ -170,7 +170,7 @@ class FileSystem {
* @param {string} mode * @param {string} mode
*/ */
write(filePath, data, mode) { write(filePath, data, mode) {
let fd = new FileDescriptor(filePath, mode, 'utf8'); const fd = new FileDescriptor(filePath, mode, 'utf8');
fd.write(data); fd.write(data);
fd.close(); fd.close();
} }
@ -288,8 +288,8 @@ class FileSystem {
} }
} }
let fdwrite = deasync(fs.write); const fdwrite = deasync(fs.write);
let fdread = deasync(fs.read); const fdread = deasync(fs.read);
class FileDescriptor { class FileDescriptor {
/** /**
@ -318,8 +318,8 @@ class FileDescriptor {
* @param {string} data * @param {string} data
*/ */
write(data) { write(data) {
let buffer = Buffer.from(data, this._encoding); const buffer = Buffer.from(data, this._encoding);
let written = fdwrite(this._fd, buffer, 0, buffer.length, this._position); const written = fdwrite(this._fd, buffer, 0, buffer.length, this._position);
this._position += written; this._position += written;
} }
@ -344,8 +344,8 @@ class FileDescriptor {
size = fs.fstatSync(this._fd).size; size = fs.fstatSync(this._fd).size;
position = 0; position = 0;
} }
let buffer = new Buffer(size); const buffer = new Buffer(size);
let bytesRead = fdread(this._fd, buffer, 0, size, position); const bytesRead = fdread(this._fd, buffer, 0, size, position);
this._position += bytesRead; this._position += bytesRead;
return buffer.toString(this._encoding); return buffer.toString(this._encoding);
} }

View File

@ -123,7 +123,7 @@ module.exports.create = function(context, scriptPath) {
* @param {string} filename * @param {string} filename
*/ */
loadModule: function(moduleSource, filename) { loadModule: function(moduleSource, filename) {
let code = [ const code = [
'(function(require, exports, module) {\n', '(function(require, exports, module) {\n',
moduleSource, moduleSource,
'\n}.call({},', '\n}.call({},',

View File

@ -61,7 +61,7 @@ class StandardInput {
if (this._closed && !this._lines.length) if (this._closed && !this._lines.length)
return ''; return '';
if (!this._lines.length) { if (!this._lines.length) {
let linePromise = new Promise(fulfill => this._readline.once('line', fulfill)); const linePromise = new Promise(fulfill => this._readline.once('line', fulfill));
await(linePromise); await(linePromise);
} }
return this._lines.shift(); return this._lines.shift();
@ -72,10 +72,10 @@ class StandardInput {
*/ */
read() { read() {
if (!this._closed) { if (!this._closed) {
let closePromise = new Promise(fulfill => this._readline.once('close', fulfill)); const closePromise = new Promise(fulfill => this._readline.once('close', fulfill));
await(closePromise); await(closePromise);
} }
let text = this._lines.join('\n'); const text = this._lines.join('\n');
this._lines = []; this._lines = [];
return text; return text;
} }

View File

@ -152,7 +152,7 @@ class WebPage {
* @return {string} * @return {string}
*/ */
get focusedFrameName() { get focusedFrameName() {
let focusedFrame = this._focusedFrame(); const focusedFrame = this._focusedFrame();
return focusedFrame ? focusedFrame.name() : ''; return focusedFrame ? focusedFrame.name() : '';
} }
@ -160,10 +160,10 @@ class WebPage {
* @return {?Frame} * @return {?Frame}
*/ */
_focusedFrame() { _focusedFrame() {
let frames = this._currentFrame.childFrames().slice(); const frames = this._currentFrame.childFrames().slice();
frames.push(this._currentFrame); frames.push(this._currentFrame);
let promises = frames.map(frame => frame.evaluate(() => document.hasFocus())); const promises = frames.map(frame => frame.evaluate(() => document.hasFocus()));
let result = await(Promise.all(promises)); const result = await(Promise.all(promises));
for (let i = 0; i < result.length; ++i) { for (let i = 0; i < result.length; ++i) {
if (result[i]) if (result[i])
return frames[i]; return frames[i];
@ -172,7 +172,7 @@ class WebPage {
} }
switchToFocusedFrame() { switchToFocusedFrame() {
let frame = this._focusedFrame(); const frame = this._focusedFrame();
this._currentFrame = frame; this._currentFrame = frame;
} }
@ -196,7 +196,7 @@ class WebPage {
* @return {boolean} * @return {boolean}
*/ */
switchToParentFrame() { switchToParentFrame() {
let frame = this._currentFrame.parentFrame(); const frame = this._currentFrame.parentFrame();
if (!frame) if (!frame)
return false; return false;
this._currentFrame = frame; this._currentFrame = frame;
@ -236,8 +236,8 @@ class WebPage {
_onRequest(request) { _onRequest(request) {
if (!this._onResourceRequestedCallback) if (!this._onResourceRequestedCallback)
return; return;
let requestData = new RequestData(request); const requestData = new RequestData(request);
let phantomRequest = new PhantomRequest(); const phantomRequest = new PhantomRequest();
this._onResourceRequestedCallback.call(null, requestData, phantomRequest); this._onResourceRequestedCallback.call(null, requestData, phantomRequest);
if (phantomRequest._aborted) { if (phantomRequest._aborted) {
request.abort(); request.abort();
@ -252,14 +252,14 @@ class WebPage {
_onResponseReceived(response) { _onResponseReceived(response) {
if (!this.onResourceReceived) if (!this.onResourceReceived)
return; return;
let phantomResponse = new PhantomResponse(response, false /* isResponseFinished */); const phantomResponse = new PhantomResponse(response, false /* isResponseFinished */);
this.onResourceReceived.call(null, phantomResponse); this.onResourceReceived.call(null, phantomResponse);
} }
_onRequestFinished(request) { _onRequestFinished(request) {
if (!this.onResourceReceived) if (!this.onResourceReceived)
return; return;
let phantomResponse = new PhantomResponse(request.response(), true /* isResponseFinished */); const phantomResponse = new PhantomResponse(request.response(), true /* isResponseFinished */);
this.onResourceReceived.call(null, phantomResponse); this.onResourceReceived.call(null, phantomResponse);
} }
@ -391,10 +391,10 @@ class WebPage {
this._onAlertCallback.call(null, dialog.message()); this._onAlertCallback.call(null, dialog.message());
await(dialog.accept()); await(dialog.accept());
} else if (dialog.type === 'confirm' && this._onConfirmCallback) { } else if (dialog.type === 'confirm' && this._onConfirmCallback) {
let result = this._onConfirmCallback.call(null, dialog.message()); const result = this._onConfirmCallback.call(null, dialog.message());
await(result ? dialog.accept() : dialog.dismiss()); await(result ? dialog.accept() : dialog.dismiss());
} else if (dialog.type === 'prompt' && this._onPromptCallback) { } else if (dialog.type === 'prompt' && this._onPromptCallback) {
let result = this._onPromptCallback.call(null, dialog.message(), dialog.defaultValue()); const result = this._onPromptCallback.call(null, dialog.message(), dialog.defaultValue());
await(result ? dialog.accept(result) : dialog.dismiss()); await(result ? dialog.accept(result) : dialog.dismiss());
} }
} }
@ -449,7 +449,7 @@ class WebPage {
await(this._page.keyboard.up(String.fromCharCode(keyOrKeys))); await(this._page.keyboard.up(String.fromCharCode(keyOrKeys)));
break; break;
} }
for (let key of keyOrKeys) for (const key of keyOrKeys)
await(this._page.keyboard.up(key)); await(this._page.keyboard.up(key));
break; break;
case 'keypress': case 'keypress':
@ -475,7 +475,7 @@ class WebPage {
await(this._page.keyboard.down(String.fromCharCode(keyOrKeys))); await(this._page.keyboard.down(String.fromCharCode(keyOrKeys)));
break; break;
} }
for (let key of keyOrKeys) for (const key of keyOrKeys)
await(this._page.keyboard.down(key)); await(this._page.keyboard.down(key));
break; break;
} }
@ -539,7 +539,7 @@ class WebPage {
errorString: 'SSL handshake failed' errorString: 'SSL handshake failed'
}); });
} }
let status = error ? 'fail' : 'success'; const status = error ? 'fail' : 'success';
if (this.onLoadFinished) if (this.onLoadFinished)
this.onLoadFinished.call(null, status); this.onLoadFinished.call(null, status);
if (callback) if (callback)
@ -574,8 +574,8 @@ class WebPage {
*/ */
render(fileName) { render(fileName) {
if (fileName.endsWith('pdf')) { if (fileName.endsWith('pdf')) {
let options = {}; const options = {};
let paperSize = this.paperSize || {}; const paperSize = this.paperSize || {};
options.margin = paperSize.margin; options.margin = paperSize.margin;
options.format = paperSize.format; options.format = paperSize.format;
options.landscape = paperSize.orientation === 'landscape'; options.landscape = paperSize.orientation === 'landscape';
@ -584,7 +584,7 @@ class WebPage {
options.path = fileName; options.path = fileName;
await(this._page.pdf(options)); await(this._page.pdf(options));
} else { } else {
let options = {}; const options = {};
if (this.clipRect && (this.clipRect.left || this.clipRect.top || this.clipRect.width || this.clipRect.height)) { if (this.clipRect && (this.clipRect.left || this.clipRect.top || this.clipRect.width || this.clipRect.height)) {
options.clip = { options.clip = {
x: this.clipRect.left, x: this.clipRect.left,
@ -669,7 +669,7 @@ class PhantomResponse {
this.statusText = response.statusText; this.statusText = response.statusText;
this.stage = isResponseFinished ? 'end' : 'start'; this.stage = isResponseFinished ? 'end' : 'start';
this.headers = []; this.headers = [];
for (let entry of response.headers.entries()) { for (const entry of response.headers.entries()) {
this.headers.push({ this.headers.push({
name: entry[0], name: entry[0],
value: entry[1] value: entry[1]
@ -685,7 +685,7 @@ class RequestData {
constructor(request) { constructor(request) {
this.url = request.url, this.url = request.url,
this.headers = {}; this.headers = {};
for (let entry of request.headers.entries()) for (const entry of request.headers.entries())
this.headers[entry[0]] = entry[1]; this.headers[entry[0]] = entry[1];
} }
} }
@ -714,7 +714,7 @@ class AsyncEmitter extends EventEmitter {
_onListenerAdded(event, listener) { _onListenerAdded(event, listener) {
// Async listener calls original listener on next tick. // Async listener calls original listener on next tick.
let asyncListener = (...args) => { const asyncListener = (...args) => {
process.nextTick(() => listener.apply(null, args)); process.nextTick(() => listener.apply(null, args));
}; };
listener[this._symbol] = asyncListener; listener[this._symbol] = asyncListener;

View File

@ -47,17 +47,17 @@ class WebServer {
return false; return false;
this.newRequest = callback; this.newRequest = callback;
this._server.listen(port); this._server.listen(port);
let errorPromise = new Promise(x => this._server.once('error', x)); const errorPromise = new Promise(x => this._server.once('error', x));
let successPromise = new Promise(x => this._server.once('listening', x)); const successPromise = new Promise(x => this._server.once('listening', x));
await(Promise.race([errorPromise, successPromise])); await(Promise.race([errorPromise, successPromise]));
if (!this._server.listening) if (!this._server.listening)
return false; return false;
this._server.on('request', (req, res) => { this._server.on('request', (req, res) => {
res.close = res.end.bind(res); res.close = res.end.bind(res);
let headers = res.getHeaders(); const headers = res.getHeaders();
res.headers = []; res.headers = [];
for (let key in headers) { for (const key in headers) {
res.headers.push({ res.headers.push({
name: key, name: key,
value: headers[key] value: headers[key]
@ -65,7 +65,7 @@ class WebServer {
} }
res.header = res.getHeader; res.header = res.getHeader;
res.setHeaders = headers => { res.setHeaders = headers => {
for (let key in headers) for (const key in headers)
res.setHeader(key, headers[key]); res.setHeader(key, headers[key]);
}; };
Object.defineProperty(res, 'statusCode', { Object.defineProperty(res, 'statusCode', {

View File

@ -43,21 +43,21 @@ if (argv['ssl-certificates-path']) {
return; return;
} }
let scriptArguments = argv._; const scriptArguments = argv._;
if (!scriptArguments.length) { if (!scriptArguments.length) {
console.log(__filename.split('/').pop() + ' [scriptfile]'); console.log(__filename.split('/').pop() + ' [scriptfile]');
return; return;
} }
let scriptPath = path.resolve(process.cwd(), scriptArguments[0]); const scriptPath = path.resolve(process.cwd(), scriptArguments[0]);
if (!fs.existsSync(scriptPath)) { if (!fs.existsSync(scriptPath)) {
console.error(`script not found: ${scriptPath}`); console.error(`script not found: ${scriptPath}`);
process.exit(1); process.exit(1);
return; return;
} }
let context = createPhantomContext(argv.headless, scriptPath, argv); const context = createPhantomContext(argv.headless, scriptPath, argv);
let scriptContent = fs.readFileSync(scriptPath, 'utf8'); const scriptContent = fs.readFileSync(scriptPath, 'utf8');
vm.runInContext(scriptContent, context); vm.runInContext(scriptContent, context);
/** /**
@ -67,7 +67,7 @@ vm.runInContext(scriptContent, context);
* @return {!Object} * @return {!Object}
*/ */
function createPhantomContext(headless, scriptPath, argv) { function createPhantomContext(headless, scriptPath, argv) {
let context = {}; const context = {};
let browser = null; let browser = null;
context.setInterval = setInterval; context.setInterval = setInterval;
context.setTimeout = setTimeout; context.setTimeout = setTimeout;
@ -81,7 +81,7 @@ function createPhantomContext(headless, scriptPath, argv) {
vm.createContext(context); vm.createContext(context);
let nativeExports = { const nativeExports = {
fs: new FileSystem(), fs: new FileSystem(),
system: new System(argv._), system: new System(argv._),
webpage: { webpage: {
@ -95,8 +95,8 @@ function createPhantomContext(headless, scriptPath, argv) {
}, },
child_process: child_process child_process: child_process
}; };
let bootstrapPath = path.join(__dirname, '..', 'third_party', 'phantomjs', 'bootstrap.js'); const bootstrapPath = path.join(__dirname, '..', 'third_party', 'phantomjs', 'bootstrap.js');
let bootstrapCode = fs.readFileSync(bootstrapPath, 'utf8'); const bootstrapCode = fs.readFileSync(bootstrapPath, 'utf8');
vm.runInContext(bootstrapCode, context, { vm.runInContext(bootstrapCode, context, {
filename: 'bootstrap.js' filename: 'bootstrap.js'
})(nativeExports); })(nativeExports);

View File

@ -1,9 +1,9 @@
// This injects a box into the page that moves with the mouse; // This injects a box into the page that moves with the mouse;
// Useful for debugging // Useful for debugging
(function(){ (function(){
let box = document.createElement('div'); const box = document.createElement('div');
box.classList.add('mouse-helper'); box.classList.add('mouse-helper');
let styleElement = document.createElement('style'); const styleElement = document.createElement('style');
styleElement.innerHTML = ` styleElement.innerHTML = `
.mouse-helper { .mouse-helper {
pointer-events: none; pointer-events: none;

View File

@ -25,7 +25,7 @@ const utils = module.exports = {
await page.evaluate(attachFrame, frameId, url); await page.evaluate(attachFrame, frameId, url);
function attachFrame(frameId, url) { function attachFrame(frameId, url) {
let frame = document.createElement('iframe'); const frame = document.createElement('iframe');
frame.src = url; frame.src = url;
frame.id = frameId; frame.id = frameId;
document.body.appendChild(frame); document.body.appendChild(frame);
@ -42,7 +42,7 @@ const utils = module.exports = {
await page.evaluate(detachFrame, frameId); await page.evaluate(detachFrame, frameId);
function detachFrame(frameId) { function detachFrame(frameId) {
let frame = document.getElementById(frameId); const frame = document.getElementById(frameId);
frame.remove(); frame.remove();
} }
}, },
@ -57,7 +57,7 @@ const utils = module.exports = {
await page.evaluate(navigateFrame, frameId, url); await page.evaluate(navigateFrame, frameId, url);
function navigateFrame(frameId, url) { function navigateFrame(frameId, url) {
let frame = document.getElementById(frameId); const frame = document.getElementById(frameId);
frame.src = url; frame.src = url;
return new Promise(x => frame.onload = x); return new Promise(x => frame.onload = x);
} }
@ -71,7 +71,7 @@ const utils = module.exports = {
dumpFrames: function(frame, indentation) { dumpFrames: function(frame, indentation) {
indentation = indentation || ''; indentation = indentation || '';
let result = indentation + frame.url(); let result = indentation + frame.url();
for (let child of frame.childFrames()) for (const child of frame.childFrames())
result += '\n' + utils.dumpFrames(child, ' ' + indentation); result += '\n' + utils.dumpFrames(child, ' ' + indentation);
return result; return result;
}, },

View File

@ -30,7 +30,7 @@ module.exports = {
}, },
}; };
let GoldenComparators = { const GoldenComparators = {
'image/png': compareImages, 'image/png': compareImages,
'text/plain': compareText 'text/plain': compareText
}; };
@ -44,15 +44,15 @@ function compareImages(actualBuffer, expectedBuffer) {
if (!actualBuffer || !(actualBuffer instanceof Buffer)) if (!actualBuffer || !(actualBuffer instanceof Buffer))
return { errorMessage: 'Actual result should be Buffer.' }; return { errorMessage: 'Actual result should be Buffer.' };
let actual = PNG.sync.read(actualBuffer); const actual = PNG.sync.read(actualBuffer);
let expected = PNG.sync.read(expectedBuffer); const expected = PNG.sync.read(expectedBuffer);
if (expected.width !== actual.width || expected.height !== actual.height) { if (expected.width !== actual.width || expected.height !== actual.height) {
return { return {
errorMessage: `Sizes differ: expected image ${expected.width}px X ${expected.height}px, but got ${actual.width}px X ${actual.height}px. ` errorMessage: `Sizes differ: expected image ${expected.width}px X ${expected.height}px, but got ${actual.width}px X ${actual.height}px. `
}; };
} }
let diff = new PNG({width: expected.width, height: expected.height}); const diff = new PNG({width: expected.width, height: expected.height});
let count = pixelmatch(expected.data, actual.data, diff.data, expected.width, expected.height, {threshold: 0.1}); const count = pixelmatch(expected.data, actual.data, diff.data, expected.width, expected.height, {threshold: 0.1});
return count > 0 ? { diff: PNG.sync.write(diff) } : null; return count > 0 ? { diff: PNG.sync.write(diff) } : null;
} }
@ -64,14 +64,14 @@ function compareImages(actualBuffer, expectedBuffer) {
function compareText(actual, expectedBuffer) { function compareText(actual, expectedBuffer) {
if (typeof actual !== 'string') if (typeof actual !== 'string')
return { errorMessage: 'Actual result should be string' }; return { errorMessage: 'Actual result should be string' };
let expected = expectedBuffer.toString('utf-8'); const expected = expectedBuffer.toString('utf-8');
if (expected === actual) if (expected === actual)
return null; return null;
let diff = new Diff(); const diff = new Diff();
let result = diff.main(expected, actual); const result = diff.main(expected, actual);
diff.cleanupSemantic(result); diff.cleanupSemantic(result);
let html = diff.prettyHtml(result); let html = diff.prettyHtml(result);
let diffStylePath = path.join(__dirname, 'diffstyle.css'); const diffStylePath = path.join(__dirname, 'diffstyle.css');
html = `<link rel="stylesheet" href="file://${diffStylePath}">` + html; html = `<link rel="stylesheet" href="file://${diffStylePath}">` + html;
return { return {
diff: html, diff: html,
@ -85,10 +85,10 @@ function compareText(actual, expectedBuffer) {
* @return {!{pass: boolean, message: (undefined|string)}} * @return {!{pass: boolean, message: (undefined|string)}}
*/ */
function compare(goldenPath, outputPath, actual, goldenName) { function compare(goldenPath, outputPath, actual, goldenName) {
let expectedPath = path.join(goldenPath, goldenName); const expectedPath = path.join(goldenPath, goldenName);
let actualPath = path.join(outputPath, goldenName); const actualPath = path.join(outputPath, goldenName);
let messageSuffix = 'Output is saved in "' + path.basename(outputPath + '" directory'); const messageSuffix = 'Output is saved in "' + path.basename(outputPath + '" directory');
if (!fs.existsSync(expectedPath)) { if (!fs.existsSync(expectedPath)) {
ensureOutputDir(); ensureOutputDir();
@ -98,15 +98,15 @@ function compare(goldenPath, outputPath, actual, goldenName) {
message: goldenName + ' is missing in golden results. ' + messageSuffix message: goldenName + ' is missing in golden results. ' + messageSuffix
}; };
} }
let expected = fs.readFileSync(expectedPath); const expected = fs.readFileSync(expectedPath);
let comparator = GoldenComparators[mime.lookup(goldenName)]; const comparator = GoldenComparators[mime.lookup(goldenName)];
if (!comparator) { if (!comparator) {
return { return {
pass: false, pass: false,
message: 'Failed to find comparator with type ' + mime.lookup(goldenName) + ': ' + goldenName message: 'Failed to find comparator with type ' + mime.lookup(goldenName) + ': ' + goldenName
}; };
} }
let result = comparator(actual, expected); const result = comparator(actual, expected);
if (!result) if (!result)
return { pass: true }; return { pass: true };
ensureOutputDir(); ensureOutputDir();
@ -114,7 +114,7 @@ function compare(goldenPath, outputPath, actual, goldenName) {
// Copy expected to the output/ folder for convenience. // Copy expected to the output/ folder for convenience.
fs.writeFileSync(addSuffix(actualPath, '-expected'), expected); fs.writeFileSync(addSuffix(actualPath, '-expected'), expected);
if (result.diff) { if (result.diff) {
let diffPath = addSuffix(actualPath, '-diff', result.diffExtension); const diffPath = addSuffix(actualPath, '-diff', result.diffExtension);
fs.writeFileSync(diffPath, result.diff); fs.writeFileSync(diffPath, result.diff);
} }
@ -139,8 +139,8 @@ function compare(goldenPath, outputPath, actual, goldenName) {
* @return {string} * @return {string}
*/ */
function addSuffix(filePath, suffix, customExtension) { function addSuffix(filePath, suffix, customExtension) {
let dirname = path.dirname(filePath); const dirname = path.dirname(filePath);
let ext = path.extname(filePath); const ext = path.extname(filePath);
let name = path.basename(filePath, ext); const name = path.basename(filePath, ext);
return path.join(dirname, name + suffix + (customExtension || ext)); return path.join(dirname, name + suffix + (customExtension || ext));
} }

View File

@ -32,7 +32,7 @@ class SimpleServer {
* @return {!SimpleServer} * @return {!SimpleServer}
*/ */
static async create(dirPath, port) { static async create(dirPath, port) {
let server = new SimpleServer(dirPath, port); const server = new SimpleServer(dirPath, port);
await new Promise(x => server._server.once('listening', x)); await new Promise(x => server._server.once('listening', x));
return server; return server;
} }
@ -43,7 +43,7 @@ class SimpleServer {
* @return {!SimpleServer} * @return {!SimpleServer}
*/ */
static async createHTTPS(dirPath, port) { static async createHTTPS(dirPath, port) {
let server = new SimpleServer(dirPath, port, { const server = new SimpleServer(dirPath, port, {
key: fs.readFileSync(path.join(__dirname, 'key.pem')), key: fs.readFileSync(path.join(__dirname, 'key.pem')),
cert: fs.readFileSync(path.join(__dirname, 'cert.pem')), cert: fs.readFileSync(path.join(__dirname, 'cert.pem')),
passphrase: 'aaaa', passphrase: 'aaaa',
@ -93,7 +93,7 @@ class SimpleServer {
*/ */
async stop() { async stop() {
this.reset(); this.reset();
for (let socket of this._sockets) for (const socket of this._sockets)
socket.destroy(); socket.destroy();
this._sockets.clear(); this._sockets.clear();
await new Promise(x => this._server.close(x)); await new Promise(x => this._server.close(x));
@ -139,8 +139,8 @@ class SimpleServer {
reset() { reset() {
this._routes.clear(); this._routes.clear();
let error = new Error('Static Server has been reset'); const error = new Error('Static Server has been reset');
for (let subscriber of this._requestSubscribers.values()) for (const subscriber of this._requestSubscribers.values())
subscriber[rejectSymbol].call(null, error); subscriber[rejectSymbol].call(null, error);
this._requestSubscribers.clear(); this._requestSubscribers.clear();
} }
@ -152,11 +152,11 @@ class SimpleServer {
else else
throw error; throw error;
}); });
let pathName = url.parse(request.url).path; const pathName = url.parse(request.url).path;
// Notify request subscriber. // Notify request subscriber.
if (this._requestSubscribers.has(pathName)) if (this._requestSubscribers.has(pathName))
this._requestSubscribers.get(pathName)[fulfillSymbol].call(null, request); this._requestSubscribers.get(pathName)[fulfillSymbol].call(null, request);
let handler = this._routes.get(pathName); const handler = this._routes.get(pathName);
if (handler) if (handler)
handler.call(null, request, response); handler.call(null, request, response);
else else

View File

@ -82,9 +82,9 @@ afterAll(SX(async function() {
describe('Browser', function() { describe('Browser', function() {
it('Browser.Options.ignoreHTTPSErrors', SX(async function() { it('Browser.Options.ignoreHTTPSErrors', SX(async function() {
let options = Object.assign({ignoreHTTPSErrors: true}, defaultBrowserOptions); const options = Object.assign({ignoreHTTPSErrors: true}, defaultBrowserOptions);
let browser = await puppeteer.launch(options); const browser = await puppeteer.launch(options);
let page = await browser.newPage(); const page = await browser.newPage();
let error = null; let error = null;
let response = null; let response = null;
try { try {
@ -97,20 +97,20 @@ describe('Browser', function() {
browser.close(); browser.close();
})); }));
it('should reject all promises when browser is closed', SX(async function() { it('should reject all promises when browser is closed', SX(async function() {
let browser = await puppeteer.launch(defaultBrowserOptions); const browser = await puppeteer.launch(defaultBrowserOptions);
let page = await browser.newPage(); const page = await browser.newPage();
let error = null; let error = null;
let neverResolves = page.evaluate(() => new Promise(r => {})).catch(e => error = e); const neverResolves = page.evaluate(() => new Promise(r => {})).catch(e => error = e);
browser.close(); browser.close();
await neverResolves; await neverResolves;
expect(error.message).toContain('Protocol error'); expect(error.message).toContain('Protocol error');
})); }));
it('Puppeteer.connect', SX(async function() { it('Puppeteer.connect', SX(async function() {
let originalBrowser = await puppeteer.launch(defaultBrowserOptions); const originalBrowser = await puppeteer.launch(defaultBrowserOptions);
let browser = await puppeteer.connect({ const browser = await puppeteer.connect({
browserWSEndpoint: originalBrowser.wsEndpoint() browserWSEndpoint: originalBrowser.wsEndpoint()
}); });
let page = await browser.newPage(); const page = await browser.newPage();
expect(await page.evaluate(() => 7 * 8)).toBe(56); expect(await page.evaluate(() => 7 * 8)).toBe(56);
originalBrowser.close(); originalBrowser.close();
})); }));
@ -144,7 +144,7 @@ describe('Page', function() {
describe('Browser.version', function() { describe('Browser.version', function() {
it('should return whether we are in headless', SX(async function() { it('should return whether we are in headless', SX(async function() {
let version = await browser.version(); const version = await browser.version();
expect(version.length).toBeGreaterThan(0); expect(version.length).toBeGreaterThan(0);
expect(version.startsWith('Headless')).toBe(headless); expect(version.startsWith('Headless')).toBe(headless);
})); }));
@ -152,8 +152,8 @@ describe('Page', function() {
describe('Page.close', function() { describe('Page.close', function() {
it('should reject all promises when page is closed', SX(async function() { it('should reject all promises when page is closed', SX(async function() {
let newPage = await browser.newPage(); const newPage = await browser.newPage();
let neverResolves = newPage.evaluate(() => new Promise(r => {})); const neverResolves = newPage.evaluate(() => new Promise(r => {}));
newPage.close(); newPage.close();
let error = null; let error = null;
try { try {
@ -177,11 +177,11 @@ describe('Page', function() {
describe('Page.evaluate', function() { describe('Page.evaluate', function() {
it('should work', SX(async function() { it('should work', SX(async function() {
let result = await page.evaluate(() => 7 * 3); const result = await page.evaluate(() => 7 * 3);
expect(result).toBe(21); expect(result).toBe(21);
})); }));
it('should await promise', SX(async function() { it('should await promise', SX(async function() {
let result = await page.evaluate(() => Promise.resolve(8 * 7)); const result = await page.evaluate(() => Promise.resolve(8 * 7));
expect(result).toBe(56); expect(result).toBe(56);
})); }));
it('should work from-inside an exposed function', SX(async function() { it('should work from-inside an exposed function', SX(async function() {
@ -189,7 +189,7 @@ describe('Page', function() {
await page.exposeFunction('callController', async function(a, b) { await page.exposeFunction('callController', async function(a, b) {
return await page.evaluate((a, b) => a * b, a, b); return await page.evaluate((a, b) => a * b, a, b);
}); });
let result = await page.evaluate(async function() { const result = await page.evaluate(async function() {
return await callController(9, 3); return await callController(9, 3);
}); });
expect(result).toBe(27); expect(result).toBe(27);
@ -206,40 +206,40 @@ describe('Page', function() {
})); }));
it('should return complex objects', SX(async function() { it('should return complex objects', SX(async function() {
const object = {foo: 'bar!'}; const object = {foo: 'bar!'};
let result = await page.evaluate(a => a, object); const result = await page.evaluate(a => a, object);
expect(result).not.toBe(object); expect(result).not.toBe(object);
expect(result).toEqual(object); expect(result).toEqual(object);
})); }));
it('should return NaN', SX(async function() { it('should return NaN', SX(async function() {
let result = await page.evaluate(() => NaN); const result = await page.evaluate(() => NaN);
expect(Object.is(result, NaN)).toBe(true); expect(Object.is(result, NaN)).toBe(true);
})); }));
it('should return -0', SX(async function() { it('should return -0', SX(async function() {
let result = await page.evaluate(() => -0); const result = await page.evaluate(() => -0);
expect(Object.is(result, -0)).toBe(true); expect(Object.is(result, -0)).toBe(true);
})); }));
it('should return Infinity', SX(async function() { it('should return Infinity', SX(async function() {
let result = await page.evaluate(() => Infinity); const result = await page.evaluate(() => Infinity);
expect(Object.is(result, Infinity)).toBe(true); expect(Object.is(result, Infinity)).toBe(true);
})); }));
it('should return -Infinity', SX(async function() { it('should return -Infinity', SX(async function() {
let result = await page.evaluate(() => -Infinity); const result = await page.evaluate(() => -Infinity);
expect(Object.is(result, -Infinity)).toBe(true); expect(Object.is(result, -Infinity)).toBe(true);
})); }));
it('should not fail for window object', SX(async function() { it('should not fail for window object', SX(async function() {
let result = await page.evaluate(() => window); const result = await page.evaluate(() => window);
expect(result).toBe('Window'); expect(result).toBe('Window');
})); }));
it('should accept a string', SX(async function() { it('should accept a string', SX(async function() {
let result = await page.evaluate('1 + 2'); const result = await page.evaluate('1 + 2');
expect(result).toBe(3); expect(result).toBe(3);
})); }));
it('should accept a string with semi colons', SX(async function() { it('should accept a string with semi colons', SX(async function() {
let result = await page.evaluate('1 + 5;'); const result = await page.evaluate('1 + 5;');
expect(result).toBe(6); expect(result).toBe(6);
})); }));
it('should accept a string with comments', SX(async function() { it('should accept a string with comments', SX(async function() {
let result = await page.evaluate('2 + 5;\n// do some math!'); const result = await page.evaluate('2 + 5;\n// do some math!');
expect(result).toBe(7); expect(result).toBe(7);
})); }));
}); });
@ -260,13 +260,13 @@ describe('Page', function() {
}); });
describe('Frame.evaluate', function() { describe('Frame.evaluate', function() {
let FrameUtils = require('./frame-utils'); const FrameUtils = require('./frame-utils');
it('should have different execution contexts', SX(async function() { it('should have different execution contexts', SX(async function() {
await page.goto(EMPTY_PAGE); await page.goto(EMPTY_PAGE);
await FrameUtils.attachFrame(page, 'frame1', EMPTY_PAGE); await FrameUtils.attachFrame(page, 'frame1', EMPTY_PAGE);
expect(page.frames().length).toBe(2); expect(page.frames().length).toBe(2);
let frame1 = page.frames()[0]; const frame1 = page.frames()[0];
let frame2 = page.frames()[1]; const frame2 = page.frames()[1];
await frame1.evaluate(() => window.FOO = 'foo'); await frame1.evaluate(() => window.FOO = 'foo');
await frame2.evaluate(() => window.FOO = 'bar'); await frame2.evaluate(() => window.FOO = 'bar');
expect(await frame1.evaluate(() => window.FOO)).toBe('foo'); expect(await frame1.evaluate(() => window.FOO)).toBe('foo');
@ -274,7 +274,7 @@ describe('Page', function() {
})); }));
it('should execute after cross-site navigation', SX(async function() { it('should execute after cross-site navigation', SX(async function() {
await page.goto(EMPTY_PAGE); await page.goto(EMPTY_PAGE);
let mainFrame = page.mainFrame(); const mainFrame = page.mainFrame();
expect(await mainFrame.evaluate(() => window.location.href)).toContain('localhost'); expect(await mainFrame.evaluate(() => window.location.href)).toContain('localhost');
await page.goto(CROSS_PROCESS_PREFIX + '/empty.html'); await page.goto(CROSS_PROCESS_PREFIX + '/empty.html');
expect(await mainFrame.evaluate(() => window.location.href)).toContain('127'); expect(await mainFrame.evaluate(() => window.location.href)).toContain('127');
@ -336,12 +336,12 @@ describe('Page', function() {
}); });
describe('Frame.waitForSelector', function() { describe('Frame.waitForSelector', function() {
let FrameUtils = require('./frame-utils'); const FrameUtils = require('./frame-utils');
let addElement = tag => document.body.appendChild(document.createElement(tag)); const addElement = tag => document.body.appendChild(document.createElement(tag));
it('should immediately resolve promise if node exists', SX(async function() { it('should immediately resolve promise if node exists', SX(async function() {
await page.goto(EMPTY_PAGE); await page.goto(EMPTY_PAGE);
let frame = page.mainFrame(); const frame = page.mainFrame();
let added = false; let added = false;
await frame.waitForSelector('*').then(() => added = true); await frame.waitForSelector('*').then(() => added = true);
expect(added).toBe(true); expect(added).toBe(true);
@ -354,9 +354,9 @@ describe('Page', function() {
it('should resolve promise when node is added', SX(async function() { it('should resolve promise when node is added', SX(async function() {
await page.goto(EMPTY_PAGE); await page.goto(EMPTY_PAGE);
let frame = page.mainFrame(); const frame = page.mainFrame();
let added = false; let added = false;
let watchdog = frame.waitForSelector('div').then(() => added = true); const watchdog = frame.waitForSelector('div').then(() => added = true);
// run nop function.. // run nop function..
await frame.evaluate(() => 42); await frame.evaluate(() => 42);
// .. to be sure that waitForSelector promise is not resolved yet. // .. to be sure that waitForSelector promise is not resolved yet.
@ -370,7 +370,7 @@ describe('Page', function() {
it('should work when node is added through innerHTML', SX(async function() { it('should work when node is added through innerHTML', SX(async function() {
await page.goto(EMPTY_PAGE); await page.goto(EMPTY_PAGE);
let watchdog = page.waitForSelector('h3 div'); const watchdog = page.waitForSelector('h3 div');
await page.evaluate(addElement, 'span'); await page.evaluate(addElement, 'span');
await page.evaluate(() => document.querySelector('span').innerHTML = '<h3><div></div></h3>'); await page.evaluate(() => document.querySelector('span').innerHTML = '<h3><div></div></h3>');
await watchdog; await watchdog;
@ -379,7 +379,7 @@ describe('Page', function() {
it('Page.waitForSelector is shortcut for main frame', SX(async function() { it('Page.waitForSelector is shortcut for main frame', SX(async function() {
await page.goto(EMPTY_PAGE); await page.goto(EMPTY_PAGE);
await FrameUtils.attachFrame(page, 'frame1', EMPTY_PAGE); await FrameUtils.attachFrame(page, 'frame1', EMPTY_PAGE);
let otherFrame = page.frames()[1]; const otherFrame = page.frames()[1];
let added = false; let added = false;
page.waitForSelector('div').then(() => added = true); page.waitForSelector('div').then(() => added = true);
await otherFrame.evaluate(addElement, 'div'); await otherFrame.evaluate(addElement, 'div');
@ -391,8 +391,8 @@ describe('Page', function() {
it('should run in specified frame', SX(async function() { it('should run in specified frame', SX(async function() {
await FrameUtils.attachFrame(page, 'frame1', EMPTY_PAGE); await FrameUtils.attachFrame(page, 'frame1', EMPTY_PAGE);
await FrameUtils.attachFrame(page, 'frame2', EMPTY_PAGE); await FrameUtils.attachFrame(page, 'frame2', EMPTY_PAGE);
let frame1 = page.frames()[1]; const frame1 = page.frames()[1];
let frame2 = page.frames()[2]; const frame2 = page.frames()[2];
let added = false; let added = false;
frame2.waitForSelector('div').then(() => added = true); frame2.waitForSelector('div').then(() => added = true);
expect(added).toBe(false); expect(added).toBe(false);
@ -416,9 +416,9 @@ describe('Page', function() {
})); }));
it('should throw when frame is detached', SX(async function() { it('should throw when frame is detached', SX(async function() {
await FrameUtils.attachFrame(page, 'frame1', EMPTY_PAGE); await FrameUtils.attachFrame(page, 'frame1', EMPTY_PAGE);
let frame = page.frames()[1]; const frame = page.frames()[1];
let waitError = null; let waitError = null;
let waitPromise = frame.waitForSelector('.box').catch(e => waitError = e); const waitPromise = frame.waitForSelector('.box').catch(e => waitError = e);
await FrameUtils.detachFrame(page, 'frame1'); await FrameUtils.detachFrame(page, 'frame1');
await waitPromise; await waitPromise;
expect(waitError).toBeTruthy(); expect(waitError).toBeTruthy();
@ -426,7 +426,7 @@ describe('Page', function() {
})); }));
it('should survive cross-process navigation', SX(async function() { it('should survive cross-process navigation', SX(async function() {
let boxFound = false; let boxFound = false;
let waitForSelector = page.waitForSelector('.box').then(() => boxFound = true); const waitForSelector = page.waitForSelector('.box').then(() => boxFound = true);
await page.goto(EMPTY_PAGE); await page.goto(EMPTY_PAGE);
expect(boxFound).toBe(false); expect(boxFound).toBe(false);
await page.reload(); await page.reload();
@ -437,7 +437,7 @@ describe('Page', function() {
})); }));
it('should wait for visible', SX(async function() { it('should wait for visible', SX(async function() {
let divFound = false; let divFound = false;
let waitForSelector = page.waitForSelector('div', {visible: true}).then(() => divFound = true); const waitForSelector = page.waitForSelector('div', {visible: true}).then(() => divFound = true);
await page.setContent(`<div style='display: none;visibility: hidden'></div>`); await page.setContent(`<div style='display: none;visibility: hidden'></div>`);
expect(divFound).toBe(false); expect(divFound).toBe(false);
await page.evaluate(() => document.querySelector('div').style.removeProperty('display')); await page.evaluate(() => document.querySelector('div').style.removeProperty('display'));
@ -456,7 +456,7 @@ describe('Page', function() {
describe('Page.waitFor', function() { describe('Page.waitFor', function() {
it('should wait for selector', SX(async function() { it('should wait for selector', SX(async function() {
let found = false; let found = false;
let waitFor = page.waitFor('div').then(() => found = true); const waitFor = page.waitFor('div').then(() => found = true);
await page.goto(EMPTY_PAGE); await page.goto(EMPTY_PAGE);
expect(found).toBe(false); expect(found).toBe(false);
await page.goto(PREFIX + '/grid.html'); await page.goto(PREFIX + '/grid.html');
@ -464,7 +464,7 @@ describe('Page', function() {
expect(found).toBe(true); expect(found).toBe(true);
})); }));
it('should timeout', SX(async function() { it('should timeout', SX(async function() {
let startTime = Date.now(); const startTime = Date.now();
const timeout = 42; const timeout = 42;
await page.waitFor(timeout); await page.waitFor(timeout);
expect(Date.now() - startTime).not.toBeLessThan(timeout / 2); expect(Date.now() - startTime).not.toBeLessThan(timeout / 2);
@ -495,7 +495,7 @@ describe('Page', function() {
expect(commandArgs).toEqual([5, 'hello', {foo: 'bar'}]); expect(commandArgs).toEqual([5, 'hello', {foo: 'bar'}]);
})); }));
it('should work for different console API calls', SX(async function() { it('should work for different console API calls', SX(async function() {
let messages = []; const messages = [];
page.on('console', msg => messages.push(msg)); page.on('console', msg => messages.push(msg));
await Promise.all([ await Promise.all([
page.evaluate(() => { page.evaluate(() => {
@ -533,7 +533,7 @@ describe('Page', function() {
describe('Page.goto', function() { describe('Page.goto', function() {
it('should navigate to about:blank', SX(async function() { it('should navigate to about:blank', SX(async function() {
let response = await page.goto('about:blank'); const response = await page.goto('about:blank');
expect(response).toBe(null); expect(response).toBe(null);
})); }));
it('should fail when navigating to bad url', SX(async function() { it('should fail when navigating to bad url', SX(async function() {
@ -607,16 +607,16 @@ describe('Page', function() {
server.setRoute('/fetch-request-b.js', (req, res) => responses.push(res)); server.setRoute('/fetch-request-b.js', (req, res) => responses.push(res));
server.setRoute('/fetch-request-c.js', (req, res) => responses.push(res)); server.setRoute('/fetch-request-c.js', (req, res) => responses.push(res));
server.setRoute('/fetch-request-d.js', (req, res) => responses.push(res)); server.setRoute('/fetch-request-d.js', (req, res) => responses.push(res));
let initialFetchResourcesRequested = Promise.all([ const initialFetchResourcesRequested = Promise.all([
server.waitForRequest('/fetch-request-a.js'), server.waitForRequest('/fetch-request-a.js'),
server.waitForRequest('/fetch-request-b.js'), server.waitForRequest('/fetch-request-b.js'),
server.waitForRequest('/fetch-request-c.js'), server.waitForRequest('/fetch-request-c.js'),
]); ]);
let secondFetchResourceRequested = server.waitForRequest('/fetch-request-d.js'); const secondFetchResourceRequested = server.waitForRequest('/fetch-request-d.js');
// Navigate to a page which loads immediately and then does a bunch of // Navigate to a page which loads immediately and then does a bunch of
// requests via javascript's fetch method. // requests via javascript's fetch method.
let navigationPromise = page.goto(PREFIX + '/networkidle.html', { const navigationPromise = page.goto(PREFIX + '/networkidle.html', {
waitUntil: 'networkidle', waitUntil: 'networkidle',
networkIdleTimeout: 100, networkIdleTimeout: 100,
networkIdleInflight: 0, // Only be idle when there are 0 inflight requests networkIdleInflight: 0, // Only be idle when there are 0 inflight requests
@ -636,7 +636,7 @@ describe('Page', function() {
expect(navigationFinished).toBe(false); expect(navigationFinished).toBe(false);
// Respond to initial requests. // Respond to initial requests.
for (let response of responses) { for (const response of responses) {
response.statusCode = 404; response.statusCode = 404;
response.end(`File not found`); response.end(`File not found`);
} }
@ -650,7 +650,7 @@ describe('Page', function() {
expect(navigationFinished).toBe(false); expect(navigationFinished).toBe(false);
// Respond to requests. // Respond to requests.
for (let response of responses) { for (const response of responses) {
response.statusCode = 404; response.statusCode = 404;
response.end(`File not found`); response.end(`File not found`);
} }
@ -660,13 +660,13 @@ describe('Page', function() {
expect(response.ok).toBe(true); expect(response.ok).toBe(true);
})); }));
it('should wait for websockets to succeed navigation', SX(async function() { it('should wait for websockets to succeed navigation', SX(async function() {
let responses = []; const responses = [];
// Hold on to the fetch request without answering. // Hold on to the fetch request without answering.
server.setRoute('/fetch-request.js', (req, res) => responses.push(res)); server.setRoute('/fetch-request.js', (req, res) => responses.push(res));
let fetchResourceRequested = server.waitForRequest('/fetch-request.js'); const fetchResourceRequested = server.waitForRequest('/fetch-request.js');
// Navigate to a page which loads immediately and then opens a bunch of // Navigate to a page which loads immediately and then opens a bunch of
// websocket connections and then a fetch request. // websocket connections and then a fetch request.
let navigationPromise = page.goto(PREFIX + '/websocket.html', { const navigationPromise = page.goto(PREFIX + '/websocket.html', {
waitUntil: 'networkidle', waitUntil: 'networkidle',
networkIdleTimeout: 100, networkIdleTimeout: 100,
networkIdleInflight: 0, // Only be idle when there are 0 inflight requests/connections networkIdleInflight: 0, // Only be idle when there are 0 inflight requests/connections
@ -686,7 +686,7 @@ describe('Page', function() {
expect(navigationFinished).toBe(false); expect(navigationFinished).toBe(false);
// Respond to the request. // Respond to the request.
for (let response of responses) { for (const response of responses) {
response.statusCode = 404; response.statusCode = 404;
response.end(`File not found`); response.end(`File not found`);
} }
@ -704,18 +704,18 @@ describe('Page', function() {
expect(warning).toBe(null); expect(warning).toBe(null);
})); }));
it('should navigate to dataURL and fire dataURL requests', SX(async function() { it('should navigate to dataURL and fire dataURL requests', SX(async function() {
let requests = []; const requests = [];
page.on('request', request => requests.push(request)); page.on('request', request => requests.push(request));
let dataURL = 'data:text/html,<div>yo</div>'; const dataURL = 'data:text/html,<div>yo</div>';
let response = await page.goto(dataURL); const response = await page.goto(dataURL);
expect(response.status).toBe(200); expect(response.status).toBe(200);
expect(requests.length).toBe(1); expect(requests.length).toBe(1);
expect(requests[0].url).toBe(dataURL); expect(requests[0].url).toBe(dataURL);
})); }));
it('should navigate to URL with hash and fire requests without hash', SX(async function() { it('should navigate to URL with hash and fire requests without hash', SX(async function() {
let requests = []; const requests = [];
page.on('request', request => requests.push(request)); page.on('request', request => requests.push(request));
let response = await page.goto(EMPTY_PAGE + '#hash'); const response = await page.goto(EMPTY_PAGE + '#hash');
expect(response.status).toBe(200); expect(response.status).toBe(200);
expect(response.url).toBe(EMPTY_PAGE); expect(response.url).toBe(EMPTY_PAGE);
expect(requests.length).toBe(1); expect(requests.length).toBe(1);
@ -759,7 +759,7 @@ describe('Page', function() {
await page.exposeFunction('compute', function(a, b) { await page.exposeFunction('compute', function(a, b) {
return a * b; return a * b;
}); });
let result = await page.evaluate(async function() { const result = await page.evaluate(async function() {
return await compute(9, 4); return await compute(9, 4);
}); });
expect(result).toBe(36); expect(result).toBe(36);
@ -770,7 +770,7 @@ describe('Page', function() {
}); });
await page.goto(EMPTY_PAGE); await page.goto(EMPTY_PAGE);
let result = await page.evaluate(async function() { const result = await page.evaluate(async function() {
return await compute(9, 4); return await compute(9, 4);
}); });
expect(result).toBe(36); expect(result).toBe(36);
@ -780,7 +780,7 @@ describe('Page', function() {
return Promise.resolve(a * b); return Promise.resolve(a * b);
}); });
let result = await page.evaluate(async function() { const result = await page.evaluate(async function() {
return await compute(3, 5); return await compute(3, 5);
}); });
expect(result).toBe(15); expect(result).toBe(15);
@ -829,7 +829,7 @@ describe('Page', function() {
it('should amend HTTP headers', SX(async function() { it('should amend HTTP headers', SX(async function() {
await page.setRequestInterceptionEnabled(true); await page.setRequestInterceptionEnabled(true);
page.on('request', request => { page.on('request', request => {
let headers = new Map(request.headers); const headers = new Map(request.headers);
headers.set('foo', 'bar'); headers.set('foo', 'bar');
request.continue({ headers }); request.continue({ headers });
}); });
@ -859,7 +859,7 @@ describe('Page', function() {
server.setRedirect('/non-existing-page-2.html', '/non-existing-page-3.html'); server.setRedirect('/non-existing-page-2.html', '/non-existing-page-3.html');
server.setRedirect('/non-existing-page-3.html', '/non-existing-page-4.html'); server.setRedirect('/non-existing-page-3.html', '/non-existing-page-4.html');
server.setRedirect('/non-existing-page-4.html', '/empty.html'); server.setRedirect('/non-existing-page-4.html', '/empty.html');
let response = await page.goto(PREFIX + '/non-existing-page.html'); const response = await page.goto(PREFIX + '/non-existing-page.html');
expect(response.status).toBe(200); expect(response.status).toBe(200);
expect(response.url).toContain('empty.html'); expect(response.url).toContain('empty.html');
})); }));
@ -874,7 +874,7 @@ describe('Page', function() {
request.continue(); request.continue();
}); });
await page.goto(EMPTY_PAGE); await page.goto(EMPTY_PAGE);
let result = await page.evaluate(async() => { const result = await page.evaluate(async() => {
try { try {
await fetch('/non-existing.json'); await fetch('/non-existing.json');
} catch (e) { } catch (e) {
@ -895,7 +895,7 @@ describe('Page', function() {
spinner ? request.abort() : request.continue(); spinner ? request.abort() : request.continue();
spinner = !spinner; spinner = !spinner;
}); });
let results = await page.evaluate(() => Promise.all([ const results = await page.evaluate(() => Promise.all([
fetch('/zzz').then(response => response.text()).catch(e => 'FAILED'), fetch('/zzz').then(response => response.text()).catch(e => 'FAILED'),
fetch('/zzz').then(response => response.text()).catch(e => 'FAILED'), fetch('/zzz').then(response => response.text()).catch(e => 'FAILED'),
fetch('/zzz').then(response => response.text()).catch(e => 'FAILED'), fetch('/zzz').then(response => response.text()).catch(e => 'FAILED'),
@ -904,25 +904,25 @@ describe('Page', function() {
})); }));
it('should navigate to dataURL and fire dataURL requests', SX(async function() { it('should navigate to dataURL and fire dataURL requests', SX(async function() {
await page.setRequestInterceptionEnabled(true); await page.setRequestInterceptionEnabled(true);
let requests = []; const requests = [];
page.on('request', request => { page.on('request', request => {
requests.push(request); requests.push(request);
request.continue(); request.continue();
}); });
let dataURL = 'data:text/html,<div>yo</div>'; const dataURL = 'data:text/html,<div>yo</div>';
let response = await page.goto(dataURL); const response = await page.goto(dataURL);
expect(response.status).toBe(200); expect(response.status).toBe(200);
expect(requests.length).toBe(1); expect(requests.length).toBe(1);
expect(requests[0].url).toBe(dataURL); expect(requests[0].url).toBe(dataURL);
})); }));
it('should navigate to URL with hash and and fire requests without hash', SX(async function() { it('should navigate to URL with hash and and fire requests without hash', SX(async function() {
await page.setRequestInterceptionEnabled(true); await page.setRequestInterceptionEnabled(true);
let requests = []; const requests = [];
page.on('request', request => { page.on('request', request => {
requests.push(request); requests.push(request);
request.continue(); request.continue();
}); });
let response = await page.goto(EMPTY_PAGE + '#hash'); const response = await page.goto(EMPTY_PAGE + '#hash');
expect(response.status).toBe(200); expect(response.status).toBe(200);
expect(response.url).toBe(EMPTY_PAGE); expect(response.url).toBe(EMPTY_PAGE);
expect(requests.length).toBe(1); expect(requests.length).toBe(1);
@ -947,14 +947,14 @@ describe('Page', function() {
expect(dialog.message()).toBe('question?'); expect(dialog.message()).toBe('question?');
dialog.accept('answer!'); dialog.accept('answer!');
}); });
let result = await page.evaluate(() => prompt('question?', 'yes.')); const result = await page.evaluate(() => prompt('question?', 'yes.'));
expect(result).toBe('answer!'); expect(result).toBe('answer!');
})); }));
it('should dismiss the prompt', SX(async function() { it('should dismiss the prompt', SX(async function() {
page.on('dialog', dialog => { page.on('dialog', dialog => {
dialog.dismiss(); dialog.dismiss();
}); });
let result = await page.evaluate(() => prompt('question?')); const result = await page.evaluate(() => prompt('question?'));
expect(result).toBe(null); expect(result).toBe(null);
})); }));
}); });
@ -971,7 +971,7 @@ describe('Page', function() {
describe('Page.Events.Request', function() { describe('Page.Events.Request', function() {
it('should fire', SX(async function() { it('should fire', SX(async function() {
let requests = []; const requests = [];
page.on('request', request => requests.push(request)); page.on('request', request => requests.push(request));
await page.goto(EMPTY_PAGE); await page.goto(EMPTY_PAGE);
expect(requests.length).toBe(1); expect(requests.length).toBe(1);
@ -980,7 +980,7 @@ describe('Page', function() {
}); });
describe('Frame Management', function() { describe('Frame Management', function() {
let FrameUtils = require('./frame-utils'); const FrameUtils = require('./frame-utils');
it('should handle nested frames', SX(async function() { it('should handle nested frames', SX(async function() {
await page.goto(PREFIX + '/frames/nested-frames.html'); await page.goto(PREFIX + '/frames/nested-frames.html');
expect(FrameUtils.dumpFrames(page.mainFrame())).toBeGolden('nested-frames.txt'); expect(FrameUtils.dumpFrames(page.mainFrame())).toBeGolden('nested-frames.txt');
@ -988,21 +988,21 @@ describe('Page', function() {
it('should send events when frames are manipulated dynamically', SX(async function() { it('should send events when frames are manipulated dynamically', SX(async function() {
await page.goto(EMPTY_PAGE); await page.goto(EMPTY_PAGE);
// validate frameattached events // validate frameattached events
let attachedFrames = []; const attachedFrames = [];
page.on('frameattached', frame => attachedFrames.push(frame)); page.on('frameattached', frame => attachedFrames.push(frame));
await FrameUtils.attachFrame(page, 'frame1', './assets/frame.html'); await FrameUtils.attachFrame(page, 'frame1', './assets/frame.html');
expect(attachedFrames.length).toBe(1); expect(attachedFrames.length).toBe(1);
expect(attachedFrames[0].url()).toContain('/assets/frame.html'); expect(attachedFrames[0].url()).toContain('/assets/frame.html');
// validate framenavigated events // validate framenavigated events
let navigatedFrames = []; const navigatedFrames = [];
page.on('framenavigated', frame => navigatedFrames.push(frame)); page.on('framenavigated', frame => navigatedFrames.push(frame));
await FrameUtils.navigateFrame(page, 'frame1', './empty.html'); await FrameUtils.navigateFrame(page, 'frame1', './empty.html');
expect(navigatedFrames.length).toBe(1); expect(navigatedFrames.length).toBe(1);
expect(navigatedFrames[0].url()).toContain('/empty.html'); expect(navigatedFrames[0].url()).toContain('/empty.html');
// validate framedetached events // validate framedetached events
let detachedFrames = []; const detachedFrames = [];
page.on('framedetached', frame => detachedFrames.push(frame)); page.on('framedetached', frame => detachedFrames.push(frame));
await FrameUtils.detachFrame(page, 'frame1'); await FrameUtils.detachFrame(page, 'frame1');
expect(detachedFrames.length).toBe(1); expect(detachedFrames.length).toBe(1);
@ -1010,7 +1010,7 @@ describe('Page', function() {
})); }));
it('should persist mainFrame on cross-process navigation', SX(async function() { it('should persist mainFrame on cross-process navigation', SX(async function() {
await page.goto(EMPTY_PAGE); await page.goto(EMPTY_PAGE);
let mainFrame = page.mainFrame(); const mainFrame = page.mainFrame();
await page.goto('http://127.0.0.1:' + PORT + '/empty.html'); await page.goto('http://127.0.0.1:' + PORT + '/empty.html');
expect(page.mainFrame() === mainFrame).toBeTruthy(); expect(page.mainFrame() === mainFrame).toBeTruthy();
})); }));
@ -1044,7 +1044,7 @@ describe('Page', function() {
it('should report frame.name()', SX(async function() { it('should report frame.name()', SX(async function() {
await FrameUtils.attachFrame(page, 'theFrameId', EMPTY_PAGE); await FrameUtils.attachFrame(page, 'theFrameId', EMPTY_PAGE);
await page.evaluate(url => { await page.evaluate(url => {
let frame = document.createElement('iframe'); const frame = document.createElement('iframe');
frame.name = 'theFrameName'; frame.name = 'theFrameName';
frame.src = url; frame.src = url;
document.body.appendChild(frame); document.body.appendChild(frame);
@ -1066,11 +1066,11 @@ describe('Page', function() {
describe('Page.$', function() { describe('Page.$', function() {
it('should query existing element', SX(async function() { it('should query existing element', SX(async function() {
await page.setContent('<section>test</section>'); await page.setContent('<section>test</section>');
let element = await page.$('section'); const element = await page.$('section');
expect(element).toBeTruthy(); expect(element).toBeTruthy();
})); }));
it('should return null for non-existing element', SX(async function() { it('should return null for non-existing element', SX(async function() {
let element = await page.$('non-existing-element'); const element = await page.$('non-existing-element');
expect(element).toBe(null); expect(element).toBe(null);
})); }));
}); });
@ -1078,20 +1078,20 @@ describe('Page', function() {
describe('ElementHandle.evaluate', function() { describe('ElementHandle.evaluate', function() {
it('should work', SX(async function() { it('should work', SX(async function() {
await page.setContent('<section>42</section>'); await page.setContent('<section>42</section>');
let element = await page.$('section'); const element = await page.$('section');
let text = await element.evaluate(e => e.textContent); const text = await element.evaluate(e => e.textContent);
expect(text).toBe('42'); expect(text).toBe('42');
})); }));
it('should await promise if any', SX(async function() { it('should await promise if any', SX(async function() {
await page.setContent('<section>39</section>'); await page.setContent('<section>39</section>');
let element = await page.$('section'); const element = await page.$('section');
let text = await element.evaluate(e => Promise.resolve(e.textContent)); const text = await element.evaluate(e => Promise.resolve(e.textContent));
expect(text).toBe('39'); expect(text).toBe('39');
})); }));
it('should throw if underlying page got closed', SX(async function() { it('should throw if underlying page got closed', SX(async function() {
let otherPage = await browser.newPage(); const otherPage = await browser.newPage();
await otherPage.setContent('<section>88</section>'); await otherPage.setContent('<section>88</section>');
let element = await otherPage.$('section'); const element = await otherPage.$('section');
expect(element).toBeTruthy(); expect(element).toBeTruthy();
await otherPage.close(); await otherPage.close();
let error = null; let error = null;
@ -1104,7 +1104,7 @@ describe('Page', function() {
})); }));
it('should throw if underlying element was disposed', SX(async function() { it('should throw if underlying element was disposed', SX(async function() {
await page.setContent('<section>39</section>'); await page.setContent('<section>39</section>');
let element = await page.$('section'); const element = await page.$('section');
expect(element).toBeTruthy(); expect(element).toBeTruthy();
await element.dispose(); await element.dispose();
let error = null; let error = null;
@ -1120,7 +1120,7 @@ describe('Page', function() {
describe('ElementHandle.click', function() { describe('ElementHandle.click', function() {
it('should work', SX(async function() { it('should work', SX(async function() {
await page.goto(PREFIX + '/input/button.html'); await page.goto(PREFIX + '/input/button.html');
let button = await page.$('button'); const button = await page.$('button');
await button.click('button'); await button.click('button');
expect(await page.evaluate(() => result)).toBe('Clicked'); expect(await page.evaluate(() => result)).toBe('Clicked');
})); }));
@ -1129,7 +1129,7 @@ describe('Page', function() {
describe('ElementHandle.hover', function() { describe('ElementHandle.hover', function() {
it('should work', SX(async function() { it('should work', SX(async function() {
await page.goto(PREFIX + '/input/scrollable.html'); await page.goto(PREFIX + '/input/scrollable.html');
let button = await page.$('#button-6'); const button = await page.$('#button-6');
await button.hover(); await button.hover();
expect(await page.evaluate(() => document.querySelector('button:hover').id)).toBe('button-6'); expect(await page.evaluate(() => document.querySelector('button:hover').id)).toBe('button-6');
})); }));
@ -1173,12 +1173,12 @@ describe('Page', function() {
it('should upload the file', SX(async function(){ it('should upload the file', SX(async function(){
await page.goto(PREFIX + '/input/fileupload.html'); await page.goto(PREFIX + '/input/fileupload.html');
const filePath = path.relative(process.cwd(), __dirname + '/assets/file-to-upload.txt'); const filePath = path.relative(process.cwd(), __dirname + '/assets/file-to-upload.txt');
let input = await page.$('input'); const input = await page.$('input');
await input.uploadFile(filePath); await input.uploadFile(filePath);
expect(await input.evaluate(e => e.files[0].name)).toBe('file-to-upload.txt'); expect(await input.evaluate(e => e.files[0].name)).toBe('file-to-upload.txt');
expect(await input.evaluate(e => { expect(await input.evaluate(e => {
let reader = new FileReader(); const reader = new FileReader();
let promise = new Promise(fulfill => reader.onload = fulfill); const promise = new Promise(fulfill => reader.onload = fulfill);
reader.readAsText(e.files[0]); reader.readAsText(e.files[0]);
return promise.then(() => reader.result); return promise.then(() => reader.result);
})).toBe('contents of the file'); })).toBe('contents of the file');
@ -1221,9 +1221,9 @@ describe('Page', function() {
})); }));
it('should report shiftKey', SX(async function(){ it('should report shiftKey', SX(async function(){
await page.goto(PREFIX + '/input/keyboard.html'); await page.goto(PREFIX + '/input/keyboard.html');
let keyboard = page.keyboard; const keyboard = page.keyboard;
let codeForKey = {'Shift': 16, 'Alt': 18, 'Meta': 91, 'Control': 17}; const codeForKey = {'Shift': 16, 'Alt': 18, 'Meta': 91, 'Control': 17};
for (let modifierKey in codeForKey) { for (const modifierKey in codeForKey) {
await keyboard.down(modifierKey); await keyboard.down(modifierKey);
expect(await page.evaluate(() => getResult())).toBe('Keydown: ' + modifierKey + ' ' + codeForKey[modifierKey] + ' [' + modifierKey + ']'); expect(await page.evaluate(() => getResult())).toBe('Keydown: ' + modifierKey + ' ' + codeForKey[modifierKey] + ' [' + modifierKey + ']');
await keyboard.down('!'); await keyboard.down('!');
@ -1236,7 +1236,7 @@ describe('Page', function() {
})); }));
it('should report multiple modifiers', SX(async function(){ it('should report multiple modifiers', SX(async function(){
await page.goto(PREFIX + '/input/keyboard.html'); await page.goto(PREFIX + '/input/keyboard.html');
let keyboard = page.keyboard; const keyboard = page.keyboard;
await keyboard.down('Control'); await keyboard.down('Control');
expect(await page.evaluate(() => getResult())).toBe('Keydown: Control 17 [Control]'); expect(await page.evaluate(() => getResult())).toBe('Keydown: Control 17 [Control]');
await keyboard.down('Meta'); await keyboard.down('Meta');
@ -1265,7 +1265,7 @@ describe('Page', function() {
})); }));
it('should send propery codes while typing with shift', SX(async function(){ it('should send propery codes while typing with shift', SX(async function(){
await page.goto(PREFIX + '/input/keyboard.html'); await page.goto(PREFIX + '/input/keyboard.html');
let keyboard = page.keyboard; const keyboard = page.keyboard;
await keyboard.down('Shift'); await keyboard.down('Shift');
await page.type('~'); await page.type('~');
expect(await page.evaluate(() => getResult())).toBe( expect(await page.evaluate(() => getResult())).toBe(
@ -1292,7 +1292,7 @@ describe('Page', function() {
expect(await page.evaluate(() => textarea.value)).toBe('He Wrd!'); expect(await page.evaluate(() => textarea.value)).toBe('He Wrd!');
})); }));
it('keyboard.modifiers()', SX(async function(){ it('keyboard.modifiers()', SX(async function(){
let keyboard = page.keyboard; const keyboard = page.keyboard;
expect(keyboard._modifiers).toBe(0); expect(keyboard._modifiers).toBe(0);
await keyboard.down('Shift'); await keyboard.down('Shift');
expect(keyboard._modifiers).toBe(8); expect(keyboard._modifiers).toBe(8);
@ -1304,13 +1304,13 @@ describe('Page', function() {
})); }));
it('should resize the textarea', SX(async function(){ it('should resize the textarea', SX(async function(){
await page.goto(PREFIX + '/input/textarea.html'); await page.goto(PREFIX + '/input/textarea.html');
let {x, y, width, height} = await page.evaluate(dimensions); const {x, y, width, height} = await page.evaluate(dimensions);
let mouse = page.mouse; const mouse = page.mouse;
await mouse.move(x + width - 4, y + height - 4); await mouse.move(x + width - 4, y + height - 4);
await mouse.down(); await mouse.down();
await mouse.move(x + width + 100, y + height + 100); await mouse.move(x + width + 100, y + height + 100);
await mouse.up(); await mouse.up();
let newDimensions = await page.evaluate(dimensions); const newDimensions = await page.evaluate(dimensions);
expect(newDimensions.width).toBe(width + 104); expect(newDimensions.width).toBe(width + 104);
expect(newDimensions.height).toBe(height + 104); expect(newDimensions.height).toBe(height + 104);
})); }));
@ -1324,7 +1324,7 @@ describe('Page', function() {
it('should click a partially obscured button', SX(async function() { it('should click a partially obscured button', SX(async function() {
await page.goto(PREFIX + '/input/button.html'); await page.goto(PREFIX + '/input/button.html');
await page.evaluate(() => { await page.evaluate(() => {
let button = document.querySelector('button'); const button = document.querySelector('button');
button.textContent = 'Some really long text that will go offscreen'; button.textContent = 'Some really long text that will go offscreen';
button.style.position = 'absolute'; button.style.position = 'absolute';
button.style.left = '368px'; button.style.left = '368px';
@ -1335,10 +1335,10 @@ describe('Page', function() {
it('should select the text with mouse', SX(async function(){ it('should select the text with mouse', SX(async function(){
await page.goto(PREFIX + '/input/textarea.html'); await page.goto(PREFIX + '/input/textarea.html');
await page.focus('textarea'); await page.focus('textarea');
let text = 'This is the text that we are going to try to select. Let\'s see how it goes.'; const text = 'This is the text that we are going to try to select. Let\'s see how it goes.';
await page.type(text); await page.type(text);
await page.evaluate(() => document.querySelector('textarea').scrollTop = 0); await page.evaluate(() => document.querySelector('textarea').scrollTop = 0);
let {x, y} = await page.evaluate(dimensions); const {x, y} = await page.evaluate(dimensions);
await page.mouse.move(x + 2,y + 2); await page.mouse.move(x + 2,y + 2);
await page.mouse.down(); await page.mouse.down();
await page.mouse.move(100,100); await page.mouse.move(100,100);
@ -1348,7 +1348,7 @@ describe('Page', function() {
it('should select the text by triple clicking', SX(async function(){ it('should select the text by triple clicking', SX(async function(){
await page.goto(PREFIX + '/input/textarea.html'); await page.goto(PREFIX + '/input/textarea.html');
await page.focus('textarea'); await page.focus('textarea');
let text = 'This is the text that we are going to try to select. Let\'s see how it goes.'; const text = 'This is the text that we are going to try to select. Let\'s see how it goes.';
await page.type(text); await page.type(text);
await page.click('textarea'); await page.click('textarea');
await page.click('textarea', {clickCount: 2}); await page.click('textarea', {clickCount: 2});
@ -1372,8 +1372,8 @@ describe('Page', function() {
it('should set modifier keys on click', SX(async function(){ it('should set modifier keys on click', SX(async function(){
await page.goto(PREFIX + '/input/scrollable.html'); await page.goto(PREFIX + '/input/scrollable.html');
await page.evaluate(() => document.querySelector('#button-3').addEventListener('mousedown', e => window.lastEvent = e, true)); await page.evaluate(() => document.querySelector('#button-3').addEventListener('mousedown', e => window.lastEvent = e, true));
let modifiers = {'Shift': 'shiftKey', 'Control': 'ctrlKey', 'Alt': 'altKey', 'Meta': 'metaKey'}; const modifiers = {'Shift': 'shiftKey', 'Control': 'ctrlKey', 'Alt': 'altKey', 'Meta': 'metaKey'};
for (let modifier in modifiers) { for (const modifier in modifiers) {
await page.keyboard.down(modifier); await page.keyboard.down(modifier);
await page.click('#button-3'); await page.click('#button-3');
if (!(await page.evaluate(mod => window.lastEvent[mod], modifiers[modifier]))) if (!(await page.evaluate(mod => window.lastEvent[mod], modifiers[modifier])))
@ -1381,7 +1381,7 @@ describe('Page', function() {
await page.keyboard.up(modifier); await page.keyboard.up(modifier);
} }
await page.click('#button-3'); await page.click('#button-3');
for (let modifier in modifiers) { for (const modifier in modifiers) {
if ((await page.evaluate(mod => window.lastEvent[mod], modifiers[modifier]))) if ((await page.evaluate(mod => window.lastEvent[mod], modifiers[modifier])))
fail(modifiers[modifier] + ' should be false'); fail(modifiers[modifier] + ' should be false');
} }
@ -1402,7 +1402,7 @@ describe('Page', function() {
await page.click('a'); await page.click('a');
})); }));
function dimensions() { function dimensions() {
let rect = document.querySelector('textarea').getBoundingClientRect(); const rect = document.querySelector('textarea').getBoundingClientRect();
return { return {
x: rect.left, x: rect.left,
y: rect.top, y: rect.top,
@ -1417,7 +1417,7 @@ describe('Page', function() {
expect(await page.evaluate(() => navigator.userAgent)).toContain('Mozilla'); expect(await page.evaluate(() => navigator.userAgent)).toContain('Mozilla');
page.setUserAgent('foobar'); page.setUserAgent('foobar');
page.goto(EMPTY_PAGE); page.goto(EMPTY_PAGE);
let request = await server.waitForRequest('/empty.html'); const request = await server.waitForRequest('/empty.html');
expect(request.headers['user-agent']).toBe('foobar'); expect(request.headers['user-agent']).toBe('foobar');
})); }));
it('should emulate device user-agent', SX(async function() { it('should emulate device user-agent', SX(async function() {
@ -1433,7 +1433,7 @@ describe('Page', function() {
foo: 'bar' foo: 'bar'
}))); })));
page.goto(EMPTY_PAGE); page.goto(EMPTY_PAGE);
let request = await server.waitForRequest('/empty.html'); const request = await server.waitForRequest('/empty.html');
expect(request.headers['foo']).toBe('bar'); expect(request.headers['foo']).toBe('bar');
})); }));
}); });
@ -1441,26 +1441,26 @@ describe('Page', function() {
const expectedOutput = '<html><head></head><body><div>hello</div></body></html>'; const expectedOutput = '<html><head></head><body><div>hello</div></body></html>';
it('should work', SX(async function() { it('should work', SX(async function() {
await page.setContent('<div>hello</div>'); await page.setContent('<div>hello</div>');
let result = await page.content(); const result = await page.content();
expect(result).toBe(expectedOutput); expect(result).toBe(expectedOutput);
})); }));
it('should work with doctype', SX(async function() { it('should work with doctype', SX(async function() {
const doctype = '<!DOCTYPE html>'; const doctype = '<!DOCTYPE html>';
await page.setContent(`${doctype}<div>hello</div>`); await page.setContent(`${doctype}<div>hello</div>`);
let result = await page.content(); const result = await page.content();
expect(result).toBe(`${doctype}${expectedOutput}`); expect(result).toBe(`${doctype}${expectedOutput}`);
})); }));
it('should work with HTML 4 doctype', SX(async function() { it('should work with HTML 4 doctype', SX(async function() {
const doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" ' + const doctype = '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" ' +
'"http://www.w3.org/TR/html4/strict.dtd">'; '"http://www.w3.org/TR/html4/strict.dtd">';
await page.setContent(`${doctype}<div>hello</div>`); await page.setContent(`${doctype}<div>hello</div>`);
let result = await page.content(); const result = await page.content();
expect(result).toBe(`${doctype}${expectedOutput}`); expect(result).toBe(`${doctype}${expectedOutput}`);
})); }));
}); });
describe('Network Events', function() { describe('Network Events', function() {
it('Page.Events.Request', SX(async function() { it('Page.Events.Request', SX(async function() {
let requests = []; const requests = [];
page.on('request', request => requests.push(request)); page.on('request', request => requests.push(request));
await page.goto(EMPTY_PAGE); await page.goto(EMPTY_PAGE);
expect(requests.length).toBe(1); expect(requests.length).toBe(1);
@ -1478,7 +1478,7 @@ describe('Page', function() {
expect(request.postData).toBe('{"foo":"bar"}'); expect(request.postData).toBe('{"foo":"bar"}');
})); }));
it('Page.Events.Response', SX(async function() { it('Page.Events.Response', SX(async function() {
let responses = []; const responses = [];
page.on('response', response => responses.push(response)); page.on('response', response => responses.push(response));
await page.goto(EMPTY_PAGE); await page.goto(EMPTY_PAGE);
expect(responses.length).toBe(1); expect(responses.length).toBe(1);
@ -1519,7 +1519,7 @@ describe('Page', function() {
expect(pageResponse.status).toBe(200); expect(pageResponse.status).toBe(200);
expect(requestFinished).toBe(false); expect(requestFinished).toBe(false);
let responseText = pageResponse.text(); const responseText = pageResponse.text();
// Write part of the response and wait for it to be flushed. // Write part of the response and wait for it to be flushed.
await new Promise(x => serverResponse.write('wor', x)); await new Promise(x => serverResponse.write('wor', x));
// Finish response. // Finish response.
@ -1534,7 +1534,7 @@ describe('Page', function() {
else else
request.continue(); request.continue();
}); });
let failedRequests = []; const failedRequests = [];
page.on('requestfailed', request => failedRequests.push(request)); page.on('requestfailed', request => failedRequests.push(request));
await page.goto(PREFIX + '/one-style.html'); await page.goto(PREFIX + '/one-style.html');
expect(failedRequests.length).toBe(1); expect(failedRequests.length).toBe(1);
@ -1542,7 +1542,7 @@ describe('Page', function() {
expect(failedRequests[0].response()).toBe(null); expect(failedRequests[0].response()).toBe(null);
})); }));
it('Page.Events.RequestFinished', SX(async function() { it('Page.Events.RequestFinished', SX(async function() {
let requests = []; const requests = [];
page.on('requestfinished', request => requests.push(request)); page.on('requestfinished', request => requests.push(request));
await page.goto(EMPTY_PAGE); await page.goto(EMPTY_PAGE);
expect(requests.length).toBe(1); expect(requests.length).toBe(1);
@ -1550,7 +1550,7 @@ describe('Page', function() {
expect(requests[0].response()).toBeTruthy(); expect(requests[0].response()).toBeTruthy();
})); }));
it('should fire events in proper order', SX(async function() { it('should fire events in proper order', SX(async function() {
let events = []; const events = [];
page.on('request', request => events.push('request')); page.on('request', request => events.push('request'));
page.on('response', response => events.push('response')); page.on('response', response => events.push('response'));
page.on('requestfinished', request => events.push('requestfinished')); page.on('requestfinished', request => events.push('requestfinished'));
@ -1558,7 +1558,7 @@ describe('Page', function() {
expect(events).toEqual(['request', 'response', 'requestfinished']); expect(events).toEqual(['request', 'response', 'requestfinished']);
})); }));
it('should support redirects', SX(async function() { it('should support redirects', SX(async function() {
let events = []; const events = [];
page.on('request', request => events.push(`${request.method} ${request.url}`)); page.on('request', request => events.push(`${request.method} ${request.url}`));
page.on('response', response => events.push(`${response.status} ${response.url}`)); page.on('response', response => events.push(`${response.status} ${response.url}`));
page.on('requestfinished', request => events.push(`DONE ${request.url}`)); page.on('requestfinished', request => events.push(`DONE ${request.url}`));
@ -1618,7 +1618,7 @@ describe('Page', function() {
function dispatchTouch() { function dispatchTouch() {
let fulfill; let fulfill;
let promise = new Promise(x => fulfill = x); const promise = new Promise(x => fulfill = x);
window.ontouchstart = function(e) { window.ontouchstart = function(e) {
fulfill('Recieved touch'); fulfill('Recieved touch');
}; };
@ -1692,13 +1692,13 @@ describe('Page', function() {
fs.unlinkSync(outputFile); fs.unlinkSync(outputFile);
})); }));
it('should default to printing in Letter format', SX(async function() { it('should default to printing in Letter format', SX(async function() {
let pages = await getPDFPages(await page.pdf()); const pages = await getPDFPages(await page.pdf());
expect(pages.length).toBe(1); expect(pages.length).toBe(1);
expect(pages[0].width).toBeCloseTo(8.5, 2); expect(pages[0].width).toBeCloseTo(8.5, 2);
expect(pages[0].height).toBeCloseTo(11, 2); expect(pages[0].height).toBeCloseTo(11, 2);
})); }));
it('should support setting custom format', SX(async function() { it('should support setting custom format', SX(async function() {
let pages = await getPDFPages(await page.pdf({ const pages = await getPDFPages(await page.pdf({
format: 'a4' format: 'a4'
})); }));
expect(pages.length).toBe(1); expect(pages.length).toBe(1);
@ -1706,7 +1706,7 @@ describe('Page', function() {
expect(pages[0].height).toBeCloseTo(11.7, 1); expect(pages[0].height).toBeCloseTo(11.7, 1);
})); }));
it('should support setting paper width and height', SX(async function() { it('should support setting paper width and height', SX(async function() {
let pages = await getPDFPages(await page.pdf({ const pages = await getPDFPages(await page.pdf({
width: '10in', width: '10in',
height: '10in', height: '10in',
})); }));
@ -1719,7 +1719,7 @@ describe('Page', function() {
// Define width and height in CSS pixels. // Define width and height in CSS pixels.
const width = 50 * 5 + 1; const width = 50 * 5 + 1;
const height = 50 * 5 + 1; const height = 50 * 5 + 1;
let pages = await getPDFPages(await page.pdf({width, height})); const pages = await getPDFPages(await page.pdf({width, height}));
expect(pages.length).toBe(8); expect(pages.length).toBe(8);
expect(pages[0].width).toBeCloseTo(cssPixelsToInches(width), 2); expect(pages[0].width).toBeCloseTo(cssPixelsToInches(width), 2);
expect(pages[0].height).toBeCloseTo(cssPixelsToInches(height), 2); expect(pages[0].height).toBeCloseTo(cssPixelsToInches(height), 2);
@ -1729,7 +1729,7 @@ describe('Page', function() {
// Define width and height in CSS pixels. // Define width and height in CSS pixels.
const width = 50 * 5 + 1; const width = 50 * 5 + 1;
const height = 50 * 5 + 1; const height = 50 * 5 + 1;
let pages = await getPDFPages(await page.pdf({width, height, pageRanges: '1,4-7'})); const pages = await getPDFPages(await page.pdf({width, height, pageRanges: '1,4-7'}));
expect(pages.length).toBe(5); expect(pages.length).toBe(5);
})); }));
it('should throw if format is unknown', SX(async function() { it('should throw if format is unknown', SX(async function() {
@ -1777,13 +1777,13 @@ describe('Page', function() {
it('should work', SX(async function() { it('should work', SX(async function() {
await page.setViewport({width: 500, height: 500}); await page.setViewport({width: 500, height: 500});
await page.goto(PREFIX + '/grid.html'); await page.goto(PREFIX + '/grid.html');
let screenshot = await page.screenshot(); const screenshot = await page.screenshot();
expect(screenshot).toBeGolden('screenshot-sanity.png'); expect(screenshot).toBeGolden('screenshot-sanity.png');
})); }));
it('should clip rect', SX(async function() { it('should clip rect', SX(async function() {
await page.setViewport({width: 500, height: 500}); await page.setViewport({width: 500, height: 500});
await page.goto(PREFIX + '/grid.html'); await page.goto(PREFIX + '/grid.html');
let screenshot = await page.screenshot({ const screenshot = await page.screenshot({
clip: { clip: {
x: 50, x: 50,
y: 100, y: 100,
@ -1796,7 +1796,7 @@ describe('Page', function() {
it('should work for offscreen clip', SX(async function() { it('should work for offscreen clip', SX(async function() {
await page.setViewport({width: 500, height: 500}); await page.setViewport({width: 500, height: 500});
await page.goto(PREFIX + '/grid.html'); await page.goto(PREFIX + '/grid.html');
let screenshot = await page.screenshot({ const screenshot = await page.screenshot({
clip: { clip: {
x: 50, x: 50,
y: 600, y: 600,
@ -1809,7 +1809,7 @@ describe('Page', function() {
it('should run in parallel', SX(async function() { it('should run in parallel', SX(async function() {
await page.setViewport({width: 500, height: 500}); await page.setViewport({width: 500, height: 500});
await page.goto(PREFIX + '/grid.html'); await page.goto(PREFIX + '/grid.html');
let promises = []; const promises = [];
for (let i = 0; i < 3; ++i) { for (let i = 0; i < 3; ++i) {
promises.push(page.screenshot({ promises.push(page.screenshot({
clip: { clip: {
@ -1820,28 +1820,28 @@ describe('Page', function() {
} }
})); }));
} }
let screenshots = await Promise.all(promises); const screenshots = await Promise.all(promises);
expect(screenshots[1]).toBeGolden('grid-cell-1.png'); expect(screenshots[1]).toBeGolden('grid-cell-1.png');
})); }));
it('should take fullPage screenshots', SX(async function() { it('should take fullPage screenshots', SX(async function() {
await page.setViewport({width: 500, height: 500}); await page.setViewport({width: 500, height: 500});
await page.goto(PREFIX + '/grid.html'); await page.goto(PREFIX + '/grid.html');
let screenshot = await page.screenshot({ const screenshot = await page.screenshot({
fullPage: true fullPage: true
}); });
expect(screenshot).toBeGolden('screenshot-grid-fullpage.png'); expect(screenshot).toBeGolden('screenshot-grid-fullpage.png');
})); }));
it('should run in parallel in multiple pages', SX(async function() { it('should run in parallel in multiple pages', SX(async function() {
const N = 2; const N = 2;
let pages = await Promise.all(Array(N).fill(0).map(async() => { const pages = await Promise.all(Array(N).fill(0).map(async() => {
let page = await browser.newPage(); const page = await browser.newPage();
await page.goto(PREFIX + '/grid.html'); await page.goto(PREFIX + '/grid.html');
return page; return page;
})); }));
let promises = []; const promises = [];
for (let i = 0; i < N; ++i) for (let i = 0; i < N; ++i)
promises.push(pages[i].screenshot({ clip: { x: 50 * i, y: 0, width: 50, height: 50 } })); promises.push(pages[i].screenshot({ clip: { x: 50 * i, y: 0, width: 50, height: 50 } }));
let screenshots = await Promise.all(promises); const screenshots = await Promise.all(promises);
for (let i = 0; i < N; ++i) for (let i = 0; i < N; ++i)
expect(screenshots[i]).toBeGolden(`grid-cell-${i}.png`); expect(screenshots[i]).toBeGolden(`grid-cell-${i}.png`);
await Promise.all(pages.map(page => page.close())); await Promise.all(pages.map(page => page.close()));
@ -1849,13 +1849,13 @@ describe('Page', function() {
it('should allow transparency', SX(async function() { it('should allow transparency', SX(async function() {
await page.setViewport({ width: 100, height: 100 }); await page.setViewport({ width: 100, height: 100 });
await page.goto(EMPTY_PAGE); await page.goto(EMPTY_PAGE);
let screenshot = await page.screenshot({omitBackground:true}); const screenshot = await page.screenshot({omitBackground:true});
expect(screenshot).toBeGolden('transparent.png'); expect(screenshot).toBeGolden('transparent.png');
})); }));
}); });
describe('Tracing', function() { describe('Tracing', function() {
let outputFile = path.join(__dirname, 'assets', 'trace.json'); const outputFile = path.join(__dirname, 'assets', 'trace.json');
afterEach(function() { afterEach(function() {
fs.unlinkSync(outputFile); fs.unlinkSync(outputFile);
}); });
@ -1867,7 +1867,7 @@ describe('Page', function() {
})); }));
it('should throw if tracing on two pages', SX(async function() { it('should throw if tracing on two pages', SX(async function() {
await page.tracing.start({path: outputFile}); await page.tracing.start({path: outputFile});
let newPage = await browser.newPage(); const newPage = await browser.newPage();
let error = null; let error = null;
try { try {
await newPage.tracing.start({path: outputFile}); await newPage.tracing.start({path: outputFile});
@ -1883,12 +1883,12 @@ describe('Page', function() {
if (process.env.COVERAGE) { if (process.env.COVERAGE) {
describe('COVERAGE', function(){ describe('COVERAGE', function(){
let coverage = helper.publicAPICoverage(); const coverage = helper.publicAPICoverage();
let disabled = new Set(); const disabled = new Set();
if (!headless) if (!headless)
disabled.add('page.pdf'); disabled.add('page.pdf');
for (let method of coverage.keys()) { for (const method of coverage.keys()) {
(disabled.has(method) ? xit : it)(`public api '${method}' should be called`, SX(async function(){ (disabled.has(method) ? xit : it)(`public api '${method}' should be called`, SX(async function(){
expect(coverage.get(method)).toBe(true); expect(coverage.get(method)).toBe(true);
})); }));
@ -1903,7 +1903,7 @@ if (process.env.COVERAGE) {
*/ */
function waitForEvents(emitter, eventName, eventCount = 1) { function waitForEvents(emitter, eventName, eventCount = 1) {
let fulfill; let fulfill;
let promise = new Promise(x => fulfill = x); const promise = new Promise(x => fulfill = x);
emitter.on(eventName, onEvent); emitter.on(eventName, onEvent);
return promise; return promise;
@ -1925,10 +1925,10 @@ async function getPDFPages(pdfBuffer) {
PDFJS.disableWorker = true; PDFJS.disableWorker = true;
const data = new Uint8Array(pdfBuffer); const data = new Uint8Array(pdfBuffer);
const doc = await PDFJS.getDocument(data); const doc = await PDFJS.getDocument(data);
let pages = []; const pages = [];
for (let i = 0; i < doc.numPages; ++i) { for (let i = 0; i < doc.numPages; ++i) {
let page = await doc.getPage(i + 1); const page = await doc.getPage(i + 1);
let viewport = page.getViewport(1); const viewport = page.getViewport(1);
// Viewport width and height is in PDF points, which is // Viewport width and height is in PDF points, which is
// 1/72 of an inch. // 1/72 of an inch.
pages.push({ pages.push({

View File

@ -44,7 +44,7 @@ module.exports = {
* @return {string} * @return {string}
*/ */
currentPlatform: function() { currentPlatform: function() {
let platform = os.platform(); const platform = os.platform();
if (platform === 'darwin') if (platform === 'darwin')
return 'mac'; return 'mac';
if (platform === 'linux') if (platform === 'linux')
@ -61,15 +61,15 @@ module.exports = {
*/ */
canDownloadRevision: function(platform, revision) { canDownloadRevision: function(platform, revision) {
console.assert(downloadURLs[platform], 'Unknown platform: ' + platform); console.assert(downloadURLs[platform], 'Unknown platform: ' + platform);
let url = URL.parse(util.format(downloadURLs[platform], revision)); const url = URL.parse(util.format(downloadURLs[platform], revision));
let options = { const options = {
method: 'HEAD', method: 'HEAD',
host: url.host, host: url.host,
path: url.pathname, path: url.pathname,
}; };
let resolve; let resolve;
let promise = new Promise(x => resolve = x); const promise = new Promise(x => resolve = x);
let request = https.request(options, response => { const request = https.request(options, response => {
resolve(response.statusCode === 200); resolve(response.statusCode === 200);
}); });
request.on('error', error => { request.on('error', error => {
@ -90,8 +90,8 @@ module.exports = {
let url = downloadURLs[platform]; let url = downloadURLs[platform];
console.assert(url, `Unsupported platform: ${platform}`); console.assert(url, `Unsupported platform: ${platform}`);
url = util.format(url, revision); url = util.format(url, revision);
let zipPath = path.join(DOWNLOADS_FOLDER, `download-${platform}-${revision}.zip`); const zipPath = path.join(DOWNLOADS_FOLDER, `download-${platform}-${revision}.zip`);
let folderPath = getFolderPath(platform, revision); const folderPath = getFolderPath(platform, revision);
if (fs.existsSync(folderPath)) if (fs.existsSync(folderPath))
return; return;
try { try {
@ -111,7 +111,7 @@ module.exports = {
downloadedRevisions: function() { downloadedRevisions: function() {
if (!fs.existsSync(DOWNLOADS_FOLDER)) if (!fs.existsSync(DOWNLOADS_FOLDER))
return []; return [];
let fileNames = fs.readdirSync(DOWNLOADS_FOLDER); const fileNames = fs.readdirSync(DOWNLOADS_FOLDER);
return fileNames.map(fileName => parseFolderPath(fileName)).filter(revision => !!revision); return fileNames.map(fileName => parseFolderPath(fileName)).filter(revision => !!revision);
}, },
@ -133,7 +133,7 @@ module.exports = {
*/ */
revisionInfo: function(platform, revision) { revisionInfo: function(platform, revision) {
console.assert(downloadURLs[platform], `Unsupported platform: ${platform}`); console.assert(downloadURLs[platform], `Unsupported platform: ${platform}`);
let folderPath = getFolderPath(platform, revision); const folderPath = getFolderPath(platform, revision);
let executablePath = ''; let executablePath = '';
if (platform === 'mac') if (platform === 'mac')
executablePath = path.join(folderPath, 'chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium'); executablePath = path.join(folderPath, 'chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium');
@ -166,11 +166,11 @@ function getFolderPath(platform, revision) {
* @return {?{platform: string, revision: string}} * @return {?{platform: string, revision: string}}
*/ */
function parseFolderPath(folderPath) { function parseFolderPath(folderPath) {
let name = path.basename(folderPath); const name = path.basename(folderPath);
let splits = name.split('-'); const splits = name.split('-');
if (splits.length !== 2) if (splits.length !== 2)
return null; return null;
let [platform, revision] = splits; const [platform, revision] = splits;
if (!downloadURLs[platform]) if (!downloadURLs[platform])
return null; return null;
return {platform, revision}; return {platform, revision};
@ -184,20 +184,20 @@ function parseFolderPath(folderPath) {
*/ */
function downloadFile(url, destinationPath, progressCallback) { function downloadFile(url, destinationPath, progressCallback) {
let fulfill, reject; let fulfill, reject;
let promise = new Promise((x, y) => { fulfill = x; reject = y; }); const promise = new Promise((x, y) => { fulfill = x; reject = y; });
let request = https.get(url, response => { const request = https.get(url, response => {
if (response.statusCode !== 200) { if (response.statusCode !== 200) {
let error = new Error(`Download failed: server returned code ${response.statusCode}. URL: ${url}`); const error = new Error(`Download failed: server returned code ${response.statusCode}. URL: ${url}`);
// consume response data to free up memory // consume response data to free up memory
response.resume(); response.resume();
reject(error); reject(error);
return; return;
} }
let file = fs.createWriteStream(destinationPath); const file = fs.createWriteStream(destinationPath);
file.on('finish', () => fulfill()); file.on('finish', () => fulfill());
file.on('error', error => reject(error)); file.on('error', error => reject(error));
response.pipe(file); response.pipe(file);
let totalBytes = parseInt(response.headers['content-length'], 10); const totalBytes = parseInt(response.headers['content-length'], 10);
if (progressCallback) if (progressCallback)
response.on('data', onData.bind(null, totalBytes)); response.on('data', onData.bind(null, totalBytes));
}); });

View File

@ -59,8 +59,8 @@ Running command without arguments will check against omahaproxy revisions.`);
return; return;
} }
let fromRevision = parseInt(process.argv[2], 10); const fromRevision = parseInt(process.argv[2], 10);
let toRevision = parseInt(process.argv[3], 10); const toRevision = parseInt(process.argv[3], 10);
checkRangeAvailability(fromRevision, toRevision); checkRangeAvailability(fromRevision, toRevision);
/** /**
@ -68,23 +68,23 @@ checkRangeAvailability(fromRevision, toRevision);
*/ */
async function checkOmahaProxyAvailability() { async function checkOmahaProxyAvailability() {
console.log('Fetching revisions from ' + OMAHA_PROXY); console.log('Fetching revisions from ' + OMAHA_PROXY);
let platforms = await loadJSON(OMAHA_PROXY); const platforms = await loadJSON(OMAHA_PROXY);
if (!platforms) { if (!platforms) {
console.error('ERROR: failed to fetch chromium revisions from omahaproxy.'); console.error('ERROR: failed to fetch chromium revisions from omahaproxy.');
return; return;
} }
let table = new Table([27, 7, 7, 7, 7]); const table = new Table([27, 7, 7, 7, 7]);
table.drawRow([''].concat(Downloader.supportedPlatforms())); table.drawRow([''].concat(Downloader.supportedPlatforms()));
for (let platform of platforms) { for (const platform of platforms) {
// Trust only to the main platforms. // Trust only to the main platforms.
if (platform.os !== 'mac' && platform.os !== 'win' && platform.os !== 'win64' && platform.os !== 'linux') if (platform.os !== 'mac' && platform.os !== 'win' && platform.os !== 'win64' && platform.os !== 'linux')
continue; continue;
let osName = platform.os === 'win' ? 'win32' : platform.os; const osName = platform.os === 'win' ? 'win32' : platform.os;
for (let version of platform.versions) { for (const version of platform.versions) {
if (version.channel !== 'dev' && version.channel !== 'beta' && version.channel !== 'canary' && version.channel !== 'stable') if (version.channel !== 'dev' && version.channel !== 'beta' && version.channel !== 'canary' && version.channel !== 'stable')
continue; continue;
let revisionName = padLeft('[' + osName + ' ' + version.channel + ']', 15); const revisionName = padLeft('[' + osName + ' ' + version.channel + ']', 15);
let revision = parseInt(version.branch_base_position, 10); const revision = parseInt(version.branch_base_position, 10);
await checkAndDrawRevisionAvailability(table, revisionName, revision); await checkAndDrawRevisionAvailability(table, revisionName, revision);
} }
} }
@ -96,9 +96,9 @@ async function checkOmahaProxyAvailability() {
* @return {!Promise} * @return {!Promise}
*/ */
async function checkRangeAvailability(fromRevision, toRevision) { async function checkRangeAvailability(fromRevision, toRevision) {
let table = new Table([10, 7, 7, 7, 7]); const table = new Table([10, 7, 7, 7, 7]);
table.drawRow([''].concat(Downloader.supportedPlatforms())); table.drawRow([''].concat(Downloader.supportedPlatforms()));
let inc = fromRevision < toRevision ? 1 : -1; const inc = fromRevision < toRevision ? 1 : -1;
for (let revision = fromRevision; revision !== toRevision; revision += inc) for (let revision = fromRevision; revision !== toRevision; revision += inc)
await checkAndDrawRevisionAvailability(table, '', revision); await checkAndDrawRevisionAvailability(table, '', revision);
} }
@ -110,15 +110,15 @@ async function checkRangeAvailability(fromRevision, toRevision) {
* @return {!Promise} * @return {!Promise}
*/ */
async function checkAndDrawRevisionAvailability(table, name, revision) { async function checkAndDrawRevisionAvailability(table, name, revision) {
let promises = []; const promises = [];
for (let platform of Downloader.supportedPlatforms()) for (const platform of Downloader.supportedPlatforms())
promises.push(Downloader.canDownloadRevision(platform, revision)); promises.push(Downloader.canDownloadRevision(platform, revision));
let availability = await Promise.all(promises); const availability = await Promise.all(promises);
let allAvailable = availability.every(e => !!e); const allAvailable = availability.every(e => !!e);
let values = [name + ' ' + (allAvailable ? colors.green + revision + colors.reset : revision)]; const values = [name + ' ' + (allAvailable ? colors.green + revision + colors.reset : revision)];
for (let i = 0; i < availability.length; ++i) { for (let i = 0; i < availability.length; ++i) {
let decoration = availability[i] ? '+' : '-'; const decoration = availability[i] ? '+' : '-';
let color = availability[i] ? colors.green : colors.red; const color = availability[i] ? colors.green : colors.red;
values.push(color + decoration + colors.reset); values.push(color + decoration + colors.reset);
} }
table.drawRow(values); table.drawRow(values);
@ -130,7 +130,7 @@ async function checkAndDrawRevisionAvailability(table, name, revision) {
*/ */
function loadJSON(url) { function loadJSON(url) {
let resolve; let resolve;
let promise = new Promise(x => resolve = x); const promise = new Promise(x => resolve = x);
https.get(url, response => { https.get(url, response => {
if (response.statusCode !== 200) { if (response.statusCode !== 200) {
resolve(null); resolve(null);
@ -141,7 +141,7 @@ function loadJSON(url) {
body += chunk; body += chunk;
}); });
response.on('end', function(){ response.on('end', function(){
let json = JSON.parse(body); const json = JSON.parse(body);
resolve(json); resolve(json);
}); });
}).on('error', function(e){ }).on('error', function(e){
@ -164,8 +164,8 @@ function spaceString(size) {
* @return {string} * @return {string}
*/ */
function filterOutColors(text) { function filterOutColors(text) {
for (let colorName in colors) { for (const colorName in colors) {
let color = colors[colorName]; const color = colors[colorName];
text = text.replace(color, ''); text = text.replace(color, '');
} }
return text; return text;
@ -177,7 +177,7 @@ function filterOutColors(text) {
* @return {string} * @return {string}
*/ */
function padLeft(text, length) { function padLeft(text, length) {
let printableCharacters = filterOutColors(text); const printableCharacters = filterOutColors(text);
return printableCharacters.length >= length ? text : spaceString(length - text.length) + text; return printableCharacters.length >= length ? text : spaceString(length - text.length) + text;
} }
@ -187,10 +187,10 @@ function padLeft(text, length) {
* @return {string} * @return {string}
*/ */
function padCenter(text, length) { function padCenter(text, length) {
let printableCharacters = filterOutColors(text); const printableCharacters = filterOutColors(text);
if (printableCharacters.length >= length) if (printableCharacters.length >= length)
return text; return text;
let left = Math.floor((length - printableCharacters.length) / 2); const left = Math.floor((length - printableCharacters.length) / 2);
let right = Math.ceil((length - printableCharacters.length) / 2); const right = Math.ceil((length - printableCharacters.length) / 2);
return spaceString(left) + text + spaceString(right); return spaceString(left) + text + spaceString(right);
} }

View File

@ -21,7 +21,7 @@ class Documentation {
constructor(classesArray) { constructor(classesArray) {
this.classesArray = classesArray; this.classesArray = classesArray;
this.classes = new Map(); this.classes = new Map();
for (let cls of classesArray) for (const cls of classesArray)
this.classes.set(cls.name, cls); this.classes.set(cls.name, cls);
} }
} }
@ -38,7 +38,7 @@ Documentation.Class = class {
this.properties = new Map(); this.properties = new Map();
this.methods = new Map(); this.methods = new Map();
this.events = new Map(); this.events = new Map();
for (let member of membersArray) { for (const member of membersArray) {
this.members.set(member.name, member); this.members.set(member.name, member);
if (member.type === 'method') if (member.type === 'method')
this.methods.set(member.name, member); this.methods.set(member.name, member);
@ -65,7 +65,7 @@ Documentation.Member = class {
this.args = new Map(); this.args = new Map();
this.hasReturn = hasReturn; this.hasReturn = hasReturn;
this.async = async; this.async = async;
for (let arg of argsArray) for (const arg of argsArray)
this.args.set(arg.name, arg); this.args.set(arg.name, arg);
} }

View File

@ -36,13 +36,13 @@ class ESTreeWalker {
return; return;
} }
let walkOrder = ESTreeWalker._walkOrder[node.type]; const walkOrder = ESTreeWalker._walkOrder[node.type];
if (!walkOrder) if (!walkOrder)
return; return;
if (node.type === 'TemplateLiteral') { if (node.type === 'TemplateLiteral') {
let templateLiteral = /** @type {!ESTree.TemplateLiteralNode} */ (node); const templateLiteral = /** @type {!ESTree.TemplateLiteralNode} */ (node);
let expressionsLength = templateLiteral.expressions.length; const expressionsLength = templateLiteral.expressions.length;
for (let i = 0; i < expressionsLength; ++i) { for (let i = 0; i < expressionsLength; ++i) {
this._innerWalk(templateLiteral.quasis[i], templateLiteral); this._innerWalk(templateLiteral.quasis[i], templateLiteral);
this._innerWalk(templateLiteral.expressions[i], templateLiteral); this._innerWalk(templateLiteral.expressions[i], templateLiteral);
@ -50,7 +50,7 @@ class ESTreeWalker {
this._innerWalk(templateLiteral.quasis[expressionsLength], templateLiteral); this._innerWalk(templateLiteral.quasis[expressionsLength], templateLiteral);
} else { } else {
for (let i = 0; i < walkOrder.length; ++i) { for (let i = 0; i < walkOrder.length; ++i) {
let entity = node[walkOrder[i]]; const entity = node[walkOrder[i]];
if (Array.isArray(entity)) if (Array.isArray(entity))
this._walkArray(entity, node); this._walkArray(entity, node);
else else

View File

@ -27,8 +27,8 @@ class JSOutline {
this._currentClassMembers = []; this._currentClassMembers = [];
this._text = text; this._text = text;
let ast = esprima.parseScript(this._text, {loc: true, range: true}); const ast = esprima.parseScript(this._text, {loc: true, range: true});
let walker = new ESTreeWalker(node => { const walker = new ESTreeWalker(node => {
if (node.type === 'ClassDeclaration') if (node.type === 'ClassDeclaration')
this._onClassDeclaration(node); this._onClassDeclaration(node);
else if (node.type === 'MethodDefinition') else if (node.type === 'MethodDefinition')
@ -49,9 +49,9 @@ class JSOutline {
_onMethodDefinition(node) { _onMethodDefinition(node) {
console.assert(this._currentClassName !== null); console.assert(this._currentClassName !== null);
console.assert(node.value.type === 'FunctionExpression'); console.assert(node.value.type === 'FunctionExpression');
let methodName = this._extractText(node.key); const methodName = this._extractText(node.key);
if (node.kind === 'get') { if (node.kind === 'get') {
let property = Documentation.Member.createProperty(methodName); const property = Documentation.Member.createProperty(methodName);
this._currentClassMembers.push(property); this._currentClassMembers.push(property);
return; return;
} }
@ -60,7 +60,7 @@ class JSOutline {
// Extract properties from constructor. // Extract properties from constructor.
if (node.kind === 'constructor') { if (node.kind === 'constructor') {
// Extract properties from constructor. // Extract properties from constructor.
let walker = new ESTreeWalker(node => { const walker = new ESTreeWalker(node => {
if (node.type !== 'AssignmentExpression') if (node.type !== 'AssignmentExpression')
return; return;
node = node.left; node = node.left;
@ -71,7 +71,7 @@ class JSOutline {
}); });
walker.walk(node); walker.walk(node);
} else if (!hasReturn) { } else if (!hasReturn) {
let walker = new ESTreeWalker(node => { const walker = new ESTreeWalker(node => {
if (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression') if (node.type === 'FunctionExpression' || node.type === 'FunctionDeclaration' || node.type === 'ArrowFunctionExpression')
return ESTreeWalker.SkipSubtree; return ESTreeWalker.SkipSubtree;
if (node.type === 'ReturnStatement') if (node.type === 'ReturnStatement')
@ -80,7 +80,7 @@ class JSOutline {
walker.walk(node.value.body); walker.walk(node.value.body);
} }
const args = []; const args = [];
for (let param of node.value.params) { for (const param of node.value.params) {
if (param.type === 'AssignmentPattern') if (param.type === 'AssignmentPattern')
args.push(new Documentation.Argument(param.left.name)); args.push(new Documentation.Argument(param.left.name));
else if (param.type === 'RestElement') else if (param.type === 'RestElement')
@ -92,7 +92,7 @@ class JSOutline {
else else
this.errors.push(`JS Parsing issue: unsupported syntax to define parameter in ${this._currentClassName}.${methodName}(): ${this._extractText(param)}`); this.errors.push(`JS Parsing issue: unsupported syntax to define parameter in ${this._currentClassName}.${methodName}(): ${this._extractText(param)}`);
} }
let method = Documentation.Member.createMethod(methodName, args, hasReturn, node.value.async); const method = Documentation.Member.createMethod(methodName, args, hasReturn, node.value.async);
this._currentClassMembers.push(method); this._currentClassMembers.push(method);
return ESTreeWalker.SkipSubtree; return ESTreeWalker.SkipSubtree;
} }
@ -108,7 +108,7 @@ class JSOutline {
events = []; events = [];
this._eventsByClassName.set(className, events); this._eventsByClassName.set(className, events);
} }
for (let property of node.right.properties) { for (const property of node.right.properties) {
if (property.type !== 'Property' || property.key.type !== 'Identifier' || property.value.type !== 'Literal') if (property.type !== 'Property' || property.key.type !== 'Identifier' || property.value.type !== 'Literal')
continue; continue;
events.push(Documentation.Member.createEvent(property.value.value)); events.push(Documentation.Member.createEvent(property.value.value));
@ -118,7 +118,7 @@ class JSOutline {
_flushClassIfNeeded() { _flushClassIfNeeded() {
if (this._currentClassName === null) if (this._currentClassName === null)
return; return;
let jsClass = new Documentation.Class(this._currentClassName, this._currentClassMembers); const jsClass = new Documentation.Class(this._currentClassName, this._currentClassMembers);
this.classes.push(jsClass); this.classes.push(jsClass);
this._currentClassName = null; this._currentClassName = null;
this._currentClassMembers = []; this._currentClassMembers = [];
@ -126,8 +126,8 @@ class JSOutline {
_recreateClassesWithEvents() { _recreateClassesWithEvents() {
this.classes = this.classes.map(cls => { this.classes = this.classes.map(cls => {
let events = this._eventsByClassName.get(cls.name) || []; const events = this._eventsByClassName.get(cls.name) || [];
let members = cls.membersArray.concat(events); const members = cls.membersArray.concat(events);
return new Documentation.Class(cls.name, members); return new Documentation.Class(cls.name, members);
}); });
} }
@ -135,7 +135,7 @@ class JSOutline {
_extractText(node) { _extractText(node) {
if (!node) if (!node)
return null; return null;
let text = this._text.substring(node.range[0], node.range[1]).trim(); const text = this._text.substring(node.range[0], node.range[1]).trim();
return text; return text;
} }
} }
@ -145,10 +145,10 @@ class JSOutline {
* @return {!Promise<{documentation: !Documentation, errors: !Array<string>}>} * @return {!Promise<{documentation: !Documentation, errors: !Array<string>}>}
*/ */
module.exports = async function(sources) { module.exports = async function(sources) {
let classes = []; const classes = [];
let errors = []; const errors = [];
for (let source of sources) { for (const source of sources) {
let outline = new JSOutline(source.text()); const outline = new JSOutline(source.text());
classes.push(...outline.classes); classes.push(...outline.classes);
errors.push(...outline.errors); errors.push(...outline.errors);
} }

View File

@ -33,11 +33,11 @@ class MDOutline {
// Extract headings. // Extract headings.
await page.setContent(html); await page.setContent(html);
const {classes, errors} = await page.evaluate(() => { const {classes, errors} = await page.evaluate(() => {
let classes = []; const classes = [];
let currentClass = {}; let currentClass = {};
let member = {}; let member = {};
let errors = []; const errors = [];
for (let element of document.body.querySelectorAll('h3, h4, h4 + ul > li')) { for (const element of document.body.querySelectorAll('h3, h4, h4 + ul > li')) {
if (element.matches('h3')) { if (element.matches('h3')) {
currentClass = { currentClass = {
name: element.textContent, name: element.textContent,
@ -82,22 +82,22 @@ class MDOutline {
let currentClassName = null; let currentClassName = null;
let currentClassMembers = []; let currentClassMembers = [];
for (const cls of classes) { for (const cls of classes) {
let match = cls.name.match(classHeading); const match = cls.name.match(classHeading);
if (!match) if (!match)
continue; continue;
currentClassName = match[1]; currentClassName = match[1];
for (let member of cls.members) { for (const member of cls.members) {
if (constructorRegex.test(member.name)) { if (constructorRegex.test(member.name)) {
let match = member.name.match(constructorRegex); const match = member.name.match(constructorRegex);
handleMethod.call(this, member, match[1], 'constructor', match[2]); handleMethod.call(this, member, match[1], 'constructor', match[2]);
} else if (methodRegex.test(member.name)) { } else if (methodRegex.test(member.name)) {
let match = member.name.match(methodRegex); const match = member.name.match(methodRegex);
handleMethod.call(this, member, match[1], match[2], match[3]); handleMethod.call(this, member, match[1], match[2], match[3]);
} else if (propertyRegex.test(member.name)) { } else if (propertyRegex.test(member.name)) {
let match = member.name.match(propertyRegex); const match = member.name.match(propertyRegex);
handleProperty.call(this, member, match[1], match[2]); handleProperty.call(this, member, match[1], match[2]);
} else if (eventRegex.test(member.name)) { } else if (eventRegex.test(member.name)) {
let match = member.name.match(eventRegex); const match = member.name.match(eventRegex);
handleEvent.call(this, member, match[1]); handleEvent.call(this, member, match[1]);
} }
} }
@ -112,8 +112,8 @@ class MDOutline {
parameters = parameters.trim().replace(/[\[\]]/g, ''); parameters = parameters.trim().replace(/[\[\]]/g, '');
if (parameters !== member.args.join(', ')) if (parameters !== member.args.join(', '))
this.errors.push(`Heading arguments for "${member.name}" do not match described ones, i.e. "${parameters}" != "${member.args.join(', ')}"`); this.errors.push(`Heading arguments for "${member.name}" do not match described ones, i.e. "${parameters}" != "${member.args.join(', ')}"`);
let args = member.args.map(arg => new Documentation.Argument(arg)); const args = member.args.map(arg => new Documentation.Argument(arg));
let method = Documentation.Member.createMethod(methodName, args, member.hasReturn, false); const method = Documentation.Member.createMethod(methodName, args, member.hasReturn, false);
currentClassMembers.push(method); currentClassMembers.push(method);
} }
@ -149,10 +149,10 @@ class MDOutline {
* @return {!Promise<{documentation: !Documentation, errors: !Array<string>}>} * @return {!Promise<{documentation: !Documentation, errors: !Array<string>}>}
*/ */
module.exports = async function(page, sources) { module.exports = async function(page, sources) {
let classes = []; const classes = [];
let errors = []; const errors = [];
for (let source of sources) { for (const source of sources) {
let outline = await MDOutline.create(page, source.text()); const outline = await MDOutline.create(page, source.text());
classes.push(...outline.classes); classes.push(...outline.classes);
errors.push(...outline.errors); errors.push(...outline.errors);
} }

View File

@ -58,21 +58,21 @@ const EXCLUDE_METHODS = new Set([
* @return {!Promise<!Array<!Message>>} * @return {!Promise<!Array<!Message>>}
*/ */
module.exports = async function lint(page, mdSources, jsSources) { module.exports = async function lint(page, mdSources, jsSources) {
let mdResult = await mdBuilder(page, mdSources); const mdResult = await mdBuilder(page, mdSources);
let jsResult = await jsBuilder(jsSources); const jsResult = await jsBuilder(jsSources);
let jsDocumentation = filterJSDocumentation(jsResult.documentation); const jsDocumentation = filterJSDocumentation(jsResult.documentation);
let mdDocumentation = mdResult.documentation; const mdDocumentation = mdResult.documentation;
let jsErrors = jsResult.errors; const jsErrors = jsResult.errors;
jsErrors.push(...checkDuplicates(jsDocumentation)); jsErrors.push(...checkDuplicates(jsDocumentation));
let mdErrors = mdResult.errors; const mdErrors = mdResult.errors;
mdErrors.push(...compareDocumentations(mdDocumentation, jsDocumentation)); mdErrors.push(...compareDocumentations(mdDocumentation, jsDocumentation));
mdErrors.push(...checkDuplicates(mdDocumentation)); mdErrors.push(...checkDuplicates(mdDocumentation));
mdErrors.push(...checkSorting(mdDocumentation)); mdErrors.push(...checkSorting(mdDocumentation));
// Push all errors with proper prefixes // Push all errors with proper prefixes
let errors = jsErrors.map(error => '[JavaScript] ' + error); const errors = jsErrors.map(error => '[JavaScript] ' + error);
errors.push(...mdErrors.map(error => '[MarkDown] ' + error)); errors.push(...mdErrors.map(error => '[MarkDown] ' + error));
return errors.map(error => Message.error(error)); return errors.map(error => Message.error(error));
}; };
@ -83,8 +83,8 @@ module.exports = async function lint(page, mdSources, jsSources) {
*/ */
function checkSorting(doc) { function checkSorting(doc) {
const errors = []; const errors = [];
for (let cls of doc.classesArray) { for (const cls of doc.classesArray) {
let members = cls.membersArray; const members = cls.membersArray;
// Events should go first. // Events should go first.
let eventIndex = 0; let eventIndex = 0;
@ -94,14 +94,14 @@ function checkSorting(doc) {
errors.push(`Events should go first. Event '${members[eventIndex].name}' in class ${cls.name} breaks order`); errors.push(`Events should go first. Event '${members[eventIndex].name}' in class ${cls.name} breaks order`);
// Constructor should be right after events and before all other members. // Constructor should be right after events and before all other members.
let constructorIndex = members.findIndex(member => member.type === 'method' && member.name === 'constructor'); const constructorIndex = members.findIndex(member => member.type === 'method' && member.name === 'constructor');
if (constructorIndex > 0 && members[constructorIndex - 1].type !== 'event') if (constructorIndex > 0 && members[constructorIndex - 1].type !== 'event')
errors.push(`Constructor of ${cls.name} should go before other methods`); errors.push(`Constructor of ${cls.name} should go before other methods`);
// Events should be sorted alphabetically. // Events should be sorted alphabetically.
for (let i = 0; i < members.length - 1; ++i) { for (let i = 0; i < members.length - 1; ++i) {
let member1 = cls.membersArray[i]; const member1 = cls.membersArray[i];
let member2 = cls.membersArray[i + 1]; const member2 = cls.membersArray[i + 1];
if (member1.type !== 'event' || member2.type !== 'event') if (member1.type !== 'event' || member2.type !== 'event')
continue; continue;
if (member1.name > member2.name) if (member1.name > member2.name)
@ -110,8 +110,8 @@ function checkSorting(doc) {
// All other members should be sorted alphabetically. // All other members should be sorted alphabetically.
for (let i = 0; i < members.length - 1; ++i) { for (let i = 0; i < members.length - 1; ++i) {
let member1 = cls.membersArray[i]; const member1 = cls.membersArray[i];
let member2 = cls.membersArray[i + 1]; const member2 = cls.membersArray[i + 1];
if (member1.type === 'event' || member2.type === 'event') if (member1.type === 'event' || member2.type === 'event')
continue; continue;
if (member1.type === 'method' && member1.name === 'constructor') if (member1.type === 'method' && member1.name === 'constructor')
@ -136,11 +136,11 @@ function checkSorting(doc) {
*/ */
function filterJSDocumentation(jsDocumentation) { function filterJSDocumentation(jsDocumentation) {
// Filter classes and methods. // Filter classes and methods.
let classes = []; const classes = [];
for (let cls of jsDocumentation.classesArray) { for (const cls of jsDocumentation.classesArray) {
if (EXCLUDE_CLASSES.has(cls.name)) if (EXCLUDE_CLASSES.has(cls.name))
continue; continue;
let members = cls.membersArray.filter(member => { const members = cls.membersArray.filter(member => {
if (member.name.startsWith('_')) if (member.name.startsWith('_'))
return false; return false;
return !EXCLUDE_METHODS.has(`${cls.name}.${member.name}`); return !EXCLUDE_METHODS.has(`${cls.name}.${member.name}`);
@ -156,19 +156,19 @@ function filterJSDocumentation(jsDocumentation) {
*/ */
function checkDuplicates(doc) { function checkDuplicates(doc) {
const errors = []; const errors = [];
let classes = new Set(); const classes = new Set();
// Report duplicates. // Report duplicates.
for (let cls of doc.classesArray) { for (const cls of doc.classesArray) {
if (classes.has(cls.name)) if (classes.has(cls.name))
errors.push(`Duplicate declaration of class ${cls.name}`); errors.push(`Duplicate declaration of class ${cls.name}`);
classes.add(cls.name); classes.add(cls.name);
let members = new Set(); const members = new Set();
for (let member of cls.membersArray) { for (const member of cls.membersArray) {
if (members.has(member.name)) if (members.has(member.name))
errors.push(`Duplicate declaration of method ${cls.name}.${member.name}()`); errors.push(`Duplicate declaration of method ${cls.name}.${member.name}()`);
members.add(member.name); members.add(member.name);
let args = new Set(); const args = new Set();
for (let arg of member.argsArray) { for (const arg of member.argsArray) {
if (args.has(arg.name)) if (args.has(arg.name))
errors.push(`Duplicate declaration of argument ${cls.name}.${member.name} "${arg.name}"`); errors.push(`Duplicate declaration of argument ${cls.name}.${member.name} "${arg.name}"`);
args.add(arg.name); args.add(arg.name);
@ -188,24 +188,24 @@ function compareDocumentations(actual, expected) {
const actualClasses = Array.from(actual.classes.keys()).sort(); const actualClasses = Array.from(actual.classes.keys()).sort();
const expectedClasses = Array.from(expected.classes.keys()).sort(); const expectedClasses = Array.from(expected.classes.keys()).sort();
let classesDiff = diff(actualClasses, expectedClasses); const classesDiff = diff(actualClasses, expectedClasses);
for (let className of classesDiff.extra) for (const className of classesDiff.extra)
errors.push(`Non-existing class found: ${className}`); errors.push(`Non-existing class found: ${className}`);
for (let className of classesDiff.missing) for (const className of classesDiff.missing)
errors.push(`Class not found: ${className}`); errors.push(`Class not found: ${className}`);
for (let className of classesDiff.equal) { for (const className of classesDiff.equal) {
const actualClass = actual.classes.get(className); const actualClass = actual.classes.get(className);
const expectedClass = expected.classes.get(className); const expectedClass = expected.classes.get(className);
const actualMethods = Array.from(actualClass.methods.keys()).sort(); const actualMethods = Array.from(actualClass.methods.keys()).sort();
const expectedMethods = Array.from(expectedClass.methods.keys()).sort(); const expectedMethods = Array.from(expectedClass.methods.keys()).sort();
const methodDiff = diff(actualMethods, expectedMethods); const methodDiff = diff(actualMethods, expectedMethods);
for (let methodName of methodDiff.extra) for (const methodName of methodDiff.extra)
errors.push(`Non-existing method found: ${className}.${methodName}()`); errors.push(`Non-existing method found: ${className}.${methodName}()`);
for (let methodName of methodDiff.missing) for (const methodName of methodDiff.missing)
errors.push(`Method not found: ${className}.${methodName}()`); errors.push(`Method not found: ${className}.${methodName}()`);
for (let methodName of methodDiff.equal) { for (const methodName of methodDiff.equal) {
const actualMethod = actualClass.methods.get(methodName); const actualMethod = actualClass.methods.get(methodName);
const expectedMethod = expectedClass.methods.get(methodName); const expectedMethod = expectedClass.methods.get(methodName);
if (actualMethod.hasReturn !== expectedMethod.hasReturn) { if (actualMethod.hasReturn !== expectedMethod.hasReturn) {
@ -220,10 +220,10 @@ function compareDocumentations(actual, expected) {
const expectedArgs = Array.from(expectedMethod.args.keys()); const expectedArgs = Array.from(expectedMethod.args.keys());
const argDiff = diff(actualArgs, expectedArgs); const argDiff = diff(actualArgs, expectedArgs);
if (argDiff.extra.length || argDiff.missing.length) { if (argDiff.extra.length || argDiff.missing.length) {
let text = [`Method ${className}.${methodName}() fails to describe its parameters:`]; const text = [`Method ${className}.${methodName}() fails to describe its parameters:`];
for (let arg of argDiff.missing) for (const arg of argDiff.missing)
text.push(`- Argument not found: ${arg}`); text.push(`- Argument not found: ${arg}`);
for (let arg of argDiff.extra) for (const arg of argDiff.extra)
text.push(`- Non-existing argument found: ${arg}`); text.push(`- Non-existing argument found: ${arg}`);
errors.push(text.join('\n')); errors.push(text.join('\n'));
} }
@ -231,17 +231,17 @@ function compareDocumentations(actual, expected) {
const actualProperties = Array.from(actualClass.properties.keys()).sort(); const actualProperties = Array.from(actualClass.properties.keys()).sort();
const expectedProperties = Array.from(expectedClass.properties.keys()).sort(); const expectedProperties = Array.from(expectedClass.properties.keys()).sort();
const propertyDiff = diff(actualProperties, expectedProperties); const propertyDiff = diff(actualProperties, expectedProperties);
for (let propertyName of propertyDiff.extra) for (const propertyName of propertyDiff.extra)
errors.push(`Non-existing property found: ${className}.${propertyName}`); errors.push(`Non-existing property found: ${className}.${propertyName}`);
for (let propertyName of propertyDiff.missing) for (const propertyName of propertyDiff.missing)
errors.push(`Property not found: ${className}.${propertyName}`); errors.push(`Property not found: ${className}.${propertyName}`);
const actualEvents = Array.from(actualClass.events.keys()).sort(); const actualEvents = Array.from(actualClass.events.keys()).sort();
const expectedEvents = Array.from(expectedClass.events.keys()).sort(); const expectedEvents = Array.from(expectedClass.events.keys()).sort();
const eventsDiff = diff(actualEvents, expectedEvents); const eventsDiff = diff(actualEvents, expectedEvents);
for (let eventName of eventsDiff.extra) for (const eventName of eventsDiff.extra)
errors.push(`Non-existing event found in class ${className}: '${eventName}'`); errors.push(`Non-existing event found in class ${className}: '${eventName}'`);
for (let eventName of eventsDiff.missing) for (const eventName of eventsDiff.missing)
errors.push(`Event not found in class ${className}: '${eventName}'`); errors.push(`Event not found in class ${className}: '${eventName}'`);
} }
return errors; return errors;
@ -261,8 +261,8 @@ function diff(actual, expected) {
return {extra: [], missing: expected.slice(), equal: []}; return {extra: [], missing: expected.slice(), equal: []};
if (M === 0) if (M === 0)
return {extra: actual.slice(), missing: [], equal: []}; return {extra: actual.slice(), missing: [], equal: []};
let d = new Array(N); const d = new Array(N);
let bt = new Array(N); const bt = new Array(N);
for (let i = 0; i < N; ++i) { for (let i = 0; i < N; ++i) {
d[i] = new Array(M); d[i] = new Array(M);
bt[i] = new Array(M); bt[i] = new Array(M);
@ -276,7 +276,7 @@ function diff(actual, expected) {
d[i][j] = left; d[i][j] = left;
bt[i][j] = 'missing'; bt[i][j] = 'missing';
} }
let diag = val(i - 1, j - 1); const diag = val(i - 1, j - 1);
if (actual[i] === expected[j] && d[i][j] < diag + 1) { if (actual[i] === expected[j] && d[i][j] < diag + 1) {
d[i][j] = diag + 1; d[i][j] = diag + 1;
bt[i][j] = 'eq'; bt[i][j] = 'eq';
@ -286,9 +286,9 @@ function diff(actual, expected) {
// Backtrack results. // Backtrack results.
let i = N - 1; let i = N - 1;
let j = M - 1; let j = M - 1;
let missing = []; const missing = [];
let extra = []; const extra = [];
let equal = []; const equal = [];
while (i >= 0 && j >= 0) { while (i >= 0 && j >= 0) {
switch (bt[i][j]) { switch (bt[i][j]) {
case 'extra': case 'extra':

View File

@ -19,9 +19,9 @@ const Message = require('../Message');
const PUPPETEER_VERSION = require('../../../package.json').version; const PUPPETEER_VERSION = require('../../../package.json').version;
module.exports = function(sources) { module.exports = function(sources) {
let messages = []; const messages = [];
let commands = []; let commands = [];
for (let source of sources) { for (const source of sources) {
const text = source.text(); const text = source.text();
const commandStartRegex = /<!--\s*gen:([a-z]+)(?:\s*\(\s*([^)]*)\s*\))?\s*-->/ig; const commandStartRegex = /<!--\s*gen:([a-z]+)(?:\s*\(\s*([^)]*)\s*\))?\s*-->/ig;
const commandEndRegex = /<!--\s*gen:stop\s*-->/ig; const commandEndRegex = /<!--\s*gen:stop\s*-->/ig;
@ -45,10 +45,10 @@ module.exports = function(sources) {
commands = validateCommands(commands, messages); commands = validateCommands(commands, messages);
let changedSources = new Set(); const changedSources = new Set();
// Iterate commands in reverse order so that edits don't conflict. // Iterate commands in reverse order so that edits don't conflict.
commands.sort((a, b) => b.from - a.from); commands.sort((a, b) => b.from - a.from);
for (let command of commands) { for (const command of commands) {
let newText = command.source.text(); let newText = command.source.text();
if (command.name === 'version') if (command.name === 'version')
newText = replaceInText(newText, command.from, command.to, PUPPETEER_VERSION); newText = replaceInText(newText, command.from, command.to, PUPPETEER_VERSION);
@ -67,7 +67,7 @@ module.exports = function(sources) {
*/ */
function validateCommands(commands, outMessages) { function validateCommands(commands, outMessages) {
// Filter sane commands // Filter sane commands
let goodCommands = commands.filter(command => { const goodCommands = commands.filter(command => {
if (command.name === 'version') if (command.name === 'version')
return check(command, !command.arg, `"gen:version" should not have argument`); return check(command, !command.arg, `"gen:version" should not have argument`);
check(command, false, `Unknown command: "gen:${command.name}"`); check(command, false, `Unknown command: "gen:${command.name}"`);

View File

@ -21,8 +21,8 @@ const VERSION = require('../../../package.json').version;
describe('preprocessor', function() { describe('preprocessor', function() {
it('should throw for unknown command', function() { it('should throw for unknown command', function() {
let source = factory.createForTest('doc.md', getCommand('unknownCommand()')); const source = factory.createForTest('doc.md', getCommand('unknownCommand()'));
let messages = preprocessor([source]); const messages = preprocessor([source]);
expect(source.hasUpdatedText()).toBe(false); expect(source.hasUpdatedText()).toBe(false);
expect(messages.length).toBe(1); expect(messages.length).toBe(1);
expect(messages[0].type).toBe('error'); expect(messages[0].type).toBe('error');
@ -30,22 +30,22 @@ describe('preprocessor', function() {
}); });
describe('gen:version', function() { describe('gen:version', function() {
it('should work', function() { it('should work', function() {
let source = factory.createForTest('doc.md', `Puppeteer v${getCommand('version')}`); const source = factory.createForTest('doc.md', `Puppeteer v${getCommand('version')}`);
let messages = preprocessor([source]); const messages = preprocessor([source]);
expect(messages.length).toBe(1); expect(messages.length).toBe(1);
expect(messages[0].type).toBe('warning'); expect(messages[0].type).toBe('warning');
expect(messages[0].text).toContain('doc.md'); expect(messages[0].text).toContain('doc.md');
expect(source.text()).toBe(`Puppeteer v${getCommand('version', VERSION)}`); expect(source.text()).toBe(`Puppeteer v${getCommand('version', VERSION)}`);
}); });
it('should tolerate different writing', function() { it('should tolerate different writing', function() {
let source = factory.createForTest('doc.md', `Puppeteer v<!-- gEn:version ( ) -->WHAT const source = factory.createForTest('doc.md', `Puppeteer v<!-- gEn:version ( ) -->WHAT
<!-- GEN:stop -->`); <!-- GEN:stop -->`);
preprocessor([source]); preprocessor([source]);
expect(source.text()).toBe(`Puppeteer v<!-- gEn:version ( ) -->${VERSION}<!-- GEN:stop -->`); expect(source.text()).toBe(`Puppeteer v<!-- gEn:version ( ) -->${VERSION}<!-- GEN:stop -->`);
}); });
it('should not tolerate missing gen:stop', function() { it('should not tolerate missing gen:stop', function() {
let source = factory.createForTest('doc.md', `<!--GEN:version-->`); const source = factory.createForTest('doc.md', `<!--GEN:version-->`);
let messages = preprocessor([source]); const messages = preprocessor([source]);
expect(source.hasUpdatedText()).toBe(false); expect(source.hasUpdatedText()).toBe(false);
expect(messages.length).toBe(1); expect(messages.length).toBe(1);
expect(messages[0].type).toBe('error'); expect(messages[0].type).toBe('error');

View File

@ -23,7 +23,7 @@ const Message = require('./Message');
*/ */
module.exports = function(sources) { module.exports = function(sources) {
const warnings = []; const warnings = [];
for (let source of sources) { for (const source of sources) {
const newText = markdownToc.insert(source.text()); const newText = markdownToc.insert(source.text());
if (source.setText(newText)) if (source.setText(newText))
warnings.push('Regenerated table-of-contexts: ' + source.projectPath()); warnings.push('Regenerated table-of-contexts: ' + source.projectPath());

View File

@ -52,7 +52,7 @@ Fetch Chrome DevTools front-end emulation devices from given URL, convert them t
devices and save to the <outputPath>. devices and save to the <outputPath>.
`; `;
let argv = require('minimist')(process.argv.slice(2), { const argv = require('minimist')(process.argv.slice(2), {
alias: { u: 'url', h: 'help' }, alias: { u: 'url', h: 'help' },
}); });
@ -61,8 +61,8 @@ if (argv.help) {
return; return;
} }
let url = argv.url || DEVICES_URL; const url = argv.url || DEVICES_URL;
let outputPath = argv._[0]; const outputPath = argv._[0];
if (!outputPath) { if (!outputPath) {
console.log('ERROR: output file name is missing. Use --help for help.'); console.log('ERROR: output file name is missing. Use --help for help.');
return; return;
@ -72,7 +72,7 @@ main(url);
async function main(url) { async function main(url) {
console.log('GET ' + url); console.log('GET ' + url);
let text = await httpGET(url); const text = await httpGET(url);
let json = null; let json = null;
try { try {
json = JSON.parse(text); json = JSON.parse(text);
@ -80,11 +80,11 @@ async function main(url) {
console.error(`FAILED: error parsing response - ${e.message}`); console.error(`FAILED: error parsing response - ${e.message}`);
return; return;
} }
let devicePayloads = json.extensions.filter(extension => extension.type === 'emulated-device').map(extension => extension.device); const devicePayloads = json.extensions.filter(extension => extension.type === 'emulated-device').map(extension => extension.device);
let devices = []; let devices = [];
for (let payload of devicePayloads) { for (const payload of devicePayloads) {
let device = createDevice(payload, false); const device = createDevice(payload, false);
let landscape = createDevice(payload, true); const landscape = createDevice(payload, true);
devices.push(device); devices.push(device);
if (landscape.viewport.width !== device.viewport.width || landscape.viewport.height !== device.viewport.height) if (landscape.viewport.width !== device.viewport.width || landscape.viewport.height !== device.viewport.height)
devices.push(landscape); devices.push(landscape);
@ -92,10 +92,10 @@ async function main(url) {
devices = devices.filter(device => device.viewport.isMobile); devices = devices.filter(device => device.viewport.isMobile);
devices.sort((a, b) => a.name.localeCompare(b.name)); devices.sort((a, b) => a.name.localeCompare(b.name));
// Use single-quotes instead of double-quotes to conform with codestyle. // Use single-quotes instead of double-quotes to conform with codestyle.
let serialized = JSON.stringify(devices, null, 2) const serialized = JSON.stringify(devices, null, 2)
.replace(/'/g, `\\'`) .replace(/'/g, `\\'`)
.replace(/"/g, `'`); .replace(/"/g, `'`);
let result = util.format(template, serialized); const result = util.format(template, serialized);
fs.writeFileSync(outputPath, result, 'utf8'); fs.writeFileSync(outputPath, result, 'utf8');
} }