diff --git a/lighthouse-core/audits/bootup-time.js b/lighthouse-core/audits/bootup-time.js index b77daaa925..8e4cd017a2 100644 --- a/lighthouse-core/audits/bootup-time.js +++ b/lighthouse-core/audits/bootup-time.js @@ -13,11 +13,10 @@ const THRESHOLD_IN_MS = 10; class BootupTime extends Audit { /** - * @return {!AuditMeta} + * @return {LH.Audit.Meta} */ static get meta() { return { - category: 'Performance', name: 'bootup-time', description: 'JavaScript boot-up time', failureDescription: 'JavaScript boot-up time is too high', @@ -42,11 +41,13 @@ class BootupTime extends Audit { } /** - * @param {DevtoolsTimelineModel} timelineModel - * @return {!Map} + * Returns a mapping of URL to counts of event groups. + * @param {LH.Artifacts.DevtoolsTimelineModel} timelineModel + * @return {Map>} */ static getExecutionTimingsByURL(timelineModel) { const bottomUpByURL = timelineModel.bottomUpGroupBy('URL'); + /** @type {Map>} */ const result = new Map(); bottomUpByURL.children.forEach((perUrlNode, url) => { @@ -55,6 +56,7 @@ class BootupTime extends Audit { return; } + /** @type {Object} */ const taskGroups = {}; perUrlNode.children.forEach((perTaskPerUrlNode) => { // eventStyle() returns a string like 'Evaluate Script' @@ -71,15 +73,16 @@ class BootupTime extends Audit { } /** - * @param {!Artifacts} artifacts + * @param {LH.Artifacts} artifacts * @param {LH.Audit.Context} context - * @return {!AuditResult} + * @return {Promise} */ static audit(artifacts, context) { const trace = artifacts.traces[BootupTime.DEFAULT_PASS]; return artifacts.requestDevtoolsTimelineModel(trace).then(devtoolsTimelineModel => { const executionTimings = BootupTime.getExecutionTimingsByURL(devtoolsTimelineModel); let totalBootupTime = 0; + /** @type {Object>} */ const extendedInfo = {}; const headings = [ diff --git a/lighthouse-core/audits/content-width.js b/lighthouse-core/audits/content-width.js index 4242064177..311646df21 100644 --- a/lighthouse-core/audits/content-width.js +++ b/lighthouse-core/audits/content-width.js @@ -9,7 +9,7 @@ const Audit = require('./audit'); class ContentWidth extends Audit { /** - * @return {!AuditMeta} + * @return {LH.Audit.Meta} */ static get meta() { return { @@ -24,8 +24,8 @@ class ContentWidth extends Audit { } /** - * @param {!Artifacts} artifacts - * @return {!AuditResult} + * @param {LH.Artifacts} artifacts + * @return {LH.Audit.Product} */ static audit(artifacts) { const viewportWidth = artifacts.ViewportDimensions.innerWidth; @@ -38,6 +38,11 @@ class ContentWidth extends Audit { }; } + /** + * @param {boolean} match + * @param {LH.Artifacts.ViewportDimensions} artifact + * @return {string} + */ static createDebugString(match, artifact) { if (match) { return ''; diff --git a/lighthouse-core/audits/deprecations.js b/lighthouse-core/audits/deprecations.js index ff5ac95c0b..0518ca4d0f 100644 --- a/lighthouse-core/audits/deprecations.js +++ b/lighthouse-core/audits/deprecations.js @@ -16,7 +16,7 @@ const Util = require('../report/html/renderer/util'); class Deprecations extends Audit { /** - * @return {!AuditMeta} + * @return {LH.Audit.Meta} */ static get meta() { return { @@ -30,8 +30,8 @@ class Deprecations extends Audit { } /** - * @param {!Artifacts} artifacts - * @return {!AuditResult} + * @param {LH.Artifacts} artifacts + * @return {LH.Audit.Product} */ static audit(artifacts) { const entries = artifacts.ChromeConsoleMessages; diff --git a/lighthouse-core/audits/errors-in-console.js b/lighthouse-core/audits/errors-in-console.js index 8008be4699..a75cdb0124 100644 --- a/lighthouse-core/audits/errors-in-console.js +++ b/lighthouse-core/audits/errors-in-console.js @@ -14,7 +14,7 @@ const Audit = require('./audit'); class ErrorLogs extends Audit { /** - * @return {!AuditMeta} + * @return {LH.Audit.Meta} */ static get meta() { return { @@ -28,12 +28,13 @@ class ErrorLogs extends Audit { } /** - * @param {!Artifacts} artifacts - * @return {!AuditResult} + * @param {LH.Artifacts} artifacts + * @return {LH.Audit.Product} */ static audit(artifacts) { const consoleEntries = artifacts.ChromeConsoleMessages; const runtimeExceptions = artifacts.RuntimeExceptions; + /** @type {Array<{source: string, description: string|undefined, url: string|undefined}>} */ const consoleRows = consoleEntries.filter(log => log.entry && log.entry.level === 'error') .map(item => { diff --git a/lighthouse-core/audits/estimated-input-latency.js b/lighthouse-core/audits/estimated-input-latency.js index 02df63e742..808c43cd01 100644 --- a/lighthouse-core/audits/estimated-input-latency.js +++ b/lighthouse-core/audits/estimated-input-latency.js @@ -10,7 +10,7 @@ const Util = require('../report/html/renderer/util'); class EstimatedInputLatency extends Audit { /** - * @return {!AuditMeta} + * @return {LH.Audit.Meta} */ static get meta() { return { diff --git a/lighthouse-core/audits/first-contentful-paint.js b/lighthouse-core/audits/first-contentful-paint.js index 183af0ee68..d449427920 100644 --- a/lighthouse-core/audits/first-contentful-paint.js +++ b/lighthouse-core/audits/first-contentful-paint.js @@ -10,7 +10,7 @@ const Util = require('../report/html/renderer/util.js'); class FirstContentfulPaint extends Audit { /** - * @return {AuditMeta} + * @return {LH.Audit.Meta} */ static get meta() { return { diff --git a/lighthouse-core/audits/first-cpu-idle.js b/lighthouse-core/audits/first-cpu-idle.js index 46cf07088e..2c43d7eedd 100644 --- a/lighthouse-core/audits/first-cpu-idle.js +++ b/lighthouse-core/audits/first-cpu-idle.js @@ -10,7 +10,7 @@ const Util = require('../report/html/renderer/util.js'); class FirstCPUIdle extends Audit { /** - * @return {!AuditMeta} + * @return {LH.Audit.Meta} */ static get meta() { return { @@ -41,9 +41,9 @@ class FirstCPUIdle extends Audit { * Identify the time the page is "first interactive" * @see https://docs.google.com/document/d/1GGiI9-7KeY3TPqS3YT271upUVimo-XiL5mwWorDUD4c/edit# * - * @param {Artifacts} artifacts + * @param {LH.Artifacts} artifacts * @param {LH.Audit.Context} context - * @return {Promise} + * @return {Promise} */ static async audit(artifacts, context) { const trace = artifacts.traces[Audit.DEFAULT_PASS]; diff --git a/lighthouse-core/audits/first-meaningful-paint.js b/lighthouse-core/audits/first-meaningful-paint.js index b6fb1f4a94..5e1bb88e1e 100644 --- a/lighthouse-core/audits/first-meaningful-paint.js +++ b/lighthouse-core/audits/first-meaningful-paint.js @@ -10,7 +10,7 @@ const Util = require('../report/html/renderer/util'); class FirstMeaningfulPaint extends Audit { /** - * @return {!AuditMeta} + * @return {LH.Audit.Meta} */ static get meta() { return { @@ -40,9 +40,9 @@ class FirstMeaningfulPaint extends Audit { * Audits the page to give a score for First Meaningful Paint. * @see https://github.com/GoogleChrome/lighthouse/issues/26 * @see https://docs.google.com/document/d/1BR94tJdZLsin5poeet0XoTW60M0SjvOJQttKT-JK8HI/view - * @param {!Artifacts} artifacts The artifacts from the gather phase. + * @param {LH.Artifacts} artifacts The artifacts from the gather phase. * @param {LH.Audit.Context} context - * @return {!Promise} + * @return {Promise} */ static async audit(artifacts, context) { const trace = artifacts.traces[Audit.DEFAULT_PASS]; diff --git a/lighthouse-core/audits/font-display.js b/lighthouse-core/audits/font-display.js index e6ffa06246..76d48bff9e 100644 --- a/lighthouse-core/audits/font-display.js +++ b/lighthouse-core/audits/font-display.js @@ -11,7 +11,7 @@ const allowedFontFaceDisplays = ['block', 'fallback', 'optional', 'swap']; class FontDisplay extends Audit { /** - * @return {!AuditMeta} + * @return {LH.Audit.Meta} */ static get meta() { return { @@ -26,8 +26,8 @@ class FontDisplay extends Audit { } /** - * @param {!Artifacts} artifacts - * @return {!AuditResult} + * @param {LH.Artifacts} artifacts + * @return {Promise} */ static audit(artifacts) { const devtoolsLogs = artifacts.devtoolsLogs[this.DEFAULT_PASS]; @@ -47,14 +47,14 @@ class FontDisplay extends Audit { .filter(fontRecord => { // find the fontRecord of a font return !!fontsWithoutProperDisplay.find(fontFace => { - return fontFace.src.find(src => fontRecord.url === src); + return !!fontFace.src && !!fontFace.src.find(src => fontRecord.url === src); }); }) // calculate wasted time .map(record => { // In reality the end time should be calculated with paint time included // all browsers wait 3000ms to block text so we make sure 3000 is our max wasted time - const wastedTime = Math.min((record._endTime - record._startTime) * 1000, 3000); + const wastedTime = Math.min((record.endTime - record.startTime) * 1000, 3000); return { url: record.url, diff --git a/lighthouse-core/audits/image-aspect-ratio.js b/lighthouse-core/audits/image-aspect-ratio.js index c32cea09c7..b4a4889855 100644 --- a/lighthouse-core/audits/image-aspect-ratio.js +++ b/lighthouse-core/audits/image-aspect-ratio.js @@ -9,6 +9,7 @@ * audit will list all images that don't match with their display size * aspect ratio. */ +// @ts-nocheck - TODO(bckenny): fix optional width/height in ImageUsage artifact 'use strict'; const Audit = require('./audit'); @@ -18,7 +19,7 @@ const THRESHOLD = 0.05; class ImageAspectRatio extends Audit { /** - * @return {!AuditMeta} + * @return {LH.Audit.Meta} */ static get meta() { return { @@ -31,8 +32,8 @@ class ImageAspectRatio extends Audit { } /** - * @param {!Object} image - * @return {?Object} + * @param {Required} image + * @return {Error|{url: string, displayedAspectRatio: string, actualAspectRatio: string, doRatiosMatch: boolean}} */ static computeAspectRatios(image) { const url = URL.elideDataURI(image.src); @@ -56,13 +57,14 @@ class ImageAspectRatio extends Audit { } /** - * @param {!Artifacts} artifacts - * @return {!AuditResult} + * @param {LH.Artifacts} artifacts + * @return {LH.Audit.Product} */ static audit(artifacts) { const images = artifacts.ImageUsage; let debugString; + /** @type {Array<{url: string, displayedAspectRatio: string, actualAspectRatio: string, doRatiosMatch: boolean}>} */ const results = []; images.filter(image => { // - filter out images that don't have following properties: @@ -74,7 +76,8 @@ class ImageAspectRatio extends Audit { image.height && !image.usesObjectFit; }).forEach(image => { - const processed = ImageAspectRatio.computeAspectRatios(image); + const wellDefinedImage = /** @type {Required} */ (image); + const processed = ImageAspectRatio.computeAspectRatios(wellDefinedImage); if (processed instanceof Error) { debugString = processed.message; return; diff --git a/lighthouse-core/audits/load-fast-enough-for-pwa.js b/lighthouse-core/audits/load-fast-enough-for-pwa.js index a0fb70c9e6..7fde133ab5 100644 --- a/lighthouse-core/audits/load-fast-enough-for-pwa.js +++ b/lighthouse-core/audits/load-fast-enough-for-pwa.js @@ -22,7 +22,7 @@ const MAXIMUM_TTI = 10 * 1000; class LoadFastEnough4Pwa extends Audit { /** - * @return {!AuditMeta} + * @return {LH.Audit.Meta} */ static get meta() { return { @@ -39,7 +39,7 @@ class LoadFastEnough4Pwa extends Audit { /** * @param {LH.Artifacts} artifacts * @param {LH.Audit.Context} context - * @return {LH.AuditResult} + * @return {Promise} */ static async audit(artifacts, context) { const trace = artifacts.traces[Audit.DEFAULT_PASS]; diff --git a/lighthouse-core/audits/mainthread-work-breakdown.js b/lighthouse-core/audits/mainthread-work-breakdown.js index 7bb8da2d5b..589d339bb0 100644 --- a/lighthouse-core/audits/mainthread-work-breakdown.js +++ b/lighthouse-core/audits/mainthread-work-breakdown.js @@ -17,11 +17,10 @@ const {taskToGroup} = require('../lib/task-groups'); class MainThreadWorkBreakdown extends Audit { /** - * @return {!AuditMeta} + * @return {LH.Audit.Meta} */ static get meta() { return { - category: 'Performance', name: 'mainthread-work-breakdown', description: 'Minimizes main thread work', failureDescription: 'Has significant main thread work', @@ -44,8 +43,8 @@ class MainThreadWorkBreakdown extends Audit { } /** - * @param {!DevtoolsTimelineModel} timelineModel - * @return {!Map} + * @param {LH.Artifacts.DevtoolsTimelineModel} timelineModel + * @return {Map} */ static getExecutionTimingsByCategory(timelineModel) { const bottomUpByName = timelineModel.bottomUpGroupBy('EventName'); @@ -58,9 +57,9 @@ class MainThreadWorkBreakdown extends Audit { } /** - * @param {!Artifacts} artifacts + * @param {LH.Artifacts} artifacts * @param {LH.Audit.Context} context - * @return {!AuditResult} + * @return {Promise} */ static audit(artifacts, context) { const trace = artifacts.traces[MainThreadWorkBreakdown.DEFAULT_PASS]; @@ -94,6 +93,7 @@ class MainThreadWorkBreakdown extends Audit { {key: 'category', itemType: 'text', text: 'Work'}, {key: 'duration', itemType: 'text', text: 'Time spent'}, ]; + // @ts-ignore - stableSort added to Array by WebInspector results.stableSort((a, b) => categoryTotals[b.group] - categoryTotals[a.group]); const tableDetails = MainThreadWorkBreakdown.makeTableDetails(headings, results); diff --git a/lighthouse-core/audits/manifest-short-name-length.js b/lighthouse-core/audits/manifest-short-name-length.js index cf1f31ba4a..b86f905b26 100644 --- a/lighthouse-core/audits/manifest-short-name-length.js +++ b/lighthouse-core/audits/manifest-short-name-length.js @@ -9,7 +9,7 @@ const Audit = require('./audit'); class ManifestShortNameLength extends Audit { /** - * @return {!AuditMeta} + * @return {LH.Audit.Meta} */ static get meta() { return { @@ -25,8 +25,8 @@ class ManifestShortNameLength extends Audit { } /** - * @param {!Artifacts} artifacts - * @return {!AuditResult} + * @param {LH.Artifacts} artifacts + * @return {Promise} */ static audit(artifacts) { return artifacts.requestManifestValues(artifacts.Manifest).then(manifestValues => { @@ -36,17 +36,17 @@ class ManifestShortNameLength extends Audit { }; } - const hasShortName = manifestValues.allChecks.find(i => i.id === 'hasShortName').passing; - if (!hasShortName) { + const hasShortName = manifestValues.allChecks.find(i => i.id === 'hasShortName'); + if (!hasShortName || !hasShortName.passing) { return { rawValue: false, debugString: 'No short_name found in manifest.', }; } - const isShortEnough = manifestValues.allChecks.find(i => i.id === 'shortNameLength').passing; + const isShortEnough = manifestValues.allChecks.find(i => i.id === 'shortNameLength'); return { - rawValue: isShortEnough, + rawValue: !!isShortEnough && isShortEnough.passing, }; }); } diff --git a/lighthouse-core/audits/metrics.js b/lighthouse-core/audits/metrics.js index ac72d96fab..49bc606887 100644 --- a/lighthouse-core/audits/metrics.js +++ b/lighthouse-core/audits/metrics.js @@ -9,7 +9,7 @@ const Audit = require('./audit'); class Metrics extends Audit { /** - * @return {!AuditMeta} + * @return {LH.Audit.Meta} */ static get meta() { return { @@ -22,8 +22,9 @@ class Metrics extends Audit { } /** - * @param {!Artifacts} artifacts - * @return {!AuditResult} + * @param {LH.Artifacts} artifacts + * @param {LH.Audit.Context} context + * @return {Promise} */ static async audit(artifacts, context) { const trace = artifacts.traces[Audit.DEFAULT_PASS]; @@ -59,7 +60,9 @@ class Metrics extends Audit { } // Include all timestamps of interest from trace of tab - for (const [traceEventName, timing] of Object.entries(traceOfTab.timings)) { + const timingsEntries = /** @type {Array<[keyof LH.Artifacts.TraceTimes, number]>} */ + (Object.entries(traceOfTab.timings)); + for (const [traceEventName, timing] of timingsEntries) { const uppercased = traceEventName.slice(0, 1).toUpperCase() + traceEventName.slice(1); const metricName = `observed${uppercased}`; const timestamp = traceOfTab.timestamps[traceEventName]; diff --git a/lighthouse-core/audits/mixed-content.js b/lighthouse-core/audits/mixed-content.js index fe0f1ed2ce..bf1d8e7b5b 100644 --- a/lighthouse-core/audits/mixed-content.js +++ b/lighthouse-core/audits/mixed-content.js @@ -3,6 +3,7 @@ * 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 Audit = require('./audit'); @@ -17,11 +18,10 @@ const Util = require('../report/html/renderer/util'); */ class MixedContent extends Audit { /** - * @return {!AuditMeta} + * @return {LH.Audit.Meta} */ static get meta() { return { - category: 'Mixed Content', name: 'mixed-content', description: 'All resources loaded are secure', informative: true, @@ -86,8 +86,8 @@ class MixedContent extends Audit { } /** - * @param {!Artifacts} artifacts - * @return {!AuditResult} + * @param {LH.Artifacts} artifacts + * @return {Promise} */ static audit(artifacts) { const defaultLogs = artifacts.devtoolsLogs[Audit.DEFAULT_PASS]; diff --git a/lighthouse-core/audits/network-requests.js b/lighthouse-core/audits/network-requests.js index dfa0ecc98d..6659c92c43 100644 --- a/lighthouse-core/audits/network-requests.js +++ b/lighthouse-core/audits/network-requests.js @@ -10,7 +10,7 @@ const URL = require('../lib/url-shim'); class NetworkRequests extends Audit { /** - * @return {!AuditMeta} + * @return {LH.Audit.Meta} */ static get meta() { return { @@ -23,8 +23,8 @@ class NetworkRequests extends Audit { } /** - * @param {!Artifacts} artifacts - * @return {!AuditResult} + * @param {LH.Artifacts} artifacts + * @return {Promise} */ static audit(artifacts) { const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS]; @@ -41,7 +41,7 @@ class NetworkRequests extends Audit { endTime: (record.endTime - earliestStartTime) * 1000, transferSize: record.transferSize, statusCode: record.statusCode, - mimeType: record.mimeType, + mimeType: record._mimeType, resourceType: record._resourceType && record._resourceType._name, }; }); diff --git a/lighthouse-core/test/audits/font-display-test.js b/lighthouse-core/test/audits/font-display-test.js index 64fd3ba347..4c4f97cb3f 100644 --- a/lighthouse-core/test/audits/font-display-test.js +++ b/lighthouse-core/test/audits/font-display-test.js @@ -50,12 +50,12 @@ describe('Performance: Font Display audit', () => { return Audit.audit(getArtifacts([ { url: openSansFont.src[0], - _endTime: 3, _startTime: 1, + endTime: 3, startTime: 1, _resourceType: WebInspector.resourceTypes.Font, }, { url: openSansFontBold.src[0], - _endTime: 3, _startTime: 1, + endTime: 3, startTime: 1, _resourceType: WebInspector.resourceTypes.Font, }, ], webFonts)).then(result => { @@ -77,12 +77,12 @@ describe('Performance: Font Display audit', () => { return Audit.audit(getArtifacts([ { url: openSansFont.src[0], - _endTime: 3, _startTime: 1, + endTime: 3, startTime: 1, _resourceType: WebInspector.resourceTypes.Font, }, { url: openSansFontBold.src[0], - _endTime: 3, _startTime: 1, + endTime: 3, startTime: 1, _resourceType: WebInspector.resourceTypes.Font, }, ], webFonts)).then(result => { diff --git a/tsconfig.json b/tsconfig.json index 94b3d0b9e7..60bdb283a7 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -18,6 +18,22 @@ "lighthouse-cli/**/*.js", "lighthouse-core/audits/audit.js", "lighthouse-core/audits/redirects.js", + "lighthouse-core/audits/bootup-time.js", + "lighthouse-core/audits/content-width.js", + "lighthouse-core/audits/deprecations.js", + "lighthouse-core/audits/errors-in-console.js", + "lighthouse-core/audits/estimated-input-latency.js", + "lighthouse-core/audits/first-contentful-paint.js", + "lighthouse-core/audits/first-cpu-idle.js", + "lighthouse-core/audits/first-meaningful-paint.js", + "lighthouse-core/audits/font-display.js", + "lighthouse-core/audits/image-aspect-ratio.js", + "lighthouse-core/audits/load-fast-enough-for-pwa.js", + "lighthouse-core/audits/mainthread-work-breakdown.js", + "lighthouse-core/audits/manifest-short-name-length.js", + "lighthouse-core/audits/metrics.js", + "lighthouse-core/audits/mixed-content.js", + "lighthouse-core/audits/network-requests.js", "lighthouse-core/audits/accessibility/**/*.js", "lighthouse-core/audits/dobetterweb/**/*.js", "lighthouse-core/audits/byte-efficiency/**/*.js", diff --git a/typings/artifacts.d.ts b/typings/artifacts.d.ts index 62ba7e6191..ecaca440b8 100644 --- a/typings/artifacts.d.ts +++ b/typings/artifacts.d.ts @@ -99,7 +99,8 @@ declare global { } export interface ComputedArtifacts { - requestDevtoolsTimelineModel(trace: Trace): Promise<{filmStripModel(): Artifacts.DevtoolsTimelineFilmStripModel}>; + requestCriticalRequestChains(data: {devtoolsLog: DevtoolsLog, URL: Artifacts['URL']}): Promise; + requestDevtoolsTimelineModel(trace: Trace): Promise; requestLoadSimulator(data: {devtoolsLog: DevtoolsLog, settings: Config.Settings}): Promise; requestMainResource(data: {devtoolsLog: DevtoolsLog, URL: Artifacts['URL']}): Promise; requestManifestValues(manifest: LH.Artifacts['Manifest']): Promise; @@ -278,6 +279,20 @@ declare global { }>; } + export interface DevtoolsTimelineModelNode { + children: Map; + selfTime: number; + // SDK.TracingModel.Event + event: { + name: string; + }; + } + + export interface DevtoolsTimelineModel { + filmStripModel(): Artifacts.DevtoolsTimelineFilmStripModel; + bottomUpGroupBy(grouping: string): DevtoolsTimelineModelNode; + } + export interface ManifestValues { isParseFailure: boolean; parseFailureReason: string | undefined; diff --git a/typings/audit.d.ts b/typings/audit.d.ts index 45eefb44c4..63b62b518a 100644 --- a/typings/audit.d.ts +++ b/typings/audit.d.ts @@ -76,7 +76,8 @@ declare global { } export type DetailsItem = string | number | DetailsRendererNodeDetailsJSON | - DetailsRendererLinkDetailsJSON | DetailsRendererCodeDetailJSON; + DetailsRendererLinkDetailsJSON | DetailsRendererCodeDetailJSON | undefined | + boolean; export interface DetailsRendererNodeDetailsJSON { type: 'node';