lighthouse 12.4.0-dev.20250318 → 12.4.0-dev.20250319

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 (142) hide show
  1. package/core/audits/audit.js +2 -1
  2. package/core/audits/bootup-time.js +1 -1
  3. package/core/audits/byte-efficiency/efficient-animated-content.js +1 -1
  4. package/core/audits/byte-efficiency/modern-image-formats.js +1 -1
  5. package/core/audits/byte-efficiency/offscreen-images.js +3 -3
  6. package/core/audits/byte-efficiency/render-blocking-resources.js +5 -3
  7. package/core/audits/byte-efficiency/unminified-css.js +2 -1
  8. package/core/audits/byte-efficiency/unminified-javascript.js +2 -1
  9. package/core/audits/byte-efficiency/unused-css-rules.js +1 -1
  10. package/core/audits/byte-efficiency/unused-javascript.js +1 -1
  11. package/core/audits/byte-efficiency/uses-long-cache-ttl.js +1 -1
  12. package/core/audits/byte-efficiency/uses-optimized-images.js +1 -1
  13. package/core/audits/byte-efficiency/uses-responsive-images.js +1 -1
  14. package/core/audits/byte-efficiency/uses-text-compression.js +2 -1
  15. package/core/audits/critical-request-chains.js +4 -3
  16. package/core/audits/dobetterweb/dom-size.js +1 -1
  17. package/core/audits/dobetterweb/uses-http2.js +1 -1
  18. package/core/audits/insights/cls-culprits-insight.js +1 -1
  19. package/core/audits/insights/document-latency-insight.js +1 -1
  20. package/core/audits/insights/dom-size-insight.js +1 -1
  21. package/core/audits/insights/duplicated-javascript-insight.d.ts +11 -0
  22. package/core/audits/insights/duplicated-javascript-insight.js +54 -0
  23. package/core/audits/insights/font-display-insight.js +1 -1
  24. package/core/audits/insights/forced-reflow-insight.d.ts +10 -0
  25. package/core/audits/insights/forced-reflow-insight.js +64 -12
  26. package/core/audits/insights/image-delivery-insight.js +1 -1
  27. package/core/audits/insights/insight-audit.js +2 -1
  28. package/core/audits/insights/interaction-to-next-paint-insight.js +1 -1
  29. package/core/audits/insights/lcp-discovery-insight.js +1 -1
  30. package/core/audits/insights/lcp-phases-insight.js +1 -1
  31. package/core/audits/insights/network-dependency-tree-insight.js +1 -1
  32. package/core/audits/insights/render-blocking-insight.js +1 -1
  33. package/core/audits/insights/slow-css-selector-insight.js +1 -1
  34. package/core/audits/insights/third-parties-insight.js +1 -1
  35. package/core/audits/insights/{duplicate-javascript-insight.d.ts → use-cache-insight.d.ts} +3 -3
  36. package/core/audits/insights/{duplicate-javascript-insight.js → use-cache-insight.js} +6 -6
  37. package/core/audits/insights/viewport-insight.js +1 -1
  38. package/core/audits/largest-contentful-paint-element.js +3 -2
  39. package/core/audits/layout-shifts.js +4 -2
  40. package/core/audits/lcp-lazy-loaded.js +1 -1
  41. package/core/audits/long-tasks.js +4 -4
  42. package/core/audits/mainthread-work-breakdown.js +1 -1
  43. package/core/audits/metrics/first-contentful-paint.js +2 -2
  44. package/core/audits/metrics/interactive.js +2 -2
  45. package/core/audits/metrics/largest-contentful-paint.js +3 -2
  46. package/core/audits/metrics/max-potential-fid.js +2 -2
  47. package/core/audits/metrics/speed-index.js +2 -2
  48. package/core/audits/metrics/total-blocking-time.js +2 -2
  49. package/core/audits/metrics.js +4 -3
  50. package/core/audits/predictive-perf.js +3 -3
  51. package/core/audits/prioritize-lcp-image.js +4 -3
  52. package/core/audits/redirects.js +3 -2
  53. package/core/audits/script-treemap-data.js +1 -1
  54. package/core/audits/third-party-facades.js +1 -1
  55. package/core/audits/third-party-summary.js +1 -1
  56. package/core/audits/uses-rel-preconnect.js +6 -5
  57. package/core/audits/uses-rel-preload.js +3 -3
  58. package/core/computed/critical-request-chains.d.ts +3 -1
  59. package/core/computed/critical-request-chains.js +3 -3
  60. package/core/computed/metrics/first-contentful-paint-all-frames.js +1 -1
  61. package/core/computed/metrics/first-contentful-paint.js +1 -1
  62. package/core/computed/metrics/interactive.js +1 -1
  63. package/core/computed/metrics/lantern-first-contentful-paint.js +1 -1
  64. package/core/computed/metrics/lantern-interactive.js +1 -1
  65. package/core/computed/metrics/lantern-largest-contentful-paint.js +1 -1
  66. package/core/computed/metrics/lantern-max-potential-fid.js +1 -1
  67. package/core/computed/metrics/lantern-speed-index.js +1 -1
  68. package/core/computed/metrics/lantern-total-blocking-time.js +1 -1
  69. package/core/computed/metrics/largest-contentful-paint-all-frames.js +1 -1
  70. package/core/computed/metrics/largest-contentful-paint.js +1 -1
  71. package/core/computed/metrics/lcp-breakdown.js +1 -1
  72. package/core/computed/metrics/max-potential-fid.js +1 -1
  73. package/core/computed/metrics/metric.js +1 -0
  74. package/core/computed/metrics/speed-index.js +1 -1
  75. package/core/computed/metrics/time-to-first-byte.js +1 -1
  76. package/core/computed/metrics/timing-summary.d.ts +5 -2
  77. package/core/computed/metrics/timing-summary.js +6 -4
  78. package/core/computed/metrics/total-blocking-time.js +1 -1
  79. package/core/computed/navigation-insights.d.ts +3 -1
  80. package/core/computed/navigation-insights.js +6 -4
  81. package/core/computed/page-dependency-graph.d.ts +3 -1
  82. package/core/computed/page-dependency-graph.js +5 -4
  83. package/core/computed/tbt-impact-tasks.js +1 -1
  84. package/core/computed/trace-engine-result.d.ts +5 -2
  85. package/core/computed/trace-engine-result.js +18 -4
  86. package/core/config/default-config.js +4 -2
  87. package/core/config/experimental-config.js +2 -1
  88. package/core/gather/gatherers/source-maps.d.ts +1 -0
  89. package/core/gather/gatherers/source-maps.js +3 -0
  90. package/core/gather/gatherers/trace-elements.d.ts +4 -4
  91. package/core/gather/gatherers/trace-elements.js +7 -4
  92. package/core/gather/gatherers/trace.js +5 -0
  93. package/package.json +2 -2
  94. package/shared/localization/locales/ar-XB.json +235 -1
  95. package/shared/localization/locales/ar.json +235 -7
  96. package/shared/localization/locales/bg.json +235 -7
  97. package/shared/localization/locales/ca.json +235 -7
  98. package/shared/localization/locales/cs.json +234 -6
  99. package/shared/localization/locales/da.json +236 -8
  100. package/shared/localization/locales/de.json +234 -6
  101. package/shared/localization/locales/el.json +235 -7
  102. package/shared/localization/locales/en-GB.json +235 -19
  103. package/shared/localization/locales/en-US.json +30 -3
  104. package/shared/localization/locales/en-XA.json +0 -6
  105. package/shared/localization/locales/en-XL.json +30 -3
  106. package/shared/localization/locales/es-419.json +235 -7
  107. package/shared/localization/locales/es.json +234 -6
  108. package/shared/localization/locales/fi.json +235 -7
  109. package/shared/localization/locales/fil.json +237 -3
  110. package/shared/localization/locales/fr.json +236 -8
  111. package/shared/localization/locales/he.json +234 -0
  112. package/shared/localization/locales/hi.json +236 -2
  113. package/shared/localization/locales/hr.json +235 -7
  114. package/shared/localization/locales/hu.json +235 -7
  115. package/shared/localization/locales/id.json +234 -0
  116. package/shared/localization/locales/it.json +238 -10
  117. package/shared/localization/locales/ja.json +234 -6
  118. package/shared/localization/locales/ko.json +235 -16
  119. package/shared/localization/locales/lt.json +235 -7
  120. package/shared/localization/locales/lv.json +236 -8
  121. package/shared/localization/locales/nl.json +235 -4
  122. package/shared/localization/locales/no.json +235 -7
  123. package/shared/localization/locales/pl.json +236 -8
  124. package/shared/localization/locales/pt-PT.json +235 -1
  125. package/shared/localization/locales/pt.json +235 -1
  126. package/shared/localization/locales/ro.json +234 -0
  127. package/shared/localization/locales/ru.json +235 -1
  128. package/shared/localization/locales/sk.json +235 -1
  129. package/shared/localization/locales/sl.json +236 -2
  130. package/shared/localization/locales/sr-Latn.json +235 -1
  131. package/shared/localization/locales/sr.json +235 -1
  132. package/shared/localization/locales/sv.json +235 -1
  133. package/shared/localization/locales/ta.json +235 -1
  134. package/shared/localization/locales/te.json +237 -3
  135. package/shared/localization/locales/th.json +235 -1
  136. package/shared/localization/locales/tr.json +236 -2
  137. package/shared/localization/locales/uk.json +235 -1
  138. package/shared/localization/locales/vi.json +236 -2
  139. package/shared/localization/locales/zh-HK.json +235 -1
  140. package/shared/localization/locales/zh-TW.json +236 -2
  141. package/shared/localization/locales/zh.json +234 -0
  142. package/types/artifacts.d.ts +1 -0
