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.
Files changed (164) hide show
  1. package/core/audits/audit.js +3 -1
  2. package/core/audits/bootup-time.js +1 -1
  3. package/core/audits/byte-efficiency/duplicated-javascript.js +1 -1
  4. package/core/audits/byte-efficiency/efficient-animated-content.js +1 -1
  5. package/core/audits/byte-efficiency/legacy-javascript.d.ts +0 -65
  6. package/core/audits/byte-efficiency/legacy-javascript.js +11 -363
  7. package/core/audits/byte-efficiency/modern-image-formats.js +1 -1
  8. package/core/audits/byte-efficiency/offscreen-images.js +4 -3
  9. package/core/audits/byte-efficiency/render-blocking-resources.js +6 -3
  10. package/core/audits/byte-efficiency/unminified-css.js +2 -1
  11. package/core/audits/byte-efficiency/unminified-javascript.js +2 -1
  12. package/core/audits/byte-efficiency/unused-css-rules.js +1 -1
  13. package/core/audits/byte-efficiency/unused-javascript.js +2 -2
  14. package/core/audits/byte-efficiency/uses-long-cache-ttl.js +1 -1
  15. package/core/audits/byte-efficiency/uses-optimized-images.js +1 -1
  16. package/core/audits/byte-efficiency/uses-responsive-images.js +1 -1
  17. package/core/audits/byte-efficiency/uses-text-compression.js +2 -1
  18. package/core/audits/critical-request-chains.js +5 -3
  19. package/core/audits/dobetterweb/dom-size.js +1 -1
  20. package/core/audits/dobetterweb/uses-http2.js +1 -1
  21. package/core/audits/insights/cls-culprits-insight.js +1 -1
  22. package/core/audits/insights/document-latency-insight.js +1 -1
  23. package/core/audits/insights/dom-size-insight.js +1 -1
  24. package/core/audits/insights/{long-critical-network-tree-insight.d.ts → duplicated-javascript-insight.d.ts} +3 -3
  25. package/core/audits/insights/duplicated-javascript-insight.js +54 -0
  26. package/core/audits/insights/font-display-insight.js +8 -7
  27. package/core/audits/insights/forced-reflow-insight.d.ts +10 -0
  28. package/core/audits/insights/forced-reflow-insight.js +64 -12
  29. package/core/audits/insights/image-delivery-insight.js +9 -10
  30. package/core/audits/insights/insight-audit.js +9 -4
  31. package/core/audits/insights/interaction-to-next-paint-insight.js +1 -1
  32. package/core/audits/insights/lcp-discovery-insight.js +1 -1
  33. package/core/audits/insights/lcp-phases-insight.js +1 -1
  34. package/core/audits/insights/network-dependency-tree-insight.d.ts +11 -0
  35. package/core/audits/insights/{long-critical-network-tree-insight.js → network-dependency-tree-insight.js} +7 -7
  36. package/core/audits/insights/render-blocking-insight.js +1 -1
  37. package/core/audits/insights/slow-css-selector-insight.js +1 -1
  38. package/core/audits/insights/third-parties-insight.js +1 -1
  39. package/core/audits/insights/use-cache-insight.d.ts +11 -0
  40. package/core/audits/insights/use-cache-insight.js +61 -0
  41. package/core/audits/insights/viewport-insight.js +1 -1
  42. package/core/audits/largest-contentful-paint-element.js +7 -3
  43. package/core/audits/layout-shifts.js +5 -2
  44. package/core/audits/lcp-lazy-loaded.js +1 -1
  45. package/core/audits/long-tasks.js +6 -4
  46. package/core/audits/mainthread-work-breakdown.js +1 -1
  47. package/core/audits/metrics/first-contentful-paint.js +4 -2
  48. package/core/audits/metrics/interactive.js +6 -3
  49. package/core/audits/metrics/largest-contentful-paint.js +7 -3
  50. package/core/audits/metrics/max-potential-fid.js +6 -3
  51. package/core/audits/metrics/speed-index.js +6 -3
  52. package/core/audits/metrics/total-blocking-time.js +6 -3
  53. package/core/audits/metrics.js +4 -3
  54. package/core/audits/predictive-perf.js +4 -3
  55. package/core/audits/prioritize-lcp-image.js +5 -3
  56. package/core/audits/redirects.js +4 -2
  57. package/core/audits/script-treemap-data.js +8 -4
  58. package/core/audits/third-party-facades.js +1 -1
  59. package/core/audits/third-party-summary.js +1 -1
  60. package/core/audits/uses-rel-preconnect.js +7 -5
  61. package/core/audits/uses-rel-preload.js +5 -3
  62. package/core/computed/computed-artifact.d.ts +5 -1
  63. package/core/computed/computed-artifact.js +23 -2
  64. package/core/computed/critical-request-chains.d.ts +5 -1
  65. package/core/computed/critical-request-chains.js +4 -4
  66. package/core/computed/js-bundles.d.ts +1 -1
  67. package/core/computed/metrics/first-contentful-paint-all-frames.js +1 -1
  68. package/core/computed/metrics/first-contentful-paint.js +1 -1
  69. package/core/computed/metrics/interactive.js +1 -1
  70. package/core/computed/metrics/lantern-first-contentful-paint.js +1 -1
  71. package/core/computed/metrics/lantern-interactive.js +1 -1
  72. package/core/computed/metrics/lantern-largest-contentful-paint.js +1 -1
  73. package/core/computed/metrics/lantern-max-potential-fid.js +1 -1
  74. package/core/computed/metrics/lantern-metric.js +1 -1
  75. package/core/computed/metrics/lantern-speed-index.js +1 -1
  76. package/core/computed/metrics/lantern-total-blocking-time.js +1 -1
  77. package/core/computed/metrics/largest-contentful-paint-all-frames.js +1 -1
  78. package/core/computed/metrics/largest-contentful-paint.js +1 -1
  79. package/core/computed/metrics/lcp-breakdown.js +1 -1
  80. package/core/computed/metrics/max-potential-fid.js +1 -1
  81. package/core/computed/metrics/metric.js +2 -0
  82. package/core/computed/metrics/speed-index.js +1 -1
  83. package/core/computed/metrics/time-to-first-byte.js +1 -1
  84. package/core/computed/metrics/timing-summary.d.ts +5 -2
  85. package/core/computed/metrics/timing-summary.js +8 -4
  86. package/core/computed/metrics/total-blocking-time.js +1 -1
  87. package/core/computed/module-duplication.d.ts +1 -1
  88. package/core/computed/navigation-insights.d.ts +11 -3
  89. package/core/computed/navigation-insights.js +7 -4
  90. package/core/computed/page-dependency-graph.d.ts +7 -3
  91. package/core/computed/page-dependency-graph.js +6 -5
  92. package/core/computed/tbt-impact-tasks.js +1 -1
  93. package/core/computed/trace-engine-result.d.ts +36 -2
  94. package/core/computed/trace-engine-result.js +119 -25
  95. package/core/computed/unused-javascript-summary.d.ts +2 -2
  96. package/core/computed/unused-javascript-summary.js +1 -1
  97. package/core/config/default-config.js +19 -15
  98. package/core/config/experimental-config.js +19 -0
  99. package/core/gather/gatherers/source-maps.d.ts +1 -0
  100. package/core/gather/gatherers/source-maps.js +3 -0
  101. package/core/gather/gatherers/trace-elements.d.ts +4 -4
  102. package/core/gather/gatherers/trace-elements.js +8 -4
  103. package/core/gather/gatherers/trace.js +5 -0
  104. package/core/lib/bf-cache-strings.d.ts +0 -122
  105. package/core/lib/bf-cache-strings.js +1 -2
  106. package/core/lib/deprecation-description.js +2 -1
  107. package/core/lib/legacy-javascript/legacy-javascript.d.ts +29 -0
  108. package/core/lib/legacy-javascript/legacy-javascript.js +351 -0
  109. package/core/lib/legacy-javascript/polyfill-graph-data.json +93 -0
  110. package/core/lib/legacy-javascript/polyfill-module-data.json +623 -0
  111. package/core/lib/trace-engine.d.ts +6 -1
  112. package/core/lib/trace-engine.js +1 -2
  113. package/package.json +10 -8
  114. package/shared/localization/locales/ar-XB.json +783 -513
  115. package/shared/localization/locales/ar.json +783 -513
  116. package/shared/localization/locales/bg.json +933 -663
  117. package/shared/localization/locales/ca.json +925 -655
  118. package/shared/localization/locales/cs.json +926 -656
  119. package/shared/localization/locales/da.json +926 -656
  120. package/shared/localization/locales/de.json +803 -533
  121. package/shared/localization/locales/el.json +928 -658
  122. package/shared/localization/locales/en-GB.json +929 -659
  123. package/shared/localization/locales/en-US.json +593 -551
  124. package/shared/localization/locales/en-XA.json +28 -508
  125. package/shared/localization/locales/en-XL.json +593 -551
  126. package/shared/localization/locales/es-419.json +928 -658
  127. package/shared/localization/locales/es.json +787 -517
  128. package/shared/localization/locales/fi.json +925 -655
  129. package/shared/localization/locales/fil.json +929 -659
  130. package/shared/localization/locales/fr.json +927 -657
  131. package/shared/localization/locales/he.json +795 -528
  132. package/shared/localization/locales/hi.json +798 -528
  133. package/shared/localization/locales/hr.json +929 -659
  134. package/shared/localization/locales/hu.json +926 -656
  135. package/shared/localization/locales/id.json +926 -656
  136. package/shared/localization/locales/it.json +930 -660
  137. package/shared/localization/locales/ja.json +927 -657
  138. package/shared/localization/locales/ko.json +936 -666
  139. package/shared/localization/locales/lt.json +933 -663
  140. package/shared/localization/locales/lv.json +809 -539
  141. package/shared/localization/locales/nl.json +925 -655
  142. package/shared/localization/locales/no.json +928 -658
  143. package/shared/localization/locales/pl.json +927 -657
  144. package/shared/localization/locales/pt-PT.json +841 -571
  145. package/shared/localization/locales/pt.json +841 -571
  146. package/shared/localization/locales/ro.json +925 -655
  147. package/shared/localization/locales/ru.json +935 -668
  148. package/shared/localization/locales/sk.json +925 -655
  149. package/shared/localization/locales/sl.json +927 -657
  150. package/shared/localization/locales/sr-Latn.json +925 -655
  151. package/shared/localization/locales/sr.json +925 -655
  152. package/shared/localization/locales/sv.json +936 -666
  153. package/shared/localization/locales/ta.json +935 -668
  154. package/shared/localization/locales/te.json +785 -515
  155. package/shared/localization/locales/th.json +813 -543
  156. package/shared/localization/locales/tr.json +927 -657
  157. package/shared/localization/locales/uk.json +795 -525
  158. package/shared/localization/locales/vi.json +929 -659
  159. package/shared/localization/locales/zh-HK.json +926 -656
  160. package/shared/localization/locales/zh-TW.json +784 -514
  161. package/shared/localization/locales/zh.json +926 -656
  162. package/tsconfig.json +2 -1
  163. package/types/artifacts.d.ts +2 -1
  164. package/core/audits/byte-efficiency/polyfill-graph-data.json +0 -53
