lighthouse 12.4.0 → 12.5.0-dev.20250325
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/core/audits/audit.js +3 -1
- package/core/audits/bootup-time.js +1 -1
- package/core/audits/byte-efficiency/duplicated-javascript.js +1 -1
- package/core/audits/byte-efficiency/efficient-animated-content.js +1 -1
- package/core/audits/byte-efficiency/legacy-javascript.d.ts +0 -65
- package/core/audits/byte-efficiency/legacy-javascript.js +11 -363
- package/core/audits/byte-efficiency/modern-image-formats.js +1 -1
- package/core/audits/byte-efficiency/offscreen-images.js +4 -3
- package/core/audits/byte-efficiency/render-blocking-resources.js +6 -3
- package/core/audits/byte-efficiency/unminified-css.js +2 -1
- package/core/audits/byte-efficiency/unminified-javascript.js +2 -1
- package/core/audits/byte-efficiency/unused-css-rules.js +1 -1
- package/core/audits/byte-efficiency/unused-javascript.js +2 -2
- package/core/audits/byte-efficiency/uses-long-cache-ttl.js +1 -1
- package/core/audits/byte-efficiency/uses-optimized-images.js +1 -1
- package/core/audits/byte-efficiency/uses-responsive-images.js +1 -1
- package/core/audits/byte-efficiency/uses-text-compression.js +2 -1
- package/core/audits/critical-request-chains.js +5 -3
- package/core/audits/dobetterweb/dom-size.js +1 -1
- package/core/audits/dobetterweb/uses-http2.js +1 -1
- package/core/audits/insights/cls-culprits-insight.js +1 -1
- package/core/audits/insights/document-latency-insight.js +1 -1
- package/core/audits/insights/dom-size-insight.js +1 -1
- package/core/audits/insights/{long-critical-network-tree-insight.d.ts → duplicated-javascript-insight.d.ts} +3 -3
- package/core/audits/insights/duplicated-javascript-insight.js +54 -0
- package/core/audits/insights/font-display-insight.js +8 -7
- package/core/audits/insights/forced-reflow-insight.d.ts +10 -0
- package/core/audits/insights/forced-reflow-insight.js +64 -12
- package/core/audits/insights/image-delivery-insight.js +9 -10
- package/core/audits/insights/insight-audit.js +9 -4
- package/core/audits/insights/interaction-to-next-paint-insight.js +1 -1
- package/core/audits/insights/lcp-discovery-insight.js +1 -1
- package/core/audits/insights/lcp-phases-insight.js +1 -1
- package/core/audits/insights/network-dependency-tree-insight.d.ts +11 -0
- package/core/audits/insights/{long-critical-network-tree-insight.js → network-dependency-tree-insight.js} +7 -7
- package/core/audits/insights/render-blocking-insight.js +1 -1
- package/core/audits/insights/slow-css-selector-insight.js +1 -1
- package/core/audits/insights/third-parties-insight.js +1 -1
- package/core/audits/insights/use-cache-insight.d.ts +11 -0
- package/core/audits/insights/use-cache-insight.js +61 -0
- package/core/audits/insights/viewport-insight.js +1 -1
- package/core/audits/largest-contentful-paint-element.js +7 -3
- package/core/audits/layout-shifts.js +5 -2
- package/core/audits/lcp-lazy-loaded.js +1 -1
- package/core/audits/long-tasks.js +6 -4
- package/core/audits/mainthread-work-breakdown.js +1 -1
- package/core/audits/metrics/first-contentful-paint.js +4 -2
- package/core/audits/metrics/interactive.js +6 -3
- package/core/audits/metrics/largest-contentful-paint.js +7 -3
- package/core/audits/metrics/max-potential-fid.js +6 -3
- package/core/audits/metrics/speed-index.js +6 -3
- package/core/audits/metrics/total-blocking-time.js +6 -3
- package/core/audits/metrics.js +4 -3
- package/core/audits/predictive-perf.js +4 -3
- package/core/audits/prioritize-lcp-image.js +5 -3
- package/core/audits/redirects.js +4 -2
- package/core/audits/script-treemap-data.js +8 -4
- package/core/audits/third-party-facades.js +1 -1
- package/core/audits/third-party-summary.js +1 -1
- package/core/audits/uses-rel-preconnect.js +7 -5
- package/core/audits/uses-rel-preload.js +5 -3
- package/core/computed/computed-artifact.d.ts +5 -1
- package/core/computed/computed-artifact.js +23 -2
- package/core/computed/critical-request-chains.d.ts +5 -1
- package/core/computed/critical-request-chains.js +4 -4
- package/core/computed/js-bundles.d.ts +1 -1
- package/core/computed/metrics/first-contentful-paint-all-frames.js +1 -1
- package/core/computed/metrics/first-contentful-paint.js +1 -1
- package/core/computed/metrics/interactive.js +1 -1
- package/core/computed/metrics/lantern-first-contentful-paint.js +1 -1
- package/core/computed/metrics/lantern-interactive.js +1 -1
- package/core/computed/metrics/lantern-largest-contentful-paint.js +1 -1
- package/core/computed/metrics/lantern-max-potential-fid.js +1 -1
- package/core/computed/metrics/lantern-metric.js +1 -1
- package/core/computed/metrics/lantern-speed-index.js +1 -1
- package/core/computed/metrics/lantern-total-blocking-time.js +1 -1
- package/core/computed/metrics/largest-contentful-paint-all-frames.js +1 -1
- package/core/computed/metrics/largest-contentful-paint.js +1 -1
- package/core/computed/metrics/lcp-breakdown.js +1 -1
- package/core/computed/metrics/max-potential-fid.js +1 -1
- package/core/computed/metrics/metric.js +2 -0
- package/core/computed/metrics/speed-index.js +1 -1
- package/core/computed/metrics/time-to-first-byte.js +1 -1
- package/core/computed/metrics/timing-summary.d.ts +5 -2
- package/core/computed/metrics/timing-summary.js +8 -4
- package/core/computed/metrics/total-blocking-time.js +1 -1
- package/core/computed/module-duplication.d.ts +1 -1
- package/core/computed/navigation-insights.d.ts +11 -3
- package/core/computed/navigation-insights.js +7 -4
- package/core/computed/page-dependency-graph.d.ts +7 -3
- package/core/computed/page-dependency-graph.js +6 -5
- package/core/computed/tbt-impact-tasks.js +1 -1
- package/core/computed/trace-engine-result.d.ts +36 -2
- package/core/computed/trace-engine-result.js +119 -25
- package/core/computed/unused-javascript-summary.d.ts +2 -2
- package/core/computed/unused-javascript-summary.js +1 -1
- package/core/config/default-config.js +19 -15
- package/core/config/experimental-config.js +19 -0
- package/core/gather/gatherers/source-maps.d.ts +1 -0
- package/core/gather/gatherers/source-maps.js +3 -0
- package/core/gather/gatherers/trace-elements.d.ts +4 -4
- package/core/gather/gatherers/trace-elements.js +8 -4
- package/core/gather/gatherers/trace.js +5 -0
- package/core/lib/bf-cache-strings.d.ts +0 -122
- package/core/lib/bf-cache-strings.js +1 -2
- package/core/lib/deprecation-description.js +2 -1
- package/core/lib/legacy-javascript/legacy-javascript.d.ts +29 -0
- package/core/lib/legacy-javascript/legacy-javascript.js +351 -0
- package/core/lib/legacy-javascript/polyfill-graph-data.json +93 -0
- package/core/lib/legacy-javascript/polyfill-module-data.json +623 -0
- package/core/lib/trace-engine.d.ts +6 -1
- package/core/lib/trace-engine.js +1 -2
- package/package.json +10 -8
- package/shared/localization/locales/ar-XB.json +783 -513
- package/shared/localization/locales/ar.json +783 -513
- package/shared/localization/locales/bg.json +933 -663
- package/shared/localization/locales/ca.json +925 -655
- package/shared/localization/locales/cs.json +926 -656
- package/shared/localization/locales/da.json +926 -656
- package/shared/localization/locales/de.json +803 -533
- package/shared/localization/locales/el.json +928 -658
- package/shared/localization/locales/en-GB.json +929 -659
- package/shared/localization/locales/en-US.json +593 -551
- package/shared/localization/locales/en-XA.json +28 -508
- package/shared/localization/locales/en-XL.json +593 -551
- package/shared/localization/locales/es-419.json +928 -658
- package/shared/localization/locales/es.json +787 -517
- package/shared/localization/locales/fi.json +925 -655
- package/shared/localization/locales/fil.json +929 -659
- package/shared/localization/locales/fr.json +927 -657
- package/shared/localization/locales/he.json +795 -528
- package/shared/localization/locales/hi.json +798 -528
- package/shared/localization/locales/hr.json +929 -659
- package/shared/localization/locales/hu.json +926 -656
- package/shared/localization/locales/id.json +926 -656
- package/shared/localization/locales/it.json +930 -660
- package/shared/localization/locales/ja.json +927 -657
- package/shared/localization/locales/ko.json +936 -666
- package/shared/localization/locales/lt.json +933 -663
- package/shared/localization/locales/lv.json +809 -539
- package/shared/localization/locales/nl.json +925 -655
- package/shared/localization/locales/no.json +928 -658
- package/shared/localization/locales/pl.json +927 -657
- package/shared/localization/locales/pt-PT.json +841 -571
- package/shared/localization/locales/pt.json +841 -571
- package/shared/localization/locales/ro.json +925 -655
- package/shared/localization/locales/ru.json +935 -668
- package/shared/localization/locales/sk.json +925 -655
- package/shared/localization/locales/sl.json +927 -657
- package/shared/localization/locales/sr-Latn.json +925 -655
- package/shared/localization/locales/sr.json +925 -655
- package/shared/localization/locales/sv.json +936 -666
- package/shared/localization/locales/ta.json +935 -668
- package/shared/localization/locales/te.json +785 -515
- package/shared/localization/locales/th.json +813 -543
- package/shared/localization/locales/tr.json +927 -657
- package/shared/localization/locales/uk.json +795 -525
- package/shared/localization/locales/vi.json +929 -659
- package/shared/localization/locales/zh-HK.json +926 -656
- package/shared/localization/locales/zh-TW.json +784 -514
- package/shared/localization/locales/zh.json +926 -656
- package/tsconfig.json +2 -1
- package/types/artifacts.d.ts +2 -1
- package/core/audits/byte-efficiency/polyfill-graph-data.json +0 -53
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright 2025 Google LLC
|
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {UIStrings} from '@paulirish/trace_engine/models/trace/insights/UseCache.js';
|
|
8
|
+
|
|
9
|
+
import {Audit} from '../audit.js';
|
|
10
|
+
import * as i18n from '../../lib/i18n/i18n.js';
|
|
11
|
+
import {adaptInsightToAuditProduct} from './insight-audit.js';
|
|
12
|
+
|
|
13
|
+
// eslint-disable-next-line max-len
|
|
14
|
+
const str_ = i18n.createIcuMessageFn('node_modules/@paulirish/trace_engine/models/trace/insights/UseCache.js', UIStrings);
|
|
15
|
+
|
|
16
|
+
class UseCacheInsight extends Audit {
|
|
17
|
+
/**
|
|
18
|
+
* @return {LH.Audit.Meta}
|
|
19
|
+
*/
|
|
20
|
+
static get meta() {
|
|
21
|
+
return {
|
|
22
|
+
id: 'use-cache-insight',
|
|
23
|
+
title: str_(UIStrings.title),
|
|
24
|
+
failureTitle: str_(UIStrings.title),
|
|
25
|
+
description: str_(UIStrings.description),
|
|
26
|
+
guidanceLevel: 3,
|
|
27
|
+
requiredArtifacts: ['traces', 'SourceMaps'],
|
|
28
|
+
replacesAudits: ['uses-long-cache-ttl'],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* @param {LH.Artifacts} artifacts
|
|
34
|
+
* @param {LH.Audit.Context} context
|
|
35
|
+
* @return {Promise<LH.Audit.Product>}
|
|
36
|
+
*/
|
|
37
|
+
static async audit(artifacts, context) {
|
|
38
|
+
return adaptInsightToAuditProduct(artifacts, context, 'UseCache', (insight) => {
|
|
39
|
+
/** @type {LH.Audit.Details.Table['headings']} */
|
|
40
|
+
const headings = [
|
|
41
|
+
/* eslint-disable max-len */
|
|
42
|
+
{key: 'url', valueType: 'url', label: str_(UIStrings.requestColumn)},
|
|
43
|
+
{key: 'cacheLifetimeMs', valueType: 'ms', label: str_(UIStrings.cacheTTL), displayUnit: 'duration'},
|
|
44
|
+
{key: 'totalBytes', valueType: 'bytes', label: str_(i18n.UIStrings.columnTransferSize), displayUnit: 'kb', granularity: 1},
|
|
45
|
+
/* eslint-enable max-len */
|
|
46
|
+
];
|
|
47
|
+
/** @type {LH.Audit.Details.Table['items']} */
|
|
48
|
+
const items = insight.requests.map(request => ({
|
|
49
|
+
url: request.request.args.data.url,
|
|
50
|
+
cacheLifetimeMs: request.ttl * 1000,
|
|
51
|
+
totalBytes: request.request.args.data.encodedDataLength,
|
|
52
|
+
}));
|
|
53
|
+
return Audit.makeTableDetails(headings, items, {
|
|
54
|
+
sortedBy: ['totalBytes'],
|
|
55
|
+
skipSumming: ['cacheLifetimeMs'],
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export default UseCacheInsight;
|
|
@@ -24,7 +24,7 @@ class ViewportInsight extends Audit {
|
|
|
24
24
|
failureTitle: str_(UIStrings.title),
|
|
25
25
|
description: str_(UIStrings.description),
|
|
26
26
|
guidanceLevel: 3,
|
|
27
|
-
requiredArtifacts: ['traces', 'TraceElements'],
|
|
27
|
+
requiredArtifacts: ['traces', 'TraceElements', 'SourceMaps'],
|
|
28
28
|
replacesAudits: ['viewport'],
|
|
29
29
|
};
|
|
30
30
|
}
|
|
@@ -50,7 +50,8 @@ class LargestContentfulPaintElement extends Audit {
|
|
|
50
50
|
guidanceLevel: 1,
|
|
51
51
|
supportedModes: ['navigation'],
|
|
52
52
|
requiredArtifacts:
|
|
53
|
-
['traces', 'TraceElements', 'devtoolsLogs', 'GatherContext', 'settings', 'URL'
|
|
53
|
+
['traces', 'TraceElements', 'devtoolsLogs', 'GatherContext', 'settings', 'URL',
|
|
54
|
+
'SourceMaps'],
|
|
54
55
|
};
|
|
55
56
|
}
|
|
56
57
|
|
|
@@ -122,8 +123,11 @@ class LargestContentfulPaintElement extends Audit {
|
|
|
122
123
|
const trace = artifacts.traces[Audit.DEFAULT_PASS];
|
|
123
124
|
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
|
|
124
125
|
const gatherContext = artifacts.GatherContext;
|
|
125
|
-
const metricComputationData = {
|
|
126
|
-
|
|
126
|
+
const metricComputationData = {
|
|
127
|
+
trace, devtoolsLog, gatherContext,
|
|
128
|
+
settings: context.settings, URL: artifacts.URL,
|
|
129
|
+
SourceMaps: artifacts.SourceMaps, simulator: null,
|
|
130
|
+
};
|
|
127
131
|
|
|
128
132
|
const elementTable = this.makeElementTable(artifacts);
|
|
129
133
|
if (!elementTable) {
|
|
@@ -47,7 +47,7 @@ class LayoutShifts extends Audit {
|
|
|
47
47
|
description: str_(UIStrings.description),
|
|
48
48
|
scoreDisplayMode: Audit.SCORING_MODES.METRIC_SAVINGS,
|
|
49
49
|
guidanceLevel: 2,
|
|
50
|
-
requiredArtifacts: ['traces', 'TraceElements'],
|
|
50
|
+
requiredArtifacts: ['traces', 'TraceElements', 'SourceMaps'],
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
53
|
|
|
@@ -57,8 +57,11 @@ class LayoutShifts extends Audit {
|
|
|
57
57
|
* @return {Promise<LH.Audit.Product>}
|
|
58
58
|
*/
|
|
59
59
|
static async audit(artifacts, context) {
|
|
60
|
+
const settings = context.settings;
|
|
60
61
|
const trace = artifacts.traces[Audit.DEFAULT_PASS];
|
|
61
|
-
const
|
|
62
|
+
const SourceMaps = artifacts.SourceMaps;
|
|
63
|
+
const traceEngineResult =
|
|
64
|
+
await TraceEngineResult.request({trace, settings, SourceMaps}, context);
|
|
62
65
|
const clusters = traceEngineResult.data.LayoutShifts.clusters ?? [];
|
|
63
66
|
const {cumulativeLayoutShift: clsSavings, impactByNodeId} =
|
|
64
67
|
await CumulativeLayoutShiftComputed.request(trace, context);
|
|
@@ -36,7 +36,7 @@ class LargestContentfulPaintLazyLoaded extends Audit {
|
|
|
36
36
|
scoreDisplayMode: Audit.SCORING_MODES.METRIC_SAVINGS,
|
|
37
37
|
guidanceLevel: 3,
|
|
38
38
|
requiredArtifacts: ['TraceElements', 'ViewportDimensions', 'ImageElements',
|
|
39
|
-
'traces', 'devtoolsLogs', 'GatherContext', 'URL'],
|
|
39
|
+
'traces', 'devtoolsLogs', 'GatherContext', 'URL', 'SourceMaps'],
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -68,7 +68,7 @@ class LongTasks extends Audit {
|
|
|
68
68
|
scoreDisplayMode: Audit.SCORING_MODES.INFORMATIVE,
|
|
69
69
|
title: str_(UIStrings.title),
|
|
70
70
|
description: str_(UIStrings.description),
|
|
71
|
-
requiredArtifacts: ['traces', 'devtoolsLogs', 'URL', 'GatherContext'],
|
|
71
|
+
requiredArtifacts: ['traces', 'devtoolsLogs', 'URL', 'GatherContext', 'SourceMaps'],
|
|
72
72
|
guidanceLevel: 1,
|
|
73
73
|
};
|
|
74
74
|
}
|
|
@@ -176,7 +176,7 @@ class LongTasks extends Audit {
|
|
|
176
176
|
*/
|
|
177
177
|
static async audit(artifacts, context) {
|
|
178
178
|
const settings = context.settings || {};
|
|
179
|
-
const URL = artifacts
|
|
179
|
+
const {URL, SourceMaps} = artifacts;
|
|
180
180
|
const trace = artifacts.traces[Audit.DEFAULT_PASS];
|
|
181
181
|
const tasks = await MainThreadTasks.request(trace, context);
|
|
182
182
|
const devtoolsLog = artifacts.devtoolsLogs[LongTasks.DEFAULT_PASS];
|
|
@@ -192,9 +192,11 @@ class LongTasks extends Audit {
|
|
|
192
192
|
taskTimingsByEvent = new Map();
|
|
193
193
|
|
|
194
194
|
const simulatorOptions = {devtoolsLog, settings: context.settings};
|
|
195
|
-
const pageGraph =
|
|
195
|
+
const pageGraph =
|
|
196
|
+
// eslint-disable-next-line max-len
|
|
197
|
+
await PageDependencyGraph.request({settings, trace, devtoolsLog, URL, SourceMaps, fromTrace: false}, context);
|
|
196
198
|
const simulator = await LoadSimulator.request(simulatorOptions, context);
|
|
197
|
-
const simulation =
|
|
199
|
+
const simulation = simulator.simulate(pageGraph, {label: 'long-tasks-diagnostic'});
|
|
198
200
|
for (const [node, timing] of simulation.nodeTimings.entries()) {
|
|
199
201
|
if (node.type !== 'cpu') continue;
|
|
200
202
|
taskTimingsByEvent.set(node.event, timing);
|
|
@@ -46,7 +46,7 @@ class MainThreadWorkBreakdown extends Audit {
|
|
|
46
46
|
description: str_(UIStrings.description),
|
|
47
47
|
scoreDisplayMode: Audit.SCORING_MODES.METRIC_SAVINGS,
|
|
48
48
|
guidanceLevel: 1,
|
|
49
|
-
requiredArtifacts: ['traces', 'devtoolsLogs', 'URL', 'GatherContext'],
|
|
49
|
+
requiredArtifacts: ['traces', 'devtoolsLogs', 'URL', 'GatherContext', 'SourceMaps'],
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
52
|
|
|
@@ -27,7 +27,7 @@ class FirstContentfulPaint extends Audit {
|
|
|
27
27
|
description: str_(UIStrings.description),
|
|
28
28
|
scoreDisplayMode: Audit.SCORING_MODES.NUMERIC,
|
|
29
29
|
supportedModes: ['navigation'],
|
|
30
|
-
requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL'],
|
|
30
|
+
requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL', 'SourceMaps'],
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -65,7 +65,9 @@ class FirstContentfulPaint extends Audit {
|
|
|
65
65
|
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
|
|
66
66
|
const gatherContext = artifacts.GatherContext;
|
|
67
67
|
const metricComputationData = {trace, devtoolsLog, gatherContext,
|
|
68
|
-
settings: context.settings, URL: artifacts.URL
|
|
68
|
+
settings: context.settings, URL: artifacts.URL,
|
|
69
|
+
SourceMaps: artifacts.SourceMaps, simulator: null,
|
|
70
|
+
};
|
|
69
71
|
const metricResult = await ComputedFcp.request(metricComputationData, context);
|
|
70
72
|
const options = context.options[context.settings.formFactor];
|
|
71
73
|
|
|
@@ -33,7 +33,7 @@ class InteractiveMetric extends Audit {
|
|
|
33
33
|
description: str_(UIStrings.description),
|
|
34
34
|
scoreDisplayMode: Audit.SCORING_MODES.NUMERIC,
|
|
35
35
|
supportedModes: ['navigation'],
|
|
36
|
-
requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL'],
|
|
36
|
+
requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL', 'SourceMaps'],
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -70,8 +70,11 @@ class InteractiveMetric extends Audit {
|
|
|
70
70
|
const trace = artifacts.traces[Audit.DEFAULT_PASS];
|
|
71
71
|
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
|
|
72
72
|
const gatherContext = artifacts.GatherContext;
|
|
73
|
-
const metricComputationData = {
|
|
74
|
-
|
|
73
|
+
const metricComputationData = {
|
|
74
|
+
trace, devtoolsLog, gatherContext,
|
|
75
|
+
settings: context.settings, URL: artifacts.URL,
|
|
76
|
+
SourceMaps: artifacts.SourceMaps, simulator: null,
|
|
77
|
+
};
|
|
75
78
|
const metricResult = await Interactive.request(metricComputationData, context);
|
|
76
79
|
const timeInMs = metricResult.timing;
|
|
77
80
|
const options = context.options[context.settings.formFactor];
|
|
@@ -27,7 +27,8 @@ class LargestContentfulPaint extends Audit {
|
|
|
27
27
|
description: str_(UIStrings.description),
|
|
28
28
|
scoreDisplayMode: Audit.SCORING_MODES.NUMERIC,
|
|
29
29
|
supportedModes: ['navigation'],
|
|
30
|
-
requiredArtifacts: ['HostUserAgent', 'traces', 'devtoolsLogs', 'GatherContext', 'URL'
|
|
30
|
+
requiredArtifacts: ['HostUserAgent', 'traces', 'devtoolsLogs', 'GatherContext', 'URL',
|
|
31
|
+
'SourceMaps'],
|
|
31
32
|
};
|
|
32
33
|
}
|
|
33
34
|
|
|
@@ -72,8 +73,11 @@ class LargestContentfulPaint extends Audit {
|
|
|
72
73
|
const trace = artifacts.traces[Audit.DEFAULT_PASS];
|
|
73
74
|
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
|
|
74
75
|
const gatherContext = artifacts.GatherContext;
|
|
75
|
-
const metricComputationData = {
|
|
76
|
-
|
|
76
|
+
const metricComputationData = {
|
|
77
|
+
trace, devtoolsLog, gatherContext,
|
|
78
|
+
settings: context.settings, URL: artifacts.URL,
|
|
79
|
+
SourceMaps: artifacts.SourceMaps, simulator: null,
|
|
80
|
+
};
|
|
77
81
|
|
|
78
82
|
const metricResult = await ComputedLcp.request(metricComputationData, context);
|
|
79
83
|
const options = context.options[context.settings.formFactor];
|
|
@@ -43,7 +43,7 @@ class MaxPotentialFID extends Audit {
|
|
|
43
43
|
description: str_(UIStrings.description),
|
|
44
44
|
scoreDisplayMode: Audit.SCORING_MODES.NUMERIC,
|
|
45
45
|
supportedModes: ['navigation'],
|
|
46
|
-
requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL'],
|
|
46
|
+
requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL', 'SourceMaps'],
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
49
|
|
|
@@ -120,8 +120,11 @@ class MaxPotentialFID extends Audit {
|
|
|
120
120
|
const trace = artifacts.traces[Audit.DEFAULT_PASS];
|
|
121
121
|
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
|
|
122
122
|
const gatherContext = artifacts.GatherContext;
|
|
123
|
-
const metricComputationData = {
|
|
124
|
-
|
|
123
|
+
const metricComputationData = {
|
|
124
|
+
trace, devtoolsLog, gatherContext,
|
|
125
|
+
settings: context.settings, URL: artifacts.URL,
|
|
126
|
+
SourceMaps: artifacts.SourceMaps, simulator: null,
|
|
127
|
+
};
|
|
125
128
|
const metricResult = await ComputedFid.request(metricComputationData, context);
|
|
126
129
|
|
|
127
130
|
const processedTrace = await ProcessedTrace.request(trace, context);
|
|
@@ -27,7 +27,7 @@ class SpeedIndex extends Audit {
|
|
|
27
27
|
description: str_(UIStrings.description),
|
|
28
28
|
scoreDisplayMode: Audit.SCORING_MODES.NUMERIC,
|
|
29
29
|
supportedModes: ['navigation'],
|
|
30
|
-
requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL'],
|
|
30
|
+
requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL', 'SourceMaps'],
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -66,8 +66,11 @@ class SpeedIndex extends Audit {
|
|
|
66
66
|
const trace = artifacts.traces[Audit.DEFAULT_PASS];
|
|
67
67
|
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
|
|
68
68
|
const gatherContext = artifacts.GatherContext;
|
|
69
|
-
const metricComputationData = {
|
|
70
|
-
|
|
69
|
+
const metricComputationData = {
|
|
70
|
+
trace, devtoolsLog, gatherContext,
|
|
71
|
+
settings: context.settings, URL: artifacts.URL,
|
|
72
|
+
SourceMaps: artifacts.SourceMaps, simulator: null,
|
|
73
|
+
};
|
|
71
74
|
const metricResult = await ComputedSi.request(metricComputationData, context);
|
|
72
75
|
const options = context.options[context.settings.formFactor];
|
|
73
76
|
|
|
@@ -27,7 +27,7 @@ class TotalBlockingTime extends Audit {
|
|
|
27
27
|
title: str_(i18n.UIStrings.totalBlockingTimeMetric),
|
|
28
28
|
description: str_(UIStrings.description),
|
|
29
29
|
scoreDisplayMode: Audit.SCORING_MODES.NUMERIC,
|
|
30
|
-
requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL'],
|
|
30
|
+
requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL', 'SourceMaps'],
|
|
31
31
|
};
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -88,8 +88,11 @@ class TotalBlockingTime extends Audit {
|
|
|
88
88
|
const trace = artifacts.traces[Audit.DEFAULT_PASS];
|
|
89
89
|
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
|
|
90
90
|
const gatherContext = artifacts.GatherContext;
|
|
91
|
-
const metricComputationData = {
|
|
92
|
-
|
|
91
|
+
const metricComputationData = {
|
|
92
|
+
trace, devtoolsLog, gatherContext,
|
|
93
|
+
settings: context.settings, URL: artifacts.URL,
|
|
94
|
+
SourceMaps: artifacts.SourceMaps, simulator: null,
|
|
95
|
+
};
|
|
93
96
|
if (
|
|
94
97
|
gatherContext.gatherMode === 'timespan' &&
|
|
95
98
|
context.settings.throttlingMethod === 'simulate'
|
package/core/audits/metrics.js
CHANGED
|
@@ -26,7 +26,7 @@ class Metrics extends Audit {
|
|
|
26
26
|
title: 'Metrics',
|
|
27
27
|
description: 'Collects all available metrics.',
|
|
28
28
|
supportedModes: ['navigation'],
|
|
29
|
-
requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL'],
|
|
29
|
+
requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL', 'SourceMaps'],
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -36,12 +36,13 @@ class Metrics extends Audit {
|
|
|
36
36
|
* @return {Promise<LH.Audit.Product>}
|
|
37
37
|
*/
|
|
38
38
|
static async audit(artifacts, context) {
|
|
39
|
+
const settings = context.settings;
|
|
39
40
|
const gatherContext = artifacts.GatherContext;
|
|
40
41
|
const trace = artifacts.traces[Audit.DEFAULT_PASS];
|
|
41
42
|
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
|
|
42
|
-
const URL = artifacts
|
|
43
|
+
const {URL, SourceMaps} = artifacts;
|
|
43
44
|
const summary = await TimingSummary
|
|
44
|
-
.request({trace, devtoolsLog, gatherContext, settings
|
|
45
|
+
.request({trace, devtoolsLog, gatherContext, settings, URL, SourceMaps}, context);
|
|
45
46
|
const metrics = summary.metrics;
|
|
46
47
|
const debugInfo = summary.debugInfo;
|
|
47
48
|
|
|
@@ -33,7 +33,7 @@ class PredictivePerf extends Audit {
|
|
|
33
33
|
'a cellular connection on a mobile device.',
|
|
34
34
|
scoreDisplayMode: Audit.SCORING_MODES.NUMERIC,
|
|
35
35
|
supportedModes: ['navigation'],
|
|
36
|
-
requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL'],
|
|
36
|
+
requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL', 'SourceMaps'],
|
|
37
37
|
};
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -46,10 +46,11 @@ class PredictivePerf extends Audit {
|
|
|
46
46
|
const gatherContext = artifacts.GatherContext;
|
|
47
47
|
const trace = artifacts.traces[Audit.DEFAULT_PASS];
|
|
48
48
|
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
|
|
49
|
-
const URL = artifacts
|
|
49
|
+
const {URL, SourceMaps} = artifacts;
|
|
50
50
|
/** @type {LH.Config.Settings} */
|
|
51
51
|
const settings = JSON.parse(JSON.stringify(defaultSettings)); // Use default settings.
|
|
52
|
-
const computationData =
|
|
52
|
+
const computationData =
|
|
53
|
+
{trace, devtoolsLog, gatherContext, settings, URL, SourceMaps, simulator: null};
|
|
53
54
|
const fcp = await LanternFirstContentfulPaint.request(computationData, context);
|
|
54
55
|
const tti = await LanternInteractive.request(computationData, context);
|
|
55
56
|
const si = await LanternSpeedIndex.request(computationData, context);
|
|
@@ -38,7 +38,8 @@ class PrioritizeLcpImage extends Audit {
|
|
|
38
38
|
description: str_(UIStrings.description),
|
|
39
39
|
supportedModes: ['navigation'],
|
|
40
40
|
guidanceLevel: 4,
|
|
41
|
-
requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL', 'TraceElements'
|
|
41
|
+
requiredArtifacts: ['traces', 'devtoolsLogs', 'GatherContext', 'URL', 'TraceElements',
|
|
42
|
+
'SourceMaps'],
|
|
42
43
|
scoreDisplayMode: Audit.SCORING_MODES.METRIC_SAVINGS,
|
|
43
44
|
};
|
|
44
45
|
}
|
|
@@ -237,9 +238,10 @@ class PrioritizeLcpImage extends Audit {
|
|
|
237
238
|
const gatherContext = artifacts.GatherContext;
|
|
238
239
|
const trace = artifacts.traces[PrioritizeLcpImage.DEFAULT_PASS];
|
|
239
240
|
const devtoolsLog = artifacts.devtoolsLogs[PrioritizeLcpImage.DEFAULT_PASS];
|
|
240
|
-
const URL = artifacts
|
|
241
|
+
const {URL, SourceMaps} = artifacts;
|
|
241
242
|
const settings = context.settings;
|
|
242
|
-
const metricData =
|
|
243
|
+
const metricData =
|
|
244
|
+
{trace, devtoolsLog, gatherContext, settings, URL, SourceMaps, simulator: null};
|
|
243
245
|
const lcpElement = artifacts.TraceElements
|
|
244
246
|
.find(element => element.traceEventType === 'largest-contentful-paint');
|
|
245
247
|
|
package/core/audits/redirects.js
CHANGED
|
@@ -31,7 +31,7 @@ class Redirects extends Audit {
|
|
|
31
31
|
scoreDisplayMode: Audit.SCORING_MODES.METRIC_SAVINGS,
|
|
32
32
|
supportedModes: ['navigation'],
|
|
33
33
|
guidanceLevel: 2,
|
|
34
|
-
requiredArtifacts: ['URL', 'GatherContext', 'devtoolsLogs', 'traces'],
|
|
34
|
+
requiredArtifacts: ['URL', 'GatherContext', 'devtoolsLogs', 'traces', 'SourceMaps'],
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -87,12 +87,14 @@ class Redirects extends Audit {
|
|
|
87
87
|
const trace = artifacts.traces[Audit.DEFAULT_PASS];
|
|
88
88
|
const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
|
|
89
89
|
const gatherContext = artifacts.GatherContext;
|
|
90
|
+
const {URL, SourceMaps} = artifacts;
|
|
90
91
|
|
|
91
92
|
const processedTrace = await ProcessedTrace.request(trace, context);
|
|
92
93
|
const networkRecords = await NetworkRecords.request(devtoolsLog, context);
|
|
93
94
|
const documentRequests = Redirects.getDocumentRequestChain(networkRecords, processedTrace);
|
|
94
95
|
|
|
95
|
-
const metricComputationData =
|
|
96
|
+
const metricComputationData =
|
|
97
|
+
{trace, devtoolsLog, gatherContext, settings, URL, SourceMaps, simulator: null};
|
|
96
98
|
const metricResult = await LanternInteractive.request(metricComputationData, context);
|
|
97
99
|
|
|
98
100
|
/** @type {Map<string, LH.Gatherer.Simulation.NodeTiming>} */
|
|
@@ -31,7 +31,7 @@ class ScriptTreemapDataAudit extends Audit {
|
|
|
31
31
|
title: 'Script Treemap Data',
|
|
32
32
|
description: 'Used for treemap app',
|
|
33
33
|
requiredArtifacts:
|
|
34
|
-
['traces', 'devtoolsLogs', 'SourceMaps', 'Scripts', 'JsUsage', 'URL'],
|
|
34
|
+
['traces', 'devtoolsLogs', 'SourceMaps', 'Scripts', 'JsUsage', 'URL', 'SourceMaps'],
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -114,8 +114,12 @@ class ScriptTreemapDataAudit extends Audit {
|
|
|
114
114
|
*/
|
|
115
115
|
function collapseAll(node) {
|
|
116
116
|
while (node.children && node.children.length === 1) {
|
|
117
|
-
|
|
118
|
-
node.
|
|
117
|
+
const child = node.children[0];
|
|
118
|
+
node.name += '/' + child.name;
|
|
119
|
+
if (child.duplicatedNormalizedModuleName) {
|
|
120
|
+
node.duplicatedNormalizedModuleName = child.duplicatedNormalizedModuleName;
|
|
121
|
+
}
|
|
122
|
+
node.children = child.children;
|
|
119
123
|
}
|
|
120
124
|
|
|
121
125
|
if (node.children) {
|
|
@@ -174,7 +178,7 @@ class ScriptTreemapDataAudit extends Audit {
|
|
|
174
178
|
if (script.scriptLanguage !== 'JavaScript') continue;
|
|
175
179
|
|
|
176
180
|
const name = script.url;
|
|
177
|
-
const bundle = bundles.find(bundle => script.scriptId === bundle.script.scriptId);
|
|
181
|
+
const bundle = bundles.find(bundle => script.scriptId === bundle.script.scriptId) ?? null;
|
|
178
182
|
const scriptCoverage = /** @type {LH.Artifacts['JsUsage'][string] | undefined} */
|
|
179
183
|
(artifacts.JsUsage[script.scriptId]);
|
|
180
184
|
const unusedJavascriptSummary = scriptCoverage ?
|
|
@@ -87,7 +87,7 @@ class ThirdPartyFacades extends Audit {
|
|
|
87
87
|
description: str_(UIStrings.description),
|
|
88
88
|
supportedModes: ['navigation'],
|
|
89
89
|
guidanceLevel: 3,
|
|
90
|
-
requiredArtifacts: ['traces', 'devtoolsLogs', 'URL', 'GatherContext'],
|
|
90
|
+
requiredArtifacts: ['traces', 'devtoolsLogs', 'URL', 'GatherContext', 'SourceMaps'],
|
|
91
91
|
scoreDisplayMode: Audit.SCORING_MODES.METRIC_SAVINGS,
|
|
92
92
|
};
|
|
93
93
|
}
|
|
@@ -67,7 +67,7 @@ class ThirdPartySummary extends Audit {
|
|
|
67
67
|
description: str_(UIStrings.description),
|
|
68
68
|
guidanceLevel: 1,
|
|
69
69
|
scoreDisplayMode: Audit.SCORING_MODES.METRIC_SAVINGS,
|
|
70
|
-
requiredArtifacts: ['traces', 'devtoolsLogs', 'URL', 'GatherContext'],
|
|
70
|
+
requiredArtifacts: ['traces', 'devtoolsLogs', 'URL', 'GatherContext', 'SourceMaps'],
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
73
|
|
|
@@ -62,7 +62,7 @@ class UsesRelPreconnectAudit extends Audit {
|
|
|
62
62
|
description: str_(UIStrings.description),
|
|
63
63
|
supportedModes: ['navigation'],
|
|
64
64
|
guidanceLevel: 3,
|
|
65
|
-
requiredArtifacts: ['traces', 'devtoolsLogs', 'URL', 'LinkElements'],
|
|
65
|
+
requiredArtifacts: ['traces', 'devtoolsLogs', 'URL', 'LinkElements', 'SourceMaps'],
|
|
66
66
|
scoreDisplayMode: Audit.SCORING_MODES.METRIC_SAVINGS,
|
|
67
67
|
};
|
|
68
68
|
}
|
|
@@ -124,6 +124,7 @@ class UsesRelPreconnectAudit extends Audit {
|
|
|
124
124
|
static async audit(artifacts, context) {
|
|
125
125
|
const trace = artifacts.traces[UsesRelPreconnectAudit.DEFAULT_PASS];
|
|
126
126
|
const devtoolsLog = artifacts.devtoolsLogs[UsesRelPreconnectAudit.DEFAULT_PASS];
|
|
127
|
+
const {URL, SourceMaps} = artifacts;
|
|
127
128
|
const settings = context.settings;
|
|
128
129
|
|
|
129
130
|
let maxWastedLcp = 0;
|
|
@@ -134,15 +135,16 @@ class UsesRelPreconnectAudit extends Audit {
|
|
|
134
135
|
const [networkRecords, mainResource, loadSimulator, processedNavigation, pageGraph] =
|
|
135
136
|
await Promise.all([
|
|
136
137
|
NetworkRecords.request(devtoolsLog, context),
|
|
137
|
-
MainResource.request({devtoolsLog, URL
|
|
138
|
+
MainResource.request({devtoolsLog, URL}, context),
|
|
138
139
|
LoadSimulator.request({devtoolsLog, settings}, context),
|
|
139
140
|
ProcessedNavigation.request(trace, context),
|
|
140
|
-
PageDependencyGraph.request(
|
|
141
|
+
PageDependencyGraph.request(
|
|
142
|
+
{settings, trace, devtoolsLog, URL, SourceMaps, fromTrace: false}, context),
|
|
141
143
|
]);
|
|
142
144
|
|
|
143
145
|
const {rtt, additionalRttByOrigin} = loadSimulator.getOptions();
|
|
144
146
|
const lcpGraph =
|
|
145
|
-
|
|
147
|
+
LanternLargestContentfulPaint.getPessimisticGraph(pageGraph, processedNavigation);
|
|
146
148
|
/** @type {Set<string>} */
|
|
147
149
|
const lcpGraphURLs = new Set();
|
|
148
150
|
lcpGraph.traverse(node => {
|
|
@@ -150,7 +152,7 @@ class UsesRelPreconnectAudit extends Audit {
|
|
|
150
152
|
});
|
|
151
153
|
|
|
152
154
|
const fcpGraph =
|
|
153
|
-
|
|
155
|
+
LanternFirstContentfulPaint.getPessimisticGraph(pageGraph, processedNavigation);
|
|
154
156
|
const fcpGraphURLs = new Set();
|
|
155
157
|
fcpGraph.traverse(node => {
|
|
156
158
|
if (node.type === 'network') fcpGraphURLs.add(node.request.url);
|
|
@@ -44,7 +44,7 @@ class UsesRelPreloadAudit extends Audit {
|
|
|
44
44
|
description: str_(UIStrings.description),
|
|
45
45
|
supportedModes: ['navigation'],
|
|
46
46
|
guidanceLevel: 3,
|
|
47
|
-
requiredArtifacts: ['devtoolsLogs', 'traces', 'URL'],
|
|
47
|
+
requiredArtifacts: ['devtoolsLogs', 'traces', 'URL', 'SourceMaps'],
|
|
48
48
|
scoreDisplayMode: Audit.SCORING_MODES.METRIC_SAVINGS,
|
|
49
49
|
};
|
|
50
50
|
}
|
|
@@ -212,14 +212,16 @@ class UsesRelPreloadAudit extends Audit {
|
|
|
212
212
|
* @return {Promise<LH.Audit.Product>}
|
|
213
213
|
*/
|
|
214
214
|
static async audit(artifacts, context) {
|
|
215
|
+
const settings = context.settings;
|
|
215
216
|
const trace = artifacts.traces[UsesRelPreloadAudit.DEFAULT_PASS];
|
|
216
217
|
const devtoolsLog = artifacts.devtoolsLogs[UsesRelPreloadAudit.DEFAULT_PASS];
|
|
217
|
-
const URL = artifacts
|
|
218
|
+
const {URL, SourceMaps} = artifacts;
|
|
218
219
|
const simulatorOptions = {devtoolsLog, settings: context.settings};
|
|
219
220
|
|
|
220
221
|
const [mainResource, graph, simulator] = await Promise.all([
|
|
221
222
|
MainResource.request({devtoolsLog, URL}, context),
|
|
222
|
-
PageDependencyGraph.request(
|
|
223
|
+
PageDependencyGraph.request(
|
|
224
|
+
{settings, trace, devtoolsLog, URL, SourceMaps, fromTrace: false}, context),
|
|
223
225
|
LoadSimulator.request(simulatorOptions, context),
|
|
224
226
|
]);
|
|
225
227
|
|
|
@@ -4,7 +4,11 @@
|
|
|
4
4
|
* @template {{name: string, compute_(dependencies: unknown, context: LH.Artifacts.ComputedContext): Promise<unknown>}} C
|
|
5
5
|
* @template {Array<keyof LH.Util.FirstParamType<C['compute_']>>} K
|
|
6
6
|
* @param {C} computableArtifact
|
|
7
|
-
* @param {(K & ([keyof LH.Util.FirstParamType<C['compute_']>] extends [K[number]] ? unknown : never)) | null} keys
|
|
7
|
+
* @param {(K & ([keyof LH.Util.FirstParamType<C['compute_']>] extends [K[number]] ? unknown : never)) | null} keys
|
|
8
|
+
* List of properties of `dependencies` used by `compute_`; other properties are filtered out.
|
|
9
|
+
* Use `null` to allow all properties. Ensures that only required properties are used for caching result.
|
|
10
|
+
* For optional properties of `dependencies`, undefined cannot be used and if found is treated as an error.
|
|
11
|
+
* This is to guard against developer mistakes. For optional properties, make it nullable instead.
|
|
8
12
|
*/
|
|
9
13
|
export function makeComputedArtifact<C extends {
|
|
10
14
|
name: string;
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import log from 'lighthouse-logger';
|
|
8
8
|
|
|
9
9
|
import {ArbitraryEqualityMap} from '../lib/arbitrary-equality-map.js';
|
|
10
|
+
import {isUnderTest} from '../lib/lh-env.js';
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Decorate computableArtifact with a caching `request()` method which will
|
|
@@ -14,7 +15,11 @@ import {ArbitraryEqualityMap} from '../lib/arbitrary-equality-map.js';
|
|
|
14
15
|
* @template {{name: string, compute_(dependencies: unknown, context: LH.Artifacts.ComputedContext): Promise<unknown>}} C
|
|
15
16
|
* @template {Array<keyof LH.Util.FirstParamType<C['compute_']>>} K
|
|
16
17
|
* @param {C} computableArtifact
|
|
17
|
-
* @param {(K & ([keyof LH.Util.FirstParamType<C['compute_']>] extends [K[number]] ? unknown : never)) | null} keys
|
|
18
|
+
* @param {(K & ([keyof LH.Util.FirstParamType<C['compute_']>] extends [K[number]] ? unknown : never)) | null} keys
|
|
19
|
+
* List of properties of `dependencies` used by `compute_`; other properties are filtered out.
|
|
20
|
+
* Use `null` to allow all properties. Ensures that only required properties are used for caching result.
|
|
21
|
+
* For optional properties of `dependencies`, undefined cannot be used and if found is treated as an error.
|
|
22
|
+
* This is to guard against developer mistakes. For optional properties, make it nullable instead.
|
|
18
23
|
*/
|
|
19
24
|
function makeComputedArtifact(computableArtifact, keys) {
|
|
20
25
|
// tsc (3.1) has more difficulty with template inter-references in jsdoc, so
|
|
@@ -27,13 +32,29 @@ function makeComputedArtifact(computableArtifact, keys) {
|
|
|
27
32
|
* @return {ReturnType<C['compute_']>}
|
|
28
33
|
*/
|
|
29
34
|
const request = (dependencies, context) => {
|
|
35
|
+
const computedName = computableArtifact.name;
|
|
36
|
+
|
|
37
|
+
// Guard against missing properties. Optional properties must be passed as null - if missing or
|
|
38
|
+
// undefined, throw an error.
|
|
39
|
+
for (const key of keys || []) {
|
|
40
|
+
if (dependencies && typeof dependencies === 'object' && dependencies[key] === undefined) {
|
|
41
|
+
// eslint-disable-next-line max-len
|
|
42
|
+
const err = new Error(`missing required key "${String(key)}" for computed artifact ${computableArtifact.name}`);
|
|
43
|
+
if (isUnderTest) {
|
|
44
|
+
throw err;
|
|
45
|
+
} else {
|
|
46
|
+
// For now, simply log in production.
|
|
47
|
+
log.error(`lh:computed:${computedName}`, err);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
30
52
|
const pickedDependencies = keys ?
|
|
31
53
|
Object.fromEntries(keys.map(key => [key, dependencies[key]])) :
|
|
32
54
|
dependencies;
|
|
33
55
|
|
|
34
56
|
// NOTE: break immutability solely for this caching-controller function.
|
|
35
57
|
const computedCache = /** @type {Map<string, ArbitraryEqualityMap>} */ (context.computedCache);
|
|
36
|
-
const computedName = computableArtifact.name;
|
|
37
58
|
|
|
38
59
|
const cache = computedCache.get(computedName) || new ArbitraryEqualityMap();
|
|
39
60
|
computedCache.set(computedName, cache);
|
|
@@ -2,8 +2,10 @@ export { CriticalRequestChainsComputed as CriticalRequestChains };
|
|
|
2
2
|
declare const CriticalRequestChainsComputed: typeof CriticalRequestChains & {
|
|
3
3
|
request: (dependencies: {
|
|
4
4
|
URL: LH.Artifacts["URL"];
|
|
5
|
+
SourceMaps: LH.Artifacts["SourceMaps"];
|
|
5
6
|
devtoolsLog: LH.DevtoolsLog;
|
|
6
7
|
trace: LH.Trace;
|
|
8
|
+
settings: LH.Audit.Context["settings"];
|
|
7
9
|
}, context: LH.Artifacts.ComputedContext) => ReturnType<typeof CriticalRequestChains.compute_>;
|
|
8
10
|
};
|
|
9
11
|
declare class CriticalRequestChains {
|
|
@@ -24,14 +26,16 @@ declare class CriticalRequestChains {
|
|
|
24
26
|
*/
|
|
25
27
|
static extractChainsFromGraph(mainResource: LH.Artifacts.NetworkRequest, graph: LH.Gatherer.Simulation.GraphNode): LH.Artifacts.CriticalRequestNode;
|
|
26
28
|
/**
|
|
27
|
-
* @param {{URL: LH.Artifacts['URL'], devtoolsLog: LH.DevtoolsLog, trace: LH.Trace}} data
|
|
29
|
+
* @param {{URL: LH.Artifacts['URL'], SourceMaps: LH.Artifacts['SourceMaps'], devtoolsLog: LH.DevtoolsLog, trace: LH.Trace, settings: LH.Audit.Context['settings']}} data
|
|
28
30
|
* @param {LH.Artifacts.ComputedContext} context
|
|
29
31
|
* @return {Promise<LH.Artifacts.CriticalRequestNode>}
|
|
30
32
|
*/
|
|
31
33
|
static compute_(data: {
|
|
32
34
|
URL: LH.Artifacts["URL"];
|
|
35
|
+
SourceMaps: LH.Artifacts["SourceMaps"];
|
|
33
36
|
devtoolsLog: LH.DevtoolsLog;
|
|
34
37
|
trace: LH.Trace;
|
|
38
|
+
settings: LH.Audit.Context["settings"];
|
|
35
39
|
}, context: LH.Artifacts.ComputedContext): Promise<LH.Artifacts.CriticalRequestNode>;
|
|
36
40
|
}
|
|
37
41
|
import * as Lantern from '../lib/lantern/lantern.js';
|