@@ -491,7 +491,8 @@ class Audit {
491
491
  const trace = artifacts.traces[Audit.DEFAULT_PASS];
492
492
  const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
493
493
  const gatherContext = artifacts.GatherContext;
494
- return {trace, devtoolsLog, gatherContext, settings: context.settings, URL: artifacts.URL};
494
+ const {URL, SourceMaps} = artifacts;
495
+ return {trace, devtoolsLog, gatherContext, settings: context.settings, URL, SourceMaps};
495
496
  }
496
497
  }
497
498
 
@@ -49,7 +49,7 @@ class BootupTime extends Audit {
49
49
  description: str_(UIStrings.description),
50
50
  scoreDisplayMode: Audit.SCORING_MODES.METRIC_SAVINGS,
51
51
  guidanceLevel: 1,
52
- requiredArtifacts: ['traces', 'devtoolsLogs', 'URL', 'GatherContext'],
52
+ requiredArtifacts: ['traces', 'devtoolsLogs', 'URL', 'GatherContext', 'SourceMaps'],
53
53
  };
54
54
  }
55
55
 
@@ -38,7 +38,7 @@ class EfficientAnimatedContent extends ByteEfficiencyAudit {
38
38
  description: str_(UIStrings.description),
39
39
  scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.METRIC_SAVINGS,
40
40
  guidanceLevel: 3,
41
- requiredArtifacts: ['devtoolsLogs', 'traces', 'GatherContext', 'URL'],
41
+ requiredArtifacts: ['devtoolsLogs', 'traces', 'GatherContext', 'URL', 'SourceMaps'],
42
42
  };