@@ -69,7 +69,7 @@ class UnusedJavaScript extends ByteEfficiencyAudit {
69
69
  scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.METRIC_SAVINGS,
70
70
  guidanceLevel: 1,
71
71
  requiredArtifacts: ['JsUsage', 'Scripts', 'SourceMaps', 'GatherContext',
72
- 'devtoolsLogs', 'traces', 'URL'],
72
+ 'devtoolsLogs', 'traces', 'URL', 'SourceMaps'],
73
73
  };
74
74
  }
75
75
 
@@ -94,7 +94,7 @@ class UnusedJavaScript extends ByteEfficiencyAudit {
94
94
  const script = artifacts.Scripts.find(s => s.scriptId === scriptId);
95
95
  if (!script) continue; // This should never happen.
96
96
 
97
- const bundle = bundles.find(b => b.script.scriptId === scriptId);
97
+ const bundle = bundles.find(b => b.script.scriptId === scriptId) ?? null;
98
98
  const unusedJsSummary =
99
99
  await UnusedJavascriptSummary.request({scriptId, scriptCoverage, bundle}, context);
100
100
  if (unusedJsSummary.wastedBytes === 0 || unusedJsSummary.totalBytes === 0) continue;
@@ -46,7 +46,7 @@ class CacheHeaders extends Audit {
46
46
  description: str_(UIStrings.description),
47
47
  scoreDisplayMode: Audit.SCORING_MODES.METRIC_SAVINGS,
48
48
  guidanceLevel: 3,
49
- requiredArtifacts: ['devtoolsLogs'],
49
+ requiredArtifacts: ['devtoolsLogs', 'SourceMaps'],
50
50
  };
51
51
  }
