lighthouse 11.7.1 → 12.0.0

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 (272) hide show
  1. package/CONTRIBUTING.md +2 -2
  2. package/cli/bin.js +0 -7
  3. package/cli/cli-flags.d.ts +1 -5
  4. package/cli/cli-flags.js +4 -8
  5. package/cli/test/smokehouse/__snapshots__/report-assert-test.js.snap +14 -14
  6. package/cli/test/smokehouse/config/exclusions.js +3 -0
  7. package/cli/test/smokehouse/core-tests.js +6 -20
  8. package/cli/test/smokehouse/frontends/smokehouse-bin.js +2 -2
  9. package/core/audits/accessibility/aria-conditional-attr.d.ts +10 -0
  10. package/core/audits/accessibility/aria-conditional-attr.js +43 -0
  11. package/core/audits/accessibility/{duplicate-id-active.d.ts → aria-deprecated-role.d.ts} +3 -3
  12. package/core/audits/accessibility/aria-deprecated-role.js +43 -0
  13. package/core/audits/accessibility/aria-prohibited-attr.d.ts +10 -0
  14. package/core/audits/accessibility/aria-prohibited-attr.js +44 -0
  15. package/core/audits/accessibility/target-size.js +0 -1
  16. package/core/audits/byte-efficiency/byte-efficiency-audit.d.ts +0 -16
  17. package/core/audits/byte-efficiency/byte-efficiency-audit.js +1 -38
  18. package/core/audits/byte-efficiency/offscreen-images.d.ts +0 -11
  19. package/core/audits/byte-efficiency/offscreen-images.js +0 -15
  20. package/core/audits/byte-efficiency/render-blocking-resources.js +27 -26
  21. package/core/audits/byte-efficiency/unminified-css.js +2 -2
  22. package/core/audits/byte-efficiency/unused-css-rules.js +3 -1
  23. package/core/audits/dobetterweb/uses-http2.d.ts +0 -13
  24. package/core/audits/dobetterweb/uses-http2.js +4 -38
  25. package/core/audits/font-display.js +2 -2
  26. package/core/audits/layout-shifts.js +1 -1
  27. package/core/audits/preload-fonts.d.ts +1 -5
  28. package/core/audits/preload-fonts.js +1 -10
  29. package/core/audits/prioritize-lcp-image.js +2 -2
  30. package/core/audits/redirects-http.d.ts +19 -0
  31. package/core/audits/redirects-http.js +75 -0
  32. package/core/audits/resource-summary.d.ts +2 -0
  33. package/core/audits/resource-summary.js +5 -4
  34. package/core/audits/seo/is-crawlable.d.ts +2 -1
  35. package/core/audits/seo/link-text.js +12 -0
  36. package/core/audits/uses-rel-preload.d.ts +1 -5
  37. package/core/audits/uses-rel-preload.js +5 -15
  38. package/core/audits/work-during-interaction.d.ts +2 -2
  39. package/core/audits/work-during-interaction.js +2 -2
  40. package/core/computed/js-bundles.d.ts +1 -1
  41. package/core/computed/metrics/lantern-first-contentful-paint.d.ts +13 -82
  42. package/core/computed/metrics/lantern-first-contentful-paint.js +16 -178
  43. package/core/computed/metrics/lantern-first-meaningful-paint.d.ts +13 -12
  44. package/core/computed/metrics/lantern-first-meaningful-paint.js +11 -49
  45. package/core/computed/metrics/lantern-interactive.d.ts +13 -21
  46. package/core/computed/metrics/lantern-interactive.js +12 -84
  47. package/core/computed/metrics/lantern-largest-contentful-paint.d.ts +13 -25
  48. package/core/computed/metrics/lantern-largest-contentful-paint.js +13 -80
  49. package/core/computed/metrics/lantern-max-potential-fid.d.ts +13 -24
  50. package/core/computed/metrics/lantern-max-potential-fid.js +12 -64
  51. package/core/computed/metrics/lantern-metric.d.ts +14 -18
  52. package/core/computed/metrics/lantern-metric.js +34 -30
  53. package/core/computed/metrics/lantern-speed-index.d.ts +13 -32
  54. package/core/computed/metrics/lantern-speed-index.js +13 -116
  55. package/core/computed/metrics/lantern-total-blocking-time.d.ts +13 -25
  56. package/core/computed/metrics/lantern-total-blocking-time.js +10 -94
  57. package/core/computed/metrics/metric.js +1 -3
  58. package/core/computed/module-duplication.d.ts +1 -1
  59. package/core/computed/navigation-insights.d.ts +36 -0
  60. package/core/computed/navigation-insights.js +35 -0
  61. package/core/computed/page-dependency-graph.js +3 -7
  62. package/core/computed/resource-summary.d.ts +10 -12
  63. package/core/computed/resource-summary.js +12 -19
  64. package/core/computed/trace-engine-result.d.ts +16 -3
  65. package/core/computed/trace-engine-result.js +19 -14
  66. package/core/computed/unused-css.d.ts +3 -1
  67. package/core/computed/unused-css.js +6 -5
  68. package/core/config/config-helpers.js +0 -4
  69. package/core/config/constants.js +0 -1
  70. package/core/config/default-config.js +63 -142
  71. package/core/config/experimental-config.js +11 -0
  72. package/core/config/filters.js +0 -1
  73. package/core/gather/driver/navigation.js +4 -1
  74. package/core/gather/driver/prepare.js +1 -1
  75. package/core/gather/driver/target-manager.js +4 -3
  76. package/core/gather/driver/wait-for-condition.js +2 -3
  77. package/core/gather/driver.d.ts +12 -0
  78. package/core/gather/driver.js +27 -0
  79. package/core/gather/gatherers/accessibility.js +4 -6
  80. package/core/gather/gatherers/css-usage.d.ts +0 -21
  81. package/core/gather/gatherers/css-usage.js +9 -119
  82. package/core/gather/gatherers/root-causes.d.ts +2 -2
  83. package/core/gather/gatherers/root-causes.js +6 -5
  84. package/core/gather/gatherers/stylesheets.d.ts +26 -0
  85. package/core/gather/gatherers/stylesheets.js +138 -0
  86. package/core/gather/gatherers/trace-elements.d.ts +2 -12
  87. package/core/gather/gatherers/trace-elements.js +2 -21
  88. package/core/gather/navigation-runner.js +3 -1
  89. package/core/gather/session.d.ts +8 -0
  90. package/core/gather/session.js +14 -1
  91. package/core/lib/emulation.js +2 -2
  92. package/core/lib/i18n/i18n.d.ts +0 -1
  93. package/core/lib/i18n/i18n.js +0 -2
  94. package/core/lib/lantern/cpu-node.d.ts +7 -1
  95. package/core/lib/lantern/cpu-node.js +12 -2
  96. package/core/lib/lantern/lantern-error.d.ts +8 -0
  97. package/core/lib/lantern/lantern-error.js +9 -0
  98. package/core/lib/lantern/metric.js +2 -6
  99. package/core/lib/lantern/metrics/first-contentful-paint.d.ts +79 -0
  100. package/core/lib/lantern/metrics/first-contentful-paint.js +200 -0
  101. package/core/lib/lantern/metrics/first-meaningful-paint.d.ts +6 -0
  102. package/core/lib/lantern/metrics/first-meaningful-paint.js +64 -0
  103. package/core/lib/lantern/metrics/interactive.d.ts +26 -0
  104. package/core/lib/lantern/metrics/interactive.js +112 -0
  105. package/core/lib/lantern/metrics/largest-contentful-paint.d.ts +19 -0
  106. package/core/lib/lantern/metrics/largest-contentful-paint.js +108 -0
  107. package/core/lib/lantern/metrics/max-potential-fid.d.ts +30 -0
  108. package/core/lib/lantern/metrics/max-potential-fid.js +92 -0
  109. package/core/lib/lantern/metrics/speed-index.d.ts +38 -0
  110. package/core/lib/lantern/metrics/speed-index.js +144 -0
  111. package/core/lib/lantern/metrics/total-blocking-time.d.ts +31 -0
  112. package/core/lib/lantern/metrics/total-blocking-time.js +128 -0
  113. package/core/lib/lantern/network-node.js +28 -4
  114. package/core/lib/lantern/page-dependency-graph.d.ts +4 -4
  115. package/core/lib/lantern/page-dependency-graph.js +19 -7
  116. package/core/lib/lantern/simulator/connection-pool.d.ts +2 -12
  117. package/core/lib/lantern/simulator/connection-pool.js +3 -22
  118. package/core/lib/lantern/simulator/network-analyzer.js +1 -12
  119. package/core/lib/lantern/simulator/simulator.d.ts +2 -4
  120. package/core/lib/lantern/simulator/simulator.js +7 -14
  121. package/core/lib/lantern/types/lantern.d.ts +5 -3
  122. package/core/lib/lantern-trace-saver.js +0 -1
  123. package/core/lib/lh-error.d.ts +9 -0
  124. package/core/lib/lh-error.js +13 -3
  125. package/core/lib/lighthouse-compatibility.js +53 -10
  126. package/core/lib/navigation-error.js +3 -0
  127. package/core/lib/network-request.d.ts +1 -0
  128. package/core/lib/network-request.js +28 -0
  129. package/core/runner.js +18 -25
  130. package/dist/report/bundle.esm.js +11 -112
  131. package/dist/report/flow.js +16 -117
  132. package/dist/report/standalone.js +12 -113
  133. package/flow-report/src/help-dialog.tsx +0 -1
  134. package/flow-report/src/i18n/i18n.d.ts +0 -4
  135. package/flow-report/src/i18n/ui-strings.d.ts +0 -1
  136. package/flow-report/src/i18n/ui-strings.js +0 -2
  137. package/flow-report/src/summary/category.tsx +10 -12
  138. package/package.json +5 -5
  139. package/readme.md +4 -4
  140. package/report/assets/styles.css +1 -60
  141. package/report/assets/templates.html +0 -95
  142. package/report/renderer/category-renderer.js +1 -1
  143. package/report/renderer/components.d.ts +2 -2
  144. package/report/renderer/components.js +2 -103
  145. package/report/renderer/dom.d.ts +1 -1
  146. package/report/renderer/dom.js +1 -1
  147. package/report/renderer/performance-category-renderer.d.ts +0 -7
  148. package/report/renderer/performance-category-renderer.js +1 -32
  149. package/report/renderer/report-renderer.js +3 -13
  150. package/report/renderer/report-ui-features.js +1 -1
  151. package/report/renderer/report-utils.d.ts +0 -1
  152. package/report/renderer/report-utils.js +13 -13
  153. package/shared/localization/locales/ar-XB.json +62 -329
  154. package/shared/localization/locales/ar.json +62 -329
  155. package/shared/localization/locales/bg.json +62 -329
  156. package/shared/localization/locales/ca.json +62 -329
  157. package/shared/localization/locales/cs.json +62 -329
  158. package/shared/localization/locales/da.json +62 -329
  159. package/shared/localization/locales/de.json +62 -329
  160. package/shared/localization/locales/el.json +62 -329
  161. package/shared/localization/locales/en-GB.json +62 -329
  162. package/shared/localization/locales/en-US.json +41 -272
  163. package/shared/localization/locales/en-XA.json +62 -329
  164. package/shared/localization/locales/en-XL.json +41 -272
  165. package/shared/localization/locales/es-419.json +62 -329
  166. package/shared/localization/locales/es.json +62 -329
  167. package/shared/localization/locales/fi.json +62 -329
  168. package/shared/localization/locales/fil.json +61 -328
  169. package/shared/localization/locales/fr.json +62 -329
  170. package/shared/localization/locales/he.json +62 -329
  171. package/shared/localization/locales/hi.json +62 -329
  172. package/shared/localization/locales/hr.json +63 -330
  173. package/shared/localization/locales/hu.json +62 -329
  174. package/shared/localization/locales/id.json +62 -329
  175. package/shared/localization/locales/it.json +62 -329
  176. package/shared/localization/locales/ja.json +62 -329
  177. package/shared/localization/locales/ko.json +62 -329
  178. package/shared/localization/locales/lt.json +62 -329
  179. package/shared/localization/locales/lv.json +62 -329
  180. package/shared/localization/locales/nl.json +62 -329
  181. package/shared/localization/locales/no.json +62 -329
  182. package/shared/localization/locales/pl.json +61 -328
  183. package/shared/localization/locales/pt-PT.json +62 -329
  184. package/shared/localization/locales/pt.json +64 -331
  185. package/shared/localization/locales/ro.json +62 -329
  186. package/shared/localization/locales/ru.json +62 -329
  187. package/shared/localization/locales/sk.json +62 -329
  188. package/shared/localization/locales/sl.json +62 -329
  189. package/shared/localization/locales/sr-Latn.json +62 -329
  190. package/shared/localization/locales/sr.json +62 -329
  191. package/shared/localization/locales/sv.json +62 -329
  192. package/shared/localization/locales/ta.json +61 -328
  193. package/shared/localization/locales/te.json +62 -329
  194. package/shared/localization/locales/th.json +62 -329
  195. package/shared/localization/locales/tr.json +62 -329
  196. package/shared/localization/locales/uk.json +62 -329
  197. package/shared/localization/locales/vi.json +61 -328
  198. package/shared/localization/locales/zh-HK.json +62 -329
  199. package/shared/localization/locales/zh-TW.json +61 -328
  200. package/shared/localization/locales/zh.json +62 -329
  201. package/tsconfig.json +1 -3
  202. package/types/artifacts.d.ts +21 -110
  203. package/types/audit.d.ts +0 -10
  204. package/types/config.d.ts +0 -1
  205. package/types/externs.d.ts +0 -2
  206. package/types/gatherer.d.ts +3 -0
  207. package/types/internal/smokehouse.d.ts +1 -1
  208. package/types/lh.d.ts +0 -2
  209. package/types/lhr/audit-details.d.ts +9 -4
  210. package/types/lhr/lhr.d.ts +0 -4
  211. package/types/lhr/settings.d.ts +0 -4
  212. package/core/audits/accessibility/duplicate-id-active.js +0 -42
  213. package/core/audits/content-width.d.ts +0 -17
  214. package/core/audits/content-width.js +0 -76
  215. package/core/audits/installable-manifest.d.ts +0 -111
  216. package/core/audits/installable-manifest.js +0 -248
  217. package/core/audits/layout-shift-elements.d.ts +0 -16
  218. package/core/audits/layout-shift-elements.js +0 -101
  219. package/core/audits/manual/pwa-cross-browser.d.ts +0 -12
  220. package/core/audits/manual/pwa-cross-browser.js +0 -40
  221. package/core/audits/manual/pwa-each-page-has-url.d.ts +0 -12
  222. package/core/audits/manual/pwa-each-page-has-url.js +0 -38
  223. package/core/audits/manual/pwa-page-transitions.d.ts +0 -12
  224. package/core/audits/manual/pwa-page-transitions.js +0 -38
  225. package/core/audits/maskable-icon.d.ts +0 -25
  226. package/core/audits/maskable-icon.js +0 -70
  227. package/core/audits/multi-check-audit.d.ts +0 -28
  228. package/core/audits/multi-check-audit.js +0 -82
  229. package/core/audits/no-unload-listeners.d.ts +0 -16
  230. package/core/audits/no-unload-listeners.js +0 -86
  231. package/core/audits/performance-budget.d.ts +0 -39
  232. package/core/audits/performance-budget.js +0 -154
  233. package/core/audits/script-elements-test-audit.d.ts +0 -14
  234. package/core/audits/script-elements-test-audit.js +0 -29
  235. package/core/audits/seo/plugins.d.ts +0 -15
  236. package/core/audits/seo/plugins.js +0 -150
  237. package/core/audits/seo/tap-targets.d.ts +0 -50
  238. package/core/audits/seo/tap-targets.js +0 -352
  239. package/core/audits/splash-screen.d.ts +0 -37
  240. package/core/audits/splash-screen.js +0 -98
  241. package/core/audits/themed-omnibox.d.ts +0 -42
  242. package/core/audits/themed-omnibox.js +0 -102
  243. package/core/audits/timing-budget.d.ts +0 -43
  244. package/core/audits/timing-budget.js +0 -175
  245. package/core/computed/manifest-values.d.ts +0 -24
  246. package/core/computed/manifest-values.js +0 -136
  247. package/core/config/budget.d.ts +0 -74
  248. package/core/config/budget.js +0 -340
  249. package/core/config/metrics-to-audits.d.ts +0 -19
  250. package/core/config/metrics-to-audits.js +0 -62
  251. package/core/gather/driver/service-workers.d.ts +0 -16
  252. package/core/gather/driver/service-workers.js +0 -52
  253. package/core/gather/gatherers/dobetterweb/tags-blocking-first-paint.d.ts +0 -47
  254. package/core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js +0 -233
  255. package/core/gather/gatherers/global-listeners.d.ts +0 -27
  256. package/core/gather/gatherers/global-listeners.js +0 -108
  257. package/core/gather/gatherers/installability-errors.d.ts +0 -17
  258. package/core/gather/gatherers/installability-errors.js +0 -56
  259. package/core/gather/gatherers/script-elements.d.ts +0 -21
  260. package/core/gather/gatherers/script-elements.js +0 -100
  261. package/core/gather/gatherers/seo/embedded-content.d.ts +0 -10
  262. package/core/gather/gatherers/seo/embedded-content.js +0 -63
  263. package/core/gather/gatherers/seo/tap-targets.d.ts +0 -21
  264. package/core/gather/gatherers/seo/tap-targets.js +0 -389
  265. package/core/gather/gatherers/service-worker.d.ts +0 -10
  266. package/core/gather/gatherers/service-worker.js +0 -32
  267. package/core/gather/gatherers/web-app-manifest.d.ts +0 -32
  268. package/core/gather/gatherers/web-app-manifest.js +0 -106
  269. package/report/renderer/pwa-category-renderer.d.ts +0 -55
  270. package/report/renderer/pwa-category-renderer.js +0 -184
  271. package/third-party/chromium-synchronization/installability-errors-test.js +0 -79
  272. package/types/lhr/budget.d.ts +0 -60
