From 7bf970590a5e15834032ecc812e0e0eba68d7784 Mon Sep 17 00:00:00 2001 From: Brendan Kenny Date: Wed, 14 Mar 2018 13:34:54 -0700 Subject: [PATCH 1/6] core: add type checking to audit and gatherer base classes --- lighthouse-core/audits/audit.js | 68 +++-- lighthouse-core/gather/gatherers/gatherer.js | 28 +- tsconfig.json | 1 + typings/externs.d.ts | 272 ++++++++++--------- 4 files changed, 210 insertions(+), 159 deletions(-) diff --git a/lighthouse-core/audits/audit.js b/lighthouse-core/audits/audit.js index dfd7d9020b30..c8c97072678a 100644 --- a/lighthouse-core/audits/audit.js +++ b/lighthouse-core/audits/audit.js @@ -3,7 +3,6 @@ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -// @ts-nocheck 'use strict'; const statistics = require('../lib/statistics'); @@ -19,14 +18,14 @@ const clampTo2Decimals = val => Math.round(val * 100) / 100; class Audit { /** - * @return {!string} + * @return {string} */ static get DEFAULT_PASS() { return DEFAULT_PASS; } /** - * @return {{NUMERIC: string, BINARY: string}} + * @return {Audit.ScoringModes} */ static get SCORING_MODES() { return { @@ -36,14 +35,14 @@ class Audit { } /** - * @throws {Error} + * @return {Audit.Meta} */ static get meta() { throw new Error('Audit meta information must be overridden.'); } /** - * Computes a clamped score between 0 and 100 based on the measured value. Score is determined by + * Computes a clamped score between 0 and 1 based on the measured value. Score is determined by * considering a log-normal distribution governed by the two control points, point of diminishing * returns and the median value, and returning the percentage of sites that have higher value. * @@ -65,9 +64,9 @@ class Audit { } /** - * @param {!Audit} audit + * @param {typeof Audit} audit * @param {string} debugString - * @return {!AuditFullResult} + * @return {LH.AuditFullResult} */ static generateErrorAuditResult(audit, debugString) { return Audit.generateAuditResult(audit, { @@ -78,10 +77,10 @@ class Audit { } /** - * @param {!Audit.Headings} headings - * @param {!Array>} results - * @param {!DetailsRenderer.DetailsSummary} summary - * @return {!DetailsRenderer.DetailsJSON} + * @param {Audit.Headings} headings + * @param {Array>} results + * @param {Audit.DetailsRenderer.DetailsSummary} summary + * @return {Audit.DetailsRenderer.DetailsJSON} */ static makeTableDetails(headings, results, summary) { if (results.length === 0) { @@ -102,9 +101,9 @@ class Audit { } /** - * @param {!Audit} audit - * @param {!AuditResult} result - * @return {{score: number, scoreDisplayMode: string}} + * @param {typeof Audit} audit + * @param {LH.AuditResult} result + * @return {{score: number, scoreDisplayMode: Audit.ScoringModeValues}} */ static _normalizeAuditScore(audit, result) { // Cast true/false to 1/0 @@ -125,9 +124,9 @@ class Audit { } /** - * @param {!Audit} audit - * @param {!AuditResult} result - * @return {!AuditFullResult} + * @param {typeof Audit} audit + * @param {LH.AuditResult} result + * @return {LH.AuditFullResult} */ static generateAuditResult(audit, result) { if (typeof result.rawValue === 'undefined') { @@ -175,6 +174,28 @@ class Audit { module.exports = Audit; +/** + * @typedef {Object} Audit.ScoringModes + * @property {'numeric'} NUMERIC + * @property {'binary'} BINARY + */ + +/** + * @typedef {Audit.ScoringModes[keyof Audit.ScoringModes]} Audit.ScoringModeValues + */ + +/** + * @typedef {Object} Audit.Meta + * @property {string} name + * @property {string} description + * @property {string} helpText + * @property {Array} requiredArtifacts + * @property {string=} failureDescription + * @property {boolean=} informative + * @property {boolean=} manual + * @property {Audit.ScoringModeValues=} scoreDisplayMode + */ + /** * @typedef {Object} Audit.Heading * @property {string} key @@ -193,3 +214,16 @@ module.exports = Audit; * @property {boolean} passes * @property {string=} debugString */ + +// TODO: placeholder typedefs until Details are typed +/** + * @typedef {void} Audit.DetailsRenderer.DetailsSummary + */ + +/** + * @typedef {object} Audit.DetailsRenderer.DetailsJSON + * @property {'table'} type + * @property {Array} headings + * @property {Array>} items + * @property {void} summary + */ diff --git a/lighthouse-core/gather/gatherers/gatherer.js b/lighthouse-core/gather/gatherers/gatherer.js index 40871a031609..529a75e38fcb 100644 --- a/lighthouse-core/gather/gatherers/gatherer.js +++ b/lighthouse-core/gather/gatherers/gatherer.js @@ -28,28 +28,42 @@ class Gatherer { /** * Called before navigation to target url. - * @param {!Object} options + * @param {Gatherer.PassContext} passContext + * @return {*|!Promise<*>} */ - beforePass(options) { } + beforePass(passContext) { } /** * Called after target page is loaded. If a trace is enabled for this pass, * the trace is still being recorded. - * @param {!Object} options + * @param {Gatherer.PassContext} passContext + * @return {*|!Promise<*>} */ - pass(options) { } + pass(passContext) { } /** * Called after target page is loaded, all gatherer `pass` methods have been * executed, and — if generated in this pass — the trace is ended. The trace * and record of network activity are provided in `loadData`. - * @param {!Object} options - * @param {{networkRecords: !Array, trace: {traceEvents: !Array}}} loadData + * @param {Gatherer.PassContext} passContext + * @param {Gatherer.LoadData} loadData * @return {*|!Promise<*>} */ - afterPass(options, loadData) { } + afterPass(passContext, loadData) { } /* eslint-enable no-unused-vars */ } +/** + * @typedef {Object} Gatherer.PassContext + * @property {object} options + */ + +/** + * @typedef {Object} Gatherer.LoadData + * @property {Array} networkRecords + * @property {Array} devtoolsLog + * @property {{traceEvents: Array}} trace + */ + module.exports = Gatherer; diff --git a/tsconfig.json b/tsconfig.json index 4773dd5566ae..4aeec0756559 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,6 +18,7 @@ "lighthouse-cli/**/*.js", "lighthouse-core/lib/dependency-graph/**/*.js", "lighthouse-core/gather/connections/**/*.js", + "lighthouse-core/gather/gatherers/gatherer.js", "./typings/externs.d.ts" ], "exclude": [ diff --git a/typings/externs.d.ts b/typings/externs.d.ts index c1652c1e59c2..668fbc6634f2 100644 --- a/typings/externs.d.ts +++ b/typings/externs.d.ts @@ -4,139 +4,141 @@ * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ -export as namespace LH; - -export interface Flags { - _: string[]; - port: number; - chromeFlags: string; - output: any; - outputPath: string; - saveAssets: boolean; - view: boolean; - maxWaitForLoad: number; - logLevel: string; - hostname: string; - blockedUrlPatterns: string[]; - extraHeaders: string; - enableErrorReporting: boolean; - listAllAudits: boolean; - listTraceCategories: boolean; - auditMode: boolean; - gatherMode: boolean; - configPath?: string; - perf: boolean; - mixedContent: boolean; - verbose: boolean; - quiet: boolean; -} - -export interface Config {} - -export interface AuditResult { - rawValue: boolean | number; - displayValue?: string; - debugString?: string; - score?: number; - optimalValue: number | string; - extendedInfo?: {value: string}; -} - -export interface AuditResults { - [metric: string]: AuditResult; -} - -export interface AuditFullResult { - rawValue: boolean | number; - displayValue: string; - debugString?: string; - score: number; - scoreDisplayMode: string; - error?: boolean; - description: string; - name: string; - helpText?: string; - extendedInfo?: {value: string}; -} - -export interface AuditFullResults { - [metric: string]: AuditFullResult; -} - -export interface Results { - url: string; - audits: AuditFullResults; - lighthouseVersion: string; - artifacts?: Object; - initialUrl: string; - generatedTime: string; -} - -export interface LaunchedChrome { - pid: number; - port: number; - kill: () => Promise<{}>; -} - -export interface LighthouseError extends Error { - code?: string; - friendlyMessage?: string; -} - -export interface TraceEvent { - name: string; - args: any; - tid: number; - ts: number; - dur: number; -} - -export interface NetworkRequest { - requestId: string; - connectionId: string; - connectionReused: boolean; - - url: string; - protocol: string; - origin: string | null; - parsedURL: DevToolsParsedURL; - - startTime: number; - endTime: number; - - transferSize: number; - - _initiator: NetworkRequestInitiator; - _timing: NetworkRequestTiming; - _resourceType: any; - priority(): 'VeryHigh' | 'High' | 'Medium' | 'Low'; -} - -export interface NetworkRequestInitiator { - type: 'script' | 'parser'; -} - -export interface NetworkRequestTiming { - connectStart: number; - connectEnd: number - sslStart: number; - sslEnd: number; - sendStart: number; - sendEnd: number; - receiveHeadersEnd: number; -} - -export interface DevToolsParsedURL { - scheme: string; - host: string; -} - -export interface DevToolsJsonTarget { - description: string; - devtoolsFrontendUrl: string; - id: string; - title: string; - type: string; - url: string; - webSocketDebuggerUrl: string; +declare namespace LH { + + export interface Flags { + _: string[]; + port: number; + chromeFlags: string; + output: any; + outputPath: string; + saveAssets: boolean; + view: boolean; + maxWaitForLoad: number; + logLevel: string; + hostname: string; + blockedUrlPatterns: string[]; + extraHeaders: string; + enableErrorReporting: boolean; + listAllAudits: boolean; + listTraceCategories: boolean; + auditMode: boolean; + gatherMode: boolean; + configPath?: string; + perf: boolean; + mixedContent: boolean; + verbose: boolean; + quiet: boolean; + } + + export interface Config {} + + export interface AuditResult { + rawValue: boolean | number | null; + displayValue?: string; + debugString?: string; + score?: number; + extendedInfo?: {value: string}; + notApplicable?: boolean; + error?: boolean; + // TODO: define details + details?: object; + } + + export interface AuditResults { + [metric: string]: AuditResult; + } + + export interface AuditFullResult extends AuditResult { + displayValue: string; + score: number; + scoreDisplayMode: 'numeric' | 'binary'; + description: string; + name: string; + helpText?: string; + informative?: boolean; + manual?: boolean; + } + + export interface AuditFullResults { + [metric: string]: AuditFullResult; + } + + export interface Results { + url: string; + audits: AuditFullResults; + lighthouseVersion: string; + artifacts?: Object; + initialUrl: string; + generatedTime: string; + } + + export interface LaunchedChrome { + pid: number; + port: number; + kill: () => Promise<{}>; + } + + export interface LighthouseError extends Error { + code?: string; + friendlyMessage?: string; + } + + export interface TraceEvent { + name: string; + args: any; + tid: number; + ts: number; + dur: number; + } + + export interface NetworkRequest { + requestId: string; + connectionId: string; + connectionReused: boolean; + + url: string; + protocol: string; + origin: string | null; + parsedURL: DevToolsParsedURL; + + startTime: number; + endTime: number; + + transferSize: number; + + _initiator: NetworkRequestInitiator; + _timing: NetworkRequestTiming; + _resourceType: any; + priority(): 'VeryHigh' | 'High' | 'Medium' | 'Low'; + } + + export interface NetworkRequestInitiator { + type: 'script' | 'parser'; + } + + export interface NetworkRequestTiming { + connectStart: number; + connectEnd: number + sslStart: number; + sslEnd: number; + sendStart: number; + sendEnd: number; + receiveHeadersEnd: number; + } + + export interface DevToolsParsedURL { + scheme: string; + host: string; + } + + export interface DevToolsJsonTarget { + description: string; + devtoolsFrontendUrl: string; + id: string; + title: string; + type: string; + url: string; + webSocketDebuggerUrl: string; + } } From 0401a79b1a1dd30aaa19ccbb37ef04877e3f7a86 Mon Sep 17 00:00:00 2001 From: Brendan Kenny Date: Wed, 14 Mar 2018 13:47:11 -0700 Subject: [PATCH 2/6] explicitly check audit.js --- tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/tsconfig.json b/tsconfig.json index 4aeec0756559..ffbecdb2de06 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,6 +16,7 @@ }, "include": [ "lighthouse-cli/**/*.js", + "lighthouse-core/audits/audit.js", "lighthouse-core/lib/dependency-graph/**/*.js", "lighthouse-core/gather/connections/**/*.js", "lighthouse-core/gather/gatherers/gatherer.js", From 7dd12402ae6ca01da07059c5375a4bc1f9660fc4 Mon Sep 17 00:00:00 2001 From: Brendan Kenny Date: Wed, 14 Mar 2018 14:18:59 -0700 Subject: [PATCH 3/6] dummy summary --- lighthouse-core/audits/audit.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lighthouse-core/audits/audit.js b/lighthouse-core/audits/audit.js index c8c97072678a..9c634578f2dc 100644 --- a/lighthouse-core/audits/audit.js +++ b/lighthouse-core/audits/audit.js @@ -218,6 +218,8 @@ module.exports = Audit; // TODO: placeholder typedefs until Details are typed /** * @typedef {void} Audit.DetailsRenderer.DetailsSummary + * @property {number=} wastedMs + * @property {number=} wastedKb */ /** @@ -225,5 +227,5 @@ module.exports = Audit; * @property {'table'} type * @property {Array} headings * @property {Array>} items - * @property {void} summary + * @property {Audit.DetailsRenderer.DetailsSummary} summary */ From b8e22e29472d309b48e56df40026d81d3d93aaa0 Mon Sep 17 00:00:00 2001 From: Brendan Kenny Date: Wed, 14 Mar 2018 23:21:14 -0700 Subject: [PATCH 4/6] |undefined --- lighthouse-core/audits/audit.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lighthouse-core/audits/audit.js b/lighthouse-core/audits/audit.js index 9c634578f2dc..8cf9e3110820 100644 --- a/lighthouse-core/audits/audit.js +++ b/lighthouse-core/audits/audit.js @@ -190,10 +190,10 @@ module.exports = Audit; * @property {string} description * @property {string} helpText * @property {Array} requiredArtifacts - * @property {string=} failureDescription - * @property {boolean=} informative - * @property {boolean=} manual - * @property {Audit.ScoringModeValues=} scoreDisplayMode + * @property {string|undefined} failureDescription + * @property {boolean|undefined} informative + * @property {boolean|undefined} manual + * @property {Audit.ScoringModeValues|undefined} scoreDisplayMode */ /** @@ -212,14 +212,14 @@ module.exports = Audit; * @property {number} results * @property {Audit.Headings} headings * @property {boolean} passes - * @property {string=} debugString + * @property {string|undefined} debugString */ // TODO: placeholder typedefs until Details are typed /** * @typedef {void} Audit.DetailsRenderer.DetailsSummary - * @property {number=} wastedMs - * @property {number=} wastedKb + * @property {number|undefined} wastedMs + * @property {number|undefined} wastedKb */ /** From ddb7f5b4279c2002a57178aa68de6839bf79500d Mon Sep 17 00:00:00 2001 From: Brendan Kenny Date: Thu, 15 Mar 2018 14:39:21 -0700 Subject: [PATCH 5/6] Revert "|undefined" This reverts commit b8e22e29472d309b48e56df40026d81d3d93aaa0. --- lighthouse-core/audits/audit.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lighthouse-core/audits/audit.js b/lighthouse-core/audits/audit.js index 8cf9e3110820..9c634578f2dc 100644 --- a/lighthouse-core/audits/audit.js +++ b/lighthouse-core/audits/audit.js @@ -190,10 +190,10 @@ module.exports = Audit; * @property {string} description * @property {string} helpText * @property {Array} requiredArtifacts - * @property {string|undefined} failureDescription - * @property {boolean|undefined} informative - * @property {boolean|undefined} manual - * @property {Audit.ScoringModeValues|undefined} scoreDisplayMode + * @property {string=} failureDescription + * @property {boolean=} informative + * @property {boolean=} manual + * @property {Audit.ScoringModeValues=} scoreDisplayMode */ /** @@ -212,14 +212,14 @@ module.exports = Audit; * @property {number} results * @property {Audit.Headings} headings * @property {boolean} passes - * @property {string|undefined} debugString + * @property {string=} debugString */ // TODO: placeholder typedefs until Details are typed /** * @typedef {void} Audit.DetailsRenderer.DetailsSummary - * @property {number|undefined} wastedMs - * @property {number|undefined} wastedKb + * @property {number=} wastedMs + * @property {number=} wastedKb */ /** From 22fcbfe606e5a58f06a2012a88d56641251fa0fc Mon Sep 17 00:00:00 2001 From: Brendan Kenny Date: Thu, 15 Mar 2018 14:40:07 -0700 Subject: [PATCH 6/6] [] --- lighthouse-core/audits/audit.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lighthouse-core/audits/audit.js b/lighthouse-core/audits/audit.js index 9c634578f2dc..7f84ccc76fed 100644 --- a/lighthouse-core/audits/audit.js +++ b/lighthouse-core/audits/audit.js @@ -190,10 +190,10 @@ module.exports = Audit; * @property {string} description * @property {string} helpText * @property {Array} requiredArtifacts - * @property {string=} failureDescription - * @property {boolean=} informative - * @property {boolean=} manual - * @property {Audit.ScoringModeValues=} scoreDisplayMode + * @property {string} [failureDescription] + * @property {boolean} [informative] + * @property {boolean} [manual] + * @property {Audit.ScoringModeValues} [scoreDisplayMode] */ /** @@ -212,14 +212,14 @@ module.exports = Audit; * @property {number} results * @property {Audit.Headings} headings * @property {boolean} passes - * @property {string=} debugString + * @property {string} [debugString] */ // TODO: placeholder typedefs until Details are typed /** * @typedef {void} Audit.DetailsRenderer.DetailsSummary - * @property {number=} wastedMs - * @property {number=} wastedKb + * @property {number} [wastedMs] + * @property {number} [wastedKb] */ /**