From e6442dd767ed5958d84eea907ee8075cb3534599 Mon Sep 17 00:00:00 2001 From: jrandolf <101637635+jrandolf@users.noreply.github.com> Date: Tue, 14 Jun 2022 13:55:35 +0200 Subject: [PATCH] chore: use `curly` (#8519) --- .eslintrc.js | 4 + examples/block-images.js | 7 +- src/common/Accessibility.ts | 137 +++++++++++++----- src/common/AriaQueryHandler.ts | 3 +- src/common/Browser.ts | 18 ++- src/common/BrowserWebSocketTransport.ts | 8 +- src/common/Connection.ts | 44 ++++-- src/common/Coverage.ts | 56 +++++-- src/common/DOMWorld.ts | 117 ++++++++++----- src/common/Debug.ts | 8 +- src/common/ExecutionContext.ts | 55 ++++--- src/common/FrameManager.ts | 100 +++++++++---- src/common/HTTPRequest.ts | 40 +++-- src/common/HTTPResponse.ts | 20 ++- src/common/Input.ts | 63 ++++++-- src/common/JSHandle.ts | 60 ++++++-- src/common/LifecycleWatcher.ts | 40 +++-- src/common/NetworkManager.ts | 31 +++- src/common/Page.ts | 109 ++++++++++---- src/common/QueryHandler.ts | 20 ++- src/common/Target.ts | 25 +++- src/common/TimeoutSettings.ts | 11 +- src/common/Tracing.ts | 4 +- src/common/assert.ts | 8 +- src/common/util.ts | 37 +++-- src/initializePuppeteer.ts | 3 +- src/node/BrowserFetcher.ts | 96 ++++++++---- src/node/BrowserRunner.ts | 35 +++-- src/node/Launcher.ts | 55 ++++--- src/node/NodeWebSocketTransport.ts | 8 +- src/node/Puppeteer.ts | 12 +- src/node/install.ts | 19 ++- test/accessibility.spec.ts | 8 +- test/assets/input/mouse-helper.js | 2 +- test/browser.spec.ts | 7 +- test/browsercontext.spec.ts | 8 +- test/coverage-utils.js | 9 +- test/elementhandle.spec.ts | 6 +- test/fixtures.spec.ts | 9 +- test/golden-utils.js | 22 ++- test/headful.spec.ts | 6 +- test/jshandle.spec.ts | 6 +- test/keyboard.spec.ts | 41 ++++-- test/launcher.spec.ts | 15 +- test/mocha-utils.ts | 62 +++++--- test/mouse.spec.ts | 12 +- test/navigation.spec.ts | 44 ++++-- test/network.spec.ts | 16 +- test/page.spec.ts | 34 +++-- test/requestinterception-experimental.spec.ts | 64 +++++--- test/requestinterception.spec.ts | 40 +++-- test/screenshot.spec.ts | 6 +- test/target.spec.ts | 8 +- test/utils.js | 11 +- test/waittask.spec.ts | 4 +- typescript-if-required.js | 8 +- utils/ESTreeWalker.js | 18 ++- utils/bisect.js | 24 ++- utils/check_availability.js | 15 +- utils/doclint/Source.js | 4 +- .../doclint/check_public_api/Documentation.js | 8 +- utils/doclint/check_public_api/JSBuilder.js | 71 ++++++--- utils/doclint/check_public_api/MDBuilder.js | 35 +++-- utils/doclint/check_public_api/index.js | 128 +++++++++++----- utils/doclint/cli.js | 4 +- utils/doclint/preprocessor/index.js | 15 +- utils/fetch_devices.js | 39 +++-- utils/testserver/index.js | 35 +++-- 68 files changed, 1507 insertions(+), 590 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 13e1a0d9..dc74eca9 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -21,6 +21,8 @@ module.exports = { extends: ['plugin:prettier/recommended'], rules: { + // Brackets keep code readable. + curly: [2, 'all'], // Error if files are not formatted with Prettier correctly. 'prettier/prettier': 2, // syntax preferences @@ -130,6 +132,8 @@ module.exports = { ], plugins: ['eslint-plugin-tsdoc'], rules: { + // Brackets keep code readable. + curly: [2, 'all'], // Error if comments do not adhere to `tsdoc`. 'tsdoc/syntax': 2, 'no-unused-vars': 0, diff --git a/examples/block-images.js b/examples/block-images.js index 298e473e..25d60163 100644 --- a/examples/block-images.js +++ b/examples/block-images.js @@ -23,8 +23,11 @@ const puppeteer = require('puppeteer'); const page = await browser.newPage(); await page.setRequestInterception(true); page.on('request', (request) => { - if (request.resourceType() === 'image') request.abort(); - else request.continue(); + if (request.resourceType() === 'image') { + request.abort(); + } else { + request.continue(); + } }); await page.goto('https://news.google.com/news/'); await page.screenshot({ path: 'news.png', fullPage: true }); diff --git a/src/common/Accessibility.ts b/src/common/Accessibility.ts index 37b2aae3..3a342c7f 100644 --- a/src/common/Accessibility.ts +++ b/src/common/Accessibility.ts @@ -196,13 +196,19 @@ export class Accessibility { needle = defaultRoot.find( (node) => node.payload.backendDOMNodeId === backendNodeId ); - if (!needle) return null; + if (!needle) { + return null; + } + } + if (!interestingOnly) { + return this.serializeTree(needle)[0] ?? null; } - if (!interestingOnly) return this.serializeTree(needle)[0] ?? null; const interestingNodes = new Set(); this.collectInterestingNodes(interestingNodes, defaultRoot, false); - if (!interestingNodes.has(needle)) return null; + if (!interestingNodes.has(needle)) { + return null; + } return this.serializeTree(needle, interestingNodes)[0] ?? null; } @@ -211,13 +217,18 @@ export class Accessibility { interestingNodes?: Set ): SerializedAXNode[] { const children: SerializedAXNode[] = []; - for (const child of node.children) + for (const child of node.children) { children.push(...this.serializeTree(child, interestingNodes)); + } - if (interestingNodes && !interestingNodes.has(node)) return children; + if (interestingNodes && !interestingNodes.has(node)) { + return children; + } const serializedNode = node.serialize(); - if (children.length) serializedNode.children = children; + if (children.length) { + serializedNode.children = children; + } return [serializedNode]; } @@ -226,11 +237,16 @@ export class Accessibility { node: AXNode, insideControl: boolean ): void { - if (node.isInteresting(insideControl)) collection.add(node); - if (node.isLeafNode()) return; + if (node.isInteresting(insideControl)) { + collection.add(node); + } + if (node.isLeafNode()) { + return; + } insideControl = insideControl || node.isControl(); - for (const child of node.children) + for (const child of node.children) { this.collectInterestingNodes(collection, child, insideControl); + } } } @@ -258,14 +274,22 @@ class AXNode { this.#richlyEditable = property.value.value === 'richtext'; this.#editable = true; } - if (property.name === 'focusable') this.#focusable = property.value.value; - if (property.name === 'hidden') this.#hidden = property.value.value; + if (property.name === 'focusable') { + this.#focusable = property.value.value; + } + if (property.name === 'hidden') { + this.#hidden = property.value.value; + } } } #isPlainTextField(): boolean { - if (this.#richlyEditable) return false; - if (this.#editable) return true; + if (this.#richlyEditable) { + return false; + } + if (this.#editable) { + return true; + } return this.#role === 'textbox' || this.#role === 'searchbox'; } @@ -288,22 +312,30 @@ class AXNode { } public find(predicate: (x: AXNode) => boolean): AXNode | null { - if (predicate(this)) return this; + if (predicate(this)) { + return this; + } for (const child of this.children) { const result = child.find(predicate); - if (result) return result; + if (result) { + return result; + } } return null; } public isLeafNode(): boolean { - if (!this.children.length) return true; + if (!this.children.length) { + return true; + } // These types of objects may have children that we use as internal // implementation details, but we want to expose them as leaves to platform // accessibility APIs because screen readers might be confused if they find // any children. - if (this.#isPlainTextField() || this.#isTextOnlyObject()) return true; + if (this.#isPlainTextField() || this.#isTextOnlyObject()) { + return true; + } // Roles whose children are only presentational according to the ARIA and // HTML5 Specs should be hidden from screen readers. @@ -324,9 +356,15 @@ class AXNode { } // Here and below: Android heuristics - if (this.#hasFocusableChild()) return false; - if (this.#focusable && this.#name) return true; - if (this.#role === 'heading' && this.#name) return true; + if (this.#hasFocusableChild()) { + return false; + } + if (this.#focusable && this.#name) { + return true; + } + if (this.#role === 'heading' && this.#name) { + return true; + } return false; } @@ -361,27 +399,41 @@ class AXNode { public isInteresting(insideControl: boolean): boolean { const role = this.#role; - if (role === 'Ignored' || this.#hidden || this.#ignored) return false; + if (role === 'Ignored' || this.#hidden || this.#ignored) { + return false; + } - if (this.#focusable || this.#richlyEditable) return true; + if (this.#focusable || this.#richlyEditable) { + return true; + } // If it's not focusable but has a control role, then it's interesting. - if (this.isControl()) return true; + if (this.isControl()) { + return true; + } // A non focusable child of a control is not interesting - if (insideControl) return false; + if (insideControl) { + return false; + } return this.isLeafNode() && !!this.#name; } public serialize(): SerializedAXNode { const properties = new Map(); - for (const property of this.payload.properties || []) + for (const property of this.payload.properties || []) { properties.set(property.name.toLowerCase(), property.value.value); - if (this.payload.name) properties.set('name', this.payload.name.value); - if (this.payload.value) properties.set('value', this.payload.value.value); - if (this.payload.description) + } + if (this.payload.name) { + properties.set('name', this.payload.name.value); + } + if (this.payload.value) { + properties.set('value', this.payload.value.value); + } + if (this.payload.description) { properties.set('description', this.payload.description.value); + } const node: SerializedAXNode = { role: this.#role, @@ -407,7 +459,9 @@ class AXNode { properties.get(key) as string; for (const userStringProperty of userStringProperties) { - if (!properties.has(userStringProperty)) continue; + if (!properties.has(userStringProperty)) { + continue; + } node[userStringProperty] = getUserStringPropertyValue(userStringProperty); } @@ -440,17 +494,22 @@ class AXNode { // RootWebArea's treat focus differently than other nodes. They report whether // their frame has focus, not whether focus is specifically on the root // node. - if (booleanProperty === 'focused' && this.#role === 'RootWebArea') + if (booleanProperty === 'focused' && this.#role === 'RootWebArea') { continue; + } const value = getBooleanPropertyValue(booleanProperty); - if (!value) continue; + if (!value) { + continue; + } node[booleanProperty] = getBooleanPropertyValue(booleanProperty); } type TristateProperty = 'checked' | 'pressed'; const tristateProperties: TristateProperty[] = ['checked', 'pressed']; for (const tristateProperty of tristateProperties) { - if (!properties.has(tristateProperty)) continue; + if (!properties.has(tristateProperty)) { + continue; + } const value = properties.get(tristateProperty); node[tristateProperty] = value === 'mixed' ? 'mixed' : value === 'true' ? true : false; @@ -465,7 +524,9 @@ class AXNode { const getNumericalPropertyValue = (key: NumbericalProperty): number => properties.get(key) as number; for (const numericalProperty of numericalProperties) { - if (!properties.has(numericalProperty)) continue; + if (!properties.has(numericalProperty)) { + continue; + } node[numericalProperty] = getNumericalPropertyValue(numericalProperty); } @@ -484,7 +545,9 @@ class AXNode { properties.get(key) as string; for (const tokenProperty of tokenProperties) { const value = getTokenPropertyValue(tokenProperty); - if (!value || value === 'false') continue; + if (!value || value === 'false') { + continue; + } node[tokenProperty] = getTokenPropertyValue(tokenProperty); } return node; @@ -492,11 +555,13 @@ class AXNode { public static createTree(payloads: Protocol.Accessibility.AXNode[]): AXNode { const nodeById = new Map(); - for (const payload of payloads) + for (const payload of payloads) { nodeById.set(payload.nodeId, new AXNode(payload)); + } for (const node of nodeById.values()) { - for (const childId of node.payload.childIds || []) + for (const childId of node.payload.childIds || []) { node.children.push(nodeById.get(childId)!); + } } return nodeById.values().next().value; } diff --git a/src/common/AriaQueryHandler.ts b/src/common/AriaQueryHandler.ts index 96c4ecd1..0fb9878e 100644 --- a/src/common/AriaQueryHandler.ts +++ b/src/common/AriaQueryHandler.ts @@ -76,8 +76,9 @@ function parseAriaSelector(selector: string): ARIAQueryOption { return ''; } ); - if (defaultName && !queryOptions.name) + if (defaultName && !queryOptions.name) { queryOptions.name = normalizeValue(defaultName); + } return queryOptions; } diff --git a/src/common/Browser.ts b/src/common/Browser.ts index 21fe2158..e98eeeb6 100644 --- a/src/common/Browser.ts +++ b/src/common/Browser.ts @@ -285,11 +285,12 @@ export class Browser extends EventEmitter { this.#defaultContext = new BrowserContext(this.#connection, this); this.#contexts = new Map(); - for (const contextId of contextIds) + for (const contextId of contextIds) { this.#contexts.set( contextId, new BrowserContext(this.#connection, this, contextId) ); + } this.#targets = new Map(); this.#connection.on(ConnectionEmittedEvents.Disconnected, () => @@ -441,7 +442,9 @@ export class Browser extends EventEmitter { } async #targetDestroyed(event: { targetId: string }): Promise { - if (this.#ignoredTargets.has(event.targetId)) return; + if (this.#ignoredTargets.has(event.targetId)) { + return; + } const target = this.#targets.get(event.targetId); if (!target) { throw new Error( @@ -460,7 +463,9 @@ export class Browser extends EventEmitter { } #targetInfoChanged(event: Protocol.Target.TargetInfoChangedEvent): void { - if (this.#ignoredTargets.has(event.targetInfo.targetId)) return; + if (this.#ignoredTargets.has(event.targetInfo.targetId)) { + return; + } const target = this.#targets.get(event.targetInfo.targetId); if (!target) { throw new Error( @@ -580,7 +585,9 @@ export class Browser extends EventEmitter { this.on(BrowserEmittedEvents.TargetCreated, check); this.on(BrowserEmittedEvents.TargetChanged, check); try { - if (!timeout) return await targetPromise; + if (!timeout) { + return await targetPromise; + } this.targets().forEach(check); return await waitWithTimeout(targetPromise, 'target', timeout); } finally { @@ -827,8 +834,9 @@ export class BrowserContext extends EventEmitter { const protocolPermissions = permissions.map((permission) => { const protocolPermission = WEB_PERMISSION_TO_PROTOCOL_PERMISSION.get(permission); - if (!protocolPermission) + if (!protocolPermission) { throw new Error('Unknown permission: ' + permission); + } return protocolPermission; }); await this.#connection.send('Browser.grantPermissions', { diff --git a/src/common/BrowserWebSocketTransport.ts b/src/common/BrowserWebSocketTransport.ts index b6bf905f..ad300232 100644 --- a/src/common/BrowserWebSocketTransport.ts +++ b/src/common/BrowserWebSocketTransport.ts @@ -34,10 +34,14 @@ export class BrowserWebSocketTransport implements ConnectionTransport { constructor(ws: WebSocket) { this.#ws = ws; this.#ws.addEventListener('message', (event) => { - if (this.onmessage) this.onmessage.call(null, event.data); + if (this.onmessage) { + this.onmessage.call(null, event.data); + } }); this.#ws.addEventListener('close', () => { - if (this.onclose) this.onclose.call(null); + if (this.onclose) { + this.onclose.call(null); + } }); // Silently ignore all errors - we don't know what to do with them. this.#ws.addEventListener('error', () => {}); diff --git a/src/common/Connection.ts b/src/common/Connection.ts index da625087..e1886680 100644 --- a/src/common/Connection.ts +++ b/src/common/Connection.ts @@ -129,7 +129,9 @@ export class Connection extends EventEmitter { } async #onMessage(message: string): Promise { - if (this.#delay) await new Promise((f) => setTimeout(f, this.#delay)); + if (this.#delay) { + await new Promise((f) => setTimeout(f, this.#delay)); + } debugProtocolReceive(message); const object = JSON.parse(message); if (object.method === 'Target.attachedToTarget') { @@ -159,17 +161,21 @@ export class Connection extends EventEmitter { } if (object.sessionId) { const session = this.#sessions.get(object.sessionId); - if (session) session._onMessage(object); + if (session) { + session._onMessage(object); + } } else if (object.id) { const callback = this.#callbacks.get(object.id); // Callbacks could be all rejected if someone has called `.dispose()`. if (callback) { this.#callbacks.delete(object.id); - if (object.error) + if (object.error) { callback.reject( createProtocolError(callback.error, callback.method, object) ); - else callback.resolve(object.result); + } else { + callback.resolve(object.result); + } } } else { this.emit(object.method, object.params); @@ -177,19 +183,24 @@ export class Connection extends EventEmitter { } #onClose(): void { - if (this.#closed) return; + if (this.#closed) { + return; + } this.#closed = true; this.#transport.onmessage = undefined; this.#transport.onclose = undefined; - for (const callback of this.#callbacks.values()) + for (const callback of this.#callbacks.values()) { callback.reject( rewriteError( callback.error, `Protocol error (${callback.method}): Target closed.` ) ); + } this.#callbacks.clear(); - for (const session of this.#sessions.values()) session._onClosed(); + for (const session of this.#sessions.values()) { + session._onClosed(); + } this.#sessions.clear(); this.emit(ConnectionEmittedEvents.Disconnected); } @@ -287,7 +298,7 @@ export class CDPSession extends EventEmitter { method: T, ...paramArgs: ProtocolMapping.Commands[T]['paramsType'] ): Promise { - if (!this.#connection) + if (!this.#connection) { return Promise.reject( new Error( `Protocol error (${method}): Session closed. Most likely the ${ @@ -295,6 +306,7 @@ export class CDPSession extends EventEmitter { } has been closed.` ) ); + } // See the comment in Connection#send explaining why we do this. const params = paramArgs.length ? paramArgs[0] : undefined; @@ -322,11 +334,13 @@ export class CDPSession extends EventEmitter { const callback = object.id ? this.#callbacks.get(object.id) : undefined; if (object.id && callback) { this.#callbacks.delete(object.id); - if (object.error) + if (object.error) { callback.reject( createProtocolError(callback.error, callback.method, object) ); - else callback.resolve(object.result); + } else { + callback.resolve(object.result); + } } else { assert(!object.id); this.emit(object.method, object.params); @@ -338,12 +352,13 @@ export class CDPSession extends EventEmitter { * won't emit any events and can't be used to send messages. */ async detach(): Promise { - if (!this.#connection) + if (!this.#connection) { throw new Error( `Session already detached. Most likely the ${ this.#targetType } has been closed.` ); + } await this.#connection.send('Target.detachFromTarget', { sessionId: this.#sessionId, }); @@ -353,13 +368,14 @@ export class CDPSession extends EventEmitter { * @internal */ _onClosed(): void { - for (const callback of this.#callbacks.values()) + for (const callback of this.#callbacks.values()) { callback.reject( rewriteError( callback.error, `Protocol error (${callback.method}): Target closed.` ) ); + } this.#callbacks.clear(); this.#connection = undefined; this.emit(CDPSessionEmittedEvents.Disconnected); @@ -379,7 +395,9 @@ function createProtocolError( object: { error: { message: string; data: any; code: number } } ): Error { let message = `Protocol error (${method}): ${object.error.message}`; - if ('data' in object.error) message += ` ${object.error.data}`; + if ('data' in object.error) { + message += ` ${object.error.data}`; + } return rewriteError(error, message, object.error.message); } diff --git a/src/common/Coverage.ts b/src/common/Coverage.ts index 2c98c45a..0443db60 100644 --- a/src/common/Coverage.ts +++ b/src/common/Coverage.ts @@ -244,7 +244,9 @@ export class JSCoverage { } #onExecutionContextsCleared(): void { - if (!this.#resetOnNavigation) return; + if (!this.#resetOnNavigation) { + return; + } this.#scriptURLs.clear(); this.#scriptSources.clear(); } @@ -253,9 +255,13 @@ export class JSCoverage { event: Protocol.Debugger.ScriptParsedEvent ): Promise { // Ignore puppeteer-injected scripts - if (event.url === EVALUATION_SCRIPT_URL) return; + if (event.url === EVALUATION_SCRIPT_URL) { + return; + } // Ignore other anonymous scripts unless the reportAnonymousScripts option is true. - if (!event.url && !this.#reportAnonymousScripts) return; + if (!event.url && !this.#reportAnonymousScripts) { + return; + } try { const response = await this.#client.send('Debugger.getScriptSource', { scriptId: event.scriptId, @@ -286,12 +292,17 @@ export class JSCoverage { for (const entry of profileResponse.result) { let url = this.#scriptURLs.get(entry.scriptId); - if (!url && this.#reportAnonymousScripts) + if (!url && this.#reportAnonymousScripts) { url = 'debugger://VM' + entry.scriptId; + } const text = this.#scriptSources.get(entry.scriptId); - if (text === undefined || url === undefined) continue; + if (text === undefined || url === undefined) { + continue; + } const flattenRanges = []; - for (const func of entry.functions) flattenRanges.push(...func.ranges); + for (const func of entry.functions) { + flattenRanges.push(...func.ranges); + } const ranges = convertToDisjointRanges(flattenRanges); if (!this.#includeRawScriptCoverage) { coverage.push({ url, ranges, text }); @@ -345,7 +356,9 @@ export class CSSCoverage { } #onExecutionContextsCleared(): void { - if (!this.#resetOnNavigation) return; + if (!this.#resetOnNavigation) { + return; + } this.#stylesheetURLs.clear(); this.#stylesheetSources.clear(); } @@ -353,7 +366,9 @@ export class CSSCoverage { async #onStyleSheet(event: Protocol.CSS.StyleSheetAddedEvent): Promise { const header = event.header; // Ignore anonymous scripts - if (!header.sourceURL) return; + if (!header.sourceURL) { + return; + } try { const response = await this.#client.send('CSS.getStyleSheetText', { styleSheetId: header.styleSheetId, @@ -420,13 +435,19 @@ function convertToDisjointRanges( // Sort points to form a valid parenthesis sequence. points.sort((a, b) => { // Sort with increasing offsets. - if (a.offset !== b.offset) return a.offset - b.offset; + if (a.offset !== b.offset) { + return a.offset - b.offset; + } // All "end" points should go before "start" points. - if (a.type !== b.type) return b.type - a.type; + if (a.type !== b.type) { + return b.type - a.type; + } const aLength = a.range.endOffset - a.range.startOffset; const bLength = b.range.endOffset - b.range.startOffset; // For two "start" points, the one with longer range goes first. - if (a.type === 0) return bLength - aLength; + if (a.type === 0) { + return bLength - aLength; + } // For two "end" points, the one with shorter range goes first. return aLength - bLength; }); @@ -445,13 +466,18 @@ function convertToDisjointRanges( hitCountStack[hitCountStack.length - 1]! > 0 ) { const lastResult = results[results.length - 1]; - if (lastResult && lastResult.end === lastOffset) + if (lastResult && lastResult.end === lastOffset) { lastResult.end = point.offset; - else results.push({ start: lastOffset, end: point.offset }); + } else { + results.push({ start: lastOffset, end: point.offset }); + } } lastOffset = point.offset; - if (point.type === 0) hitCountStack.push(point.range.count); - else hitCountStack.pop(); + if (point.type === 0) { + hitCountStack.push(point.range.count); + } else { + hitCountStack.pop(); + } } // Filter out empty ranges. return results.filter((range) => range.end - range.start > 1); diff --git a/src/common/DOMWorld.ts b/src/common/DOMWorld.ts index cf18f624..11b83f8d 100644 --- a/src/common/DOMWorld.ts +++ b/src/common/DOMWorld.ts @@ -143,7 +143,9 @@ export class DOMWorld { this.#ctxBindings.clear(); this.#contextResolveCallback?.call(null, context); this.#contextResolveCallback = null; - for (const waitTask of this._waitTasks) waitTask.rerun(); + for (const waitTask of this._waitTasks) { + waitTask.rerun(); + } } else { this.#documentPromise = null; this.#contextPromise = new Promise((fulfill) => { @@ -165,19 +167,22 @@ export class DOMWorld { _detach(): void { this.#detached = true; this.#client.off('Runtime.bindingCalled', this.#onBindingCalled); - for (const waitTask of this._waitTasks) + for (const waitTask of this._waitTasks) { waitTask.terminate( new Error('waitForFunction failed: frame got detached.') ); + } } executionContext(): Promise { - if (this.#detached) + if (this.#detached) { throw new Error( `Execution context is not available in detached frame "${this.#frame.url()}" (are you trying to evaluate?)` ); - if (this.#contextPromise === null) + } + if (this.#contextPromise === null) { throw new Error(`Execution content promise is missing`); + } return this.#contextPromise; } @@ -212,7 +217,9 @@ export class DOMWorld { * @internal */ async _document(): Promise { - if (this.#documentPromise) return this.#documentPromise; + if (this.#documentPromise) { + return this.#documentPromise; + } this.#documentPromise = this.executionContext().then(async (context) => { const document = await context.evaluateHandle('document'); const element = document.asElement(); @@ -270,10 +277,12 @@ export class DOMWorld { async content(): Promise { return await this.evaluate(() => { let retVal = ''; - if (document.doctype) + if (document.doctype) { retVal = new XMLSerializer().serializeToString(document.doctype); - if (document.documentElement) + } + if (document.documentElement) { retVal += document.documentElement.outerHTML; + } return retVal; }); } @@ -307,7 +316,9 @@ export class DOMWorld { watcher.lifecyclePromise(), ]); watcher.dispose(); - if (error) throw error; + if (error) { + throw error; + } } /** @@ -406,8 +417,12 @@ export class DOMWorld { ): Promise { const script = document.createElement('script'); script.src = url; - if (id) script.id = id; - if (type) script.type = type; + if (id) { + script.id = id; + } + if (type) { + script.type = type; + } const promise = new Promise((res, rej) => { script.onload = res; script.onerror = rej; @@ -425,11 +440,15 @@ export class DOMWorld { const script = document.createElement('script'); script.type = type; script.text = content; - if (id) script.id = id; + if (id) { + script.id = id; + } let error = null; script.onerror = (e) => (error = e); document.head.appendChild(script); - if (error) throw error; + if (error) { + throw error; + } return script; } } @@ -656,7 +675,9 @@ export class DOMWorld { event: Protocol.Runtime.BindingCalledEvent ): Promise => { let payload: { type: string; name: string; seq: number; args: unknown[] }; - if (!this._hasContext()) return; + if (!this._hasContext()) { + return; + } const context = await this.executionContext(); try { payload = JSON.parse(event.payload); @@ -671,9 +692,12 @@ export class DOMWorld { !this.#ctxBindings.has( DOMWorld.#bindingIdentifier(name, context._contextId) ) - ) + ) { return; - if (context._contextId !== event.executionContextId) return; + } + if (context._contextId !== event.executionContextId) { + return; + } try { const fn = this._boundFunctions.get(name); if (!fn) { @@ -687,7 +711,9 @@ export class DOMWorld { // In both caes, the promises above are rejected with a protocol error. // We can safely ignores these, as the WaitTask is re-installed in // the next execution context if needed. - if ((error as Error).message.includes('Protocol error')) return; + if ((error as Error).message.includes('Protocol error')) { + return; + } debugError(error); } function deliverResult(name: string, seq: number, result: unknown): void { @@ -859,20 +885,24 @@ export class WaitTask { promise: Promise; constructor(options: WaitTaskOptions) { - if (isString(options.polling)) + if (isString(options.polling)) { assert( options.polling === 'raf' || options.polling === 'mutation', 'Unknown polling option: ' + options.polling ); - else if (isNumber(options.polling)) + } else if (isNumber(options.polling)) { assert( options.polling > 0, 'Cannot poll with non-positive interval: ' + options.polling ); - else throw new Error('Unknown polling options: ' + options.polling); + } else { + throw new Error('Unknown polling options: ' + options.polling); + } function getPredicateBody(predicateBody: Function | string) { - if (isString(predicateBody)) return `return (${predicateBody});`; + if (isString(predicateBody)) { + return `return (${predicateBody});`; + } return `return (${predicateBody})(...args);`; } @@ -922,11 +952,15 @@ export class WaitTask { let success: JSHandle | null = null; let error: Error | null = null; const context = await this.#domWorld.executionContext(); - if (this.#terminated || runCount !== this.#runCount) return; + if (this.#terminated || runCount !== this.#runCount) { + return; + } if (this.#binding) { await this.#domWorld._addBindingToContext(context, this.#binding.name); } - if (this.#terminated || runCount !== this.#runCount) return; + if (this.#terminated || runCount !== this.#runCount) { + return; + } try { success = await context.evaluateHandle( waitForPredicatePageFunction, @@ -942,7 +976,9 @@ export class WaitTask { } if (this.#terminated || runCount !== this.#runCount) { - if (success) await success.dispose(); + if (success) { + await success.dispose(); + } return; } @@ -953,8 +989,9 @@ export class WaitTask { !error && (await this.#domWorld.evaluate((s) => !s, success).catch(() => true)) ) { - if (!success) + if (!success) { throw new Error('Assertion: result handle is not available'); + } await success.dispose(); return; } @@ -978,17 +1015,21 @@ export class WaitTask { // When the page is navigated, the promise is rejected. // We will try again in the new execution context. - if (error.message.includes('Execution context was destroyed')) return; + if (error.message.includes('Execution context was destroyed')) { + return; + } // We could have tried to evaluate in a context which was already // destroyed. - if (error.message.includes('Cannot find context with specified id')) + if (error.message.includes('Cannot find context with specified id')) { return; + } this.#reject(error); } else { - if (!success) + if (!success) { throw new Error('Assertion: result handle is not available'); + } this.#resolve(success); } this.#cleanup(); @@ -1011,7 +1052,9 @@ async function waitForPredicatePageFunction( root = root || document; const predicate = new Function('...args', predicateBody); let timedOut = false; - if (timeout) setTimeout(() => (timedOut = true), timeout); + if (timeout) { + setTimeout(() => (timedOut = true), timeout); + } switch (polling) { case 'raf': return await pollRaf(); @@ -1025,7 +1068,9 @@ async function waitForPredicatePageFunction( const success = predicateAcceptsContextElement ? await predicate(root, ...args) : await predicate(...args); - if (success) return Promise.resolve(success); + if (success) { + return Promise.resolve(success); + } let fulfill = (_?: unknown) => {}; const result = new Promise((x) => (fulfill = x)); @@ -1067,8 +1112,11 @@ async function waitForPredicatePageFunction( const success = predicateAcceptsContextElement ? await predicate(root, ...args) : await predicate(...args); - if (success) fulfill(success); - else requestAnimationFrame(onRaf); + if (success) { + fulfill(success); + } else { + requestAnimationFrame(onRaf); + } } } @@ -1086,8 +1134,11 @@ async function waitForPredicatePageFunction( const success = predicateAcceptsContextElement ? await predicate(root, ...args) : await predicate(...args); - if (success) fulfill(success); - else setTimeout(onTimeout, pollInterval); + if (success) { + fulfill(success); + } else { + setTimeout(onTimeout, pollInterval); + } } } } diff --git a/src/common/Debug.ts b/src/common/Debug.ts index 433de847..6e2f96ba 100644 --- a/src/common/Debug.ts +++ b/src/common/Debug.ts @@ -66,7 +66,9 @@ export const debug = (prefix: string): ((...args: unknown[]) => void) => { return (...logArgs: unknown[]): void => { const debugLevel = globalThis.__PUPPETEER_DEBUG; - if (!debugLevel) return; + if (!debugLevel) { + return; + } const everythingShouldBeLogged = debugLevel === '*'; @@ -81,7 +83,9 @@ export const debug = (prefix: string): ((...args: unknown[]) => void) => { ? prefix.startsWith(debugLevel) : prefix === debugLevel); - if (!prefixMatchesDebugLevel) return; + if (!prefixMatchesDebugLevel) { + return; + } // eslint-disable-next-line no-console console.log(`${prefix}:`, ...logArgs); diff --git a/src/common/ExecutionContext.ts b/src/common/ExecutionContext.ts index 4c70ecd6..d07ed908 100644 --- a/src/common/ExecutionContext.ts +++ b/src/common/ExecutionContext.ts @@ -218,20 +218,22 @@ export class ExecutionContext { }) .catch(rewriteError); - if (exceptionDetails) + if (exceptionDetails) { throw new Error( 'Evaluation failed: ' + getExceptionMessage(exceptionDetails) ); + } return returnByValue ? valueFromRemoteObject(remoteObject) : _createJSHandle(this, remoteObject); } - if (typeof pageFunction !== 'function') + if (typeof pageFunction !== 'function') { throw new Error( `Expected to get |string| or |function| as the first argument, but got "${pageFunction}" instead.` ); + } let functionText = pageFunction.toString(); try { @@ -239,10 +241,12 @@ export class ExecutionContext { } catch (error) { // This means we might have a function shorthand. Try another // time prefixing 'function '. - if (functionText.startsWith('async ')) + if (functionText.startsWith('async ')) { functionText = 'async function ' + functionText.substring('async '.length); - else functionText = 'function ' + functionText; + } else { + functionText = 'function ' + functionText; + } try { new Function('(' + functionText + ')'); } catch (error) { @@ -271,10 +275,11 @@ export class ExecutionContext { } const { exceptionDetails, result: remoteObject } = await callFunctionOnPromise.catch(rewriteError); - if (exceptionDetails) + if (exceptionDetails) { throw new Error( 'Evaluation failed: ' + getExceptionMessage(exceptionDetails) ); + } return returnByValue ? valueFromRemoteObject(remoteObject) : _createJSHandle(this, remoteObject); @@ -283,45 +288,61 @@ export class ExecutionContext { this: ExecutionContext, arg: unknown ): Protocol.Runtime.CallArgument { - if (typeof arg === 'bigint') + if (typeof arg === 'bigint') { // eslint-disable-line valid-typeof return { unserializableValue: `${arg.toString()}n` }; - if (Object.is(arg, -0)) return { unserializableValue: '-0' }; - if (Object.is(arg, Infinity)) return { unserializableValue: 'Infinity' }; - if (Object.is(arg, -Infinity)) + } + if (Object.is(arg, -0)) { + return { unserializableValue: '-0' }; + } + if (Object.is(arg, Infinity)) { + return { unserializableValue: 'Infinity' }; + } + if (Object.is(arg, -Infinity)) { return { unserializableValue: '-Infinity' }; - if (Object.is(arg, NaN)) return { unserializableValue: 'NaN' }; + } + if (Object.is(arg, NaN)) { + return { unserializableValue: 'NaN' }; + } const objectHandle = arg && arg instanceof JSHandle ? arg : null; if (objectHandle) { - if (objectHandle._context !== this) + if (objectHandle._context !== this) { throw new Error( 'JSHandles can be evaluated only in the context they were created!' ); - if (objectHandle._disposed) throw new Error('JSHandle is disposed!'); - if (objectHandle._remoteObject.unserializableValue) + } + if (objectHandle._disposed) { + throw new Error('JSHandle is disposed!'); + } + if (objectHandle._remoteObject.unserializableValue) { return { unserializableValue: objectHandle._remoteObject.unserializableValue, }; - if (!objectHandle._remoteObject.objectId) + } + if (!objectHandle._remoteObject.objectId) { return { value: objectHandle._remoteObject.value }; + } return { objectId: objectHandle._remoteObject.objectId }; } return { value: arg }; } function rewriteError(error: Error): Protocol.Runtime.EvaluateResponse { - if (error.message.includes('Object reference chain is too long')) + if (error.message.includes('Object reference chain is too long')) { return { result: { type: 'undefined' } }; - if (error.message.includes("Object couldn't be returned by value")) + } + if (error.message.includes("Object couldn't be returned by value")) { return { result: { type: 'undefined' } }; + } if ( error.message.endsWith('Cannot find context with specified id') || error.message.endsWith('Inspected target navigated or closed') - ) + ) { throw new Error( 'Execution context was destroyed, most likely because of a navigation.' ); + } throw error; } } diff --git a/src/common/FrameManager.ts b/src/common/FrameManager.ts index 387e790a..8af2bb28 100644 --- a/src/common/FrameManager.ts +++ b/src/common/FrameManager.ts @@ -221,7 +221,9 @@ export class FrameManager extends EventEmitter { ]); } watcher.dispose(); - if (error) throw error; + if (error) { + throw error; + } return await watcher.navigationResponse(); async function navigate( @@ -267,7 +269,9 @@ export class FrameManager extends EventEmitter { watcher.newDocumentNavigationPromise(), ]); watcher.dispose(); - if (error) throw error; + if (error) { + throw error; + } return await watcher.navigationResponse(); } @@ -281,13 +285,17 @@ export class FrameManager extends EventEmitter { assert(connection); const session = connection.session(event.sessionId); assert(session); - if (frame) frame._updateClient(session); + if (frame) { + frame._updateClient(session); + } this.setupEventListeners(session); await this.initialize(session); } async #onDetachedFromTarget(event: Protocol.Target.DetachedFromTargetEvent) { - if (!event.targetId) return; + if (!event.targetId) { + return; + } const frame = this.#frames.get(event.targetId); if (frame && frame.isOOPFrame()) { // When an OOP iframe is removed from the page, it @@ -298,20 +306,26 @@ export class FrameManager extends EventEmitter { #onLifecycleEvent(event: Protocol.Page.LifecycleEventEvent): void { const frame = this.#frames.get(event.frameId); - if (!frame) return; + if (!frame) { + return; + } frame._onLifecycleEvent(event.loaderId, event.name); this.emit(FrameManagerEmittedEvents.LifecycleEvent, frame); } #onFrameStartedLoading(frameId: string): void { const frame = this.#frames.get(frameId); - if (!frame) return; + if (!frame) { + return; + } frame._onLoadingStarted(); } #onFrameStoppedLoading(frameId: string): void { const frame = this.#frames.get(frameId); - if (!frame) return; + if (!frame) { + return; + } frame._onLoadingStopped(); this.emit(FrameManagerEmittedEvents.LifecycleEvent, frame); } @@ -328,7 +342,9 @@ export class FrameManager extends EventEmitter { ); } this.#onFrameNavigated(frameTree.frame); - if (!frameTree.childFrames) return; + if (!frameTree.childFrames) { + return; + } for (const child of frameTree.childFrames) { this.#handleFrameTree(session, child); @@ -387,8 +403,9 @@ export class FrameManager extends EventEmitter { // Detach all child frames first. if (frame) { - for (const child of frame.childFrames()) + for (const child of frame.childFrames()) { this.#removeFramesRecursively(child); + } } // Update or create main frame. @@ -414,7 +431,9 @@ export class FrameManager extends EventEmitter { async _ensureIsolatedWorld(session: CDPSession, name: string): Promise { const key = `${session.id()}:${name}`; - if (this.#isolatedWorlds.has(key)) return; + if (this.#isolatedWorlds.has(key)) { + return; + } this.#isolatedWorlds.add(key); await session.send('Page.addScriptToEvaluateOnNewDocument', { @@ -439,7 +458,9 @@ export class FrameManager extends EventEmitter { #onFrameNavigatedWithinDocument(frameId: string, url: string): void { const frame = this.#frames.get(frameId); - if (!frame) return; + if (!frame) { + return; + } frame._navigatedWithinDocument(url); this.emit(FrameManagerEmittedEvents.FrameNavigatedWithinDocument, frame); this.emit(FrameManagerEmittedEvents.FrameNavigated, frame); @@ -454,7 +475,9 @@ export class FrameManager extends EventEmitter { // Only remove the frame if the reason for the detached event is // an actual removement of the frame. // For frames that become OOP iframes, the reason would be 'swap'. - if (frame) this.#removeFramesRecursively(frame); + if (frame) { + this.#removeFramesRecursively(frame); + } } else if (reason === 'swap') { this.emit(FrameManagerEmittedEvents.FrameSwapped, frame); } @@ -471,7 +494,9 @@ export class FrameManager extends EventEmitter { let world: DOMWorld | undefined; if (frame) { // Only care about execution contexts created for the current session. - if (frame._client() !== session) return; + if (frame._client() !== session) { + return; + } if (contextPayload.auxData && !!contextPayload.auxData['isDefault']) { world = frame._mainWorld; @@ -490,7 +515,9 @@ export class FrameManager extends EventEmitter { contextPayload, world ); - if (world) world._setContext(context); + if (world) { + world._setContext(context); + } const key = `${session.id()}:${contextPayload.id}`; this.#contextIdToContext.set(key, context); } @@ -501,17 +528,25 @@ export class FrameManager extends EventEmitter { ): void { const key = `${session.id()}:${executionContextId}`; const context = this.#contextIdToContext.get(key); - if (!context) return; + if (!context) { + return; + } this.#contextIdToContext.delete(key); - if (context._world) context._world._setContext(null); + if (context._world) { + context._world._setContext(null); + } } #onExecutionContextsCleared(session: CDPSession): void { for (const [key, context] of this.#contextIdToContext.entries()) { // Make sure to only clear execution contexts that belong // to the current session. - if (context._client !== session) continue; - if (context._world) context._world._setContext(null); + if (context._client !== session) { + continue; + } + if (context._world) { + context._world._setContext(null); + } this.#contextIdToContext.delete(key); } } @@ -527,8 +562,9 @@ export class FrameManager extends EventEmitter { } #removeFramesRecursively(frame: Frame): void { - for (const child of frame.childFrames()) + for (const child of frame.childFrames()) { this.#removeFramesRecursively(child); + } frame._detach(); this.#frames.delete(frame._id); this.emit(FrameManagerEmittedEvents.FrameDetached, frame); @@ -716,7 +752,9 @@ export class Frame { this._loaderId = ''; this._childFrames = new Set(); - if (this.#parentFrame) this.#parentFrame._childFrames.add(this); + if (this.#parentFrame) { + this.#parentFrame._childFrames.add(this); + } this._updateClient(client); } @@ -1237,19 +1275,23 @@ export class Frame { if (isString(selectorOrFunctionOrTimeout)) { const string = selectorOrFunctionOrTimeout; - if (xPathPattern.test(string)) return this.waitForXPath(string, options); + if (xPathPattern.test(string)) { + return this.waitForXPath(string, options); + } return this.waitForSelector(string, options); } - if (isNumber(selectorOrFunctionOrTimeout)) + if (isNumber(selectorOrFunctionOrTimeout)) { return new Promise((fulfill) => setTimeout(fulfill, selectorOrFunctionOrTimeout) ); - if (typeof selectorOrFunctionOrTimeout === 'function') + } + if (typeof selectorOrFunctionOrTimeout === 'function') { return this.waitForFunction( selectorOrFunctionOrTimeout, options, ...args ); + } return Promise.reject( new Error( 'Unsupported target type: ' + typeof selectorOrFunctionOrTimeout @@ -1324,7 +1366,9 @@ export class Frame { selector, options ); - if (!handle) return null; + if (!handle) { + return null; + } const mainExecutionContext = await this._mainWorld.executionContext(); const result = await mainExecutionContext._adoptElementHandle(handle); await handle.dispose(); @@ -1351,7 +1395,9 @@ export class Frame { options: WaitForSelectorOptions = {} ): Promise { const handle = await this._secondaryWorld.waitForXPath(xpath, options); - if (!handle) return null; + if (!handle) { + return null; + } const mainExecutionContext = await this._mainWorld.executionContext(); const result = await mainExecutionContext._adoptElementHandle(handle); await handle.dispose(); @@ -1456,7 +1502,9 @@ export class Frame { this.#detached = true; this._mainWorld._detach(); this._secondaryWorld._detach(); - if (this.#parentFrame) this.#parentFrame._childFrames.delete(this); + if (this.#parentFrame) { + this.#parentFrame._childFrames.delete(this); + } this.#parentFrame = null; } } diff --git a/src/common/HTTPRequest.ts b/src/common/HTTPRequest.ts index 2ada1d7b..4eeddae5 100644 --- a/src/common/HTTPRequest.ts +++ b/src/common/HTTPRequest.ts @@ -184,8 +184,9 @@ export class HTTPRequest { this.#interceptHandlers = []; this.#initiator = event.initiator; - for (const [key, value] of Object.entries(event.request.headers)) + for (const [key, value] of Object.entries(event.request.headers)) { this.#headers[key.toLowerCase()] = value; + } } /** @@ -234,10 +235,12 @@ export class HTTPRequest { * `disabled`, `none`, or `already-handled`. */ interceptResolutionState(): InterceptResolutionState { - if (!this.#allowInterception) + if (!this.#allowInterception) { return { action: InterceptResolutionAction.Disabled }; - if (this.#interceptionHandled) + } + if (this.#interceptionHandled) { return { action: InterceptResolutionAction.AlreadyHandled }; + } return { ...this.#interceptResolutionState }; } @@ -396,7 +399,9 @@ export class HTTPRequest { * failure text if the request fails. */ failure(): { errorText: string } | null { - if (!this._failureText) return null; + if (!this._failureText) { + return null; + } return { errorText: this._failureText, }; @@ -435,7 +440,9 @@ export class HTTPRequest { priority?: number ): Promise { // Request interception is not supported for data: urls. - if (this.#url.startsWith('data:')) return; + if (this.#url.startsWith('data:')) { + return; + } assert(this.#allowInterception, 'Request Interception is not enabled!'); assert(!this.#interceptionHandled, 'Request is already handled!'); if (priority === undefined) { @@ -473,10 +480,11 @@ export class HTTPRequest { ? Buffer.from(postData).toString('base64') : undefined; - if (this._interceptionId === undefined) + if (this._interceptionId === undefined) { throw new Error( 'HTTPRequest is missing _interceptionId needed for Fetch.continueRequest' ); + } await this.#client .send('Fetch.continueRequest', { requestId: this._interceptionId, @@ -527,7 +535,9 @@ export class HTTPRequest { priority?: number ): Promise { // Mocking responses for dataURL requests is not currently supported. - if (this.#url.startsWith('data:')) return; + if (this.#url.startsWith('data:')) { + return; + } assert(this.#allowInterception, 'Request Interception is not enabled!'); assert(!this.#interceptionHandled, 'Request is already handled!'); if (priority === undefined) { @@ -570,18 +580,21 @@ export class HTTPRequest { : String(value); } } - if (response.contentType) + if (response.contentType) { responseHeaders['content-type'] = response.contentType; - if (responseBody && !('content-length' in responseHeaders)) + } + if (responseBody && !('content-length' in responseHeaders)) { responseHeaders['content-length'] = String( Buffer.byteLength(responseBody) ); + } const status = response.status || 200; - if (this._interceptionId === undefined) + if (this._interceptionId === undefined) { throw new Error( 'HTTPRequest is missing _interceptionId needed for Fetch.fulfillRequest' ); + } await this.#client .send('Fetch.fulfillRequest', { requestId: this._interceptionId, @@ -614,7 +627,9 @@ export class HTTPRequest { priority?: number ): Promise { // Request interception is not supported for data: urls. - if (this.#url.startsWith('data:')) return; + if (this.#url.startsWith('data:')) { + return; + } const errorReason = errorReasons[errorCode]; assert(errorReason, 'Unknown error code: ' + errorCode); assert(this.#allowInterception, 'Request Interception is not enabled!'); @@ -639,10 +654,11 @@ export class HTTPRequest { errorReason: Protocol.Network.ErrorReason | null ): Promise { this.#interceptionHandled = true; - if (this._interceptionId === undefined) + if (this._interceptionId === undefined) { throw new Error( 'HTTPRequest is missing _interceptionId needed for Fetch.failRequest' ); + } await this.#client .send('Fetch.failRequest', { requestId: this._interceptionId, diff --git a/src/common/HTTPResponse.ts b/src/common/HTTPResponse.ts index 8a1784cc..257581e9 100644 --- a/src/common/HTTPResponse.ts +++ b/src/common/HTTPResponse.ts @@ -101,13 +101,21 @@ export class HTTPResponse { #parseStatusTextFromExtrInfo( extraInfo: Protocol.Network.ResponseReceivedExtraInfoEvent | null ): string | undefined { - if (!extraInfo || !extraInfo.headersText) return; + if (!extraInfo || !extraInfo.headersText) { + return; + } const firstLine = extraInfo.headersText.split('\r', 1)[0]; - if (!firstLine) return; + if (!firstLine) { + return; + } const match = firstLine.match(/[^ ]* [^ ]* (.*)/); - if (!match) return; + if (!match) { + return; + } const statusText = match[1]; - if (!statusText) return; + if (!statusText) { + return; + } return statusText; } @@ -188,7 +196,9 @@ export class HTTPResponse { buffer(): Promise { if (!this.#contentPromise) { this.#contentPromise = this.#bodyLoadedPromise.then(async (error) => { - if (error) throw error; + if (error) { + throw error; + } try { const response = await this.#client.send('Network.getResponseBody', { requestId: this.#request._requestId, diff --git a/src/common/Input.ts b/src/common/Input.ts index f3a9fd0a..ef3554f7 100644 --- a/src/common/Input.ts +++ b/src/common/Input.ts @@ -134,10 +134,18 @@ export class Keyboard { } #modifierBit(key: string): number { - if (key === 'Alt') return 1; - if (key === 'Control') return 2; - if (key === 'Meta') return 4; - if (key === 'Shift') return 8; + if (key === 'Alt') { + return 1; + } + if (key === 'Control') { + return 2; + } + if (key === 'Meta') { + return 4; + } + if (key === 'Shift') { + return 8; + } return 0; } @@ -154,24 +162,43 @@ export class Keyboard { const definition = _keyDefinitions[keyString]; assert(definition, `Unknown key: "${keyString}"`); - if (definition.key) description.key = definition.key; - if (shift && definition.shiftKey) description.key = definition.shiftKey; + if (definition.key) { + description.key = definition.key; + } + if (shift && definition.shiftKey) { + description.key = definition.shiftKey; + } - if (definition.keyCode) description.keyCode = definition.keyCode; - if (shift && definition.shiftKeyCode) + if (definition.keyCode) { + description.keyCode = definition.keyCode; + } + if (shift && definition.shiftKeyCode) { description.keyCode = definition.shiftKeyCode; + } - if (definition.code) description.code = definition.code; + if (definition.code) { + description.code = definition.code; + } - if (definition.location) description.location = definition.location; + if (definition.location) { + description.location = definition.location; + } - if (description.key.length === 1) description.text = description.key; + if (description.key.length === 1) { + description.text = description.key; + } - if (definition.text) description.text = definition.text; - if (shift && definition.shiftText) description.text = definition.shiftText; + if (definition.text) { + description.text = definition.text; + } + if (shift && definition.shiftText) { + description.text = definition.shiftText; + } // if any modifiers besides shift are pressed, no text should be sent - if (this._modifiers & ~8) description.text = ''; + if (this._modifiers & ~8) { + description.text = ''; + } return description; } @@ -249,7 +276,9 @@ export class Keyboard { if (this.charIsKey(char)) { await this.press(char, { delay }); } else { - if (delay) await new Promise((f) => setTimeout(f, delay)); + if (delay) { + await new Promise((f) => setTimeout(f, delay)); + } await this.sendCharacter(char); } } @@ -281,7 +310,9 @@ export class Keyboard { ): Promise { const { delay = null } = options; await this.down(key, options); - if (delay) await new Promise((f) => setTimeout(f, options.delay)); + if (delay) { + await new Promise((f) => setTimeout(f, options.delay)); + } await this.up(key); } } diff --git a/src/common/JSHandle.ts b/src/common/JSHandle.ts index 94fb8d87..533f890b 100644 --- a/src/common/JSHandle.ts +++ b/src/common/JSHandle.ts @@ -250,7 +250,9 @@ export class JSHandle { }); const result = new Map(); for (const property of response.result) { - if (!property.enumerable || !property.value) continue; + if (!property.enumerable || !property.value) { + continue; + } result.set(property.name, _createJSHandle(this.#context, property.value)); } return result; @@ -294,7 +296,9 @@ export class JSHandle { * successfully disposed of. */ async dispose(): Promise { - if (this.#disposed) return; + if (this.#disposed) { + return; + } this.#disposed = true; await releaseObject(this.#client, this.#remoteObject); } @@ -418,7 +422,9 @@ export class ElementHandle< root: adoptedRoot, }); await adoptedRoot.dispose(); - if (!handle) return null; + if (!handle) { + return null; + } const mainExecutionContext = await frame._mainWorld.executionContext(); const result = await mainExecutionContext._adoptElementHandle(handle); await handle.dispose(); @@ -497,7 +503,9 @@ export class ElementHandle< root: adoptedRoot, }); await adoptedRoot.dispose(); - if (!handle) return null; + if (!handle) { + return null; + } const mainExecutionContext = await frame._mainWorld.executionContext(); const result = await mainExecutionContext._adoptElementHandle(handle); await handle.dispose(); @@ -516,7 +524,9 @@ export class ElementHandle< const nodeInfo = await this._client.send('DOM.describeNode', { objectId: this._remoteObject.objectId, }); - if (typeof nodeInfo.node.frameId !== 'string') return null; + if (typeof nodeInfo.node.frameId !== 'string') { + return null; + } return this.#frameManager.frame(nodeInfo.node.frameId); } @@ -526,9 +536,12 @@ export class ElementHandle< element: Element, pageJavascriptEnabled: boolean ): Promise => { - if (!element.isConnected) return 'Node is detached from document'; - if (element.nodeType !== Node.ELEMENT_NODE) + if (!element.isConnected) { + return 'Node is detached from document'; + } + if (element.nodeType !== Node.ELEMENT_NODE) { return 'Node is not of type HTMLElement'; + } // force-scroll if page's javascript is disabled. if (!pageJavascriptEnabled) { element.scrollIntoView({ @@ -563,7 +576,9 @@ export class ElementHandle< this.#page.isJavaScriptEnabled() ); - if (error) throw new Error(error); + if (error) { + throw new Error(error); + } } async #getOOPIFOffsets( @@ -610,8 +625,9 @@ export class ElementHandle< .catch(debugError), this.#page._client().send('Page.getLayoutMetrics'), ]); - if (!result || !result.quads.length) + if (!result || !result.quads.length) { throw new Error('Node is either not clickable or not an HTMLElement'); + } // Filter out quads that have too small area to click into. // Fallback to `layoutViewport` in case of using Firefox. const { clientWidth, clientHeight } = @@ -624,8 +640,9 @@ export class ElementHandle< this.#intersectQuadWithViewport(quad, clientWidth, clientHeight) ) .filter((quad) => computeQuadArea(quad) > 1); - if (!quads.length) + if (!quads.length) { throw new Error('Node is either not clickable or not an HTMLElement'); + } const quad = quads[0]!; if (offset) { // Return the point of the first quad identified by offset. @@ -971,7 +988,9 @@ export class ElementHandle< async boundingBox(): Promise { const result = await this.#getBoxModel(); - if (!result) return null; + if (!result) { + return null; + } const { offsetX, offsetY } = await this.#getOOPIFOffsets(this.#frame); const quad = result.model.border; @@ -994,7 +1013,9 @@ export class ElementHandle< async boxModel(): Promise { const result = await this.#getBoxModel(); - if (!result) return null; + if (!result) { + return null; + } const { offsetX, offsetY } = await this.#getOOPIFOffsets(this.#frame); @@ -1078,7 +1099,9 @@ export class ElementHandle< ) ); - if (needsViewportReset) await this.#page.setViewport(viewport); + if (needsViewportReset) { + await this.#page.setViewport(viewport); + } return imageData; } @@ -1149,10 +1172,11 @@ export class ElementHandle< ...args: SerializableOrJSHandle[] ): Promise> { const elementHandle = await this.$(selector); - if (!elementHandle) + if (!elementHandle) { throw new Error( `Error: failed to find element matching selector "${selector}"` ); + } const result = await elementHandle.evaluate< ( element: Element, @@ -1236,7 +1260,9 @@ export class ElementHandle< ); const array = []; let item; - while ((item = iterator.iterateNext())) array.push(item); + while ((item = iterator.iterateNext())) { + array.push(item); + } return array; }, expression @@ -1246,7 +1272,9 @@ export class ElementHandle< const result = []; for (const property of properties.values()) { const elementHandle = property.asElement(); - if (elementHandle) result.push(elementHandle); + if (elementHandle) { + result.push(elementHandle); + } } return result; } diff --git a/src/common/LifecycleWatcher.ts b/src/common/LifecycleWatcher.ts index 6c3ad265..b44e314e 100644 --- a/src/common/LifecycleWatcher.ts +++ b/src/common/LifecycleWatcher.ts @@ -106,8 +106,11 @@ export class LifecycleWatcher { waitUntil: PuppeteerLifeCycleEvent | PuppeteerLifeCycleEvent[], timeout: number ) { - if (Array.isArray(waitUntil)) waitUntil = waitUntil.slice(); - else if (typeof waitUntil === 'string') waitUntil = [waitUntil]; + if (Array.isArray(waitUntil)) { + waitUntil = waitUntil.slice(); + } else if (typeof waitUntil === 'string') { + waitUntil = [waitUntil]; + } this.#expectedLifecycle = waitUntil.map((value) => { const protocolEvent = puppeteerToProtocolLifecycle.get(value); assert(protocolEvent, 'Unknown value for options.waitUntil: ' + value); @@ -163,8 +166,9 @@ export class LifecycleWatcher { } #onRequest(request: HTTPRequest): void { - if (request.frame() !== this.#frame || !request.isNavigationRequest()) + if (request.frame() !== this.#frame || !request.isNavigationRequest()) { return; + } this.#navigationRequest = request; } @@ -205,7 +209,9 @@ export class LifecycleWatcher { } async #createTimeoutPromise(): Promise { - if (!this.#timeout) return new Promise(noop); + if (!this.#timeout) { + return new Promise(noop); + } const errorMessage = 'Navigation timeout of ' + this.#timeout + ' ms exceeded'; await new Promise( @@ -215,38 +221,50 @@ export class LifecycleWatcher { } #navigatedWithinDocument(frame: Frame): void { - if (frame !== this.#frame) return; + if (frame !== this.#frame) { + return; + } this.#hasSameDocumentNavigation = true; this.#checkLifecycleComplete(); } #navigated(frame: Frame): void { - if (frame !== this.#frame) return; + if (frame !== this.#frame) { + return; + } this.#newDocumentNavigation = true; this.#checkLifecycleComplete(); } #frameSwapped(frame: Frame): void { - if (frame !== this.#frame) return; + if (frame !== this.#frame) { + return; + } this.#swapped = true; this.#checkLifecycleComplete(); } #checkLifecycleComplete(): void { // We expect navigation to commit. - if (!checkLifecycle(this.#frame, this.#expectedLifecycle)) return; + if (!checkLifecycle(this.#frame, this.#expectedLifecycle)) { + return; + } this.#lifecycleCallback(); - if (this.#hasSameDocumentNavigation) + if (this.#hasSameDocumentNavigation) { this.#sameDocumentNavigationCompleteCallback(); - if (this.#swapped || this.#newDocumentNavigation) + } + if (this.#swapped || this.#newDocumentNavigation) { this.#newDocumentNavigationCompleteCallback(); + } function checkLifecycle( frame: Frame, expectedLifecycle: ProtocolLifeCycleEvent[] ): boolean { for (const event of expectedLifecycle) { - if (!frame._lifecycleEvents.has(event)) return false; + if (!frame._lifecycleEvents.has(event)) { + return false; + } } for (const child of frame.childFrames()) { if ( diff --git a/src/common/NetworkManager.ts b/src/common/NetworkManager.ts index d5bb147a..be1952f3 100644 --- a/src/common/NetworkManager.ts +++ b/src/common/NetworkManager.ts @@ -133,10 +133,11 @@ export class NetworkManager extends EventEmitter { async initialize(): Promise { await this.#client.send('Network.enable'); - if (this.#ignoreHTTPSErrors) + if (this.#ignoreHTTPSErrors) { await this.#client.send('Security.setIgnoreCertificateErrors', { ignore: true, }); + } } async authenticate(credentials?: Credentials): Promise { @@ -221,7 +222,9 @@ export class NetworkManager extends EventEmitter { async #updateProtocolRequestInterception(): Promise { const enabled = this.#userRequestInterceptionEnabled || !!this.#credentials; - if (enabled === this.#protocolRequestInterceptionEnabled) return; + if (enabled === this.#protocolRequestInterceptionEnabled) { + return; + } this.#protocolRequestInterceptionEnabled = enabled; if (enabled) { await Promise.all([ @@ -420,7 +423,9 @@ export class NetworkManager extends EventEmitter { event: Protocol.Network.RequestServedFromCacheEvent ): void { const request = this.#networkEventManager.getRequest(event.requestId); - if (request) request._fromMemoryCache = true; + if (request) { + request._fromMemoryCache = true; + } this.emit(NetworkManagerEmittedEvents.RequestServedFromCache, request); } @@ -453,7 +458,9 @@ export class NetworkManager extends EventEmitter { responseReceived.requestId ); // FileUpload sends a response without a matching request. - if (!request) return; + if (!request) { + return; + } const extraInfos = this.#networkEventManager.responseExtraInfo( responseReceived.requestId @@ -561,11 +568,15 @@ export class NetworkManager extends EventEmitter { const request = this.#networkEventManager.getRequest(event.requestId); // For certain requestIds we never receive requestWillBeSent event. // @see https://crbug.com/750469 - if (!request) return; + if (!request) { + return; + } // Under certain conditions we never get the Network.responseReceived // event from protocol. @see https://crbug.com/883475 - if (request.response()) request.response()?._resolveBody(null); + if (request.response()) { + request.response()?._resolveBody(null); + } this.#forgetRequest(request, true); this.emit(NetworkManagerEmittedEvents.RequestFinished, request); } @@ -587,10 +598,14 @@ export class NetworkManager extends EventEmitter { const request = this.#networkEventManager.getRequest(event.requestId); // For certain requestIds we never receive requestWillBeSent event. // @see https://crbug.com/750469 - if (!request) return; + if (!request) { + return; + } request._failureText = event.errorText; const response = request.response(); - if (response) response._resolveBody(null); + if (response) { + response._resolveBody(null); + } this.#forgetRequest(request, true); this.emit(NetworkManagerEmittedEvents.RequestFailed, request); } diff --git a/src/common/Page.ts b/src/common/Page.ts index d8609e87..7bad98a8 100644 --- a/src/common/Page.ts +++ b/src/common/Page.ts @@ -451,7 +451,9 @@ export class Page extends EventEmitter { screenshotTaskQueue ); await page.#initialize(); - if (defaultViewport) await page.setViewport(defaultViewport); + if (defaultViewport) { + await page.setViewport(defaultViewport); + } return page; } @@ -545,7 +547,9 @@ export class Page extends EventEmitter { ); client.on('Target.detachedFromTarget', (event) => { const worker = this.#workers.get(event.sessionId); - if (!worker) return; + if (!worker) { + return; + } this.#workers.delete(event.sessionId); this.emit(PageEmittedEvents.WorkerDestroyed, worker); }); @@ -615,7 +619,9 @@ export class Page extends EventEmitter { async #onFileChooser( event: Protocol.Page.FileChooserOpenedEvent ): Promise { - if (!this.#fileChooserInterceptors.size) return; + if (!this.#fileChooserInterceptors.size) { + return; + } const frame = this.#frameManager.frame(event.frameId); assert(frame); const context = await frame.executionContext(); @@ -623,7 +629,9 @@ export class Page extends EventEmitter { const interceptors = Array.from(this.#fileChooserInterceptors); this.#fileChooserInterceptors.clear(); const fileChooser = new FileChooser(element, event); - for (const interceptor of interceptors) interceptor.call(null, fileChooser); + for (const interceptor of interceptors) { + interceptor.call(null, fileChooser); + } } /** @@ -711,10 +719,11 @@ export class Page extends EventEmitter { async waitForFileChooser( options: WaitTimeoutOptions = {} ): Promise { - if (!this.#fileChooserInterceptors.size) + if (!this.#fileChooserInterceptors.size) { await this.#client.send('Page.setInterceptFileChooserDialog', { enabled: true, }); + } const { timeout = this.#timeoutSettings.timeout() } = options; let callback!: (value: FileChooser | PromiseLike) => void; @@ -742,18 +751,21 @@ export class Page extends EventEmitter { */ async setGeolocation(options: GeolocationOptions): Promise { const { longitude, latitude, accuracy = 0 } = options; - if (longitude < -180 || longitude > 180) + if (longitude < -180 || longitude > 180) { throw new Error( `Invalid longitude "${longitude}": precondition -180 <= LONGITUDE <= 180 failed.` ); - if (latitude < -90 || latitude > 90) + } + if (latitude < -90 || latitude > 90) { throw new Error( `Invalid latitude "${latitude}": precondition -90 <= LATITUDE <= 90 failed.` ); - if (accuracy < 0) + } + if (accuracy < 0) { throw new Error( `Invalid accuracy "${accuracy}": precondition 0 <= ACCURACY failed.` ); + } await this.#client.send('Emulation.setGeolocationOverride', { longitude, latitude, @@ -795,12 +807,15 @@ export class Page extends EventEmitter { #onLogEntryAdded(event: Protocol.Log.EntryAddedEvent): void { const { level, text, args, source, url, lineNumber } = event.entry; - if (args) args.map((arg) => releaseObject(this.#client, arg)); - if (source !== 'worker') + if (args) { + args.map((arg) => releaseObject(this.#client, arg)); + } + if (source !== 'worker') { this.emit( PageEmittedEvents.Console, new ConsoleMessage(level, text, [], [{ url, lineNumber }]) ); + } } /** @@ -1284,7 +1299,9 @@ export class Page extends EventEmitter { const pageURL = this.url(); for (const cookie of cookies) { const item = Object.assign({}, cookie); - if (!cookie.url && pageURL.startsWith('http')) item.url = pageURL; + if (!cookie.url && pageURL.startsWith('http')) { + item.url = pageURL; + } await this.#client.send('Network.deleteCookies', item); } } @@ -1300,7 +1317,9 @@ export class Page extends EventEmitter { const startsWithHTTP = pageURL.startsWith('http'); const items = cookies.map((cookie) => { const item = Object.assign({}, cookie); - if (!item.url && startsWithHTTP) item.url = pageURL; + if (!item.url && startsWithHTTP) { + item.url = pageURL; + } assert( item.url !== 'about:blank', `Blank page can not have cookie "${item.name}"` @@ -1312,8 +1331,9 @@ export class Page extends EventEmitter { return item; }); await this.deleteCookie(...items); - if (items.length) + if (items.length) { await this.#client.send('Network.setCookies', { cookies: items }); + } } /** @@ -1410,10 +1430,11 @@ export class Page extends EventEmitter { name: string, puppeteerFunction: Function | { default: Function } ): Promise { - if (this.#pageBindings.has(name)) + if (this.#pageBindings.has(name)) { throw new Error( `Failed to add page binding with name ${name}: window['${name}'] already exists!` ); + } let exposedFunction: Function; if (typeof puppeteerFunction === 'function') { @@ -1580,7 +1601,9 @@ export class Page extends EventEmitter { return; } const { type, name, seq, args } = payload; - if (type !== 'exposedFun' || !this.#pageBindings.has(name)) return; + if (type !== 'exposedFun' || !this.#pageBindings.has(name)) { + return; + } let expression = null; try { const pageBinding = this.#pageBindings.get(name); @@ -1588,14 +1611,16 @@ export class Page extends EventEmitter { const result = await pageBinding(...args); expression = pageBindingDeliverResultString(name, seq, result); } catch (error) { - if (isErrorLike(error)) + if (isErrorLike(error)) { expression = pageBindingDeliverErrorString( name, seq, error.message, error.stack ); - else expression = pageBindingDeliverErrorValueString(name, seq, error); + } else { + expression = pageBindingDeliverErrorValueString(name, seq, error); + } } this.#client .send('Runtime.evaluate', { @@ -1617,8 +1642,11 @@ export class Page extends EventEmitter { const textTokens = []; for (const arg of args) { const remoteObject = arg._remoteObject; - if (remoteObject.objectId) textTokens.push(arg.toString()); - else textTokens.push(valueFromRemoteObject(remoteObject)); + if (remoteObject.objectId) { + textTokens.push(arg.toString()); + } else { + textTokens.push(valueFromRemoteObject(remoteObject)); + } } const stackTraceLocations = []; if (stackTrace) { @@ -1853,12 +1881,13 @@ export class Page extends EventEmitter { } #sessionClosePromise(): Promise { - if (!this.#disconnectPromise) + if (!this.#disconnectPromise) { this.#disconnectPromise = new Promise((fulfill) => this.#client.once(CDPSessionEmittedEvents.Disconnected, () => fulfill(new Error('Target closed')) ) ); + } return this.#disconnectPromise; } @@ -1896,9 +1925,12 @@ export class Page extends EventEmitter { this.#frameManager.networkManager(), NetworkManagerEmittedEvents.Request, (request) => { - if (isString(urlOrPredicate)) return urlOrPredicate === request.url(); - if (typeof urlOrPredicate === 'function') + if (isString(urlOrPredicate)) { + return urlOrPredicate === request.url(); + } + if (typeof urlOrPredicate === 'function') { return !!urlOrPredicate(request); + } return false; }, timeout, @@ -1942,9 +1974,12 @@ export class Page extends EventEmitter { this.#frameManager.networkManager(), NetworkManagerEmittedEvents.Response, async (response) => { - if (isString(urlOrPredicate)) return urlOrPredicate === response.url(); - if (typeof urlOrPredicate === 'function') + if (isString(urlOrPredicate)) { + return urlOrPredicate === response.url(); + } + if (typeof urlOrPredicate === 'function') { return !!(await urlOrPredicate(response)); + } return false; }, timeout, @@ -1984,8 +2019,9 @@ export class Page extends EventEmitter { const evaluate = () => { idleTimer && clearTimeout(idleTimer); - if (networkManager.numRequestsInProgress() === 0) + if (networkManager.numRequestsInProgress() === 0) { idleTimer = setTimeout(onIdle, idleTime); + } }; evaluate(); @@ -2152,7 +2188,9 @@ export class Page extends EventEmitter { ): Promise { const history = await this.#client.send('Page.getNavigationHistory'); const entry = history.entries[history.currentIndex + delta]; - if (!entry) return null; + if (!entry) { + return null; + } const result = await Promise.all([ this.waitForNavigation(options), this.#client.send('Page.navigateToHistoryEntry', { entryId: entry.id }), @@ -2208,7 +2246,9 @@ export class Page extends EventEmitter { * It will take full effect on the next navigation. */ async setJavaScriptEnabled(enabled: boolean): Promise { - if (this.#javascriptEnabled === enabled) return; + if (this.#javascriptEnabled === enabled) { + return; + } this.#javascriptEnabled = enabled; await this.#client.send('Emulation.setScriptExecutionDisabled', { value: !enabled, @@ -2328,7 +2368,9 @@ export class Page extends EventEmitter { * ``` */ async emulateMediaFeatures(features?: MediaFeature[]): Promise { - if (!features) await this.#client.send('Emulation.setEmulatedMedia', {}); + if (!features) { + await this.#client.send('Emulation.setEmulatedMedia', {}); + } if (Array.isArray(features)) { for (const mediaFeature of features) { const name = mediaFeature.name; @@ -2491,7 +2533,9 @@ export class Page extends EventEmitter { async setViewport(viewport: Viewport): Promise { const needsReload = await this.#emulationManager.emulateViewport(viewport); this.#viewport = viewport; - if (needsReload) await this.reload(); + if (needsReload) { + await this.reload(); + } } /** @@ -2813,8 +2857,9 @@ export class Page extends EventEmitter { await this.#resetDefaultBackgroundColor(); } - if (options.fullPage && this.#viewport) + if (options.fullPage && this.#viewport) { await this.setViewport(this.#viewport); + } const buffer = options.encoding === 'base64' @@ -3414,7 +3459,9 @@ const unitToPixels = { function convertPrintParameterToInches( parameter?: string | number ): number | undefined { - if (typeof parameter === 'undefined') return undefined; + if (typeof parameter === 'undefined') { + return undefined; + } let pixels; if (isNumber(parameter)) { // Treat numbers as pixel values to be aligned with phantom's paperSize. diff --git a/src/common/QueryHandler.ts b/src/common/QueryHandler.ts index 650c09cf..7c359f10 100644 --- a/src/common/QueryHandler.ts +++ b/src/common/QueryHandler.ts @@ -68,7 +68,9 @@ function makeQueryHandler(handler: CustomQueryHandler): InternalQueryHandler { internalHandler.queryOne = async (element, selector) => { const jsHandle = await element.evaluateHandle(queryOne, selector); const elementHandle = jsHandle.asElement(); - if (elementHandle) return elementHandle; + if (elementHandle) { + return elementHandle; + } await jsHandle.dispose(); return null; }; @@ -88,7 +90,9 @@ function makeQueryHandler(handler: CustomQueryHandler): InternalQueryHandler { const result = []; for (const property of properties.values()) { const elementHandle = property.asElement(); - if (elementHandle) result.push(elementHandle); + if (elementHandle) { + result.push(elementHandle); + } } return result; }; @@ -174,12 +178,14 @@ export function _registerCustomQueryHandler( name: string, handler: CustomQueryHandler ): void { - if (queryHandlers.get(name)) + if (queryHandlers.get(name)) { throw new Error(`A custom query handler named "${name}" already exists`); + } const isValidName = /^[a-zA-Z]+$/.test(name); - if (!isValidName) + if (!isValidName) { throw new Error(`Custom query handler names may only contain [a-zA-Z]`); + } const internalHandler = makeQueryHandler(handler); @@ -217,17 +223,19 @@ export function _getQueryHandlerAndSelector(selector: string): { queryHandler: InternalQueryHandler; } { const hasCustomQueryHandler = /^[a-zA-Z]+\//.test(selector); - if (!hasCustomQueryHandler) + if (!hasCustomQueryHandler) { return { updatedSelector: selector, queryHandler: _defaultHandler }; + } const index = selector.indexOf('/'); const name = selector.slice(0, index); const updatedSelector = selector.slice(index + 1); const queryHandler = queryHandlers.get(name); - if (!queryHandler) + if (!queryHandler) { throw new Error( `Query set to use "${name}", but no query handler of that name was found` ); + } return { updatedSelector, diff --git a/src/common/Target.ts b/src/common/Target.ts index 7bd8e0cb..7b5c0245 100644 --- a/src/common/Target.ts +++ b/src/common/Target.ts @@ -87,12 +87,17 @@ export class Target { this._initializedPromise = new Promise( (fulfill) => (this._initializedCallback = fulfill) ).then(async (success) => { - if (!success) return false; + if (!success) { + return false; + } const opener = this.opener(); - if (!opener || !opener.#pagePromise || this.type() !== 'page') + if (!opener || !opener.#pagePromise || this.type() !== 'page') { return true; + } const openerPage = await opener.#pagePromise; - if (!openerPage.listenerCount(PageEmittedEvents.Popup)) return true; + if (!openerPage.listenerCount(PageEmittedEvents.Popup)) { + return true; + } const popupPage = await this.page(); openerPage.emit(PageEmittedEvents.Popup, popupPage); return true; @@ -103,7 +108,9 @@ export class Target { this._isInitialized = !this._isPageTargetCallback(this.#targetInfo) || this.#targetInfo.url !== ''; - if (this._isInitialized) this._initializedCallback(true); + if (this._isInitialized) { + this._initializedCallback(true); + } } /** @@ -145,8 +152,9 @@ export class Target { if ( this.#targetInfo.type !== 'service_worker' && this.#targetInfo.type !== 'shared_worker' - ) + ) { return null; + } if (!this.#workerPromise) { // TODO(einbinder): Make workers send their console logs. this.#workerPromise = this.#sessionFactory().then( @@ -189,8 +197,9 @@ export class Target { type === 'shared_worker' || type === 'browser' || type === 'webview' - ) + ) { return type; + } return 'other'; } @@ -213,7 +222,9 @@ export class Target { */ opener(): Target | undefined { const { openerId } = this.#targetInfo; - if (!openerId) return; + if (!openerId) { + return; + } return this.browser()._targets.get(openerId); } diff --git a/src/common/TimeoutSettings.ts b/src/common/TimeoutSettings.ts index aa2ae527..97acc701 100644 --- a/src/common/TimeoutSettings.ts +++ b/src/common/TimeoutSettings.ts @@ -37,14 +37,19 @@ export class TimeoutSettings { } navigationTimeout(): number { - if (this.#defaultNavigationTimeout !== null) + if (this.#defaultNavigationTimeout !== null) { return this.#defaultNavigationTimeout; - if (this.#defaultTimeout !== null) return this.#defaultTimeout; + } + if (this.#defaultTimeout !== null) { + return this.#defaultTimeout; + } return DEFAULT_TIMEOUT; } timeout(): number { - if (this.#defaultTimeout !== null) return this.#defaultTimeout; + if (this.#defaultTimeout !== null) { + return this.#defaultTimeout; + } return DEFAULT_TIMEOUT; } } diff --git a/src/common/Tracing.ts b/src/common/Tracing.ts index 462329d5..26585bd4 100644 --- a/src/common/Tracing.ts +++ b/src/common/Tracing.ts @@ -89,7 +89,9 @@ export class Tracing { categories = defaultCategories, } = options; - if (screenshots) categories.push('disabled-by-default-devtools.screenshot'); + if (screenshots) { + categories.push('disabled-by-default-devtools.screenshot'); + } const excludedCategories = categories .filter((cat) => cat.startsWith('-')) diff --git a/src/common/assert.ts b/src/common/assert.ts index e1ba43f9..232c84d5 100644 --- a/src/common/assert.ts +++ b/src/common/assert.ts @@ -23,12 +23,16 @@ export const assert: (value: unknown, message?: string) => asserts value = ( value, message ) => { - if (!value) throw new Error(message); + if (!value) { + throw new Error(message); + } }; export const assertNever: ( value: unknown, message?: string ) => asserts value is never = (value, message) => { - if (value) throw new Error(message); + if (value) { + throw new Error(message); + } }; diff --git a/src/common/util.ts b/src/common/util.ts index 8a2b031d..59006346 100644 --- a/src/common/util.ts +++ b/src/common/util.ts @@ -28,10 +28,11 @@ export const debugError = debug('puppeteer:error'); export function getExceptionMessage( exceptionDetails: Protocol.Runtime.ExceptionDetails ): string { - if (exceptionDetails.exception) + if (exceptionDetails.exception) { return ( exceptionDetails.exception.description || exceptionDetails.exception.value ); + } let message = exceptionDetails.text; if (exceptionDetails.stackTrace) { for (const callframe of exceptionDetails.stackTrace.callFrames) { @@ -53,8 +54,9 @@ export function valueFromRemoteObject( ): any { assert(!remoteObject.objectId, 'Cannot extract value when objectId is given'); if (remoteObject.unserializableValue) { - if (remoteObject.type === 'bigint' && typeof BigInt !== 'undefined') + if (remoteObject.type === 'bigint' && typeof BigInt !== 'undefined') { return BigInt(remoteObject.unserializableValue.replace('n', '')); + } switch (remoteObject.unserializableValue) { case '-0': return -0; @@ -78,7 +80,9 @@ export async function releaseObject( client: CDPSession, remoteObject: Protocol.Runtime.RemoteObject ): Promise { - if (!remoteObject.objectId) return; + if (!remoteObject.objectId) { + return; + } await client .send('Runtime.releaseObject', { objectId: remoteObject.objectId }) .catch((error) => { @@ -110,8 +114,9 @@ export function removeEventListeners( handler: (...args: any[]) => void; }> ): void { - for (const listener of listeners) + for (const listener of listeners) { listener.emitter.removeListener(listener.eventName, listener.handler); + } listeners.length = 0; } @@ -138,7 +143,9 @@ export async function waitForEvent( rejectCallback = reject; }); const listener = addEventListener(emitter, eventName, async (event) => { - if (!(await predicate(event))) return; + if (!(await predicate(event))) { + return; + } resolveCallback(event); }); if (timeout) { @@ -179,7 +186,9 @@ export function evaluationString( } function serializeArgument(arg: unknown): string { - if (Object.is(arg, undefined)) return 'undefined'; + if (Object.is(arg, undefined)) { + return 'undefined'; + } return JSON.stringify(arg); } @@ -266,8 +275,12 @@ export function makePredicateString( waitForVisible: boolean, waitForHidden: boolean ): Node | null | boolean { - if (!node) return waitForHidden; - if (!waitForVisible && !waitForHidden) return node; + if (!node) { + return waitForHidden; + } + if (!waitForVisible && !waitForHidden) { + return node; + } const element = node.nodeType === Node.TEXT_NODE ? (node.parentElement as Element) @@ -307,11 +320,15 @@ export async function waitWithTimeout( ); const timeoutPromise = new Promise((_res, rej) => (reject = rej)); let timeoutTimer = null; - if (timeout) timeoutTimer = setTimeout(() => reject(timeoutError), timeout); + if (timeout) { + timeoutTimer = setTimeout(() => reject(timeoutError), timeout); + } try { return await Promise.race([promise, timeoutPromise]); } finally { - if (timeoutTimer) clearTimeout(timeoutTimer); + if (timeoutTimer) { + clearTimeout(timeoutTimer); + } } } diff --git a/src/initializePuppeteer.ts b/src/initializePuppeteer.ts index 4846ba0d..40e5585a 100644 --- a/src/initializePuppeteer.ts +++ b/src/initializePuppeteer.ts @@ -31,8 +31,9 @@ export const initializePuppeteer = (packageName: string): PuppeteerNode => { process.env['npm_package_config_puppeteer_product']) as Product) : undefined; - if (!isPuppeteerCore && productName === 'firefox') + if (!isPuppeteerCore && productName === 'firefox') { preferredRevision = PUPPETEER_REVISIONS.firefox; + } return new PuppeteerNode({ projectRoot: puppeteerRootDirectory, diff --git a/src/node/BrowserFetcher.ts b/src/node/BrowserFetcher.ts index c9372f47..9ccfa061 100644 --- a/src/node/BrowserFetcher.ts +++ b/src/node/BrowserFetcher.ts @@ -326,9 +326,12 @@ export class BrowserFetcher { assert(fileName, `A malformed download URL was found: ${url}.`); const archivePath = path.join(this.#downloadsFolder, fileName); const outputPath = this.#getFolderPath(revision); - if (await existsAsync(outputPath)) return this.revisionInfo(revision); - if (!(await existsAsync(this.#downloadsFolder))) + if (await existsAsync(outputPath)) { + return this.revisionInfo(revision); + } + if (!(await existsAsync(this.#downloadsFolder))) { await mkdirAsync(this.#downloadsFolder); + } // Use system Chromium builds on Linux ARM devices if (os.platform() !== 'darwin' && os.arch() === 'arm64') { @@ -339,10 +342,14 @@ export class BrowserFetcher { await _downloadFile(url, archivePath, progressCallback); await install(archivePath, outputPath); } finally { - if (await existsAsync(archivePath)) await unlinkAsync(archivePath); + if (await existsAsync(archivePath)) { + await unlinkAsync(archivePath); + } } const revisionInfo = this.revisionInfo(revision); - if (revisionInfo) await chmodAsync(revisionInfo.executablePath, 0o755); + if (revisionInfo) { + await chmodAsync(revisionInfo.executablePath, 0o755); + } return revisionInfo; } @@ -353,7 +360,9 @@ export class BrowserFetcher { * available locally on disk. */ async localRevisions(): Promise { - if (!(await existsAsync(this.#downloadsFolder))) return []; + if (!(await existsAsync(this.#downloadsFolder))) { + return []; + } const fileNames = await readdirAsync(this.#downloadsFolder); return fileNames .map((fileName) => parseFolderPath(this.#product, fileName)) @@ -390,7 +399,7 @@ export class BrowserFetcher { const folderPath = this.#getFolderPath(revision); let executablePath = ''; if (this.#product === 'chrome') { - if (this.#platform === 'mac' || this.#platform === 'mac_arm') + if (this.#platform === 'mac' || this.#platform === 'mac_arm') { executablePath = path.join( folderPath, archiveName(this.#product, this.#platform, revision), @@ -399,21 +408,23 @@ export class BrowserFetcher { 'MacOS', 'Chromium' ); - else if (this.#platform === 'linux') + } else if (this.#platform === 'linux') { executablePath = path.join( folderPath, archiveName(this.#product, this.#platform, revision), 'chrome' ); - else if (this.#platform === 'win32' || this.#platform === 'win64') + } else if (this.#platform === 'win32' || this.#platform === 'win64') { executablePath = path.join( folderPath, archiveName(this.#product, this.#platform, revision), 'chrome.exe' ); - else throw new Error('Unsupported platform: ' + this.#platform); + } else { + throw new Error('Unsupported platform: ' + this.#platform); + } } else if (this.#product === 'firefox') { - if (this.#platform === 'mac' || this.#platform === 'mac_arm') + if (this.#platform === 'mac' || this.#platform === 'mac_arm') { executablePath = path.join( folderPath, 'Firefox Nightly.app', @@ -421,12 +432,16 @@ export class BrowserFetcher { 'MacOS', 'firefox' ); - else if (this.#platform === 'linux') + } else if (this.#platform === 'linux') { executablePath = path.join(folderPath, 'firefox', 'firefox'); - else if (this.#platform === 'win32' || this.#platform === 'win64') + } else if (this.#platform === 'win32' || this.#platform === 'win64') { executablePath = path.join(folderPath, 'firefox', 'firefox.exe'); - else throw new Error('Unsupported platform: ' + this.#platform); - } else throw new Error('Unsupported product: ' + this.#product); + } else { + throw new Error('Unsupported platform: ' + this.#platform); + } + } else { + throw new Error('Unsupported product: ' + this.#product); + } const url = _downloadURL( this.#product, this.#platform, @@ -463,9 +478,13 @@ function parseFolderPath( ): { product: string; platform: string; revision: string } | undefined { const name = path.basename(folderPath); const splits = name.split('-'); - if (splits.length !== 2) return; + if (splits.length !== 2) { + return; + } const [platform, revision] = splits; - if (!revision || !platform || !(platform in downloadURLs[product])) return; + if (!revision || !platform || !(platform in downloadURLs[product])) { + return; + } return { product, platform, revision }; } @@ -503,7 +522,9 @@ function _downloadFile( file.on('error', (error) => reject(error)); response.pipe(file); totalBytes = parseInt(response.headers['content-length']!, 10); - if (progressCallback) response.on('data', onData); + if (progressCallback) { + response.on('data', onData); + } }); request.on('error', (error) => reject(error)); return promise; @@ -516,15 +537,17 @@ function _downloadFile( function install(archivePath: string, folderPath: string): Promise { debugFetcher(`Installing ${archivePath} to ${folderPath}`); - if (archivePath.endsWith('.zip')) + if (archivePath.endsWith('.zip')) { return extractZip(archivePath, { dir: folderPath }); - else if (archivePath.endsWith('.tar.bz2')) + } else if (archivePath.endsWith('.tar.bz2')) { return _extractTar(archivePath, folderPath); - else if (archivePath.endsWith('.dmg')) + } else if (archivePath.endsWith('.dmg')) { return mkdirAsync(folderPath).then(() => _installDMG(archivePath, folderPath) ); - else throw new Error(`Unsupported archive format: ${archivePath}`); + } else { + throw new Error(`Unsupported archive format: ${archivePath}`); + } } /** @@ -549,23 +572,30 @@ function _installDMG(dmgPath: string, folderPath: string): Promise { return new Promise((fulfill, reject): void => { const mountCommand = `hdiutil attach -nobrowse -noautoopen "${dmgPath}"`; childProcess.exec(mountCommand, (err, stdout) => { - if (err) return reject(err); + if (err) { + return reject(err); + } const volumes = stdout.match(/\/Volumes\/(.*)/m); - if (!volumes) + if (!volumes) { return reject(new Error(`Could not find volume path in ${stdout}`)); + } mountPath = volumes[0]!; readdirAsync(mountPath) .then((fileNames) => { const appName = fileNames.find( (item) => typeof item === 'string' && item.endsWith('.app') ); - if (!appName) + if (!appName) { return reject(new Error(`Cannot find app in ${mountPath}`)); + } const copyPath = path.join(mountPath!, appName); debugFetcher(`Copying ${copyPath} to ${folderPath}`); childProcess.exec(`cp -R "${copyPath}" "${folderPath}"`, (err) => { - if (err) reject(err); - else fulfill(); + if (err) { + reject(err); + } else { + fulfill(); + } }); }) .catch(reject); @@ -575,11 +605,15 @@ function _installDMG(dmgPath: string, folderPath: string): Promise { console.error(error); }) .finally((): void => { - if (!mountPath) return; + if (!mountPath) { + return; + } const unmountCommand = `hdiutil detach "${mountPath}" -quiet`; debugFetcher(`Unmounting ${mountPath}`); childProcess.exec(unmountCommand, (err) => { - if (err) console.error(`Error unmounting dmg: ${err}`); + if (err) { + console.error(`Error unmounting dmg: ${err}`); + } }); }); } @@ -637,9 +671,11 @@ function httpRequest( res.statusCode >= 300 && res.statusCode < 400 && res.headers.location - ) + ) { httpRequest(res.headers.location, method, response); - else response(res); + } else { + response(res); + } }; const request = options.protocol === 'https:' diff --git a/src/node/BrowserRunner.ts b/src/node/BrowserRunner.ts index 9e027804..a17e53d7 100644 --- a/src/node/BrowserRunner.ts +++ b/src/node/BrowserRunner.ts @@ -80,11 +80,17 @@ export class BrowserRunner { options; let stdio: Array<'ignore' | 'pipe'>; if (pipe) { - if (dumpio) stdio = ['ignore', 'pipe', 'pipe', 'pipe', 'pipe']; - else stdio = ['ignore', 'ignore', 'ignore', 'pipe', 'pipe']; + if (dumpio) { + stdio = ['ignore', 'pipe', 'pipe', 'pipe', 'pipe']; + } else { + stdio = ['ignore', 'ignore', 'ignore', 'pipe', 'pipe']; + } } else { - if (dumpio) stdio = ['pipe', 'pipe', 'pipe']; - else stdio = ['pipe', 'ignore', 'pipe']; + if (dumpio) { + stdio = ['pipe', 'pipe', 'pipe']; + } else { + stdio = ['pipe', 'ignore', 'pipe']; + } } assert(!this.proc, 'This process has previously been started.'); debugLauncher( @@ -147,25 +153,30 @@ export class BrowserRunner { }); }); this.#listeners = [addEventListener(process, 'exit', this.kill.bind(this))]; - if (handleSIGINT) + if (handleSIGINT) { this.#listeners.push( addEventListener(process, 'SIGINT', () => { this.kill(); process.exit(130); }) ); - if (handleSIGTERM) + } + if (handleSIGTERM) { this.#listeners.push( addEventListener(process, 'SIGTERM', this.close.bind(this)) ); - if (handleSIGHUP) + } + if (handleSIGHUP) { this.#listeners.push( addEventListener(process, 'SIGHUP', this.close.bind(this)) ); + } } close(): Promise { - if (this.#closed) return Promise.resolve(); + if (this.#closed) { + return Promise.resolve(); + } if (this.#isTempUserDataDir) { this.kill(); } else if (this.connection) { @@ -309,14 +320,18 @@ function waitForWSEndpoint( function onLine(line: string): void { stderr += line + '\n'; const match = line.match(/^DevTools listening on (ws:\/\/.*)$/); - if (!match) return; + if (!match) { + return; + } cleanup(); // The RegExp matches, so this will obviously exist. resolve(match[1]!); } function cleanup(): void { - if (timeoutId) clearTimeout(timeoutId); + if (timeoutId) { + clearTimeout(timeoutId); + } removeEventListeners(listeners); } }); diff --git a/src/node/Launcher.ts b/src/node/Launcher.ts index fd7f2fdf..0e430968 100644 --- a/src/node/Launcher.ts +++ b/src/node/Launcher.ts @@ -96,14 +96,17 @@ class ChromeLauncher implements ProductLauncher { } = options; const chromeArguments = []; - if (!ignoreDefaultArgs) chromeArguments.push(...this.defaultArgs(options)); - else if (Array.isArray(ignoreDefaultArgs)) + if (!ignoreDefaultArgs) { + chromeArguments.push(...this.defaultArgs(options)); + } else if (Array.isArray(ignoreDefaultArgs)) { chromeArguments.push( ...this.defaultArgs(options).filter( (arg) => !ignoreDefaultArgs.includes(arg) ) ); - else chromeArguments.push(...args); + } else { + chromeArguments.push(...args); + } if ( !chromeArguments.some((argument) => @@ -248,9 +251,12 @@ class ChromeLauncher implements ProductLauncher { args = [], userDataDir, } = options; - if (userDataDir) + if (userDataDir) { chromeArguments.push(`--user-data-dir=${path.resolve(userDataDir)}`); - if (devtools) chromeArguments.push('--auto-open-devtools-for-tabs'); + } + if (devtools) { + chromeArguments.push('--auto-open-devtools-for-tabs'); + } if (headless) { chromeArguments.push( headless === 'chrome' ? '--headless=chrome' : '--headless', @@ -258,8 +264,9 @@ class ChromeLauncher implements ProductLauncher { '--mute-audio' ); } - if (args.every((arg) => arg.startsWith('-'))) + if (args.every((arg) => arg.startsWith('-'))) { chromeArguments.push('about:blank'); + } chromeArguments.push(...args); return chromeArguments; } @@ -326,14 +333,17 @@ class FirefoxLauncher implements ProductLauncher { } = options; const firefoxArguments = []; - if (!ignoreDefaultArgs) firefoxArguments.push(...this.defaultArgs(options)); - else if (Array.isArray(ignoreDefaultArgs)) + if (!ignoreDefaultArgs) { + firefoxArguments.push(...this.defaultArgs(options)); + } else if (Array.isArray(ignoreDefaultArgs)) { firefoxArguments.push( ...this.defaultArgs(options).filter( (arg) => !ignoreDefaultArgs.includes(arg) ) ); - else firefoxArguments.push(...args); + } else { + firefoxArguments.push(...args); + } if ( !firefoxArguments.some((argument) => @@ -379,7 +389,9 @@ class FirefoxLauncher implements ProductLauncher { let firefoxExecutable = executablePath; if (!executablePath) { const { missingText, executablePath } = resolveExecutablePath(this); - if (missingText) throw new Error(missingText); + if (missingText) { + throw new Error(missingText); + } firefoxExecutable = executablePath; } @@ -452,7 +464,9 @@ class FirefoxLauncher implements ProductLauncher { product: this.product, }); const localRevisions = await browserFetcher.localRevisions(); - if (localRevisions[0]) this._preferredRevision = localRevisions[0]; + if (localRevisions[0]) { + this._preferredRevision = localRevisions[0]; + } } } @@ -470,18 +484,24 @@ class FirefoxLauncher implements ProductLauncher { const firefoxArguments = ['--no-remote']; - if (os.platform() === 'darwin') firefoxArguments.push('--foreground'); - else if (os.platform().startsWith('win')) { + if (os.platform() === 'darwin') { + firefoxArguments.push('--foreground'); + } else if (os.platform().startsWith('win')) { firefoxArguments.push('--wait-for-browser'); } if (userDataDir) { firefoxArguments.push('--profile'); firefoxArguments.push(userDataDir); } - if (headless) firefoxArguments.push('--headless'); - if (devtools) firefoxArguments.push('--devtools'); - if (args.every((arg) => arg.startsWith('-'))) + if (headless) { + firefoxArguments.push('--headless'); + } + if (devtools) { + firefoxArguments.push('--devtools'); + } + if (args.every((arg) => arg.startsWith('-'))) { firefoxArguments.push('about:blank'); + } firefoxArguments.push(...args); return firefoxArguments; } @@ -887,11 +907,12 @@ export default function Launcher( product?: string ): ProductLauncher { // puppeteer-core doesn't take into account PUPPETEER_* env variables. - if (!product && !isPuppeteerCore) + if (!product && !isPuppeteerCore) { product = process.env['PUPPETEER_PRODUCT'] || process.env['npm_config_puppeteer_product'] || process.env['npm_package_config_puppeteer_product']; + } switch (product) { case 'firefox': return new FirefoxLauncher( diff --git a/src/node/NodeWebSocketTransport.ts b/src/node/NodeWebSocketTransport.ts index 45276c84..a3a57bc6 100644 --- a/src/node/NodeWebSocketTransport.ts +++ b/src/node/NodeWebSocketTransport.ts @@ -57,10 +57,14 @@ export class NodeWebSocketTransport implements ConnectionTransport { constructor(ws: NodeWebSocket) { this.#ws = ws; this.#ws.addEventListener('message', (event) => { - if (this.onmessage) this.onmessage.call(null, event.data); + if (this.onmessage) { + this.onmessage.call(null, event.data); + } }); this.#ws.addEventListener('close', () => { - if (this.onclose) this.onclose.call(null); + if (this.onclose) { + this.onclose.call(null); + } }); // Silently ignore all errors - we don't know what to do with them. this.#ws.addEventListener('error', () => {}); diff --git a/src/node/Puppeteer.ts b/src/node/Puppeteer.ts index 3f2e69df..69870452 100644 --- a/src/node/Puppeteer.ts +++ b/src/node/Puppeteer.ts @@ -116,7 +116,9 @@ export class PuppeteerNode extends Puppeteer { * @returns Promise which resolves to browser instance. */ override connect(options: ConnectOptions): Promise { - if (options.product) this._productName = options.product; + if (options.product) { + this._productName = options.product; + } return super.connect(options); } @@ -131,7 +133,9 @@ export class PuppeteerNode extends Puppeteer { * @internal */ set _productName(name: Product | undefined) { - if (this.#productName !== name) this._changedProduct = true; + if (this.#productName !== name) { + this._changedProduct = true; + } this.#productName = name; } @@ -161,7 +165,9 @@ export class PuppeteerNode extends Puppeteer { * @returns Promise which resolves to browser instance. */ launch(options: PuppeteerLaunchOptions = {}): Promise { - if (options.product) this._productName = options.product; + if (options.product) { + this._productName = options.product; + } return this._launcher.launch(options); } diff --git a/src/node/install.ts b/src/node/install.ts index 6b841e5c..ffb409c8 100644 --- a/src/node/install.ts +++ b/src/node/install.ts @@ -97,9 +97,15 @@ export async function downloadBrowser(): Promise { process.env['npm_config_http_proxy'] || process.env['npm_config_proxy']; const NPM_NO_PROXY = process.env['npm_config_no_proxy']; - if (NPM_HTTPS_PROXY) process.env['HTTPS_PROXY'] = NPM_HTTPS_PROXY; - if (NPM_HTTP_PROXY) process.env['HTTP_PROXY'] = NPM_HTTP_PROXY; - if (NPM_NO_PROXY) process.env['NO_PROXY'] = NPM_NO_PROXY; + if (NPM_HTTPS_PROXY) { + process.env['HTTPS_PROXY'] = NPM_HTTPS_PROXY; + } + if (NPM_HTTP_PROXY) { + process.env['HTTP_PROXY'] = NPM_HTTP_PROXY; + } + if (NPM_NO_PROXY) { + process.env['NO_PROXY'] = NPM_NO_PROXY; + } function onSuccess(localRevisions: string[]): void { logPolitely( @@ -182,8 +188,9 @@ export async function downloadBrowser(): Promise { ); https .get(firefoxVersionsUrl, requestOptions, (r) => { - if (r.statusCode && r.statusCode >= 400) + if (r.statusCode && r.statusCode >= 400) { return reject(new Error(`Got status code ${r.statusCode}`)); + } r.on('data', (chunk) => { data += chunk; }); @@ -207,5 +214,7 @@ export function logPolitely(toBeLogged: unknown): void { const logLevelDisplay = ['silent', 'error', 'warn'].indexOf(logLevel) > -1; // eslint-disable-next-line no-console - if (!logLevelDisplay) console.log(toBeLogged); + if (!logLevelDisplay) { + console.log(toBeLogged); + } } diff --git a/test/accessibility.spec.ts b/test/accessibility.spec.ts index 870f4724..65d3cb30 100644 --- a/test/accessibility.spec.ts +++ b/test/accessibility.spec.ts @@ -493,10 +493,14 @@ describeFailsFirefox('Accessibility', function () { }); }); function findFocusedNode(node) { - if (node.focused) return node; + if (node.focused) { + return node; + } for (const child of node.children || []) { const focusedChild = findFocusedNode(child); - if (focusedChild) return focusedChild; + if (focusedChild) { + return focusedChild; + } } return null; } diff --git a/test/assets/input/mouse-helper.js b/test/assets/input/mouse-helper.js index 4f2824dc..97a764aa 100644 --- a/test/assets/input/mouse-helper.js +++ b/test/assets/input/mouse-helper.js @@ -69,6 +69,6 @@ ); function updateButtons(buttons) { for (let i = 0; i < 5; i++) - box.classList.toggle('button-' + i, buttons & (1 << i)); + {box.classList.toggle('button-' + i, buttons & (1 << i));} } })(); diff --git a/test/browser.spec.ts b/test/browser.spec.ts index 00da218d..6676d034 100644 --- a/test/browser.spec.ts +++ b/test/browser.spec.ts @@ -38,8 +38,11 @@ describe('Browser specs', function () { const userAgent = await browser.userAgent(); expect(userAgent.length).toBeGreaterThan(0); - if (isChrome) expect(userAgent).toContain('WebKit'); - else expect(userAgent).toContain('Gecko'); + if (isChrome) { + expect(userAgent).toContain('WebKit'); + } else { + expect(userAgent).toContain('Gecko'); + } }); }); diff --git a/test/browsercontext.spec.ts b/test/browsercontext.spec.ts index 88ff09b2..ba4866a7 100644 --- a/test/browsercontext.spec.ts +++ b/test/browsercontext.spec.ts @@ -113,7 +113,9 @@ describe('BrowserContext', function () { resolved = true; if (error instanceof puppeteer.errors.TimeoutError) { console.error(error); - } else throw error; + } else { + throw error; + } }); const page = await context.newPage(); expect(resolved).toBe(false); @@ -124,7 +126,9 @@ describe('BrowserContext', function () { } catch (error) { if (error instanceof puppeteer.errors.TimeoutError) { console.error(error); - } else throw error; + } else { + throw error; + } } await context.close(); }); diff --git a/test/coverage-utils.js b/test/coverage-utils.js index c23e507f..0f64f709 100644 --- a/test/coverage-utils.js +++ b/test/coverage-utils.js @@ -85,8 +85,9 @@ function traceAPICoverage(apiCoverage, className, modulePath) { typeof methodName !== 'string' || methodName.startsWith('_') || typeof method !== 'function' - ) + ) { continue; + } apiCoverage.set(`${className}.${methodName}`, false); Reflect.set(classType.prototype, methodName, function (...args) { apiCoverage.set(`${className}.${methodName}`, true); @@ -102,13 +103,15 @@ function traceAPICoverage(apiCoverage, className, modulePath) { const eventsName = `${className}EmittedEvents`; if (loadedModule[eventsName]) { for (const event of Object.values(loadedModule[eventsName])) { - if (typeof event !== 'symbol') + if (typeof event !== 'symbol') { apiCoverage.set(`${className}.emit(${JSON.stringify(event)})`, false); + } } const method = Reflect.get(classType.prototype, 'emit'); Reflect.set(classType.prototype, 'emit', function (event, ...args) { - if (typeof event !== 'symbol' && this.listenerCount(event)) + if (typeof event !== 'symbol' && this.listenerCount(event)) { apiCoverage.set(`${className}.emit(${JSON.stringify(event)})`, true); + } return method.call(this, event, ...args); }); } diff --git a/test/elementhandle.spec.ts b/test/elementhandle.spec.ts index e46e6ca0..794c41ed 100644 --- a/test/elementhandle.spec.ts +++ b/test/elementhandle.spec.ts @@ -49,9 +49,11 @@ describe('ElementHandle specs', function () { const nestedFrame = page.frames()[1].childFrames()[1]; const elementHandle = await nestedFrame.$('div'); const box = await elementHandle.boundingBox(); - if (isChrome) + if (isChrome) { expect(box).toEqual({ x: 28, y: 182, width: 264, height: 18 }); - else expect(box).toEqual({ x: 28, y: 182, width: 254, height: 18 }); + } else { + expect(box).toEqual({ x: 28, y: 182, width: 254, height: 18 }); + } }); it('should return null for invisible elements', async () => { const { page } = getTestState(); diff --git a/test/fixtures.spec.ts b/test/fixtures.spec.ts index 9f5c6213..2a5f04a6 100644 --- a/test/fixtures.spec.ts +++ b/test/fixtures.spec.ts @@ -75,8 +75,9 @@ describe('Fixtures', function () { let output = ''; res.stdout.on('data', (data) => { output += data; - if (output.indexOf('\n')) + if (output.indexOf('\n')) { wsEndPointCallback(output.substring(0, output.indexOf('\n'))); + } }); const browser = await puppeteer.connect({ browserWSEndpoint: await wsEndPointPromise, @@ -85,9 +86,11 @@ describe('Fixtures', function () { new Promise((resolve) => browser.once('disconnected', resolve)), new Promise((resolve) => res.on('close', resolve)), ]; - if (process.platform === 'win32') + if (process.platform === 'win32') { execSync(`taskkill /pid ${res.pid} /T /F`); - else process.kill(res.pid); + } else { + process.kill(res.pid); + } await Promise.all(promises); }); }); diff --git a/test/golden-utils.js b/test/golden-utils.js index f820afe6..e6e73842 100644 --- a/test/golden-utils.js +++ b/test/golden-utils.js @@ -37,8 +37,9 @@ const GoldenComparators = { * @returns {?{diff: (!Object:undefined), errorMessage: (string|undefined)}} */ function compareImages(actualBuffer, expectedBuffer, mimeType) { - if (!actualBuffer || !(actualBuffer instanceof Buffer)) + if (!actualBuffer || !(actualBuffer instanceof Buffer)) { return { errorMessage: 'Actual result should be Buffer.' }; + } const actual = mimeType === 'image/png' @@ -71,10 +72,13 @@ function compareImages(actualBuffer, expectedBuffer, mimeType) { * @returns {?{diff: (!Object:undefined), errorMessage: (string|undefined)}} */ function compareText(actual, expectedBuffer) { - if (typeof actual !== 'string') + if (typeof actual !== 'string') { return { errorMessage: 'Actual result should be string' }; + } const expected = expectedBuffer.toString('utf-8'); - if (expected === actual) return null; + if (expected === actual) { + return null; + } const diff = new Diff(); const result = diff.main(expected, actual); diff.cleanupSemantic(result); @@ -120,7 +124,9 @@ function compare(goldenPath, outputPath, actual, goldenName) { }; } const result = comparator(actual, expected, mimeType); - if (!result) return { pass: true }; + if (!result) { + return { pass: true }; + } ensureOutputDir(); if (goldenPath === outputPath) { fs.writeFileSync(addSuffix(actualPath, '-actual'), actual); @@ -135,14 +141,18 @@ function compare(goldenPath, outputPath, actual, goldenName) { } let message = goldenName + ' mismatch!'; - if (result.errorMessage) message += ' ' + result.errorMessage; + if (result.errorMessage) { + message += ' ' + result.errorMessage; + } return { pass: false, message: message + ' ' + messageSuffix, }; function ensureOutputDir() { - if (!fs.existsSync(outputPath)) fs.mkdirSync(outputPath); + if (!fs.existsSync(outputPath)) { + fs.mkdirSync(outputPath); + } } } diff --git a/test/headful.spec.ts b/test/headful.spec.ts index dbdc7aa4..44688433 100644 --- a/test/headful.spec.ts +++ b/test/headful.spec.ts @@ -338,15 +338,17 @@ describeChromeOnly('headful tests', function () { }) ); 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 }, }) ); + } 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`); + } await Promise.all(pages.map((page) => page.close())); await browser.close(); diff --git a/test/jshandle.spec.ts b/test/jshandle.spec.ts index 32ab08d8..0d4ec685 100644 --- a/test/jshandle.spec.ts +++ b/test/jshandle.spec.ts @@ -152,9 +152,11 @@ describe('JSHandle', function () { const windowHandle = await page.evaluateHandle('window'); let error = null; await windowHandle.jsonValue().catch((error_) => (error = error_)); - if (isChrome) + if (isChrome) { expect(error.message).toContain('Object reference chain is too long'); - else expect(error.message).toContain('Object is not serializable'); + } else { + expect(error.message).toContain('Object is not serializable'); + } }); }); diff --git a/test/keyboard.spec.ts b/test/keyboard.spec.ts index 5aff0f95..bfe7d3fe 100644 --- a/test/keyboard.spec.ts +++ b/test/keyboard.spec.ts @@ -64,14 +64,17 @@ describe('Keyboard', function () { expect( await page.evaluate(() => document.querySelector('textarea').value) ).toBe('Hello World!'); - for (let i = 0; i < 'World!'.length; i++) page.keyboard.press('ArrowLeft'); + for (let i = 0; i < 'World!'.length; i++) { + page.keyboard.press('ArrowLeft'); + } await page.keyboard.type('inserted '); expect( await page.evaluate(() => document.querySelector('textarea').value) ).toBe('Hello inserted World!'); page.keyboard.down('Shift'); - for (let i = 0; i < 'inserted '.length; i++) + for (let i = 0; i < 'inserted '.length; i++) { page.keyboard.press('ArrowLeft'); + } page.keyboard.up('Shift'); await page.keyboard.press('Backspace'); expect( @@ -152,7 +155,7 @@ describe('Keyboard', function () { ); await keyboard.down('!'); // Shift+! will generate a keypress - if (modifierKey === 'Shift') + if (modifierKey === 'Shift') { expect(await page.evaluate(() => globalThis.getResult())).toBe( 'Keydown: ! Digit1 49 [' + modifierKey + @@ -160,10 +163,11 @@ describe('Keyboard', function () { modifierKey + ']' ); - else + } else { expect(await page.evaluate(() => globalThis.getResult())).toBe( 'Keydown: ! Digit1 49 [' + modifierKey + ']' ); + } await keyboard.up('!'); expect(await page.evaluate(() => globalThis.getResult())).toBe( @@ -260,8 +264,12 @@ describe('Keyboard', function () { (event) => { event.stopPropagation(); event.stopImmediatePropagation(); - if (event.key === 'l') event.preventDefault(); - if (event.key === 'o') event.preventDefault(); + if (event.key === 'l') { + event.preventDefault(); + } + if (event.key === 'o') { + event.preventDefault(); + } }, false ); @@ -396,13 +404,22 @@ describe('Keyboard', function () { string, boolean ]; - if (isFirefox && os.platform() !== 'darwin') expect(key).toBe('OS'); - else expect(key).toBe('Meta'); + if (isFirefox && os.platform() !== 'darwin') { + expect(key).toBe('OS'); + } else { + expect(key).toBe('Meta'); + } - if (isFirefox) expect(code).toBe('OSLeft'); - else expect(code).toBe('MetaLeft'); + if (isFirefox) { + expect(code).toBe('OSLeft'); + } else { + expect(code).toBe('MetaLeft'); + } - if (isFirefox && os.platform() !== 'darwin') expect(metaKey).toBe(false); - else expect(metaKey).toBe(true); + if (isFirefox && os.platform() !== 'darwin') { + expect(metaKey).toBe(false); + } else { + expect(metaKey).toBe(true); + } }); }); diff --git a/test/launcher.spec.ts b/test/launcher.spec.ts index 2889c054..ec145280 100644 --- a/test/launcher.spec.ts +++ b/test/launcher.spec.ts @@ -41,7 +41,9 @@ const TMP_FOLDER = path.join(os.tmpdir(), 'pptr_tmp_folder-'); const FIREFOX_TIMEOUT = 30 * 1000; describe('Launcher specs', function () { - if (getTestState().isFirefox) this.timeout(FIREFOX_TIMEOUT); + if (getTestState().isFirefox) { + this.timeout(FIREFOX_TIMEOUT); + } describe('Puppeteer', function () { describe('BrowserFetcher', function () { @@ -394,8 +396,11 @@ describe('Launcher specs', function () { }); it('should report the correct product', async () => { const { isChrome, isFirefox, puppeteer } = getTestState(); - if (isChrome) expect(puppeteer.product).toBe('chrome'); - else if (isFirefox) expect(puppeteer.product).toBe('firefox'); + if (isChrome) { + expect(puppeteer.product).toBe('chrome'); + } else if (isFirefox) { + expect(puppeteer.product).toBe('firefox'); + } }); it('should work with no default arguments', async () => { const { defaultBrowserOptions, puppeteer } = getTestState(); @@ -468,7 +473,9 @@ describe('Launcher specs', function () { const pages = await browser.pages(); expect(pages.length).toBe(1); const page = pages[0]; - if (page.url() !== server.EMPTY_PAGE) await page.waitForNavigation(); + if (page.url() !== server.EMPTY_PAGE) { + await page.waitForNavigation(); + } expect(page.url()).toBe(server.EMPTY_PAGE); await browser.close(); } diff --git a/test/mocha-utils.ts b/test/mocha-utils.ts index 73ffe83d..3ed3fd13 100644 --- a/test/mocha-utils.ts +++ b/test/mocha-utils.ts @@ -99,15 +99,18 @@ const defaultBrowserOptions = Object.assign( } else { // TODO(jackfranklin): declare updateRevision in some form for the Firefox // launcher. - // @ts-expect-error _updateRevision is defined on the FF launcher - // but not the Chrome one. The types need tidying so that TS can infer that - // properly and not error here. - if (product === 'firefox') await puppeteer._launcher._updateRevision(); + if (product === 'firefox') { + // @ts-expect-error _updateRevision is defined on the FF launcher + // but not the Chrome one. The types need tidying so that TS can infer that + // properly and not error here. + await puppeteer._launcher._updateRevision(); + } const executablePath = puppeteer.executablePath(); - if (!fs.existsSync(executablePath)) + if (!fs.existsSync(executablePath)) { throw new Error( `Browser is not downloaded at ${executablePath}. Run 'npm install' and try to re-run tests` ); + } } })(); @@ -121,7 +124,9 @@ const setupGoldenAssertions = (): void => { const suffix = product.toLowerCase(); const GOLDEN_DIR = path.join(__dirname, 'golden-' + suffix); const OUTPUT_DIR = path.join(__dirname, 'output-' + suffix); - if (fs.existsSync(OUTPUT_DIR)) rimraf.sync(OUTPUT_DIR); + if (fs.existsSync(OUTPUT_DIR)) { + rimraf.sync(OUTPUT_DIR); + } utils.extendExpectWithToBeGolden(GOLDEN_DIR, OUTPUT_DIR); }; @@ -149,41 +154,55 @@ export const itFailsFirefox = ( description: string, body: Mocha.Func ): Mocha.Test => { - if (isFirefox) return xit(description, body); - else return it(description, body); + if (isFirefox) { + return xit(description, body); + } else { + return it(description, body); + } }; export const itChromeOnly = ( description: string, body: Mocha.Func ): Mocha.Test => { - if (isChrome) return it(description, body); - else return xit(description, body); + if (isChrome) { + return it(description, body); + } else { + return xit(description, body); + } }; export const itHeadlessOnly = ( description: string, body: Mocha.Func ): Mocha.Test => { - if (isChrome && isHeadless === true) return it(description, body); - else return xit(description, body); + if (isChrome && isHeadless === true) { + return it(description, body); + } else { + return xit(description, body); + } }; export const itFirefoxOnly = ( description: string, body: Mocha.Func ): Mocha.Test => { - if (isFirefox) return it(description, body); - else return xit(description, body); + if (isFirefox) { + return it(description, body); + } else { + return xit(description, body); + } }; export const itOnlyRegularInstall = ( description: string, body: Mocha.Func ): Mocha.Test => { - if (alternativeInstall || process.env['BINARY']) + if (alternativeInstall || process.env['BINARY']) { return xit(description, body); - else return it(description, body); + } else { + return it(description, body); + } }; export const itFailsWindowsUntilDate = ( @@ -213,15 +232,20 @@ export const describeFailsFirefox = ( description: string, body: (this: Mocha.Suite) => void ): void | Mocha.Suite => { - if (isFirefox) return xdescribe(description, body); - else return describe(description, body); + if (isFirefox) { + return xdescribe(description, body); + } else { + return describe(description, body); + } }; export const describeChromeOnly = ( description: string, body: (this: Mocha.Suite) => void ): Mocha.Suite | void => { - if (isChrome) return describe(description, body); + if (isChrome) { + return describe(description, body); + } }; console.log( diff --git a/test/mouse.spec.ts b/test/mouse.spec.ts index 33d00533..9cf880f9 100644 --- a/test/mouse.spec.ts +++ b/test/mouse.spec.ts @@ -161,20 +161,26 @@ describe('Mouse', function () { ['Meta', 'metaKey'], ]); // In Firefox, the Meta modifier only exists on Mac - if (isFirefox && os.platform() !== 'darwin') delete modifiers['Meta']; + if (isFirefox && os.platform() !== 'darwin') { + delete modifiers['Meta']; + } for (const [modifier, key] of modifiers) { await page.keyboard.down(modifier); await page.click('#button-3'); if ( !(await page.evaluate((mod: string) => globalThis.lastEvent[mod], key)) - ) + ) { throw new Error(key + ' should be true'); + } await page.keyboard.up(modifier); } await page.click('#button-3'); for (const [modifier, key] of modifiers) { - if (await page.evaluate((mod: string) => globalThis.lastEvent[mod], key)) + if ( + await page.evaluate((mod: string) => globalThis.lastEvent[mod], key) + ) { throw new Error(modifiers[modifier] + ' should be false'); + } } }); itFailsFirefox('should send mouse wheel events', async () => { diff --git a/test/navigation.spec.ts b/test/navigation.spec.ts index a7d0e36b..50a482c3 100644 --- a/test/navigation.spec.ts +++ b/test/navigation.spec.ts @@ -88,8 +88,11 @@ describe('navigation', function () { let error = null; await page.goto(server.EMPTY_PAGE).catch((error_) => (error = error_)); expect(error).not.toBe(null); - if (isChrome) expect(error.message).toContain('net::ERR_ABORTED'); - else expect(error.message).toContain('NS_BINDING_ABORTED'); + if (isChrome) { + expect(error.message).toContain('net::ERR_ABORTED'); + } else { + expect(error.message).toContain('NS_BINDING_ABORTED'); + } }); it('should navigate to empty page with domcontentloaded', async () => { const { page, server } = getTestState(); @@ -140,9 +143,11 @@ describe('navigation', function () { let error = null; await page.goto('asdfasdf').catch((error_) => (error = error_)); - if (isChrome) + if (isChrome) { expect(error.message).toContain('Cannot navigate to invalid URL'); - else expect(error.message).toContain('Invalid url'); + } else { + expect(error.message).toContain('Invalid url'); + } }); /* If you are running this on pre-Catalina versions of macOS this will fail locally. @@ -169,8 +174,11 @@ describe('navigation', function () { await page .goto(httpsServer.EMPTY_PAGE) .catch((error_) => (error = error_)); - if (isChrome) expect(error.message).toContain(EXPECTED_SSL_CERT_MESSAGE); - else expect(error.message).toContain('SSL_ERROR_UNKNOWN'); + if (isChrome) { + expect(error.message).toContain(EXPECTED_SSL_CERT_MESSAGE); + } else { + expect(error.message).toContain('SSL_ERROR_UNKNOWN'); + } expect(requests.length).toBe(2); expect(requests[0]).toBe('request'); @@ -185,8 +193,11 @@ describe('navigation', function () { await page .goto(httpsServer.PREFIX + '/redirect/1.html') .catch((error_) => (error = error_)); - if (isChrome) expect(error.message).toContain(EXPECTED_SSL_CERT_MESSAGE); - else expect(error.message).toContain('SSL_ERROR_UNKNOWN'); + if (isChrome) { + expect(error.message).toContain(EXPECTED_SSL_CERT_MESSAGE); + } else { + expect(error.message).toContain('SSL_ERROR_UNKNOWN'); + } }); it('should throw if networkidle is passed as an option', async () => { const { page, server } = getTestState(); @@ -207,9 +218,11 @@ describe('navigation', function () { await page .goto('http://localhost:44123/non-existing-url') .catch((error_) => (error = error_)); - if (isChrome) + if (isChrome) { expect(error.message).toContain('net::ERR_CONNECTION_REFUSED'); - else expect(error.message).toContain('NS_ERROR_CONNECTION_REFUSED'); + } else { + expect(error.message).toContain('NS_ERROR_CONNECTION_REFUSED'); + } }); it('should fail when exceeding maximum navigation timeout', async () => { const { page, server, puppeteer } = getTestState(); @@ -385,7 +398,9 @@ describe('navigation', function () { let warning = null; const warningHandler = (w) => (warning = w); process.on('warning', warningHandler); - for (let i = 0; i < 20; ++i) await page.goto(server.EMPTY_PAGE); + for (let i = 0; i < 20; ++i) { + await page.goto(server.EMPTY_PAGE); + } process.removeListener('warning', warningHandler); expect(warning).toBe(null); }); @@ -395,10 +410,11 @@ describe('navigation', function () { let warning = null; const warningHandler = (w) => (warning = w); process.on('warning', warningHandler); - for (let i = 0; i < 20; ++i) + for (let i = 0; i < 20; ++i) { await page.goto('asdf').catch(() => { /* swallow navigation error */ }); + } process.removeListener('warning', warningHandler); expect(warning).toBe(null); }); @@ -615,7 +631,9 @@ describe('navigation', function () { const frame = await utils.waitEvent(page, 'frameattached'); await new Promise((fulfill) => { page.on('framenavigated', (f) => { - if (f === frame) fulfill(); + if (f === frame) { + fulfill(); + } }); }); await Promise.all([ diff --git a/test/network.spec.ts b/test/network.spec.ts index f4d4b506..01db2768 100644 --- a/test/network.spec.ts +++ b/test/network.spec.ts @@ -255,7 +255,9 @@ describe('network', function () { server.setRoute('/post', (req, res) => res.end()); let request = null; page.on('request', (r) => { - if (!utils.isFavicon(r)) request = r; + if (!utils.isFavicon(r)) { + request = r; + } }); await page.evaluate(() => fetch('./post', { @@ -504,8 +506,11 @@ describe('network', function () { await page.setRequestInterception(true); page.on('request', (request) => { - if (request.url().endsWith('css')) request.abort(); - else request.continue(); + if (request.url().endsWith('css')) { + request.abort(); + } else { + request.continue(); + } }); const failedRequests = []; page.on('requestfailed', (request) => failedRequests.push(request)); @@ -514,10 +519,11 @@ describe('network', function () { expect(failedRequests[0].url()).toContain('one-style.css'); expect(failedRequests[0].response()).toBe(null); expect(failedRequests[0].resourceType()).toBe('stylesheet'); - if (isChrome) + if (isChrome) { expect(failedRequests[0].failure().errorText).toBe('net::ERR_FAILED'); - else + } else { expect(failedRequests[0].failure().errorText).toBe('NS_ERROR_FAILURE'); + } expect(failedRequests[0].frame()).toBeTruthy(); }); it('Page.Events.RequestFinished', async () => { diff --git a/test/page.spec.ts b/test/page.spec.ts index 6ba199ac..45001c45 100644 --- a/test/page.spec.ts +++ b/test/page.spec.ts @@ -67,8 +67,11 @@ describe('Page', function () { const dialog = await waitEvent(newPage, 'dialog'); expect(dialog.type()).toBe('beforeunload'); expect(dialog.defaultValue()).toBe(''); - if (isChrome) expect(dialog.message()).toBe(''); - else expect(dialog.message()).toBeTruthy(); + if (isChrome) { + expect(dialog.message()).toBe(''); + } else { + expect(dialog.message()).toBeTruthy(); + } await dialog.accept(); await pageClosingPromise; }); @@ -313,7 +316,9 @@ describe('Page', function () { const { page, server, context, isHeadless } = getTestState(); // TODO: re-enable this test in headful once crbug.com/1324480 rolls out. - if (!isHeadless) return; + if (!isHeadless) { + return; + } await page.goto(server.EMPTY_PAGE); await page.evaluate(() => { @@ -585,8 +590,11 @@ describe('Page', function () { ), ]); expect(message.text()).toContain('Access-Control-Allow-Origin'); - if (isChrome) expect(message.type()).toEqual('error'); - else expect(message.type()).toEqual('warn'); + if (isChrome) { + expect(message.type()).toEqual('error'); + } else { + expect(message.type()).toEqual('warn'); + } }); it('should have location when fetch fails', async () => { const { page, server } = getTestState(); @@ -1260,7 +1268,9 @@ describe('Page', function () { it('should work fast enough', async () => { const { page } = getTestState(); - for (let i = 0; i < 20; ++i) await page.setContent('
yo
'); + for (let i = 0; i < 20; ++i) { + await page.setContent('
yo
'); + } }); it('should work with tricky content', async () => { const { page } = getTestState(); @@ -1703,7 +1713,9 @@ describe('Page', function () { // Printing to pdf is currently only supported in headless const { isHeadless, page } = getTestState(); - if (!isHeadless) return; + if (!isHeadless) { + return; + } const outputFile = __dirname + '/assets/output.pdf'; await page.pdf({ path: outputFile }); @@ -1715,7 +1727,9 @@ describe('Page', function () { // Printing to pdf is currently only supported in headless const { isHeadless, page } = getTestState(); - if (!isHeadless) return; + if (!isHeadless) { + return; + } const stream = await page.createPDFStream(); let size = 0; @@ -1727,7 +1741,9 @@ describe('Page', function () { it('should respect timeout', async () => { const { isHeadless, page, server, puppeteer } = getTestState(); - if (!isHeadless) return; + if (!isHeadless) { + return; + } await page.goto(server.PREFIX + '/pdf.html'); diff --git a/test/requestinterception-experimental.spec.ts b/test/requestinterception-experimental.spec.ts index 70f87b36..ee941102 100644 --- a/test/requestinterception-experimental.spec.ts +++ b/test/requestinterception-experimental.spec.ts @@ -40,33 +40,42 @@ describe('request interception', function () { const actionResults: ActionResult[] = []; await page.setRequestInterception(true); page.on('request', (request) => { - if (request.url().endsWith('.css')) + if (request.url().endsWith('.css')) { request.continue( { headers: { ...request.headers(), xaction: 'continue' } }, expectedAction === 'continue' ? 1 : 0 ); - else request.continue({}, 0); + } else { + request.continue({}, 0); + } }); page.on('request', (request) => { - if (request.url().endsWith('.css')) + if (request.url().endsWith('.css')) { request.respond( { headers: { xaction: 'respond' } }, expectedAction === 'respond' ? 1 : 0 ); - else request.continue({}, 0); + } else { + request.continue({}, 0); + } }); page.on('request', (request) => { - if (request.url().endsWith('.css')) + if (request.url().endsWith('.css')) { request.abort('aborted', expectedAction === 'abort' ? 1 : 0); - else request.continue({}, 0); + } else { + request.continue({}, 0); + } }); page.on('response', (response) => { const { xaction } = response.headers(); - if (response.url().endsWith('.css') && !!xaction) + if (response.url().endsWith('.css') && !!xaction) { actionResults.push(xaction as ActionResult); + } }); page.on('requestfailed', (request) => { - if (request.url().endsWith('.css')) actionResults.push('abort'); + if (request.url().endsWith('.css')) { + actionResults.push('abort'); + } }); const response = await (async () => { @@ -172,7 +181,9 @@ describe('request interception', function () { await page.setRequestInterception(true); const requests = []; page.on('request', (request) => { - if (!utils.isFavicon(request)) requests.push(request); + if (!utils.isFavicon(request)) { + requests.push(request); + } request.continue({}, 0); }); await page.goto(server.PREFIX + '/one-style.html'); @@ -248,8 +259,11 @@ describe('request interception', function () { await page.setRequestInterception(true); page.on('request', (request) => { - if (request.url().endsWith('.css')) request.abort('failed', 0); - else request.continue({}, 0); + if (request.url().endsWith('.css')) { + request.abort('failed', 0); + } else { + request.continue({}, 0); + } }); let failedRequests = 0; page.on('requestfailed', () => ++failedRequests); @@ -310,8 +324,11 @@ describe('request interception', function () { let error = null; await page.goto(server.EMPTY_PAGE).catch((error_) => (error = error_)); expect(error).toBeTruthy(); - if (isChrome) expect(error.message).toContain('net::ERR_FAILED'); - else expect(error.message).toContain('NS_ERROR_FAILURE'); + if (isChrome) { + expect(error.message).toContain('net::ERR_FAILED'); + } else { + expect(error.message).toContain('NS_ERROR_FAILURE'); + } }); it('should work with redirects', async () => { const { page, server } = getTestState(); @@ -360,7 +377,9 @@ describe('request interception', function () { const requests = []; page.on('request', (request) => { request.continue({}, 0); - if (!utils.isFavicon(request)) requests.push(request); + if (!utils.isFavicon(request)) { + requests.push(request); + } }); server.setRedirect('/one-style.css', '/two-style.css'); server.setRedirect('/two-style.css', '/three-style.css'); @@ -388,9 +407,11 @@ describe('request interception', function () { server.setRedirect('/non-existing.json', '/non-existing-2.json'); server.setRedirect('/non-existing-2.json', '/simple.html'); page.on('request', (request) => { - if (request.url().includes('non-existing-2')) + if (request.url().includes('non-existing-2')) { request.abort('failed', 0); - else request.continue({}, 0); + } else { + request.continue({}, 0); + } }); await page.goto(server.EMPTY_PAGE); const result = await page.evaluate(async () => { @@ -400,8 +421,11 @@ describe('request interception', function () { return error.message; } }); - if (isChrome) expect(result).toContain('Failed to fetch'); - else expect(result).toContain('NetworkError'); + if (isChrome) { + expect(result).toContain('Failed to fetch'); + } else { + expect(result).toContain('NetworkError'); + } }); it('should work with equal requests', async () => { const { page, server } = getTestState(); @@ -868,6 +892,8 @@ describe('request interception', function () { function pathToFileURL(path: string): string { let pathName = path.replace(/\\/g, '/'); // Windows drive letter must be prefixed with a slash. - if (!pathName.startsWith('/')) pathName = '/' + pathName; + if (!pathName.startsWith('/')) { + pathName = '/' + pathName; + } return 'file://' + pathName; } diff --git a/test/requestinterception.spec.ts b/test/requestinterception.spec.ts index 450937a2..2bd7660f 100644 --- a/test/requestinterception.spec.ts +++ b/test/requestinterception.spec.ts @@ -111,7 +111,9 @@ describe('request interception', function () { await page.setRequestInterception(true); const requests = []; page.on('request', (request) => { - if (!utils.isFavicon(request)) requests.push(request); + if (!utils.isFavicon(request)) { + requests.push(request); + } request.continue(); }); await page.goto(server.PREFIX + '/one-style.html'); @@ -187,8 +189,11 @@ describe('request interception', function () { await page.setRequestInterception(true); page.on('request', (request) => { - if (request.url().endsWith('.css')) request.abort(); - else request.continue(); + if (request.url().endsWith('.css')) { + request.abort(); + } else { + request.continue(); + } }); let failedRequests = 0; page.on('requestfailed', () => ++failedRequests); @@ -234,8 +239,11 @@ describe('request interception', function () { let error = null; await page.goto(server.EMPTY_PAGE).catch((error_) => (error = error_)); expect(error).toBeTruthy(); - if (isChrome) expect(error.message).toContain('net::ERR_FAILED'); - else expect(error.message).toContain('NS_ERROR_FAILURE'); + if (isChrome) { + expect(error.message).toContain('net::ERR_FAILED'); + } else { + expect(error.message).toContain('NS_ERROR_FAILURE'); + } }); it('should work with redirects', async () => { const { page, server } = getTestState(); @@ -284,7 +292,9 @@ describe('request interception', function () { const requests = []; page.on('request', (request) => { request.continue(); - if (!utils.isFavicon(request)) requests.push(request); + if (!utils.isFavicon(request)) { + requests.push(request); + } }); server.setRedirect('/one-style.css', '/two-style.css'); server.setRedirect('/two-style.css', '/three-style.css'); @@ -312,8 +322,11 @@ describe('request interception', function () { server.setRedirect('/non-existing.json', '/non-existing-2.json'); server.setRedirect('/non-existing-2.json', '/simple.html'); page.on('request', (request) => { - if (request.url().includes('non-existing-2')) request.abort(); - else request.continue(); + if (request.url().includes('non-existing-2')) { + request.abort(); + } else { + request.continue(); + } }); await page.goto(server.EMPTY_PAGE); const result = await page.evaluate(async () => { @@ -323,8 +336,11 @@ describe('request interception', function () { return error.message; } }); - if (isChrome) expect(result).toContain('Failed to fetch'); - else expect(result).toContain('NetworkError'); + if (isChrome) { + expect(result).toContain('Failed to fetch'); + } else { + expect(result).toContain('NetworkError'); + } }); it('should work with equal requests', async () => { const { page, server } = getTestState(); @@ -809,6 +825,8 @@ describe('request interception', function () { function pathToFileURL(path: string): string { let pathName = path.replace(/\\/g, '/'); // Windows drive letter must be prefixed with a slash. - if (!pathName.startsWith('/')) pathName = '/' + pathName; + if (!pathName.startsWith('/')) { + pathName = '/' + pathName; + } return 'file://' + pathName; } diff --git a/test/screenshot.spec.ts b/test/screenshot.spec.ts index f2a6adc6..42ffad74 100644 --- a/test/screenshot.spec.ts +++ b/test/screenshot.spec.ts @@ -112,15 +112,17 @@ describe('Screenshots', function () { }) ); 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 }, }) ); + } 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`); + } await Promise.all(pages.map((page) => page.close())); }); itFailsFirefox('should allow transparency', async () => { diff --git a/test/target.spec.ts b/test/target.spec.ts index ba2fd86b..c35bbddf 100644 --- a/test/target.spec.ts +++ b/test/target.spec.ts @@ -288,7 +288,9 @@ describe('Target', function () { resolved = true; if (error instanceof puppeteer.errors.TimeoutError) { console.error(error); - } else throw error; + } else { + throw error; + } }); const page = await browser.newPage(); expect(resolved).toBe(false); @@ -299,7 +301,9 @@ describe('Target', function () { } catch (error) { if (error instanceof puppeteer.errors.TimeoutError) { console.error(error); - } else throw error; + } else { + throw error; + } } await page.close(); }); diff --git a/test/utils.js b/test/utils.js index f70cb47e..63f1c2d7 100644 --- a/test/utils.js +++ b/test/utils.js @@ -111,10 +111,13 @@ const utils = (module.exports = { dumpFrames: function (frame, indentation) { indentation = indentation || ''; let description = frame.url().replace(/:\d{4}\//, ':/'); - if (frame.name()) description += ' (' + frame.name() + ')'; + if (frame.name()) { + description += ' (' + frame.name() + ')'; + } const result = [indentation + description]; - for (const child of frame.childFrames()) + for (const child of frame.childFrames()) { result.push(...utils.dumpFrames(child, ' ' + indentation)); + } return result; }, @@ -126,7 +129,9 @@ const utils = (module.exports = { waitEvent: function (emitter, eventName, predicate = () => true) { return new Promise((fulfill) => { emitter.on(eventName, function listener(event) { - if (!predicate(event)) return; + if (!predicate(event)) { + return; + } emitter.removeListener(eventName, listener); fulfill(event); }); diff --git a/test/waittask.spec.ts b/test/waittask.spec.ts index 7b7f409e..641e06d4 100644 --- a/test/waittask.spec.ts +++ b/test/waittask.spec.ts @@ -146,7 +146,9 @@ describe('waittask specs', function () { await page.evaluateOnNewDocument(() => (globalThis.__RELOADED = true)); await page.waitForFunction(() => { - if (!globalThis.__RELOADED) window.location.reload(); + if (!globalThis.__RELOADED) { + window.location.reload(); + } return true; }); }); diff --git a/typescript-if-required.js b/typescript-if-required.js index 5e11f7b6..7c721a9a 100644 --- a/typescript-if-required.js +++ b/typescript-if-required.js @@ -49,13 +49,17 @@ async function compileTypeScript() { async function compileTypeScriptIfRequired() { const libPath = path.join(__dirname, 'lib'); const libExists = await fileExists(libPath); - if (libExists) return; + if (libExists) { + return; + } console.log('Puppeteer:', 'Compiling TypeScript...'); await compileTypeScript(); } // It's being run as node typescript-if-required.js, not require('..') -if (require.main === module) compileTypeScriptIfRequired(); +if (require.main === module) { + compileTypeScriptIfRequired(); +} module.exports = compileTypeScriptIfRequired; diff --git a/utils/ESTreeWalker.js b/utils/ESTreeWalker.js index 1c6c6d47..870cbbc6 100644 --- a/utils/ESTreeWalker.js +++ b/utils/ESTreeWalker.js @@ -27,7 +27,9 @@ class ESTreeWalker { * @param {?ESTree.Node} parent */ _innerWalk(node, parent) { - if (!node) return; + if (!node) { + return; + } node.parent = parent; if (this._beforeVisit.call(null, node) === ESTreeWalker.SkipSubtree) { @@ -36,7 +38,9 @@ class ESTreeWalker { } const walkOrder = ESTreeWalker._walkOrder[node.type]; - if (!walkOrder) return; + if (!walkOrder) { + return; + } if (node.type === 'TemplateLiteral') { const templateLiteral = /** @type {!ESTree.TemplateLiteralNode} */ (node); @@ -52,8 +56,11 @@ class ESTreeWalker { } else { for (let i = 0; i < walkOrder.length; ++i) { const entity = node[walkOrder[i]]; - if (Array.isArray(entity)) this._walkArray(entity, node); - else this._innerWalk(entity, node); + if (Array.isArray(entity)) { + this._walkArray(entity, node); + } else { + this._innerWalk(entity, node); + } } } @@ -65,8 +72,9 @@ class ESTreeWalker { * @param {?ESTree.Node} parentNode */ _walkArray(nodeArray, parentNode) { - for (let i = 0; i < nodeArray.length; ++i) + for (let i = 0; i < nodeArray.length; ++i) { this._innerWalk(nodeArray[i], parentNode); + } } } diff --git a/utils/bisect.js b/utils/bisect.js index 3951879d..913548fa 100755 --- a/utils/bisect.js +++ b/utils/bisect.js @@ -111,14 +111,18 @@ if (argv.script && !fs.existsSync(scriptPath)) { while (true) { const middle = Math.round((good + bad) / 2); const revision = await findDownloadableRevision(middle, good, bad); - if (!revision || revision === good || revision === bad) break; + if (!revision || revision === good || revision === bad) { + break; + } let info = browserFetcher.revisionInfo(revision); const shouldRemove = noCache && !info.local; info = await downloadRevision(revision); const exitCode = await (pattern ? runUnitTest(pattern, info) : runScript(scriptPath, info)); - if (shouldRemove) await browserFetcher.remove(revision); + if (shouldRemove) { + await browserFetcher.remove(revision); + } let outcome; if (exitCode) { bad = revision; @@ -224,7 +228,9 @@ async function findDownloadableRevision(rev, from, to) { const min = Math.min(from, to); const max = Math.max(from, to); log(`Looking around ${rev} from [${min}, ${max}]`); - if (await browserFetcher.canDownload(rev)) return rev; + if (await browserFetcher.canDownload(rev)) { + return rev; + } let down = rev; let up = rev; while (min <= down || up <= max) { @@ -232,8 +238,12 @@ async function findDownloadableRevision(rev, from, to) { down > min ? probe(--down) : Promise.resolve(false), up < max ? probe(++up) : Promise.resolve(false), ]); - if (downOk) return down; - if (upOk) return up; + if (downOk) { + return down; + } + if (upOk) { + return up; + } } return null; @@ -283,6 +293,8 @@ function getChromiumRevision(gitRevision = null) { }); const m = result.match(/chromium: '(\d+)'/); - if (!m) return null; + if (!m) { + return null; + } return parseInt(m[1], 10); } diff --git a/utils/check_availability.js b/utils/check_availability.js index 79128efa..1bb9b6a7 100755 --- a/utils/check_availability.js +++ b/utils/check_availability.js @@ -43,8 +43,9 @@ class Table { drawRow(values) { assert(values.length === this.widths.length); let row = ''; - for (let i = 0; i < values.length; ++i) + for (let i = 0; i < values.length; ++i) { row += padCenter(values[i], this.widths[i]); + } console.log(row); } } @@ -262,9 +263,13 @@ async function checkRangeAvailability({ } table.drawRow(values); } else { - if (allAvailable) console.log(revision); + if (allAvailable) { + console.log(revision); + } + } + if (allAvailable && stopWhenAllAvailable) { + break; } - if (allAvailable && stopWhenAllAvailable) break; } } @@ -328,7 +333,9 @@ function filterOutColors(text) { */ function padCenter(text, length) { const printableCharacters = filterOutColors(text); - if (printableCharacters.length >= length) return text; + if (printableCharacters.length >= length) { + return text; + } const left = Math.floor((length - printableCharacters.length) / 2); const right = Math.ceil((length - printableCharacters.length) / 2); return spaceString(left) + text + spaceString(right); diff --git a/utils/doclint/Source.js b/utils/doclint/Source.js index 0f7c1323..8fe03285 100644 --- a/utils/doclint/Source.js +++ b/utils/doclint/Source.js @@ -63,7 +63,9 @@ class Source { * @returns {boolean} */ setText(text) { - if (text === this._text) return false; + if (text === this._text) { + return false; + } this._hasUpdatedText = true; this._text = text; return true; diff --git a/utils/doclint/check_public_api/Documentation.js b/utils/doclint/check_public_api/Documentation.js index 9bbaabfc..c1a923ce 100644 --- a/utils/doclint/check_public_api/Documentation.js +++ b/utils/doclint/check_public_api/Documentation.js @@ -22,7 +22,9 @@ class Documentation { this.classesArray = classesArray; /** @type {!Map} */ this.classes = new Map(); - for (const cls of classesArray) this.classes.set(cls.name, cls); + for (const cls of classesArray) { + this.classes.set(cls.name, cls); + } } } @@ -93,7 +95,9 @@ Documentation.Member = class { this.required = required; /** @type {!Map} */ this.args = new Map(); - for (const arg of argsArray) this.args.set(arg.name, arg); + for (const arg of argsArray) { + this.args.set(arg.name, arg); + } } /** diff --git a/utils/doclint/check_public_api/JSBuilder.js b/utils/doclint/check_public_api/JSBuilder.js index ebb00209..60175c40 100644 --- a/utils/doclint/check_public_api/JSBuilder.js +++ b/utils/doclint/check_public_api/JSBuilder.js @@ -12,13 +12,14 @@ function checkSources(sources) { const eventsSource = sources.find((source) => source.name() === 'Events.js'); if (eventsSource) { const { Events } = require(eventsSource.filePath()); - for (const [className, events] of Object.entries(Events)) + for (const [className, events] of Object.entries(Events)) { classEvents.set( className, Array.from(Object.values(events)) .filter((e) => typeof e === 'string') .map((e) => Documentation.Member.createEvent(e)) ); + } } const excludeClasses = new Set([]); @@ -78,7 +79,9 @@ function checkSources(sources) { for (const member of wp.membersArray) { // Member was overridden. const memberId = member.kind + ':' + member.name; - if (membersMap.has(memberId)) continue; + if (membersMap.has(memberId)) { + continue; + } membersMap.set(memberId, member); } } @@ -98,13 +101,17 @@ function checkSources(sources) { if (className === '__class') { let parent = node; - while (parent.parent) parent = parent.parent; + while (parent.parent) { + parent = parent.parent; + } className = path.basename(parent.fileName, '.js'); } if (className && !excludeClasses.has(className)) { classes.push(serializeClass(className, symbol, node)); const parentClassName = parentClass(node); - if (parentClassName) inheritance.set(className, parentClassName); + if (parentClassName) { + inheritance.set(className, parentClassName); + } excludeClasses.add(className); } } @@ -139,7 +146,9 @@ function checkSources(sources) { * isn't going to be here for much longer so we'll just silence this * warning than try to add support which would warrant a huge rewrite. */ - if (name !== 'paramArgs') throw error; + if (name !== 'paramArgs') { + throw error; + } } } return Documentation.Member.createProperty( @@ -152,13 +161,27 @@ function checkSources(sources) { * @param {!ts.ObjectType} type */ function isRegularObject(type) { - if (type.isIntersection()) return true; - if (!type.objectFlags) return false; - if (!('aliasSymbol' in type)) return false; - if (type.getConstructSignatures().length) return false; - if (type.getCallSignatures().length) return false; - if (type.isLiteral()) return false; - if (type.isUnion()) return false; + if (type.isIntersection()) { + return true; + } + if (!type.objectFlags) { + return false; + } + if (!('aliasSymbol' in type)) { + return false; + } + if (type.getConstructSignatures().length) { + return false; + } + if (type.getCallSignatures().length) { + return false; + } + if (type.isLiteral()) { + return false; + } + if (type.isUnion()) { + return false; + } return true; } @@ -173,16 +196,18 @@ function checkSources(sources) { typeName === 'any' || typeName === '{ [x: string]: string; }' || typeName === '{}' - ) + ) { typeName = 'Object'; + } const nextCircular = [typeName].concat(circular); if (isRegularObject(type)) { let properties = undefined; - if (!circular.includes(typeName)) + if (!circular.includes(typeName)) { properties = type .getProperties() .map((property) => serializeSymbol(property, nextCircular)); + } return new Documentation.Type('Object', properties); } if (type.isUnion() && typeName.includes('|')) { @@ -199,14 +224,17 @@ function checkSources(sources) { const innerTypeNames = []; for (const typeArgument of type.typeArguments) { const innerType = serializeType(typeArgument, nextCircular); - if (innerType.properties) properties.push(...innerType.properties); + if (innerType.properties) { + properties.push(...innerType.properties); + } innerTypeNames.push(innerType.name); } if ( innerTypeNames.length === 0 || (innerTypeNames.length === 1 && innerTypeNames[0] === 'void') - ) + ) { return new Documentation.Type(type.symbol.name); + } return new Documentation.Type( `${type.symbol.name}<${innerTypeNames.join(', ')}>`, properties @@ -241,15 +269,20 @@ function checkSources(sources) { * but in TypeScript we use the private keyword * hence we check for either here. */ - if (name.startsWith('_') || symbolHasPrivateModifier(member)) continue; + if (name.startsWith('_') || symbolHasPrivateModifier(member)) { + continue; + } const memberType = checker.getTypeOfSymbolAtLocation( member, member.valueDeclaration ); const signature = memberType.getCallSignatures()[0]; - if (signature) members.push(serializeSignature(name, signature)); - else members.push(serializeProperty(name, memberType)); + if (signature) { + members.push(serializeSignature(name, signature)); + } else { + members.push(serializeProperty(name, memberType)); + } } return new Documentation.Class(className, members); diff --git a/utils/doclint/check_public_api/MDBuilder.js b/utils/doclint/check_public_api/MDBuilder.js index 3776489f..3281dd7e 100644 --- a/utils/doclint/check_public_api/MDBuilder.js +++ b/utils/doclint/check_public_api/MDBuilder.js @@ -92,9 +92,15 @@ class MDOutline { const start = str.indexOf('<') + 1; let count = 1; for (let i = start; i < str.length; i++) { - if (str[i] === '<') count++; - if (str[i] === '>') count--; - if (!count) return str.substring(start, i); + if (str[i] === '<') { + count++; + } + if (str[i] === '>') { + count--; + } + if (!count) { + return str.substring(start, i); + } } return 'unknown'; } @@ -138,7 +144,7 @@ class MDOutline { * @param {Node} content */ function parseComment(content) { - for (const code of content.querySelectorAll('pre > code')) + for (const code of content.querySelectorAll('pre > code')) { code.replaceWith( '```' + code.className.substring('language-'.length) + @@ -146,10 +152,13 @@ class MDOutline { code.textContent + '```' ); - for (const code of content.querySelectorAll('code')) + } + for (const code of content.querySelectorAll('code')) { code.replaceWith('`' + code.textContent + '`'); - for (const strong of content.querySelectorAll('strong')) + } + for (const strong of content.querySelectorAll('strong')) { strong.replaceWith('**' + parseComment(strong) + '**'); + } return content.textContent.trim(); } @@ -207,10 +216,11 @@ class MDOutline { 0, Math.min(angleIndex, spaceIndex) ); - if (actualText !== expectedText) + if (actualText !== expectedText) { errors.push( `${name} has mistyped 'return' type declaration: expected exactly '${expectedText}', found '${actualText}'.` ); + } } } const comment = parseComment( @@ -257,7 +267,9 @@ class MDOutline { let currentClassExtends = null; for (const cls of classes) { const match = cls.name.match(classHeading); - if (!match) continue; + if (!match) { + continue; + } currentClassName = match[1]; currentClassComment = cls.comment; currentClassExtends = cls.extendsName; @@ -290,7 +302,7 @@ class MDOutline { return; } parameters = parameters.trim().replace(/[\[\]]/g, ''); - if (parameters !== member.args.map((arg) => arg.name).join(', ')) + if (parameters !== member.args.map((arg) => arg.name).join(', ')) { this.errors.push( `Heading arguments for "${ member.name @@ -298,6 +310,7 @@ class MDOutline { .map((a) => a.name) .join(', ')}"` ); + } const args = member.args.map(createPropertyFromJSON); let returnType = null; let returnComment = ''; @@ -369,7 +382,9 @@ class MDOutline { } function flushClassIfNeeded() { - if (currentClassName === null) return; + if (currentClassName === null) { + return; + } this.classes.push( new Documentation.Class( currentClassName, diff --git a/utils/doclint/check_public_api/index.js b/utils/doclint/check_public_api/index.js index 741f8319..29fd9b58 100644 --- a/utils/doclint/check_public_api/index.js +++ b/utils/doclint/check_public_api/index.js @@ -78,46 +78,62 @@ function checkSorting(doc) { ; eventIndex < members.length && members[eventIndex].kind === 'event'; ++eventIndex - ); + ) {} for ( ; eventIndex < members.length && members[eventIndex].kind !== 'event'; ++eventIndex - ); - if (eventIndex < members.length) + ) {} + if (eventIndex < members.length) { 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. const constructorIndex = members.findIndex( (member) => member.kind === 'method' && member.name === 'constructor' ); - if (constructorIndex > 0 && members[constructorIndex - 1].kind !== 'event') + if ( + constructorIndex > 0 && + members[constructorIndex - 1].kind !== 'event' + ) { errors.push(`Constructor of ${cls.name} should go before other methods`); + } // Events should be sorted alphabetically. for (let i = 0; i < members.length - 1; ++i) { const member1 = cls.membersArray[i]; const member2 = cls.membersArray[i + 1]; - if (member1.kind !== 'event' || member2.kind !== 'event') continue; - if (member1.name > member2.name) + if (member1.kind !== 'event' || member2.kind !== 'event') { + continue; + } + if (member1.name > member2.name) { errors.push( `Event '${member1.name}' in class ${cls.name} breaks alphabetic ordering of events` ); + } } // All other members should be sorted alphabetically. for (let i = 0; i < members.length - 1; ++i) { const member1 = cls.membersArray[i]; const member2 = cls.membersArray[i + 1]; - if (member1.kind === 'event' || member2.kind === 'event') continue; - if (member1.kind === 'method' && member1.name === 'constructor') continue; + if (member1.kind === 'event' || member2.kind === 'event') { + continue; + } + if (member1.kind === 'method' && member1.name === 'constructor') { + continue; + } if (member1.name > member2.name) { let memberName1 = `${cls.name}.${member1.name}`; - if (member1.kind === 'method') memberName1 += '()'; + if (member1.kind === 'method') { + memberName1 += '()'; + } let memberName2 = `${cls.name}.${member2.name}`; - if (member2.kind === 'method') memberName2 += '()'; + if (member2.kind === 'method') { + memberName2 += '()'; + } errors.push( `Bad alphabetic ordering of ${cls.name} members: ${memberName1} should go after ${memberName2}` ); @@ -136,7 +152,9 @@ function filterJSDocumentation(jsDocumentation) { // Filter private classes and methods. const classes = []; for (const cls of jsDocumentation.classesArray) { - if (includedClasses && !includedClasses.has(cls.name)) continue; + if (includedClasses && !includedClasses.has(cls.name)) { + continue; + } const members = cls.membersArray.filter( (member) => !EXCLUDE_PROPERTIES.has(`${cls.name}.${member.name}`) ); @@ -154,22 +172,25 @@ function checkDuplicates(doc) { const classes = new Set(); // Report duplicates. for (const cls of doc.classesArray) { - if (classes.has(cls.name)) + if (classes.has(cls.name)) { errors.push(`Duplicate declaration of class ${cls.name}`); + } classes.add(cls.name); const members = new Set(); for (const member of cls.membersArray) { - if (members.has(member.kind + ' ' + member.name)) + if (members.has(member.kind + ' ' + member.name)) { errors.push( `Duplicate declaration of ${member.kind} ${cls.name}.${member.name}()` ); + } members.add(member.kind + ' ' + member.name); const args = new Set(); 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}"` ); + } args.add(arg.name); } } @@ -220,8 +241,9 @@ function compareDocumentations(actual, expected) { 'launch', ]); - for (const className of classesDiff.extra) + for (const className of classesDiff.extra) { errors.push(`Non-existing class found: ${className}`); + } for (const className of classesDiff.missing) { if (className === 'PuppeteerNode') { @@ -249,8 +271,9 @@ function compareDocumentations(actual, expected) { for (const methodName of methodDiff.missing) { const missingMethodsForClass = expectedNotFoundMethods.get(className); - if (missingMethodsForClass && missingMethodsForClass.has(methodName)) + if (missingMethodsForClass && missingMethodsForClass.has(methodName)) { continue; + } errors.push(`Method not found: ${className}.${methodName}()`); } @@ -258,14 +281,15 @@ function compareDocumentations(actual, expected) { const actualMethod = actualClass.methods.get(methodName); const expectedMethod = expectedClass.methods.get(methodName); if (!actualMethod.type !== !expectedMethod.type) { - if (actualMethod.type) + if (actualMethod.type) { errors.push( `Method ${className}.${methodName} has unneeded description of return type` ); - else + } else { errors.push( `Method ${className}.${methodName} is missing return type description` ); + } } else if (actualMethod.hasReturn) { checkType( `Method ${className}.${methodName} has the wrong return type: `, @@ -287,20 +311,23 @@ function compareDocumentations(actual, expected) { const text = [ `Method ${className}.${methodName}() fails to describe its parameters:`, ]; - for (const arg of argsDiff.missing) + for (const arg of argsDiff.missing) { text.push(`- Argument not found: ${arg}`); - for (const arg of argsDiff.extra) + } + for (const arg of argsDiff.extra) { text.push(`- Non-existing argument found: ${arg}`); + } errors.push(text.join('\n')); } } - for (const arg of argsDiff.equal) + for (const arg of argsDiff.equal) { checkProperty( `Method ${className}.${methodName}()`, actualMethod.args.get(arg), expectedMethod.args.get(arg) ); + } } const actualProperties = Array.from(actualClass.properties.keys()).sort(); const expectedProperties = Array.from( @@ -313,18 +340,21 @@ function compareDocumentations(actual, expected) { } errors.push(`Non-existing property found: ${className}.${propertyName}`); } - for (const propertyName of propertyDiff.missing) + for (const propertyName of propertyDiff.missing) { errors.push(`Property not found: ${className}.${propertyName}`); + } const actualEvents = Array.from(actualClass.events.keys()).sort(); const expectedEvents = Array.from(expectedClass.events.keys()).sort(); const eventsDiff = diff(actualEvents, expectedEvents); - for (const eventName of eventsDiff.extra) + for (const eventName of eventsDiff.extra) { errors.push( `Non-existing event found in class ${className}: '${eventName}'` ); - for (const eventName of eventsDiff.missing) + } + for (const eventName of eventsDiff.missing) { errors.push(`Event not found in class ${className}: '${eventName}'`); + } } /** @@ -1052,7 +1082,9 @@ function compareDocumentations(actual, expected) { ]); const expectedForSource = expectedNamingMismatches.get(source); - if (!expectedForSource) return false; + if (!expectedForSource) { + return false; + } const namingMismatchIsExpected = expectedForSource.actualName === actualName && @@ -1068,8 +1100,12 @@ function compareDocumentations(actual, expected) { */ function checkType(source, actual, expected) { // TODO(@JoelEinbinder): check functions and Serializable - if (actual.name.includes('unction') || actual.name.includes('Serializable')) + if ( + actual.name.includes('unction') || + actual.name.includes('Serializable') + ) { return; + } // We don't have nullchecks on for TypeScript const actualName = actual.name.replace(/[\? ]/g, ''); // TypeScript likes to add some spaces @@ -1079,13 +1115,16 @@ function compareDocumentations(actual, expected) { actualName, expectedName ); - if (expectedName !== actualName && !namingMismatchIsExpected) + if (expectedName !== actualName && !namingMismatchIsExpected) { errors.push(`${source} ${actualName} != ${expectedName}`); + } /* If we got a naming mismatch and it was expected, don't check the properties * as they will likely be considered "wrong" by DocLint too. */ - if (namingMismatchIsExpected) return; + if (namingMismatchIsExpected) { + return; + } /* Some methods cause errors in the property checks for an unknown reason * so we support a list of methods whose parameters are not checked. @@ -1096,7 +1135,9 @@ function compareDocumentations(actual, expected) { 'Method Puppeteer.connect() options', 'Method Page.setUserAgent() userAgentMetadata', ]); - if (skipPropertyChecksOnMethods.has(source)) return; + if (skipPropertyChecksOnMethods.has(source)) { + return; + } const actualPropertiesMap = new Map( actual.properties.map((property) => [property.name, property.type]) @@ -1108,16 +1149,19 @@ function compareDocumentations(actual, expected) { Array.from(actualPropertiesMap.keys()).sort(), Array.from(expectedPropertiesMap.keys()).sort() ); - for (const propertyName of propertiesDiff.extra) + for (const propertyName of propertiesDiff.extra) { errors.push(`${source} has unexpected property ${propertyName}`); - for (const propertyName of propertiesDiff.missing) + } + for (const propertyName of propertiesDiff.missing) { errors.push(`${source} is missing property ${propertyName}`); - for (const propertyName of propertiesDiff.equal) + } + for (const propertyName of propertiesDiff.equal) { checkType( source + '.' + propertyName, actualPropertiesMap.get(propertyName), expectedPropertiesMap.get(propertyName) ); + } } return errors; @@ -1131,9 +1175,15 @@ function compareDocumentations(actual, expected) { function diff(actual, expected) { const N = actual.length; const M = expected.length; - if (N === 0 && M === 0) return { extra: [], missing: [], equal: [] }; - if (N === 0) return { extra: [], missing: expected.slice(), equal: [] }; - if (M === 0) return { extra: actual.slice(), missing: [], equal: [] }; + if (N === 0 && M === 0) { + return { extra: [], missing: [], equal: [] }; + } + if (N === 0) { + return { extra: [], missing: expected.slice(), equal: [] }; + } + if (M === 0) { + return { extra: actual.slice(), missing: [], equal: [] }; + } const d = new Array(N); const bt = new Array(N); for (let i = 0; i < N; ++i) { @@ -1179,8 +1229,12 @@ function diff(actual, expected) { break; } } - while (i >= 0) extra.push(actual[i--]); - while (j >= 0) missing.push(expected[j--]); + while (i >= 0) { + extra.push(actual[i--]); + } + while (j >= 0) { + missing.push(expected[j--]); + } extra.reverse(); missing.reverse(); equal.reverse(); diff --git a/utils/doclint/cli.js b/utils/doclint/cli.js index a82159a8..42ad08c0 100755 --- a/utils/doclint/cli.js +++ b/utils/doclint/cli.js @@ -105,7 +105,9 @@ async function run() { await browser.close(); for (const source of mdSources) { - if (!source.hasUpdatedText()) continue; + if (!source.hasUpdatedText()) { + continue; + } await source.save(); changedFiles = true; } diff --git a/utils/doclint/preprocessor/index.js b/utils/doclint/preprocessor/index.js index f5798653..19486ad0 100644 --- a/utils/doclint/preprocessor/index.js +++ b/utils/doclint/preprocessor/index.js @@ -32,8 +32,9 @@ module.exports.ensureReleasedAPILinks = function ( for (const source of sources) { const text = source.text(); const newText = text.replace(apiLinkRegex, lastReleasedAPI); - if (source.setText(newText)) + if (source.setText(newText)) { messages.push(Message.info(`GEN: updated ${source.projectPath()}`)); + } } return messages; }; @@ -121,7 +122,9 @@ function generateTableOfContents(mdText) { insideCodeBlock = !insideCodeBlock; continue; } - if (!insideCodeBlock && line.startsWith('#')) titles.push(line); + if (!insideCodeBlock && line.startsWith('#')) { + titles.push(line); + } } const tocEntries = []; for (const title of titles) { @@ -134,7 +137,9 @@ function generateTableOfContents(mdText) { .replace(/[^-0-9a-zа-яё]/gi, ''); let dedupId = id; let counter = 0; - while (ids.has(dedupId)) dedupId = id + '-' + ++counter; + while (ids.has(dedupId)) { + dedupId = id + '-' + ++counter; + } ids.add(dedupId); tocEntries.push({ level: nesting.length, @@ -162,7 +167,9 @@ const generateVersionsPerRelease = () => { const { versionsPerRelease } = require('../../../versions.js'); const buffer = ['- Releases per Chromium version:']; for (const [chromiumVersion, puppeteerVersion] of versionsPerRelease) { - if (puppeteerVersion === 'NEXT') continue; + if (puppeteerVersion === 'NEXT') { + continue; + } buffer.push( ` * Chromium ${chromiumVersion} - [Puppeteer ${puppeteerVersion}](https://github.com/puppeteer/puppeteer/blob/${puppeteerVersion}/docs/api.md)` ); diff --git a/utils/fetch_devices.js b/utils/fetch_devices.js index 4d255b5d..5a9584aa 100755 --- a/utils/fetch_devices.js +++ b/utils/fetch_devices.js @@ -91,12 +91,15 @@ async function main(url) { let devices = []; for (const payload of devicePayloads) { let names = []; - if (payload.title === 'iPhone 6/7/8') + if (payload.title === 'iPhone 6/7/8') { names = ['iPhone 6', 'iPhone 7', 'iPhone 8']; - else if (payload.title === 'iPhone 6/7/8 Plus') + } else if (payload.title === 'iPhone 6/7/8 Plus') { names = ['iPhone 6 Plus', 'iPhone 7 Plus', 'iPhone 8 Plus']; - else if (payload.title === 'iPhone 5/SE') names = ['iPhone 5', 'iPhone SE']; - else names = [payload.title]; + } else if (payload.title === 'iPhone 5/SE') { + names = ['iPhone 5', 'iPhone SE']; + } else { + names = [payload.title]; + } for (const name of names) { const device = createDevice(chromeVersion, name, payload, false); const landscape = createDevice(chromeVersion, name, payload, true); @@ -104,8 +107,9 @@ async function main(url) { if ( landscape.viewport.width !== device.viewport.width || landscape.viewport.height !== device.viewport.height - ) + ) { devices.push(landscape); + } } } devices = devices.filter((device) => device.viewport.isMobile); @@ -164,13 +168,15 @@ function loadFromJSONV1(json) { object === null || !object.hasOwnProperty(key) ) { - if (typeof defaultValue !== 'undefined') return defaultValue; + if (typeof defaultValue !== 'undefined') { + return defaultValue; + } throw new Error( "Emulated device is missing required property '" + key + "'" ); } const value = object[key]; - if (typeof value !== type || value === null) + if (typeof value !== type || value === null) { throw new Error( "Emulated device property '" + key + @@ -178,6 +184,7 @@ function loadFromJSONV1(json) { typeof value + "'" ); + } return value; } @@ -188,8 +195,9 @@ function loadFromJSONV1(json) { */ function parseIntValue(object, key) { const value = /** @type {number} */ (parseValue(object, key, 'number')); - if (value !== Math.abs(value)) + if (value !== Math.abs(value)) { throw new Error("Emulated device value '" + key + "' must be integer"); + } return value; } @@ -206,16 +214,18 @@ function loadFromJSONV1(json) { result.width < 0 || result.width > maxDeviceSize || result.width < minDeviceSize - ) + ) { throw new Error('Emulated device has wrong width: ' + result.width); + } result.height = parseIntValue(json, 'height'); if ( result.height < 0 || result.height > maxDeviceSize || result.height < minDeviceSize - ) + ) { throw new Error('Emulated device has wrong height: ' + result.height); + } return /** @type {!{width: number, height: number}} */ (result); } @@ -227,22 +237,25 @@ function loadFromJSONV1(json) { ); const capabilities = parseValue(json, 'capabilities', 'object', []); - if (!Array.isArray(capabilities)) + if (!Array.isArray(capabilities)) { throw new Error('Emulated device capabilities must be an array'); + } result.capabilities = []; for (let i = 0; i < capabilities.length; ++i) { - if (typeof capabilities[i] !== 'string') + if (typeof capabilities[i] !== 'string') { throw new Error('Emulated device capability must be a string'); + } result.capabilities.push(capabilities[i]); } result.deviceScaleFactor = /** @type {number} */ ( parseValue(json['screen'], 'device-pixel-ratio', 'number') ); - if (result.deviceScaleFactor < 0 || result.deviceScaleFactor > 100) + if (result.deviceScaleFactor < 0 || result.deviceScaleFactor > 100) { throw new Error( 'Emulated device has wrong deviceScaleFactor: ' + result.deviceScaleFactor ); + } result.vertical = parseOrientation( parseValue(json['screen'], 'vertical', 'object') diff --git a/utils/testserver/index.js b/utils/testserver/index.js index c6cb4bb9..86191533 100644 --- a/utils/testserver/index.js +++ b/utils/testserver/index.js @@ -69,9 +69,11 @@ class TestServer { * @param {!Object=} sslOptions */ constructor(dirPath, port, sslOptions) { - if (sslOptions) + if (sslOptions) { this._server = https.createServer(sslOptions, this._onRequest.bind(this)); - else this._server = http.createServer(this._onRequest.bind(this)); + } else { + this._server = http.createServer(this._onRequest.bind(this)); + } this._server.on('connection', (socket) => this._onSocket(socket)); this._wsServer = new WebSocketServer({ server: this._server }); this._wsServer.on('connection', this._onWebSocketConnection.bind(this)); @@ -101,7 +103,9 @@ class TestServer { // ECONNRESET is a legit error given // that tab closing simply kills process. socket.on('error', (error) => { - if (error.code !== 'ECONNRESET') throw error; + if (error.code !== 'ECONNRESET') { + throw error; + } }); socket.once('close', () => this._sockets.delete(socket)); } @@ -136,7 +140,9 @@ class TestServer { async stop() { this.reset(); - for (const socket of this._sockets) socket.destroy(); + for (const socket of this._sockets) { + socket.destroy(); + } this._sockets.clear(); await new Promise((x) => this._server.close(x)); } @@ -166,7 +172,9 @@ class TestServer { */ waitForRequest(path) { let promise = this._requestSubscribers.get(path); - if (promise) return promise; + if (promise) { + return promise; + } let fulfill, reject; promise = new Promise((f, r) => { fulfill = f; @@ -184,15 +192,19 @@ class TestServer { this._csp.clear(); this._gzipRoutes.clear(); const error = new Error('Static Server has been reset'); - for (const subscriber of this._requestSubscribers.values()) + for (const subscriber of this._requestSubscribers.values()) { subscriber[rejectSymbol].call(null, error); + } this._requestSubscribers.clear(); } _onRequest(request, response) { request.on('error', (error) => { - if (error.code === 'ECONNRESET') response.end(); - else throw error; + if (error.code === 'ECONNRESET') { + response.end(); + } else { + throw error; + } }); request.postBody = new Promise((resolve) => { let body = ''; @@ -234,7 +246,9 @@ class TestServer { * @param {string} pathName */ serveFile(request, response, pathName) { - if (pathName === '/') pathName = '/index.html'; + if (pathName === '/') { + pathName = '/index.html'; + } const filePath = path.join(this._dirPath, pathName.substring(1)); if ( @@ -251,8 +265,9 @@ class TestServer { } else { response.setHeader('Cache-Control', 'no-cache, no-store'); } - if (this._csp.has(pathName)) + if (this._csp.has(pathName)) { response.setHeader('Content-Security-Policy', this._csp.get(pathName)); + } fs.readFile(filePath, (err, data) => { if (err) {