@@ -140,15 +140,6 @@ class NetworkAnalyzer {
140
140
  const {timing, connectionReused, record} = info;
141
141
  if (connectionReused) return;
142
142
 
143
- // In LR, network records are missing connection timing, but we've smuggled it in via headers.
144
- if (global.isLightrider && record.lrStatistics) {
145
- if (record.protocol.startsWith('h3')) {
146
- return record.lrStatistics.TCPMs;
147
- } else {
148
- return [record.lrStatistics.TCPMs / 2, record.lrStatistics.TCPMs / 2];
149
- }
150
- }
151
-
152
143
  const {connectStart, sslStart, sslEnd, connectEnd} = timing;
153
144
  if (connectEnd >= 0 && connectStart >= 0 && record.protocol.startsWith('h3')) {
154
145
  // These values are equal to sslStart and sslEnd for h3.
@@ -256,9 +247,7 @@ class NetworkAnalyzer {
256
247
  */
257
248
  static _estimateResponseTimeByOrigin(records, rttByOrigin) {
258
249
  return NetworkAnalyzer._estimateValueByOrigin(records, ({record, timing}) => {
259
- // Lightrider does not have timings for sendEnd, but we do have this timing which should be
260
- // close to the response time.
261
- if (global.isLightrider && record.lrStatistics) return record.lrStatistics.requestMs;
250
+ if (record.serverResponseTime !== undefined) return record.serverResponseTime;
262
251
 
263
252
  if (!Number.isFinite(timing.receiveHeadersEnd) || timing.receiveHeadersEnd < 0) return;
264
253
  if (!Number.isFinite(timing.sendEnd) || timing.sendEnd < 0) return;
@@ -29,7 +29,6 @@ export class Simulator<T = any> {
29
29
  _layoutTaskMultiplier: number;
30
30
  /** @type {Array<Node>} */
31
31
  _cachedNodeListByStartPosition: Array<Node>;
32
- _flexibleOrdering: boolean;
33
32
  _nodeTimings: SimulatorTimingMap;
34
33
  /** @type {Map<string, number>} */
35
34
  _numberInProgressByType: Map<string, number>;
@@ -131,17 +130,16 @@ export class Simulator<T = any> {
131
130
  * Estimates the time taken to process all of the graph's nodes, returns the overall time along with
132
131
  * each node annotated by start/end times.
133
132
  *
134
- * If flexibleOrdering is set, simulator/connection pool are allowed to deviate from what was
133
+ * Simulator/connection pool are allowed to deviate from what was
135
134
  * observed in the trace/devtoolsLog and start requests as soon as they are queued (i.e. do not
136
135
  * wait around for a warm connection to be available if the original record was fetched on a warm
137
136
  * connection).
138
137
  *
139
138
  * @param {Node} graph
140
- * @param {{flexibleOrdering?: boolean, label?: string}=} options
139
+ * @param {{label?: string}=} options
141
140
  * @return {Lantern.Simulation.Result<T>}
142
141
  */
143
142
  simulate(graph: Node, options?: {
144
- flexibleOrdering?: boolean;
145
143
  label?: string;
146
144
  } | undefined): Lantern.Simulation.Result<T>;
147
145
  /**
@@ -80,7 +80,6 @@ class Simulator {
80
80
  this._cachedNodeListByStartPosition = [];
81
81
 
82
82
  // Properties reset on every `.simulate` call but duplicated here for type checking
83
- this._flexibleOrdering = false;
84
83
  this._nodeTimings = new SimulatorTimingMap();
85
84
  /** @type {Map<string, number>} */
86
85
  this._numberInProgressByType = new Map();
@@ -197,9 +196,7 @@ class Simulator {
197
196
  * @return {?TcpConnection}
198
197
  */
199
198
  _acquireConnection(record) {
200
- return this._connectionPool.acquire(record, {
201
- ignoreConnectionReused: this._flexibleOrdering,
202
- });
199
+ return this._connectionPool.acquire(record);
203
200
  }
204
201
 
205
202
  /**
@@ -276,7 +273,7 @@ class Simulator {
276
273
  ? this._layoutTaskMultiplier
277
274
  : this._cpuSlowdownMultiplier;
278
275
  const totalDuration = Math.min(
279
- Math.round(cpuNode.event.dur / 1000 * multiplier),
276
+ Math.round(cpuNode.duration / 1000 * multiplier),
280
277
  DEFAULT_MAXIMUM_CPU_TASK_DURATION
281
278
  );
282
279
  const estimatedTimeElapsed = totalDuration - timingData.timeElapsed;
@@ -425,13 +422,13 @@ class Simulator {
425
422
  * Estimates the time taken to process all of the graph's nodes, returns the overall time along with
426
423
  * each node annotated by start/end times.
427
424
  *
428
- * If flexibleOrdering is set, simulator/connection pool are allowed to deviate from what was
425
+ * Simulator/connection pool are allowed to deviate from what was
429
426
  * observed in the trace/devtoolsLog and start requests as soon as they are queued (i.e. do not
430
427
  * wait around for a warm connection to be available if the original record was fetched on a warm
431
428
  * connection).
432
429
  *
433
430
  * @param {Node} graph
434
- * @param {{flexibleOrdering?: boolean, label?: string}=} options
431
+ * @param {{label?: string}=} options
435
432
  * @return {Lantern.Simulation.Result<T>}
436
433
  */
437
434
  simulate(graph, options) {
@@ -441,11 +438,9 @@ class Simulator {
441
438
 
442
439
  options = Object.assign({
443
440
  label: undefined,
444
- flexibleOrdering: false,
445
441
  }, options);
446
442
 
447
443
  // initialize the necessary data containers
448
- this._flexibleOrdering = !!options.flexibleOrdering;
449
444
  this._dns = new DNSCache({rtt: this._rtt});
450
445
  this._initializeConnectionPool(graph);
451
446
  this._initializeAuxiliaryData();
@@ -470,11 +465,9 @@ class Simulator {
470
465
  }
471
466
 
472
467
  if (!nodesInProgress.size) {
473
- // interplay between fromDiskCache and connectionReused can be incorrect
474
- // proceed with flexibleOrdering if we can, otherwise give up
475
- if (this._flexibleOrdering) throw new Error('Failed to start a node');
476
- this._flexibleOrdering = true;
477
- continue;
468
+ // Interplay between fromDiskCache and connectionReused can be incorrect,
469
+ // have to give up.
470
+ throw new Error('Failed to start a node');
478
471
  }
479
472
 
480
473
  // set the available throughput for all connections based on # inflight
@@ -67,9 +67,6 @@ export class NetworkRequest<T = any> {
67
67
  resourceSize: number;
68
68
  fromDiskCache: boolean;
69
69
  fromMemoryCache: boolean;
70
- // TODO(15841): remove from lantern.
71
- /** Extra timing information available only when run in Lightrider. */
72
- lrStatistics: LightriderStatistics | undefined;
73
70
  finished: boolean;
74
71
  statusCode: number;
75
72
  /** The network request that this one redirected to */
@@ -80,6 +77,11 @@ export class NetworkRequest<T = any> {
80
77
  /** The chain of network requests that redirected to this one */
81
78
  redirects: NetworkRequest[] | undefined;
82
79
  timing: LH.Crdp.Network.ResourceTiming | undefined;
80
+ /**
81
+ * Optional value for how long the server took to respond to this request.
82
+ * When not provided, the server response time is derived from the timing object.
83
+ */
84
+ serverResponseTime: number | undefined;
83
85
  resourceType: LH.Crdp.Network.ResourceType | undefined;
84
86
  mimeType: string;
85
87
  priority: LH.Crdp.Network.ResourcePriority;
@@ -255,7 +255,6 @@ export default {
255
255
  'unlabeled',
256
256
  // These node timings should be nearly identical to the ones produced for Interactive
257
257
  'optimisticSpeedIndex',
258
- 'optimisticFlexSpeedIndex',
259
258
  'pessimisticSpeedIndex',
260
259
  ],
261
260
  convertNodeTimingsToTrace,
@@ -105,6 +105,7 @@ export namespace UIStrings {
105
105
  const missingRequiredArtifact: string;
106
106
  const erroredRequiredArtifact: string;
107
107
  const oldChromeDoesNotSupportFeature: string;
108
+ const targetCrashed: string;
108
109
  }
109
110
  declare namespace ERRORS {
110
111
  namespace NO_SPEEDLINE_FRAMES {
@@ -340,6 +341,14 @@ declare namespace ERRORS {
340
341
  import message_30 = UIStrings.erroredRequiredArtifact;
341
342
  export { message_30 as message };
342
343
  }
344
+ namespace TARGET_CRASHED {
345
+ const code_31: string;
346
+ export { code_31 as code };
347
+ import message_31 = UIStrings.targetCrashed;
348
+ export { message_31 as message };
349
+ const lhrRuntimeError_22: boolean;
350
+ export { lhrRuntimeError_22 as lhrRuntimeError };
351
+ }
343
352
  }
344
353
  export {};
345
354
  //# sourceMappingURL=lh-error.d.ts.map
@@ -76,13 +76,13 @@ const UIStrings = {
76
76
  criTimeout: 'Timeout waiting for initial Debugger Protocol connection.',
77
77
  /**
78
78
  * @description Error message explaining that a resource that was required for testing was never collected. "artifactName" will be replaced with the name of the resource that wasn't collected.
79
- * @example {WebAppManifest} artifactName
79
+ * @example {MainDocumentContent} artifactName
80
80
  * */
81
81
  missingRequiredArtifact: 'Required {artifactName} gatherer did not run.',
82
82
  /**
83
83
  * @description Error message explaining that there was an error while trying to collect a resource that was required for testing. "artifactName" will be replaced with the name of the resource that wasn't collected; "errorMessage" will be replaced with a string description of the error that occurred.
84
- * @example {WebAppManifest} artifactName
85
- * @example {Manifest invalid} errorMessage
84
+ * @example {MainDocumentContent} artifactName
85
+ * @example {Could not find main document} errorMessage
86
86
  * */
87
87
  erroredRequiredArtifact: 'Required {artifactName} gatherer encountered an error: {errorMessage}',
88
88
 
@@ -91,6 +91,9 @@ const UIStrings = {
91
91
  * @example {Largest Contentful Paint} featureName
92
92
  * */
93
93
  oldChromeDoesNotSupportFeature: 'This version of Chrome is too old to support \'{featureName}\'. Use a newer version to see full results.',
94
+
95
+ /** Error message explaining that the browser tab that Lighthouse is inspecting has crashed. */
96
+ targetCrashed: 'Browser tab has unexpectedly crashed.',
94
97
  };
95
98
 
96
99
  const str_ = i18n.createIcuMessageFn(import.meta.url, UIStrings);
@@ -423,6 +426,13 @@ const ERRORS = {
423
426
  message: UIStrings.erroredRequiredArtifact,
424
427
  },
425
428
 
429
+ /** The page has crashed and will no longer respond to 99% of CDP commmands. */
430
+ TARGET_CRASHED: {
431
+ code: 'TARGET_CRASHED',
432
+ message: UIStrings.targetCrashed,
433
+ lhrRuntimeError: true,
434
+ },
435
+
426
436
  // Hey! When adding a new error type, update lighthouse-result.proto too.
427
437
  // Only necessary for runtime errors, which come from artifacts or pageLoadErrors.
428
438
  };
@@ -108,19 +108,62 @@ function upgradeLhrForCompatibility(lhr) {
108
108
  }
109
109
  }
110
110
 
111
- // This backcompat converts old LHRs (<9.0.0) to use the new "hidden" group.
112
- // Old LHRs used "no group" to identify audits that should be hidden in performance instead of the "hidden" group.
113
- // Newer LHRs use "no group" to identify opportunities and diagnostics whose groups are assigned by details type.
111
+ // This backcompat converts old LHRs to use the "hidden" and "diagnostics" groups.
112
+ // <9.0.0 LHRs used "no group" to identify audits that should be hidden in performance instead of the "hidden" group.
113
+ // <9.0.0 LHRs used "load-opportunities" for opportunity audits that are now grouped under "diagnostics".
114
+ // >=9.0.0 && <12.0.0 LHRs use "no group" to identify opportunities and diagnostics whose groups are assigned by details type.
115
+ // >=12.0.0 LHRs use the "hidden" group to identify hidden audits and "diagnostics" to identify diagnostics. "no group" is meaningless.
114
116
  const [majorVersion] = lhr.lighthouseVersion.split('.').map(Number);
115
117
  const perfCategory = lhr.categories['performance'];
116
- if (majorVersion < 9 && perfCategory) {
117
- if (!lhr.categoryGroups) lhr.categoryGroups = {};
118
- lhr.categoryGroups['hidden'] = {title: ''};
118
+ if (perfCategory) {
119
+ if (majorVersion < 9) {
120
+ if (!lhr.categoryGroups) lhr.categoryGroups = {};
121
+ lhr.categoryGroups['hidden'] = {title: ''};
122
+ for (const auditRef of perfCategory.auditRefs) {
123
+ if (!auditRef.group) {
124
+ auditRef.group = 'hidden';
125
+ } else if (auditRef.group === 'load-opportunities') {
126
+ auditRef.group = 'diagnostics';
127
+ }
128
+ }
129
+ } else if (majorVersion < 12) {
130
+ for (const auditRef of perfCategory.auditRefs) {
131
+ if (!auditRef.group) {
132
+ auditRef.group = 'diagnostics';
133
+ }
134
+ }
135
+ }
136
+ }
137
+
138
+ if (majorVersion < 12 && perfCategory) {
139
+ /** @type {Map<string, string[]>} */
140
+ const metricRelevanceMap = new Map();
141
+
119
142
  for (const auditRef of perfCategory.auditRefs) {
120
- if (!auditRef.group) {
121
- auditRef.group = 'hidden';
122
- } else if (['load-opportunities', 'diagnostics'].includes(auditRef.group)) {
123
- delete auditRef.group;
143
+ /** @type {string[]|undefined} */
144
+ // @ts-expect-error Removed in v12
145
+ const relevantAudits = auditRef.relevantAudits;
146
+ if (!relevantAudits || !auditRef.acronym) continue;
147
+
148
+ for (const auditId of relevantAudits) {
149
+ const acronyms = metricRelevanceMap.get(auditId) || [];
150
+ acronyms.push(auditRef.acronym);
151
+ metricRelevanceMap.set(auditId, acronyms);
152
+ }
153
+ }
154
+
155
+ for (const [auditId, acronyms] of metricRelevanceMap) {
156
+ if (!acronyms.length) continue;
157
+
158
+ const audit = lhr.audits[auditId];
159
+ if (!audit) continue;
160
+
161
+ // Old versions can still define metric savings, let's not mess with it.
162
+ if (audit.metricSavings) continue;
163
+
164
+ audit.metricSavings = {};
165
+ for (const acronym of acronyms) {
166
+ audit.metricSavings[acronym] = 0;
124
167
  }
125
168
  }
126
169
  }
@@ -150,6 +150,9 @@ function getPageLoadError(navigationError, context) {
150
150
  let finalRecord;
151
151
  if (mainRecord) {
152
152
  finalRecord = NetworkAnalyzer.resolveRedirects(mainRecord);
153
+ } else {
154
+ // We have no network requests to process, use the navError
155
+ return navigationError;
153
156
  }
154
157
 
155
158
  if (finalRecord?.mimeType === XHTML_MIME_TYPE) {
@@ -247,6 +247,7 @@ export class NetworkRequest {
247
247
  * is passed in via X-Headers similar to 'X-TotalFetchedSize'.
248
248
  */
249
249
  _updateTimingsForLightrider(): void;
250
+ serverResponseTime: number | undefined;
250
251
  }
251
252
  export namespace NetworkRequest {
252
253
  export { HEADER_TCP };
@@ -536,6 +536,7 @@ class NetworkRequest {
536
536
  requestMs: requestMs,
537
537
  responseMs: responseMs,
538
538
  };
539
+ this.serverResponseTime = responseMs;
539
540
  }
540
541
 
541
542
  /**
@@ -574,8 +575,35 @@ class NetworkRequest {
574
575
  * @return {Lantern.NetworkRequest<NetworkRequest>}
575
576
  */
576
577
  static asLanternNetworkRequest(record) {
578
+ // In LR, network records are missing connection timing, but we've smuggled it in via headers.
579
+ let timing = record.timing;
580
+ let serverResponseTime;
581
+ if (global.isLightrider && record.lrStatistics) {
582
+ if (record.protocol.startsWith('h3')) {
583
+ // @ts-expect-error We don't need all the properties set.
584
+ timing = {
585
+ connectStart: 0,
586
+ connectEnd: record.lrStatistics.TCPMs,
587
+ };
588
+ } else {
589
+ // @ts-expect-error We don't need all the properties set.
590
+ timing = {
591
+ connectStart: 0,
592
+ sslStart: record.lrStatistics.TCPMs / 2,
593
+ connectEnd: record.lrStatistics.TCPMs,
594
+ sslEnd: record.lrStatistics.TCPMs,
595
+ };
596
+
597
+ // Lightrider does not have timings for sendEnd, but we do have this timing which should be
598
+ // close to the response time.
599
+ serverResponseTime = record.lrStatistics.requestMs;
600
+ }
601
+ }
602
+
577
603
  return {
578
604
  ...record,
605
+ timing,
606
+ serverResponseTime,
579
607
  record,
580
608
  };
581
609
  }
package/core/runner.js CHANGED
@@ -106,7 +106,6 @@ class Runner {
106
106
  networkUserAgent: artifacts.NetworkUserAgent,
107
107
  hostUserAgent: artifacts.HostUserAgent,
108
108
  benchmarkIndex: artifacts.BenchmarkIndex,
109
- benchmarkIndexes: artifacts.BenchmarkIndexes,
110
109
  credits,
111
110
  },
112
111
  audits: auditResultsById,
@@ -199,32 +198,27 @@ class Runner {
199
198
  data: sentryContext,
200
199
  });
201
200
 
202
- /** @type {LH.Artifacts} */
203
- let artifacts;
204
201
  if (settings.auditMode && !settings.gatherMode) {
205
202
  // No browser required, just load the artifacts from disk.
206
203
  const path = this._getDataSavePath(settings);
207
- artifacts = assetSaver.loadArtifacts(path);
208
- } else {
209
- const runnerStatus = {msg: 'Gather phase', id: 'lh:runner:gather'};
210
- log.time(runnerStatus, 'verbose');
211
-
212
- artifacts = await gatherFn({
213
- resolvedConfig: options.resolvedConfig,
214
- });
215
-
216
- log.timeEnd(runnerStatus);
217
-
218
- // If `gather` is run multiple times before `audit`, the timing entries for each `gather` can pollute one another.
219
- // We need to clear the timing entries at the end of gathering.
220
- // Set artifacts.Timing again to ensure lh:runner:gather is included.
221
- artifacts.Timing = log.takeTimeEntries();
222
-
223
- // -G means save these to disk (e.g. ./latest-run).
224
- if (settings.gatherMode) {
225
- const path = this._getDataSavePath(settings);
226
- await assetSaver.saveArtifacts(artifacts, path);
227
- }
204
+ return assetSaver.loadArtifacts(path);
205
+ }
206
+
207
+ const runnerStatus = {msg: 'Gather phase', id: 'lh:runner:gather'};
208
+ log.time(runnerStatus, 'verbose');
209
+
210
+ const artifacts = await gatherFn({resolvedConfig: options.resolvedConfig});
211
+ log.timeEnd(runnerStatus);
212
+
213
+ // If `gather` is run multiple times before `audit`, the timing entries for each `gather` can pollute one another.
214
+ // We need to clear the timing entries at the end of gathering.
215
+ // Set artifacts.Timing again to ensure lh:runner:gather is included.
216
+ artifacts.Timing = log.takeTimeEntries();
217
+
218
+ // -G means save these to disk (e.g. ./latest-run).
219
+ if (settings.gatherMode) {
220
+ const path = this._getDataSavePath(settings);
221
+ await assetSaver.saveArtifacts(artifacts, path);
228
222
  }
229
223
 
230
224
  return artifacts;
@@ -304,7 +298,6 @@ class Runner {
304
298
  auditMode: undefined,
305
299
  output: undefined,
306
300
  channel: undefined,
307
- budgets: undefined,
308
301
  };
309
302
  const normalizedGatherSettings = Object.assign({}, artifacts.settings, overrides);
310
303
  const normalizedAuditSettings = Object.assign({}, settings, overrides);