52
52
 
@@ -37,7 +37,7 @@ class UsesOptimizedImages extends ByteEfficiencyAudit {
37
37
  scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.METRIC_SAVINGS,
38
38
  guidanceLevel: 2,
39
39
  requiredArtifacts: ['OptimizedImages', 'ImageElements', 'GatherContext', 'devtoolsLogs',
40
- 'traces', 'URL'],
40
+ 'traces', 'URL', 'SourceMaps'],
41
41
  };
42
42
  }
43
43
 
@@ -48,7 +48,7 @@ class UsesResponsiveImages extends ByteEfficiencyAudit {
48
48
  scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.METRIC_SAVINGS,
49
49
  guidanceLevel: 2,
50
50
  requiredArtifacts: ['ImageElements', 'ViewportDimensions', 'GatherContext',
51
- 'devtoolsLogs', 'traces', 'URL'],
51
+ 'devtoolsLogs', 'traces', 'URL', 'SourceMaps'],
52
52
  };
53
53
  }
54
54
 
@@ -38,7 +38,8 @@ class ResponsesAreCompressed extends ByteEfficiencyAudit {
38
38
  description: str_(UIStrings.description),
39
39
  scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.METRIC_SAVINGS,
40
40
  guidanceLevel: 3,
41
- requiredArtifacts: ['ResponseCompression', 'GatherContext', 'devtoolsLogs', 'traces', 'URL'],
41
+ requiredArtifacts: ['ResponseCompression', 'GatherContext', 'devtoolsLogs', 'traces', 'URL',
42
+ 'SourceMaps'],
42
43
  };
43
44
  }
44
45
 
@@ -38,7 +38,7 @@ class CriticalRequestChains extends Audit {
38
38
  scoreDisplayMode: Audit.SCORING_MODES.INFORMATIVE,
39
39
  supportedModes: ['navigation'],
40
40
  guidanceLevel: 1,
41
- requiredArtifacts: ['traces', 'devtoolsLogs', 'URL'],
41
+ requiredArtifacts: ['traces', 'devtoolsLogs', 'URL', 'SourceMaps'],
42
42
  };