43
43
  }
44
44
 
@@ -37,7 +37,7 @@ class ModernImageFormats extends ByteEfficiencyAudit {
37
37
  scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.METRIC_SAVINGS,
38
38
  guidanceLevel: 3,
39
39
  requiredArtifacts: ['OptimizedImages', 'devtoolsLogs', 'traces', 'URL', 'GatherContext',
40
- 'ImageElements'],
40
+ 'ImageElements', 'SourceMaps'],
41
41
  };
42
42
  }
43
43
 
@@ -52,7 +52,7 @@ class OffscreenImages extends ByteEfficiencyAudit {
52
52
  supportedModes: ['navigation'],
53
53
  guidanceLevel: 2,
54
54
  requiredArtifacts: ['ImageElements', 'ViewportDimensions', 'GatherContext', 'devtoolsLogs',
55
- 'traces', 'URL'],
55
+ 'traces', 'URL', 'SourceMaps'],
56
56
  };
57
57
  }
58
58
 
@@ -163,12 +163,12 @@ class OffscreenImages extends ByteEfficiencyAudit {
163
163
  * @return {Promise<import('./byte-efficiency-audit.js').ByteEfficiencyProduct>}
164
164
  */
165
165
  static async audit_(artifacts, networkRecords, context) {
166
+ const {URL, SourceMaps} = artifacts;
166
167
  const images = artifacts.ImageElements;
167
168
  const viewportDimensions = artifacts.ViewportDimensions;
168
169
  const gatherContext = artifacts.GatherContext;
169
170
  const trace = artifacts.traces[ByteEfficiencyAudit.DEFAULT_PASS];
170
171
  const devtoolsLog = artifacts.devtoolsLogs[ByteEfficiencyAudit.DEFAULT_PASS];
171
- const URL = artifacts.URL;
172
172
 
173
173
  /** @type {string[]} */
174
174
  const warnings = [];
@@ -199,7 +199,7 @@ class OffscreenImages extends ByteEfficiencyAudit {
199
199
  const unfilteredResults = Array.from(resultsMap.values());
200
200
  // get the interactive time or fallback to getting the end of trace time
201
201
  try {
202
- const metricComputationData = {trace, devtoolsLog, gatherContext, settings, URL};
202
+ const metricComputationData = {trace, devtoolsLog, gatherContext, settings, URL, SourceMaps};
203
203
  const interactive = await Interactive.request(metricComputationData, context);
204
204
 
205
205
  // use interactive to generate items
@@ -112,7 +112,8 @@ class RenderBlockingResources extends Audit {
112
112
  // TODO: look into adding an `optionalArtifacts` property that captures the non-required nature
113
113
  // of CSSUsage
114
114
  requiredArtifacts:
115
- ['URL', 'traces', 'devtoolsLogs', 'Stylesheets', 'CSSUsage', 'GatherContext', 'Stacks'],
115
+ // eslint-disable-next-line max-len
116
+ ['URL', 'traces', 'devtoolsLogs', 'Stylesheets', 'CSSUsage', 'GatherContext', 'Stacks', 'SourceMaps'],
116
117
  };
117
118
  }
118
119
 
@@ -126,10 +127,11 @@ class RenderBlockingResources extends Audit {
126
127
  const gatherContext = artifacts.GatherContext;
127
128
  const trace = artifacts.traces[Audit.DEFAULT_PASS];
128
129
  const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
130
+ const SourceMaps = artifacts.SourceMaps;
129
131
  const simulatorData = {devtoolsLog, settings: context.settings};
130
132
  const simulator = await LoadSimulator.request(simulatorData, context);
131
133
  const wastedCssBytes = await RenderBlockingResources.computeWastedCSSBytes(artifacts, context);
132
- const navInsights = await NavigationInsights.request({trace, settings}, context);
134
+ const navInsights = await NavigationInsights.request({trace, settings, SourceMaps}, context);
133
135
 
134
136
  const renderBlocking = navInsights.model.RenderBlocking;
135
137
  if (renderBlocking instanceof Error) throw renderBlocking;
@@ -141,7 +143,7 @@ class RenderBlockingResources extends Audit {
141
143
  };
142
144
 
143
145
  const metricComputationData = {trace, devtoolsLog, gatherContext, simulator,
144
- settings: metricSettings, URL: artifacts.URL};
146
+ settings: metricSettings, URL: artifacts.URL, SourceMaps: artifacts.SourceMaps};
145
147
 
146
148
  // Cast to just `LanternMetric` since we explicitly set `throttlingMethod: 'simulate'`.
147
149
  const fcpSimulation = /** @type {LH.Artifacts.LanternMetric} */
@@ -37,7 +37,8 @@ class UnminifiedCSS extends ByteEfficiencyAudit {
37
37
  description: str_(UIStrings.description),
38
38
  scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.METRIC_SAVINGS,
39
39
  guidanceLevel: 3,
40
- requiredArtifacts: ['Stylesheets', 'devtoolsLogs', 'traces', 'URL', 'GatherContext'],
40
+ requiredArtifacts: ['Stylesheets', 'devtoolsLogs', 'traces', 'URL', 'GatherContext',
41
+ 'SourceMaps'],
41
42
  };
42
43
  }
43
44
 
@@ -44,7 +44,8 @@ class UnminifiedJavaScript extends ByteEfficiencyAudit {
44
44
  description: str_(UIStrings.description),
45
45
  scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.METRIC_SAVINGS,
46
46
  guidanceLevel: 3,
47
- requiredArtifacts: ['Scripts', 'devtoolsLogs', 'traces', 'GatherContext', 'URL'],
47
+ requiredArtifacts: ['Scripts', 'devtoolsLogs', 'traces', 'GatherContext', 'URL',
48
+ 'SourceMaps'],
48
49
  };
49
50
  }
50
51
 
@@ -35,7 +35,7 @@ class UnusedCSSRules extends ByteEfficiencyAudit {
35
35
  scoreDisplayMode: ByteEfficiencyAudit.SCORING_MODES.METRIC_SAVINGS,
36
36
  guidanceLevel: 1,
37
37
  requiredArtifacts:
38
- ['Stylesheets', 'CSSUsage', 'URL', 'devtoolsLogs', 'traces', 'GatherContext'],
38
+ ['Stylesheets', 'CSSUsage', 'URL', 'devtoolsLogs', 'traces', 'GatherContext', 'SourceMaps'],
39
39
  };
40
40
  }
