Skip to content

Commit 1a741fe

Browse files
authored
core: refactor audits to use async syntax (#14542)
1 parent 3ee2de5 commit 1a741fe

File tree

5 files changed

+259
-266
lines changed

5 files changed

+259
-266
lines changed

core/audits/byte-efficiency/uses-long-cache-ttl.js

Lines changed: 87 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -194,103 +194,102 @@ class CacheHeaders extends Audit {
194194
* @param {LH.Audit.Context} context
195195
* @return {Promise<LH.Audit.Product>}
196196
*/
197-
static audit(artifacts, context) {
197+
static async audit(artifacts, context) {
198198
const devtoolsLogs = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
199-
return NetworkRecords.request(devtoolsLogs, context).then(records => {
200-
const results = [];
201-
let totalWastedBytes = 0;
202-
203-
for (const record of records) {
204-
if (!CacheHeaders.isCacheableAsset(record)) continue;
205-
206-
/** @type {Map<string, string>} */
207-
const headers = new Map();
208-
for (const header of record.responseHeaders || []) {
209-
if (headers.has(header.name.toLowerCase())) {
210-
const previousHeaderValue = headers.get(header.name.toLowerCase());
211-
headers.set(header.name.toLowerCase(),
212-
`${previousHeaderValue}, ${header.value}`);
213-
} else {
214-
headers.set(header.name.toLowerCase(), header.value);
215-
}
216-
}
217-
218-
const cacheControl = parseCacheControl(headers.get('cache-control'));
219-
if (this.shouldSkipRecord(headers, cacheControl)) {
220-
continue;
199+
const records = await NetworkRecords.request(devtoolsLogs, context);
200+
const results = [];
201+
let totalWastedBytes = 0;
202+
203+
for (const record of records) {
204+
if (!CacheHeaders.isCacheableAsset(record)) continue;
205+
206+
/** @type {Map<string, string>} */
207+
const headers = new Map();
208+
for (const header of record.responseHeaders || []) {
209+
if (headers.has(header.name.toLowerCase())) {
210+
const previousHeaderValue = headers.get(header.name.toLowerCase());
211+
headers.set(header.name.toLowerCase(),
212+
`${previousHeaderValue}, ${header.value}`);
213+
} else {
214+
headers.set(header.name.toLowerCase(), header.value);
221215
}
216+
}
222217

223-
// Ignore if cacheLifetimeInSeconds is a nonpositive number.
224-
let cacheLifetimeInSeconds = CacheHeaders.computeCacheLifetimeInSeconds(
225-
headers, cacheControl);
226-
if (cacheLifetimeInSeconds !== null &&
227-
(!Number.isFinite(cacheLifetimeInSeconds) || cacheLifetimeInSeconds <= 0)) {
228-
continue;
229-
}
230-
cacheLifetimeInSeconds = cacheLifetimeInSeconds || 0;
231-
232-
// Ignore assets whose cache lifetime is already high enough
233-
const cacheHitProbability = CacheHeaders.getCacheHitProbability(cacheLifetimeInSeconds);
234-
if (cacheHitProbability > IGNORE_THRESHOLD_IN_PERCENT) continue;
235-
236-
const url = UrlUtils.elideDataURI(record.url);
237-
const totalBytes = record.transferSize || 0;
238-
const wastedBytes = (1 - cacheHitProbability) * totalBytes;
239-
240-
totalWastedBytes += wastedBytes;
241-
242-
// Include cacheControl info (if it exists) per url as a diagnostic.
243-
/** @type {LH.Audit.Details.DebugData|undefined} */
244-
let debugData;
245-
if (cacheControl) {
246-
debugData = {
247-
type: 'debugdata',
248-
...cacheControl,
249-
};
250-
}
218+
const cacheControl = parseCacheControl(headers.get('cache-control'));
219+
if (this.shouldSkipRecord(headers, cacheControl)) {
220+
continue;
221+
}
251222

252-
results.push({
253-
url,
254-
debugData,
255-
cacheLifetimeMs: cacheLifetimeInSeconds * 1000,
256-
cacheHitProbability,
257-
totalBytes,
258-
wastedBytes,
259-
});
223+
// Ignore if cacheLifetimeInSeconds is a nonpositive number.
224+
let cacheLifetimeInSeconds = CacheHeaders.computeCacheLifetimeInSeconds(
225+
headers, cacheControl);
226+
if (cacheLifetimeInSeconds !== null &&
227+
(!Number.isFinite(cacheLifetimeInSeconds) || cacheLifetimeInSeconds <= 0)) {
228+
continue;
229+
}
230+
cacheLifetimeInSeconds = cacheLifetimeInSeconds || 0;
231+
232+
// Ignore assets whose cache lifetime is already high enough
233+
const cacheHitProbability = CacheHeaders.getCacheHitProbability(cacheLifetimeInSeconds);
234+
if (cacheHitProbability > IGNORE_THRESHOLD_IN_PERCENT) continue;
235+
236+
const url = UrlUtils.elideDataURI(record.url);
237+
const totalBytes = record.transferSize || 0;
238+
const wastedBytes = (1 - cacheHitProbability) * totalBytes;
239+
240+
totalWastedBytes += wastedBytes;
241+
242+
// Include cacheControl info (if it exists) per url as a diagnostic.
243+
/** @type {LH.Audit.Details.DebugData|undefined} */
244+
let debugData;
245+
if (cacheControl) {
246+
debugData = {
247+
type: 'debugdata',
248+
...cacheControl,
249+
};
260250
}
261251

262-
results.sort((a, b) => {
263-
return a.cacheLifetimeMs - b.cacheLifetimeMs ||
264-
b.totalBytes - a.totalBytes ||
265-
a.url.localeCompare(b.url);
252+
results.push({
253+
url,
254+
debugData,
255+
cacheLifetimeMs: cacheLifetimeInSeconds * 1000,
256+
cacheHitProbability,
257+
totalBytes,
258+
wastedBytes,
266259
});
260+
}
267261

268-
const score = Audit.computeLogNormalScore(
269-
{p10: context.options.p10, median: context.options.median},
270-
totalWastedBytes
271-
);
272-
273-
/** @type {LH.Audit.Details.Table['headings']} */
274-
const headings = [
275-
{key: 'url', valueType: 'url', label: str_(i18n.UIStrings.columnURL)},
276-
// TODO(i18n): pre-compute localized duration
277-
{key: 'cacheLifetimeMs', valueType: 'ms', label: str_(i18n.UIStrings.columnCacheTTL),
278-
displayUnit: 'duration'},
279-
{key: 'totalBytes', valueType: 'bytes', label: str_(i18n.UIStrings.columnTransferSize),
280-
displayUnit: 'kb', granularity: 1},
281-
];
282-
283-
const summary = {wastedBytes: totalWastedBytes};
284-
const details = Audit.makeTableDetails(headings, results, summary);
285-
286-
return {
287-
score,
288-
numericValue: totalWastedBytes,
289-
numericUnit: 'byte',
290-
displayValue: str_(UIStrings.displayValue, {itemCount: results.length}),
291-
details,
292-
};
262+
results.sort((a, b) => {
263+
return a.cacheLifetimeMs - b.cacheLifetimeMs ||
264+
b.totalBytes - a.totalBytes ||
265+
a.url.localeCompare(b.url);
293266
});
267+
268+
const score = Audit.computeLogNormalScore(
269+
{p10: context.options.p10, median: context.options.median},
270+
totalWastedBytes
271+
);
272+
273+
/** @type {LH.Audit.Details.Table['headings']} */
274+
const headings = [
275+
{key: 'url', valueType: 'url', label: str_(i18n.UIStrings.columnURL)},
276+
// TODO(i18n): pre-compute localized duration
277+
{key: 'cacheLifetimeMs', valueType: 'ms', label: str_(i18n.UIStrings.columnCacheTTL),
278+
displayUnit: 'duration'},
279+
{key: 'totalBytes', valueType: 'bytes', label: str_(i18n.UIStrings.columnTransferSize),
280+
displayUnit: 'kb', granularity: 1},
281+
];
282+
283+
const summary = {wastedBytes: totalWastedBytes};
284+
const details = Audit.makeTableDetails(headings, results, summary);
285+
286+
return {
287+
score,
288+
numericValue: totalWastedBytes,
289+
numericUnit: 'byte',
290+
displayValue: str_(UIStrings.displayValue, {itemCount: results.length}),
291+
details,
292+
};
294293
}
295294
}
296295

core/audits/critical-request-chains.js

Lines changed: 41 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -166,52 +166,51 @@ class CriticalRequestChains extends Audit {
166166
* @param {LH.Audit.Context} context
167167
* @return {Promise<LH.Audit.Product>}
168168
*/
169-
static audit(artifacts, context) {
169+
static async audit(artifacts, context) {
170170
const trace = artifacts.traces[Audit.DEFAULT_PASS];
171171
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
172172
const URL = artifacts.URL;
173-
return ComputedChains.request({devtoolsLog, trace, URL}, context).then(chains => {
174-
let chainCount = 0;
175-
/**
176-
* @param {LH.Audit.Details.SimpleCriticalRequestNode} node
177-
* @param {number} depth
178-
*/
179-
function walk(node, depth) {
180-
const childIds = Object.keys(node);
181-
182-
childIds.forEach(id => {
183-
const child = node[id];
184-
if (child.children) {
185-
walk(child.children, depth + 1);
186-
} else {
187-
// if the node doesn't have a children field, then it is a leaf, so +1
188-
chainCount++;
189-
}
190-
}, '');
191-
}
192-
// Convert
193-
const flattenedChains = CriticalRequestChains.flattenRequests(chains);
194-
195-
// Account for initial navigation
196-
const initialNavKey = Object.keys(flattenedChains)[0];
197-
const initialNavChildren = initialNavKey && flattenedChains[initialNavKey].children;
198-
if (initialNavChildren && Object.keys(initialNavChildren).length > 0) {
199-
walk(initialNavChildren, 0);
200-
}
173+
const chains = await ComputedChains.request({devtoolsLog, trace, URL}, context);
174+
let chainCount = 0;
175+
/**
176+
* @param {LH.Audit.Details.SimpleCriticalRequestNode} node
177+
* @param {number} depth
178+
*/
179+
function walk(node, depth) {
180+
const childIds = Object.keys(node);
201181

202-
const longestChain = CriticalRequestChains._getLongestChain(flattenedChains);
203-
204-
return {
205-
score: Number(chainCount === 0),
206-
notApplicable: chainCount === 0,
207-
displayValue: chainCount ? str_(UIStrings.displayValue, {itemCount: chainCount}) : '',
208-
details: {
209-
type: 'criticalrequestchain',
210-
chains: flattenedChains,
211-
longestChain,
212-
},
213-
};
214-
});
182+
childIds.forEach(id => {
183+
const child = node[id];
184+
if (child.children) {
185+
walk(child.children, depth + 1);
186+
} else {
187+
// if the node doesn't have a children field, then it is a leaf, so +1
188+
chainCount++;
189+
}
190+
}, '');
191+
}
192+
// Convert
193+
const flattenedChains = CriticalRequestChains.flattenRequests(chains);
194+
195+
// Account for initial navigation
196+
const initialNavKey = Object.keys(flattenedChains)[0];
197+
const initialNavChildren = initialNavKey && flattenedChains[initialNavKey].children;
198+
if (initialNavChildren && Object.keys(initialNavChildren).length > 0) {
199+
walk(initialNavChildren, 0);
200+
}
201+
202+
const longestChain = CriticalRequestChains._getLongestChain(flattenedChains);
203+
204+
return {
205+
score: Number(chainCount === 0),
206+
notApplicable: chainCount === 0,
207+
displayValue: chainCount ? str_(UIStrings.displayValue, {itemCount: chainCount}) : '',
208+
details: {
209+
type: 'criticalrequestchain',
210+
chains: flattenedChains,
211+
longestChain,
212+
},
213+
};
215214
}
216215
}
217216

core/audits/is-on-https.js

Lines changed: 38 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -70,53 +70,52 @@ class HTTPS extends Audit {
7070
* @param {LH.Audit.Context} context
7171
* @return {Promise<LH.Audit.Product>}
7272
*/
73-
static audit(artifacts, context) {
73+
static async audit(artifacts, context) {
7474
const devtoolsLogs = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
75-
return NetworkRecords.request(devtoolsLogs, context).then(networkRecords => {
76-
const insecureURLs = networkRecords
77-
.filter(record => !NetworkRequest.isSecureRequest(record))
78-
.map(record => UrlUtils.elideDataURI(record.url));
75+
const networkRecords = await NetworkRecords.request(devtoolsLogs, context);
76+
const insecureURLs = networkRecords
77+
.filter(record => !NetworkRequest.isSecureRequest(record))
78+
.map(record => UrlUtils.elideDataURI(record.url));
7979

80-
/** @type {Array<{url: string, resolution?: LH.IcuMessage|string}>} */
81-
const items = Array.from(new Set(insecureURLs)).map(url => ({url, resolution: undefined}));
80+
/** @type {Array<{url: string, resolution?: LH.IcuMessage|string}>} */
81+
const items = Array.from(new Set(insecureURLs)).map(url => ({url, resolution: undefined}));
8282

83-
/** @type {LH.Audit.Details.Table['headings']} */
84-
const headings = [
85-
{key: 'url', valueType: 'url', label: str_(UIStrings.columnInsecureURL)},
86-
{key: 'resolution', valueType: 'text', label: str_(UIStrings.columnResolution)},
87-
];
83+
/** @type {LH.Audit.Details.Table['headings']} */
84+
const headings = [
85+
{key: 'url', valueType: 'url', label: str_(UIStrings.columnInsecureURL)},
86+
{key: 'resolution', valueType: 'text', label: str_(UIStrings.columnResolution)},
87+
];
8888

89-
for (const details of artifacts.InspectorIssues.mixedContentIssue) {
90-
let item = items.find(item => item.url === details.insecureURL);
91-
if (!item) {
92-
item = {url: details.insecureURL};
93-
items.push(item);
94-
}
95-
item.resolution = resolutionToString[details.resolutionStatus] ?
96-
str_(resolutionToString[details.resolutionStatus]) :
97-
details.resolutionStatus;
89+
for (const details of artifacts.InspectorIssues.mixedContentIssue) {
90+
let item = items.find(item => item.url === details.insecureURL);
91+
if (!item) {
92+
item = {url: details.insecureURL};
93+
items.push(item);
9894
}
95+
item.resolution = resolutionToString[details.resolutionStatus] ?
96+
str_(resolutionToString[details.resolutionStatus]) :
97+
details.resolutionStatus;
98+
}
9999

100-
// If a resolution wasn't assigned from an InspectorIssue, then the item
101-
// is not blocked by the browser but we've determined it is insecure anyhow.
102-
// For example, if the URL is localhost, all `http` requests are valid
103-
// (localhost is a secure context), but we still identify `http` requests
104-
// as an "Allowed" insecure URL.
105-
for (const item of items) {
106-
if (!item.resolution) item.resolution = str_(UIStrings.allowed);
107-
}
100+
// If a resolution wasn't assigned from an InspectorIssue, then the item
101+
// is not blocked by the browser but we've determined it is insecure anyhow.
102+
// For example, if the URL is localhost, all `http` requests are valid
103+
// (localhost is a secure context), but we still identify `http` requests
104+
// as an "Allowed" insecure URL.
105+
for (const item of items) {
106+
if (!item.resolution) item.resolution = str_(UIStrings.allowed);
107+
}
108108

109-
let displayValue;
110-
if (items.length > 0) {
111-
displayValue = str_(UIStrings.displayValue, {itemCount: items.length});
112-
}
109+
let displayValue;
110+
if (items.length > 0) {
111+
displayValue = str_(UIStrings.displayValue, {itemCount: items.length});
112+
}
113113

114-
return {
115-
score: Number(items.length === 0),
116-
displayValue,
117-
details: Audit.makeTableDetails(headings, items),
118-
};
119-
});
114+
return {
115+
score: Number(items.length === 0),
116+
displayValue,
117+
details: Audit.makeTableDetails(headings, items),
118+
};
120119
}
121120
}
122121

0 commit comments

Comments
 (0)