43
43
  }
44
44
 
@@ -168,10 +168,12 @@ class CriticalRequestChains extends Audit {
168
168
  * @return {Promise<LH.Audit.Product>}
169
169
  */
170
170
  static async audit(artifacts, context) {
171
+ const settings = context.settings;
171
172
  const trace = artifacts.traces[Audit.DEFAULT_PASS];
172
173
  const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
173
- const URL = artifacts.URL;
174
- const chains = await ComputedChains.request({devtoolsLog, trace, URL}, context);
174
+ const {URL, SourceMaps} = artifacts;
175
+ const chains =
176
+ await ComputedChains.request({settings, devtoolsLog, trace, URL, SourceMaps}, context);
175
177
  let chainCount = 0;
176
178
  /**
177
179
  * @param {LH.Audit.Details.SimpleCriticalRequestNode} node
@@ -56,7 +56,7 @@ class DOMSize extends Audit {
56
56
  scoreDisplayMode: Audit.SCORING_MODES.METRIC_SAVINGS,
57
57
  guidanceLevel: 1,
58
58
  requiredArtifacts: ['DOMStats', 'URL', 'GatherContext'],
59
- __internalOptionalArtifacts: ['traces', 'devtoolsLogs'],
59
+ __internalOptionalArtifacts: ['traces', 'devtoolsLogs', 'SourceMaps'],
60
60
  };
61
61
  }
62
62
 
@@ -58,7 +58,7 @@ class UsesHTTP2Audit extends Audit {
58
58
  scoreDisplayMode: Audit.SCORING_MODES.METRIC_SAVINGS,
59
59
  guidanceLevel: 3,
60
60
  supportedModes: ['timespan', 'navigation'],
61
- requiredArtifacts: ['URL', 'devtoolsLogs', 'traces', 'GatherContext'],
61
+ requiredArtifacts: ['URL', 'devtoolsLogs', 'traces', 'GatherContext', 'SourceMaps'],
62
62
  };
63
63
  }
64
64
 
@@ -39,7 +39,7 @@ class CLSCulpritsInsight extends Audit {
39
39
  failureTitle: insightStr_(InsightUIStrings.title),
40
40
  description: insightStr_(InsightUIStrings.description),
41
41
  guidanceLevel: 3,
42
- requiredArtifacts: ['traces', 'TraceElements'],
42
+ requiredArtifacts: ['traces', 'TraceElements', 'SourceMaps'],
43
43
  replacesAudits: ['layout-shifts', 'non-composited-animations', 'unsized-images'],
44
44
  };
45
45
  }
@@ -24,7 +24,7 @@ class DocumentLatencyInsight 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: ['redirects', 'server-response-time', 'uses-text-compression'],
29
29
  };
30
30
  }
@@ -24,7 +24,7 @@ class DOMSizeInsight 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: ['dom-size'],
29
29
  };
30
30
  }
@@ -1,5 +1,5 @@
1
- export default LongCriticalNetworkTreeInsight;
2
- declare class LongCriticalNetworkTreeInsight extends Audit {
1
+ export default DuplicatedJavaScriptInsight;
2
+ declare class DuplicatedJavaScriptInsight extends Audit {
3
3
  /**
4
4
  * @param {LH.Artifacts} artifacts
5
5
  * @param {LH.Audit.Context} context
@@ -8,4 +8,4 @@ declare class LongCriticalNetworkTreeInsight extends Audit {
8
8
  static audit(artifacts: LH.Artifacts, context: LH.Audit.Context): Promise<LH.Audit.Product>;
9
9
  }
10
10
  import { Audit } from '../audit.js';
11
- //# sourceMappingURL=long-critical-network-tree-insight.d.ts.map
11
+ //# sourceMappingURL=duplicated-javascript-insight.d.ts.map
@@ -0,0 +1,54 @@
1
+ /* eslint-disable no-unused-vars */ // TODO: remove once implemented.
2
+
3
+ /**
4
+ * @license
5
+ * Copyright 2025 Google LLC
6
+ * SPDX-License-Identifier: Apache-2.0
7
+ */
8
+
9
+ import {UIStrings} from '@paulirish/trace_engine/models/trace/insights/DuplicatedJavaScript.js';
10
+
11
+ import {Audit} from '../audit.js';
12
+ import * as i18n from '../../lib/i18n/i18n.js';
13
+ import {adaptInsightToAuditProduct, makeNodeItemForNodeId} from './insight-audit.js';
14
+
15
+ // eslint-disable-next-line max-len
16
+ const str_ = i18n.createIcuMessageFn('node_modules/@paulirish/trace_engine/models/trace/insights/DuplicatedJavaScript.js', UIStrings);
17
+
18
+ class DuplicatedJavaScriptInsight extends Audit {
19
+ /**
20
+ * @return {LH.Audit.Meta}
21
+ */
22
+ static get meta() {
23
+ return {
24
+ id: 'duplicated-javascript-insight',
25
+ title: str_(UIStrings.title),
26
+ failureTitle: str_(UIStrings.title),
27
+ description: str_(UIStrings.description),
28
+ guidanceLevel: 3, // TODO: confirm/change.
29
+ requiredArtifacts: ['traces', 'TraceElements', 'SourceMaps'],
30
+ };
31
+ }
32
+
33
+ /**
34
+ * @param {LH.Artifacts} artifacts
35
+ * @param {LH.Audit.Context} context
36
+ * @return {Promise<LH.Audit.Product>}
37
+ */
38
+ static async audit(artifacts, context) {
39
+ // TODO: implement.
40
+ return adaptInsightToAuditProduct(artifacts, context, 'DuplicatedJavaScript', (insight) => {
41
+ /** @type {LH.Audit.Details.Table['headings']} */
42
+ const headings = [
43
+ /* eslint-disable max-len */
44
+ /* eslint-enable max-len */
45
+ ];
46
+ /** @type {LH.Audit.Details.Table['items']} */
47
+ const items = [
48
+ ];
49
+ return Audit.makeTableDetails(headings, items);
50
+ });
51
+ }
52
+ }
53
+
54
+ export default DuplicatedJavaScriptInsight;
@@ -1,5 +1,3 @@
1
- /* eslint-disable no-unused-vars */ // TODO: remove once implemented.
2
-
3
1
  /**
4
2
  * @license
5
3
  * Copyright 2025 Google LLC
@@ -10,7 +8,7 @@ import {UIStrings} from '@paulirish/trace_engine/models/trace/insights/FontDispl
10
8
 
11
9
  import {Audit} from '../audit.js';
12
10
  import * as i18n from '../../lib/i18n/i18n.js';
13
- import {adaptInsightToAuditProduct, makeNodeItemForNodeId} from './insight-audit.js';
11
+ import {adaptInsightToAuditProduct} from './insight-audit.js';
14
12
 
15
13
  // eslint-disable-next-line max-len
16
14
  const str_ = i18n.createIcuMessageFn('node_modules/@paulirish/trace_engine/models/trace/insights/FontDisplay.js', UIStrings);
@@ -26,7 +24,7 @@ class FontDisplayInsight extends Audit {
26
24
  failureTitle: str_(UIStrings.title),
27
25
  description: str_(UIStrings.description),
28
26
  guidanceLevel: 3,
29
- requiredArtifacts: ['traces', 'TraceElements'],
27
+ requiredArtifacts: ['traces', 'TraceElements', 'SourceMaps'],
30
28
  replacesAudits: ['font-display'],
31
29
  };
32
30
  }
@@ -37,14 +35,17 @@ class FontDisplayInsight extends Audit {
37
35
  * @return {Promise<LH.Audit.Product>}
38
36
  */
39
37
  static async audit(artifacts, context) {
40
- // TODO: implement.
41
38
  return adaptInsightToAuditProduct(artifacts, context, 'FontDisplay', (insight) => {
42
39
  /** @type {LH.Audit.Details.Table['headings']} */
43
40
  const headings = [
41
+ {key: 'url', valueType: 'url', label: str_(i18n.UIStrings.columnURL)},
42
+ {key: 'wastedMs', valueType: 'ms', label: str_(i18n.UIStrings.columnWastedMs)},
44
43
  ];
45
44
  /** @type {LH.Audit.Details.Table['items']} */
46
- const items = [
47
- ];
45
+ const items = insight.fonts.map(font => ({
46
+ url: font.request.args.data.url,
47
+ wastedMs: font.wastedTime,
48
+ }));
48
49
  return Audit.makeTableDetails(headings, items);
49
50
  });
50
51
  }
@@ -1,5 +1,15 @@
1
1
  export default ForcedReflowInsight;
2
2
  declare class ForcedReflowInsight extends Audit {
3
+ /**
4
+ * @param {import('@paulirish/trace_engine/models/trace/insights/ForcedReflow.js').ForcedReflowAggregatedData} topLevelFunctionCallData
5
+ * @returns {LH.Audit.Details.Table}
6
+ */
7
+ static makeTopFunctionTable(topLevelFunctionCallData: import("@paulirish/trace_engine/models/trace/insights/ForcedReflow.js").ForcedReflowAggregatedData): LH.Audit.Details.Table;
8
+ /**
9
+ * @param {import('@paulirish/trace_engine/models/trace/insights/ForcedReflow.js').ForcedReflowInsightModel} insight
10
+ * @returns {LH.Audit.Details.Table}
11
+ */
12
+ static makeBottomUpTable(insight: import("@paulirish/trace_engine/models/trace/insights/ForcedReflow.js").ForcedReflowInsightModel): LH.Audit.Details.Table;
3
13
  /**
4
14
  * @param {LH.Artifacts} artifacts
5
15
  * @param {LH.Audit.Context} context
@@ -1,5 +1,3 @@
1
- /* eslint-disable no-unused-vars */ // TODO: remove once implemented.
2
-
3
1
  /**
4
2
  * @license
5
3
  * Copyright 2025 Google LLC
@@ -10,7 +8,7 @@ import {UIStrings} from '@paulirish/trace_engine/models/trace/insights/ForcedRef
10
8
 
11
9
  import {Audit} from '../audit.js';
12
10
  import * as i18n from '../../lib/i18n/i18n.js';
13
- import {adaptInsightToAuditProduct, makeNodeItemForNodeId} from './insight-audit.js';
11
+ import {adaptInsightToAuditProduct} from './insight-audit.js';
14
12
 
15
13
  // eslint-disable-next-line max-len
16
14
  const str_ = i18n.createIcuMessageFn('node_modules/@paulirish/trace_engine/models/trace/insights/ForcedReflow.js', UIStrings);
@@ -26,25 +24,79 @@ class ForcedReflowInsight extends Audit {
26
24
  failureTitle: str_(UIStrings.title),
27
25
  description: str_(UIStrings.description),
28
26
  guidanceLevel: 3,
29
- requiredArtifacts: ['traces', 'TraceElements'],
27
+ requiredArtifacts: ['traces', 'TraceElements', 'SourceMaps'],
30
28
  };
31
29
  }
32
30
 
31
+ /**
32
+ * @param {import('@paulirish/trace_engine/models/trace/insights/ForcedReflow.js').ForcedReflowAggregatedData} topLevelFunctionCallData
33
+ * @returns {LH.Audit.Details.Table}
34
+ */
35
+ static makeTopFunctionTable(topLevelFunctionCallData) {
36
+ const {topLevelFunctionCall} = topLevelFunctionCallData;
37
+ /** @type {LH.Audit.Details.Table['headings']} */
38
+ const headings = [
39
+ // eslint-disable-next-line max-len
40
+ {key: 'source', valueType: 'source-location', label: str_(UIStrings.topTimeConsumingFunctionCall)},
41
+ {key: 'reflowTime', valueType: 'ms', granularity: 1, label: str_(UIStrings.totalReflowTime)},
42
+ ];
43
+ /** @type {LH.Audit.Details.Table['items']} */
44
+ const items = [
45
+ {
46
+ source: Audit.makeSourceLocation(
47
+ topLevelFunctionCall.url,
48
+ topLevelFunctionCall.lineNumber,
49
+ topLevelFunctionCall.columnNumber
50
+ ),
51
+ reflowTime: topLevelFunctionCallData.totalReflowTime / 1000,
52
+ },
53
+ ];
54
+ return Audit.makeTableDetails(headings, items);
55
+ }
56
+
57
+ /**
58
+ * @param {import('@paulirish/trace_engine/models/trace/insights/ForcedReflow.js').ForcedReflowInsightModel} insight
59
+ * @returns {LH.Audit.Details.Table}
60
+ */
61
+ static makeBottomUpTable(insight) {
62
+ /** @type {LH.Audit.Details.Table['headings']} */
63
+ const headings = [
64
+ {key: 'source', valueType: 'source-location', label: str_(i18n.UIStrings.columnSource)},
65
+ {key: 'reflowTime', valueType: 'ms', granularity: 1, label: str_(UIStrings.totalReflowTime)},
66
+ ];
67
+ /** @type {LH.Audit.Details.Table['items']} */
68
+ const items = insight.aggregatedBottomUpData.map((data) => {
69
+ const {bottomUpData, totalTime} = data;
70
+
71
+ const source = bottomUpData ? Audit.makeSourceLocation(
72
+ bottomUpData.url,
73
+ bottomUpData.lineNumber,
74
+ bottomUpData.columnNumber
75
+ ) : {
76
+ type: /** @type {const} */ ('text'),
77
+ value: str_(UIStrings.unattributed),
78
+ };
79
+
80
+ return {
81
+ source,
82
+ reflowTime: totalTime / 1000,
83
+ };
84
+ });
85
+ return Audit.makeTableDetails(headings, items);
86
+ }
87
+
33
88
  /**
34
89
  * @param {LH.Artifacts} artifacts
35
90
  * @param {LH.Audit.Context} context
36
91
  * @return {Promise<LH.Audit.Product>}
37
92
  */
38
93
  static async audit(artifacts, context) {
39
- // TODO: implement.
40
94
  return adaptInsightToAuditProduct(artifacts, context, 'ForcedReflow', (insight) => {
41
- /** @type {LH.Audit.Details.Table['headings']} */
42
- const headings = [
43
- ];
44
- /** @type {LH.Audit.Details.Table['items']} */
45
- const items = [
46
- ];
47
- return Audit.makeTableDetails(headings, items);
95
+ const list = [this.makeBottomUpTable(insight)];
96
+ if (insight.topLevelFunctionCallData) {
97
+ list.unshift(this.makeTopFunctionTable(insight.topLevelFunctionCallData));
98
+ }
99
+ return Audit.makeListDetails(list);
48
100
  });
49
101
  }
50
102
  }
@@ -4,15 +4,20 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
 
7
+ import * as ImageDeliveryInsightModule from '@paulirish/trace_engine/models/trace/insights/ImageDelivery.js';
7
8
  import {UIStrings} from '@paulirish/trace_engine/models/trace/insights/ImageDelivery.js';
8
9
 
9
10
  import {Audit} from '../audit.js';
10
11
  import * as i18n from '../../lib/i18n/i18n.js';
11
12
  import {adaptInsightToAuditProduct} from './insight-audit.js';
13
+ import {TraceEngineResult} from '../../computed/trace-engine-result.js';
12
14
 
13
15
  // eslint-disable-next-line max-len
14
16
  const str_ = i18n.createIcuMessageFn('node_modules/@paulirish/trace_engine/models/trace/insights/ImageDelivery.js', UIStrings);
15
17
 
18
+ const getOptimizationMessage =
19
+ TraceEngineResult.localizeFunction(str_, ImageDeliveryInsightModule.getOptimizationMessage);
20
+
16
21
  class ImageDeliveryInsight extends Audit {
17
22
  /**
18
23
  * @return {LH.Audit.Meta}
@@ -24,7 +29,7 @@ class ImageDeliveryInsight extends Audit {
24
29
  failureTitle: str_(UIStrings.title),
25
30
  description: str_(UIStrings.description),
26
31
  guidanceLevel: 3,
27
- requiredArtifacts: ['traces', 'TraceElements'],
32
+ requiredArtifacts: ['traces', 'TraceElements', 'SourceMaps'],
28
33
  replacesAudits: [
29
34
  'modern-image-formats',
30
35
  'uses-optimized-images',
@@ -46,10 +51,6 @@ class ImageDeliveryInsight extends Audit {
46
51
  return;
47
52
  }
48
53
 
49
- const relatedEventsMap = insight.relatedEvents && !Array.isArray(insight.relatedEvents) ?
50
- insight.relatedEvents :
51
- null;
52
-
53
54
  /** @type {LH.Audit.Details.Table['headings']} */
54
55
  const headings = [
55
56
  /* eslint-disable max-len */
@@ -66,11 +67,9 @@ class ImageDeliveryInsight extends Audit {
66
67
  wastedBytes: image.byteSavings,
67
68
  subItems: {
68
69
  type: /** @type {const} */ ('subitems'),
69
- // TODO: when strings update to remove number from "reason" uistrings, update this
70
- // to use `image.optimizations.map(...)` and construct strings from the type.
71
- items: (relatedEventsMap?.get(image.request) ?? []).map((reason, i) => ({
72
- reason,
73
- wastedBytes: image.optimizations[i].byteSavings,
70
+ items: image.optimizations.map(optimization => ({
71
+ reason: getOptimizationMessage(optimization),
72
+ wastedBytes: optimization.byteSavings,
74
73
  })),
75
74
  },
76
75
  }));
@@ -16,9 +16,11 @@ import {Audit} from '../audit.js';
16
16
  * @return {Promise<import('@paulirish/trace_engine/models/trace/insights/types.js').InsightSet|undefined>}
17
17
  */
18
18
  async function getInsightSet(artifacts, context) {
19
+ const settings = context.settings;
19
20
  const trace = artifacts.traces[Audit.DEFAULT_PASS];
20
21
  const processedTrace = await ProcessedTrace.request(trace, context);
21
- const traceEngineResult = await TraceEngineResult.request({trace}, context);
22
+ const SourceMaps = artifacts.SourceMaps;
23
+ const traceEngineResult = await TraceEngineResult.request({trace, settings, SourceMaps}, context);
22
24
 
23
25
  const navigationId = processedTrace.timeOriginEvt.args.data?.navigationId;
24
26
  const key = navigationId ?? NO_NAVIGATION;
@@ -71,11 +73,14 @@ async function adaptInsightToAuditProduct(artifacts, context, insightName, creat
71
73
  metricSavings = {...metricSavings, LCP: /** @type {any} */ (0)};
72
74
  }
73
75
 
74
- let score = insight.shouldShow ? 0 : 1;
75
- // TODO: change insight model to denote passing/failing/informative. Until then... hack it.
76
- if (insightName === 'LCPPhases') {
76
+ let score = 1;
77
+ if (insight.state === 'fail') {
78
+ score = 0;
79
+ } else if (insightName === 'LCPPhases') {
80
+ // TODO: change these insights to denote passing/failing/informative. Until then... hack it.
77
81
  score = metricSavings?.LCP ?? 0 >= 1000 ? 0 : 1;
78
82
  } else if (insightName === 'InteractionToNextPaint') {
83
+ // TODO: change these insights to denote passing/failing/informative. Until then... hack it.
79
84
  score = metricSavings?.INP ?? 0 >= 500 ? 0 : 1;
80
85
  }
81
86
 
@@ -24,7 +24,7 @@ class InteractionToNextPaintInsight 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: ['work-during-interaction'],
29
29
  };
30
30
  }
@@ -24,7 +24,7 @@ class LCPDiscoveryInsight 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: ['prioritize-lcp-image', 'lcp-lazy-loaded'],
29
29
  };
30
30
  }
@@ -24,7 +24,7 @@ class LCPPhasesInsight 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: ['largest-contentful-paint-element'],
29
29
  };
30
30
  }
@@ -0,0 +1,11 @@
1
+ export default NetworkDependencyTreeInsight;
2
+ declare class NetworkDependencyTreeInsight extends Audit {
3
+ /**
4
+ * @param {LH.Artifacts} artifacts
5
+ * @param {LH.Audit.Context} context
6
+ * @return {Promise<LH.Audit.Product>}
7
+ */
8
+ static audit(artifacts: LH.Artifacts, context: LH.Audit.Context): Promise<LH.Audit.Product>;
9
+ }
10
+ import { Audit } from '../audit.js';
11
+ //# sourceMappingURL=network-dependency-tree-insight.d.ts.map
@@ -6,27 +6,27 @@
6
6
  * SPDX-License-Identifier: Apache-2.0
7
7
  */
8
8
 
9
- import {UIStrings} from '@paulirish/trace_engine/models/trace/insights/LongCriticalNetworkTree.js';
9
+ import {UIStrings} from '@paulirish/trace_engine/models/trace/insights/NetworkDependencyTree.js';
10
10
 
11
11
  import {Audit} from '../audit.js';
12
12
  import * as i18n from '../../lib/i18n/i18n.js';
13
13
  import {adaptInsightToAuditProduct, makeNodeItemForNodeId} from './insight-audit.js';
14
14
 
15
15
  // eslint-disable-next-line max-len
16
- const str_ = i18n.createIcuMessageFn('node_modules/@paulirish/trace_engine/models/trace/insights/LongCriticalNetworkTree.js', UIStrings);
16
+ const str_ = i18n.createIcuMessageFn('node_modules/@paulirish/trace_engine/models/trace/insights/NetworkDependencyTree.js', UIStrings);
17
17
 
18
- class LongCriticalNetworkTreeInsight extends Audit {
18
+ class NetworkDependencyTreeInsight extends Audit {
19
19
  /**
20
20
  * @return {LH.Audit.Meta}
21
21
  */
22
22
  static get meta() {
23
23
  return {
24
- id: 'long-critical-network-tree-insight',
24
+ id: 'network-dependency-tree-insight',
25
25
  title: str_(UIStrings.title),
26
26
  failureTitle: str_(UIStrings.title),
27
27
  description: str_(UIStrings.description),
28
28
  guidanceLevel: 3,
29
- requiredArtifacts: ['traces', 'TraceElements'],
29
+ requiredArtifacts: ['traces', 'TraceElements', 'SourceMaps'],
30
30
  replacesAudits: ['critical-request-chains'],
31
31
  };
32
32
  }
@@ -38,7 +38,7 @@ class LongCriticalNetworkTreeInsight extends Audit {
38
38
  */
39
39
  static async audit(artifacts, context) {
40
40
  // TODO: implement.
41
- return adaptInsightToAuditProduct(artifacts, context, 'LongCriticalNetworkTree', (insight) => {
41
+ return adaptInsightToAuditProduct(artifacts, context, 'NetworkDependencyTree', (insight) => {
42
42
  /** @type {LH.Audit.Details.Table['headings']} */
43
43
  const headings = [
44
44
  ];
@@ -50,4 +50,4 @@ class LongCriticalNetworkTreeInsight extends Audit {
50
50
  }
51
51
  }
52
52
 
53
- export default LongCriticalNetworkTreeInsight;
53
+ export default NetworkDependencyTreeInsight;
@@ -24,7 +24,7 @@ class RenderBlockingInsight 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: ['render-blocking-resources'],
29
29
  };
30
30
  }
@@ -26,7 +26,7 @@ class SlowCSSSelectorInsight extends Audit {
26
26
  failureTitle: str_(UIStrings.title),
27
27
  description: str_(UIStrings.description),
28
28
  guidanceLevel: 3,
29
- requiredArtifacts: ['traces', 'TraceElements'],
29
+ requiredArtifacts: ['traces', 'TraceElements', 'SourceMaps'],
30
30
  };
31
31
  }
32
32
 
@@ -31,7 +31,7 @@ class ThirdPartiesInsight extends Audit {
31
31
  failureTitle: str_(UIStrings.title),
32
32
  description: str_(UIStrings.description),
33
33
  guidanceLevel: 3,
34
- requiredArtifacts: ['traces', 'TraceElements'],
34
+ requiredArtifacts: ['traces', 'TraceElements', 'SourceMaps'],
35
35
  replacesAudits: ['third-party-summary'],
36
36
  };
37
37
  }
@@ -0,0 +1,11 @@
1
+ export default UseCacheInsight;
2
+ declare class UseCacheInsight extends Audit {
3
+ /**
4
+ * @param {LH.Artifacts} artifacts
5
+ * @param {LH.Audit.Context} context
6
+ * @return {Promise<LH.Audit.Product>}
7
+ */
8
+ static audit(artifacts: LH.Artifacts, context: LH.Audit.Context): Promise<LH.Audit.Product>;
9
+ }
10
+ import { Audit } from '../audit.js';
11
+ //# sourceMappingURL=use-cache-insight.d.ts.map