41
41
 
@@ -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
 
@@ -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
 
@@ -171,8 +171,9 @@ class CriticalRequestChains extends Audit {
171
171
  const settings = context.settings;
172
172
  const trace = artifacts.traces[Audit.DEFAULT_PASS];
173
173
  const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
174
- const URL = artifacts.URL;
175
- const chains = await ComputedChains.request({settings, devtoolsLog, trace, URL}, context);
174
+ const {URL, SourceMaps} = artifacts;
175
+ const chains =
176
+ await ComputedChains.request({settings, devtoolsLog, trace, URL, SourceMaps}, context);
176
177
  let chainCount = 0;
177
178
  /**
178
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
  }
@@ -0,0 +1,11 @@
1
+ export default DuplicatedJavaScriptInsight;
2
+ declare class DuplicatedJavaScriptInsight 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=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;
@@ -24,7 +24,7 @@ class FontDisplayInsight 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: ['font-display'],
29
29
  };
30
30
  }
@@ -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
  }
@@ -29,7 +29,7 @@ class ImageDeliveryInsight extends Audit {
29
29
  failureTitle: str_(UIStrings.title),
30
30
  description: str_(UIStrings.description),
31
31
  guidanceLevel: 3,
32
- requiredArtifacts: ['traces', 'TraceElements'],
32
+ requiredArtifacts: ['traces', 'TraceElements', 'SourceMaps'],
33
33
  replacesAudits: [
34
34
  'modern-image-formats',
35
35
  'uses-optimized-images',
@@ -19,7 +19,8 @@ async function getInsightSet(artifacts, context) {
19
19
  const settings = context.settings;
20
20
  const trace = artifacts.traces[Audit.DEFAULT_PASS];
21
21
  const processedTrace = await ProcessedTrace.request(trace, context);
22
- const traceEngineResult = await TraceEngineResult.request({trace, settings}, context);
22
+ const SourceMaps = artifacts.SourceMaps;
23
+ const traceEngineResult = await TraceEngineResult.request({trace, settings, SourceMaps}, context);
23
24
 
24
25
  const navigationId = processedTrace.timeOriginEvt.args.data?.navigationId;
25
26
  const key = navigationId ?? NO_NAVIGATION;
@@ -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
  }
@@ -26,7 +26,7 @@ class NetworkDependencyTreeInsight 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
  replacesAudits: ['critical-request-chains'],
31
31
  };
32
32
  }
@@ -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
  }
@@ -1,5 +1,5 @@
1
- export default DuplicateJavaScriptInsight;
2
- declare class DuplicateJavaScriptInsight extends Audit {
1
+ export default UseCacheInsight;
2
+ declare class UseCacheInsight extends Audit {
3
3
  /**
4
4
  * @param {LH.Artifacts} artifacts
5
5
  * @param {LH.Audit.Context} context
@@ -8,4 +8,4 @@ declare class DuplicateJavaScriptInsight 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=duplicate-javascript-insight.d.ts.map
11
+ //# sourceMappingURL=use-cache-insight.d.ts.map
@@ -6,22 +6,22 @@
6
6
  * SPDX-License-Identifier: Apache-2.0
7
7
  */
8
8
 
9
- import {UIStrings} from '@paulirish/trace_engine/models/trace/insights/DuplicateJavaScript.js';
9
+ import {UIStrings} from '@paulirish/trace_engine/models/trace/insights/UseCache.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/DuplicateJavaScript.js', UIStrings);
16
+ const str_ = i18n.createIcuMessageFn('node_modules/@paulirish/trace_engine/models/trace/insights/UseCache.js', UIStrings);
17
17
 
18
- class DuplicateJavaScriptInsight extends Audit {
18
+ class UseCacheInsight extends Audit {
19
19
  /**
20
20
  * @return {LH.Audit.Meta}
21
21
  */
22
22
  static get meta() {
23
23
  return {
24
- id: 'duplicate-javascript-insight',
24
+ id: 'use-cache-insight',
25
25
  title: str_(UIStrings.title),
26
26
  failureTitle: str_(UIStrings.title),
27
27
  description: str_(UIStrings.description),
@@ -37,7 +37,7 @@ class DuplicateJavaScriptInsight extends Audit {
37
37
  */
38
38
  static async audit(artifacts, context) {
39
39
  // TODO: implement.
40
- return adaptInsightToAuditProduct(artifacts, context, 'DuplicateJavaScript', (insight) => {
40
+ return adaptInsightToAuditProduct(artifacts, context, 'UseCache', (insight) => {
41
41
  /** @type {LH.Audit.Details.Table['headings']} */
42
42
  const headings = [
43
43
  /* eslint-disable max-len */
@@ -51,4 +51,4 @@ class DuplicateJavaScriptInsight extends Audit {
51
51
  }
52
52
  }
53
53
 
54
- export default DuplicateJavaScriptInsight;
54
+ 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
  }