core(tsc): add type checking of first top-level audits (#5086)

This commit is contained in:
Brendan Kenny 2018-05-02 13:18:26 -07:00 коммит произвёл GitHub
Родитель 37f367bf61
Коммит 9ddae1eac9
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
20 изменённых файлов: 114 добавлений и 67 удалений

Просмотреть файл

@ -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<string, Number>}
* Returns a mapping of URL to counts of event groups.
* @param {LH.Artifacts.DevtoolsTimelineModel} timelineModel
* @return {Map<string, Object<string, number>>}
*/
static getExecutionTimingsByURL(timelineModel) {
const bottomUpByURL = timelineModel.bottomUpGroupBy('URL');
/** @type {Map<string, Object<string, number>>} */
const result = new Map();
bottomUpByURL.children.forEach((perUrlNode, url) => {
@ -55,6 +56,7 @@ class BootupTime extends Audit {
return;
}
/** @type {Object<string, number>} */
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<LH.Audit.Product>}
*/
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<string, Object<string, number>>} */
const extendedInfo = {};
const headings = [

Просмотреть файл

@ -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 '';

Просмотреть файл

@ -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;

Просмотреть файл

@ -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 => {

Просмотреть файл

@ -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 {

Просмотреть файл

@ -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 {

Просмотреть файл

@ -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<AuditResult>}
* @return {Promise<LH.Audit.Product>}
*/
static async audit(artifacts, context) {
const trace = artifacts.traces[Audit.DEFAULT_PASS];

Просмотреть файл

@ -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<!AuditResult>}
* @return {Promise<LH.Audit.Product>}
*/
static async audit(artifacts, context) {
const trace = artifacts.traces[Audit.DEFAULT_PASS];

Просмотреть файл

@ -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<LH.Audit.Product>}
*/
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,

Просмотреть файл

@ -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<LH.Artifacts.SingleImageUsage>} 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<LH.Artifacts.SingleImageUsage>} */ (image);
const processed = ImageAspectRatio.computeAspectRatios(wellDefinedImage);
if (processed instanceof Error) {
debugString = processed.message;
return;

Просмотреть файл

@ -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<LH.Audit.Product>}
*/
static async audit(artifacts, context) {
const trace = artifacts.traces[Audit.DEFAULT_PASS];

Просмотреть файл

@ -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<string, number>}
* @param {LH.Artifacts.DevtoolsTimelineModel} timelineModel
* @return {Map<string, number>}
*/
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<LH.Audit.Product>}
*/
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);

Просмотреть файл

@ -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<LH.Audit.Product>}
*/
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,
};
});
}

Просмотреть файл

@ -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<LH.Audit.Product>}
*/
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];

Просмотреть файл

@ -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<LH.Audit.Product>}
*/
static audit(artifacts) {
const defaultLogs = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];

Просмотреть файл

@ -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<LH.Audit.Product>}
*/
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,
};
});

Просмотреть файл

@ -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 => {

Просмотреть файл

@ -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",

17
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<Artifacts.CriticalRequestNode>;
requestDevtoolsTimelineModel(trace: Trace): Promise<Artifacts.DevtoolsTimelineModel>;
requestLoadSimulator(data: {devtoolsLog: DevtoolsLog, settings: Config.Settings}): Promise<LanternSimulator>;
requestMainResource(data: {devtoolsLog: DevtoolsLog, URL: Artifacts['URL']}): Promise<WebInspector.NetworkRequest>;
requestManifestValues(manifest: LH.Artifacts['Manifest']): Promise<LH.Artifacts.ManifestValues>;
@ -278,6 +279,20 @@ declare global {
}>;
}
export interface DevtoolsTimelineModelNode {
children: Map<string, DevtoolsTimelineModelNode>;
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;

3
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';