lighthouse 10.4.0 → 11.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 (288) hide show
  1. package/CONTRIBUTING.md +1 -1
  2. package/cli/cli-flags.d.ts +1 -6
  3. package/cli/cli-flags.js +0 -5
  4. package/cli/run.js +3 -10
  5. package/cli/sentry-prompt.js +4 -2
  6. package/cli/test/smokehouse/core-tests.js +0 -2
  7. package/cli/test/smokehouse/frontends/smokehouse-bin.js +24 -14
  8. package/cli/test/smokehouse/lighthouse-runners/bundle.d.ts +1 -2
  9. package/cli/test/smokehouse/lighthouse-runners/bundle.js +12 -21
  10. package/cli/test/smokehouse/lighthouse-runners/cli.d.ts +1 -3
  11. package/cli/test/smokehouse/lighthouse-runners/cli.js +3 -7
  12. package/cli/test/smokehouse/lighthouse-runners/devtools.d.ts +1 -5
  13. package/cli/test/smokehouse/lighthouse-runners/devtools.js +1 -12
  14. package/cli/test/smokehouse/readme.md +0 -2
  15. package/cli/test/smokehouse/report-assert.d.ts +1 -3
  16. package/cli/test/smokehouse/report-assert.js +2 -19
  17. package/cli/test/smokehouse/smokehouse.js +3 -32
  18. package/core/audits/accessibility/aria-allowed-role.d.ts +10 -0
  19. package/core/audits/accessibility/aria-allowed-role.js +46 -0
  20. package/core/audits/accessibility/image-redundant-alt.d.ts +10 -0
  21. package/core/audits/accessibility/image-redundant-alt.js +45 -0
  22. package/core/audits/accessibility/label-content-name-mismatch.d.ts +10 -0
  23. package/core/audits/accessibility/label-content-name-mismatch.js +44 -0
  24. package/core/audits/accessibility/skip-link.d.ts +10 -0
  25. package/core/audits/accessibility/skip-link.js +43 -0
  26. package/core/audits/accessibility/table-duplicate-name.d.ts +10 -0
  27. package/core/audits/accessibility/table-duplicate-name.js +44 -0
  28. package/core/audits/accessibility/target-size.js +1 -1
  29. package/core/audits/byte-efficiency/duplicated-javascript.js +2 -2
  30. package/core/audits/byte-efficiency/render-blocking-resources.js +1 -0
  31. package/core/audits/dobetterweb/uses-http2.d.ts +18 -1
  32. package/core/audits/dobetterweb/uses-http2.js +62 -16
  33. package/core/audits/installable-manifest.d.ts +1 -5
  34. package/core/audits/installable-manifest.js +2 -7
  35. package/core/audits/largest-contentful-paint-element.d.ts +0 -6
  36. package/core/audits/largest-contentful-paint-element.js +13 -15
  37. package/core/audits/metrics/{experimental-interaction-to-next-paint.d.ts → interaction-to-next-paint.d.ts} +3 -3
  38. package/core/audits/metrics/{experimental-interaction-to-next-paint.js → interaction-to-next-paint.js} +3 -3
  39. package/core/audits/uses-rel-preconnect.js +23 -8
  40. package/core/audits/work-during-interaction.js +2 -2
  41. package/core/computed/processed-navigation.d.ts +1 -1
  42. package/core/config/config-helpers.d.ts +3 -3
  43. package/core/config/config-helpers.js +5 -12
  44. package/core/config/config.js +1 -7
  45. package/core/config/constants.d.ts +0 -2
  46. package/core/config/constants.js +2 -18
  47. package/core/config/default-config.js +59 -53
  48. package/core/config/filters.js +1 -1
  49. package/core/config/validation.d.ts +7 -12
  50. package/core/config/validation.js +16 -26
  51. package/core/gather/base-artifacts.d.ts +4 -4
  52. package/core/gather/base-artifacts.js +2 -6
  53. package/core/gather/base-gatherer.d.ts +12 -37
  54. package/core/gather/base-gatherer.js +7 -54
  55. package/core/gather/driver/dom.d.ts +4 -4
  56. package/core/gather/driver/dom.js +2 -2
  57. package/core/gather/driver/environment.d.ts +4 -4
  58. package/core/gather/driver/environment.js +2 -2
  59. package/core/gather/driver/execution-context.d.ts +12 -3
  60. package/core/gather/driver/execution-context.js +34 -3
  61. package/core/gather/driver/navigation.d.ts +2 -2
  62. package/core/gather/driver/navigation.js +2 -5
  63. package/core/gather/driver/network-monitor.d.ts +7 -6
  64. package/core/gather/driver/network-monitor.js +4 -4
  65. package/core/gather/driver/network.d.ts +2 -2
  66. package/core/gather/driver/network.js +1 -1
  67. package/core/gather/driver/prepare.d.ts +10 -10
  68. package/core/gather/driver/prepare.js +10 -10
  69. package/core/gather/driver/service-workers.d.ts +4 -4
  70. package/core/gather/driver/service-workers.js +2 -2
  71. package/core/gather/driver/storage.d.ts +6 -6
  72. package/core/gather/driver/storage.js +3 -3
  73. package/core/gather/driver/target-manager.d.ts +6 -5
  74. package/core/gather/driver/target-manager.js +3 -3
  75. package/core/gather/driver/wait-for-condition.d.ts +14 -14
  76. package/core/gather/driver/wait-for-condition.js +8 -8
  77. package/core/gather/driver.d.ts +9 -6
  78. package/core/gather/driver.js +14 -4
  79. package/core/gather/fetcher.d.ts +3 -3
  80. package/core/gather/fetcher.js +1 -1
  81. package/core/gather/gatherers/accessibility.d.ts +4 -4
  82. package/core/gather/gatherers/accessibility.js +8 -3
  83. package/core/gather/gatherers/anchor-elements.d.ts +4 -4
  84. package/core/gather/gatherers/anchor-elements.js +4 -4
  85. package/core/gather/gatherers/bf-cache-failures.d.ts +8 -14
  86. package/core/gather/gatherers/bf-cache-failures.js +5 -14
  87. package/core/gather/gatherers/cache-contents.d.ts +4 -4
  88. package/core/gather/gatherers/cache-contents.js +3 -3
  89. package/core/gather/gatherers/console-messages.d.ts +6 -6
  90. package/core/gather/gatherers/console-messages.js +4 -4
  91. package/core/gather/gatherers/css-usage.d.ts +14 -14
  92. package/core/gather/gatherers/css-usage.js +9 -9
  93. package/core/gather/gatherers/devtools-log-compat.d.ts +5 -5
  94. package/core/gather/gatherers/devtools-log-compat.js +4 -4
  95. package/core/gather/gatherers/devtools-log.d.ts +6 -6
  96. package/core/gather/gatherers/devtools-log.js +4 -4
  97. package/core/gather/gatherers/dobetterweb/doctype.d.ts +4 -4
  98. package/core/gather/gatherers/dobetterweb/doctype.js +3 -3
  99. package/core/gather/gatherers/dobetterweb/domstats.d.ts +4 -4
  100. package/core/gather/gatherers/dobetterweb/domstats.js +3 -3
  101. package/core/gather/gatherers/dobetterweb/optimized-images.d.ts +10 -22
  102. package/core/gather/gatherers/dobetterweb/optimized-images.js +10 -27
  103. package/core/gather/gatherers/dobetterweb/response-compression.d.ts +6 -12
  104. package/core/gather/gatherers/dobetterweb/response-compression.js +14 -21
  105. package/core/gather/gatherers/dobetterweb/tags-blocking-first-paint.d.ts +8 -14
  106. package/core/gather/gatherers/dobetterweb/tags-blocking-first-paint.js +5 -14
  107. package/core/gather/gatherers/full-page-screenshot.d.ts +10 -10
  108. package/core/gather/gatherers/full-page-screenshot.js +7 -10
  109. package/core/gather/gatherers/global-listeners.d.ts +4 -4
  110. package/core/gather/gatherers/global-listeners.js +3 -3
  111. package/core/gather/gatherers/iframe-elements.d.ts +4 -4
  112. package/core/gather/gatherers/iframe-elements.js +3 -3
  113. package/core/gather/gatherers/image-elements.d.ts +10 -10
  114. package/core/gather/gatherers/image-elements.js +6 -6
  115. package/core/gather/gatherers/inputs.d.ts +4 -4
  116. package/core/gather/gatherers/inputs.js +3 -3
  117. package/core/gather/gatherers/inspector-issues.d.ts +8 -19
  118. package/core/gather/gatherers/inspector-issues.js +9 -26
  119. package/core/gather/gatherers/installability-errors.d.ts +6 -6
  120. package/core/gather/gatherers/installability-errors.js +4 -4
  121. package/core/gather/gatherers/js-usage.d.ts +6 -6
  122. package/core/gather/gatherers/js-usage.js +4 -4
  123. package/core/gather/gatherers/link-elements.d.ts +8 -20
  124. package/core/gather/gatherers/link-elements.js +7 -24
  125. package/core/gather/gatherers/main-document-content.d.ts +4 -16
  126. package/core/gather/gatherers/main-document-content.js +5 -23
  127. package/core/gather/gatherers/meta-elements.d.ts +4 -4
  128. package/core/gather/gatherers/meta-elements.js +3 -3
  129. package/core/gather/gatherers/network-user-agent.d.ts +5 -5
  130. package/core/gather/gatherers/network-user-agent.js +4 -4
  131. package/core/gather/gatherers/script-elements.d.ts +6 -11
  132. package/core/gather/gatherers/script-elements.js +4 -13
  133. package/core/gather/gatherers/scripts.d.ts +7 -6
  134. package/core/gather/gatherers/scripts.js +7 -9
  135. package/core/gather/gatherers/seo/embedded-content.d.ts +4 -4
  136. package/core/gather/gatherers/seo/embedded-content.js +3 -3
  137. package/core/gather/gatherers/seo/font-size.d.ts +6 -6
  138. package/core/gather/gatherers/seo/font-size.js +5 -5
  139. package/core/gather/gatherers/seo/robots-txt.d.ts +4 -4
  140. package/core/gather/gatherers/seo/robots-txt.js +3 -3
  141. package/core/gather/gatherers/seo/tap-targets.d.ts +8 -8
  142. package/core/gather/gatherers/seo/tap-targets.js +5 -5
  143. package/core/gather/gatherers/service-worker.d.ts +4 -10
  144. package/core/gather/gatherers/service-worker.js +3 -15
  145. package/core/gather/gatherers/source-maps.d.ts +11 -23
  146. package/core/gather/gatherers/source-maps.js +22 -53
  147. package/core/gather/gatherers/stacks.d.ts +7 -7
  148. package/core/gather/gatherers/stacks.js +6 -6
  149. package/core/gather/gatherers/trace-compat.d.ts +5 -5
  150. package/core/gather/gatherers/trace-compat.js +4 -4
  151. package/core/gather/gatherers/trace-elements.d.ts +13 -25
  152. package/core/gather/gatherers/trace-elements.js +19 -32
  153. package/core/gather/gatherers/trace.d.ts +8 -8
  154. package/core/gather/gatherers/trace.js +5 -5
  155. package/core/gather/gatherers/viewport-dimensions.d.ts +4 -4
  156. package/core/gather/gatherers/viewport-dimensions.js +3 -3
  157. package/core/gather/gatherers/web-app-manifest.d.ts +8 -8
  158. package/core/gather/gatherers/web-app-manifest.js +5 -5
  159. package/core/gather/navigation-runner.d.ts +9 -9
  160. package/core/gather/navigation-runner.js +14 -8
  161. package/core/gather/runner-helpers.d.ts +3 -3
  162. package/core/gather/runner-helpers.js +12 -4
  163. package/core/gather/session.d.ts +2 -2
  164. package/core/gather/session.js +1 -1
  165. package/core/gather/snapshot-runner.d.ts +2 -2
  166. package/core/gather/snapshot-runner.js +1 -1
  167. package/core/gather/timespan-runner.d.ts +2 -2
  168. package/core/gather/timespan-runner.js +1 -1
  169. package/core/index.cjs +0 -7
  170. package/core/index.d.ts +0 -15
  171. package/core/index.js +2 -40
  172. package/core/lib/asset-saver.js +14 -4
  173. package/core/lib/axe.js +1 -1
  174. package/core/lib/dependency-graph/simulator/network-analyzer.d.ts +28 -12
  175. package/core/lib/dependency-graph/simulator/network-analyzer.js +128 -100
  176. package/core/lib/emulation.d.ts +14 -14
  177. package/core/lib/emulation.js +7 -7
  178. package/core/lib/navigation-error.js +5 -0
  179. package/core/lib/network-recorder.d.ts +2 -1
  180. package/core/lib/network-recorder.js +1 -0
  181. package/core/lib/network-request.js +12 -3
  182. package/core/lib/page-functions.d.ts +10 -2
  183. package/core/lib/page-functions.js +85 -8
  184. package/core/lib/sentry.js +9 -2
  185. package/core/lib/stack-packs.js +4 -0
  186. package/core/runner.d.ts +8 -30
  187. package/core/runner.js +8 -39
  188. package/core/user-flow.d.ts +4 -4
  189. package/core/user-flow.js +2 -2
  190. package/dist/report/bundle.esm.js +2221 -5832
  191. package/dist/report/flow.js +2631 -235
  192. package/dist/report/standalone.js +2586 -234
  193. package/flow-report/src/i18n/i18n.d.ts +2 -2
  194. package/package.json +17 -24
  195. package/readme.md +3 -1
  196. package/report/assets/templates.html +3 -1
  197. package/report/renderer/category-renderer.d.ts +3 -2
  198. package/report/renderer/category-renderer.js +8 -4
  199. package/report/renderer/components.js +11 -5
  200. package/report/renderer/pwa-category-renderer.js +1 -1
  201. package/report/renderer/report-ui-features.js +9 -6
  202. package/report/renderer/report-utils.d.ts +1 -1
  203. package/report/renderer/report-utils.js +2 -2
  204. package/report/renderer/topbar-features.js +3 -0
  205. package/shared/localization/locales/ar-XB.json +185 -44
  206. package/shared/localization/locales/ar.json +185 -44
  207. package/shared/localization/locales/bg.json +185 -44
  208. package/shared/localization/locales/ca.json +190 -49
  209. package/shared/localization/locales/cs.json +185 -44
  210. package/shared/localization/locales/da.json +185 -44
  211. package/shared/localization/locales/de.json +185 -44
  212. package/shared/localization/locales/el.json +185 -44
  213. package/shared/localization/locales/en-GB.json +185 -44
  214. package/shared/localization/locales/en-US.json +99 -45
  215. package/shared/localization/locales/en-XA.json +185 -44
  216. package/shared/localization/locales/en-XL.json +99 -45
  217. package/shared/localization/locales/es-419.json +185 -44
  218. package/shared/localization/locales/es.json +185 -44
  219. package/shared/localization/locales/fi.json +185 -44
  220. package/shared/localization/locales/fil.json +185 -44
  221. package/shared/localization/locales/fr.json +185 -44
  222. package/shared/localization/locales/he.json +186 -45
  223. package/shared/localization/locales/hi.json +185 -44
  224. package/shared/localization/locales/hr.json +185 -44
  225. package/shared/localization/locales/hu.json +185 -44
  226. package/shared/localization/locales/id.json +185 -44
  227. package/shared/localization/locales/it.json +185 -44
  228. package/shared/localization/locales/ja.json +185 -44
  229. package/shared/localization/locales/ko.json +185 -44
  230. package/shared/localization/locales/lt.json +185 -44
  231. package/shared/localization/locales/lv.json +185 -44
  232. package/shared/localization/locales/nl.json +185 -44
  233. package/shared/localization/locales/no.json +185 -44
  234. package/shared/localization/locales/pl.json +185 -44
  235. package/shared/localization/locales/pt-PT.json +185 -44
  236. package/shared/localization/locales/pt.json +190 -49
  237. package/shared/localization/locales/ro.json +185 -44
  238. package/shared/localization/locales/ru.json +185 -44
  239. package/shared/localization/locales/sk.json +185 -44
  240. package/shared/localization/locales/sl.json +185 -44
  241. package/shared/localization/locales/sr-Latn.json +185 -44
  242. package/shared/localization/locales/sr.json +185 -44
  243. package/shared/localization/locales/sv.json +185 -44
  244. package/shared/localization/locales/ta.json +185 -44
  245. package/shared/localization/locales/te.json +185 -44
  246. package/shared/localization/locales/th.json +185 -44
  247. package/shared/localization/locales/tr.json +185 -44
  248. package/shared/localization/locales/uk.json +185 -44
  249. package/shared/localization/locales/vi.json +185 -44
  250. package/shared/localization/locales/zh-HK.json +185 -44
  251. package/shared/localization/locales/zh-TW.json +185 -44
  252. package/shared/localization/locales/zh.json +185 -44
  253. package/third-party/esbuild-plugins-polyfills/LICENSE +3 -0
  254. package/third-party/esbuild-plugins-polyfills/README.md +7 -0
  255. package/third-party/esbuild-plugins-polyfills/esbuild-polyfills.d.ts +9 -0
  256. package/third-party/esbuild-plugins-polyfills/esbuild-polyfills.js +129 -0
  257. package/tsconfig.json +2 -1
  258. package/types/artifacts.d.ts +16 -45
  259. package/types/config.d.ts +10 -52
  260. package/types/externs.d.ts +0 -2
  261. package/types/gatherer.d.ts +24 -47
  262. package/types/internal/rxjs.d.ts +26 -0
  263. package/types/internal/smokehouse.d.ts +1 -3
  264. package/types/lh.d.ts +0 -2
  265. package/types/lhr/settings.d.ts +1 -1
  266. package/core/audits/metrics/first-contentful-paint-3g.d.ts +0 -15
  267. package/core/audits/metrics/first-contentful-paint-3g.js +0 -69
  268. package/core/audits/resource-summary.d.ts +0 -16
  269. package/core/audits/resource-summary.js +0 -104
  270. package/core/audits/service-worker.d.ts +0 -46
  271. package/core/audits/service-worker.js +0 -182
  272. package/core/gather/gatherers/gatherer.d.ts +0 -46
  273. package/core/gather/gatherers/gatherer.js +0 -58
  274. package/core/legacy/config/config.d.ts +0 -107
  275. package/core/legacy/config/config.js +0 -566
  276. package/core/legacy/config/legacy-default-config.d.ts +0 -4
  277. package/core/legacy/config/legacy-default-config.js +0 -87
  278. package/core/legacy/gather/connections/connection.d.ts +0 -77
  279. package/core/legacy/gather/connections/connection.js +0 -196
  280. package/core/legacy/gather/connections/cri.d.ts +0 -27
  281. package/core/legacy/gather/connections/cri.js +0 -162
  282. package/core/legacy/gather/connections/raw.d.ts +0 -20
  283. package/core/legacy/gather/connections/raw.js +0 -57
  284. package/core/legacy/gather/driver.d.ts +0 -216
  285. package/core/legacy/gather/driver.js +0 -480
  286. package/core/legacy/gather/gather-runner.d.ts +0 -166
  287. package/core/legacy/gather/gather-runner.js +0 -590
  288. package/types/internal/lighthouse-logger.d.ts +0 -34
@@ -95,6 +95,9 @@ function getNonHtmlError(finalRecord) {
95
95
  // If we never requested a document, there's no doctype error, let other cases handle it.
96
96
  if (!finalRecord) return undefined;
97
97
 
98
+ // If the document request error'd, we should not complain about a bad mimeType.
99
+ if (!finalRecord.mimeType || finalRecord.statusCode === -1) return undefined;
100
+
98
101
  // mimeType is determined by the browser, we assume Chrome is determining mimeType correctly,
99
102
  // independently of 'Content-Type' response headers, and always sending mimeType if well-formed.
100
103
  if (finalRecord.mimeType !== HTML_MIME_TYPE && finalRecord.mimeType !== XHTML_MIME_TYPE) {
@@ -163,6 +166,8 @@ function getPageLoadError(navigationError, context) {
163
166
  // Navigation errors are rather generic and express some failure of the page to render properly.
164
167
  // Use `navigationError` as the last resort.
165
168
  // Example: `NO_FCP`, the page never painted content for some unknown reason.
169
+ // Note that the caller possibly gave this to us as undefined, in which case we have determined
170
+ // there to be no error with this page load - but there was perhaps a warning.
166
171
  return navigationError;
167
172
  }
168
173
 
@@ -17,7 +17,7 @@ export class NetworkRecorder extends NetworkRecorder_base {
17
17
  * @param {LH.DevtoolsLog} devtoolsLog
18
18
  * @return {Array<LH.Artifacts.NetworkRequest>}
19
19
  */
20
- static recordsFromLogs(devtoolsLog: import("../index.js").DevtoolsLog): Array<LH.Artifacts.NetworkRequest>;
20
+ static recordsFromLogs(devtoolsLog: LH.DevtoolsLog): Array<LH.Artifacts.NetworkRequest>;
21
21
  /** @type {NetworkRequest[]} */
22
22
  _records: NetworkRequest[];
23
23
  /** @type {Map<string, NetworkRequest>} */
@@ -117,5 +117,6 @@ export class NetworkRecorder extends NetworkRecorder_base {
117
117
  _findRealRequestAndSetSession(requestId: string, targetType: LH.Protocol.TargetType, sessionId: string | undefined): NetworkRequest | undefined;
118
118
  }
119
119
  import { NetworkRequest } from './network-request.js';
120
+ import * as LH from '../../types/lh.js';
120
121
  export {};
121
122
  //# sourceMappingURL=network-recorder.d.ts.map
@@ -8,6 +8,7 @@ import {EventEmitter} from 'events';
8
8
 
9
9
  import log from 'lighthouse-logger';
10
10
 
11
+ import * as LH from '../../types/lh.js';
11
12
  import {NetworkRequest} from './network-request.js';
12
13
  import {PageDependencyGraph} from '../computed/page-dependency-graph.js';
13
14
 
@@ -489,7 +489,7 @@ class NetworkRequest {
489
489
  // Bail if there was no totalTime.
490
490
  if (!totalHeader) return;
491
491
 
492
- const totalMs = parseInt(totalHeader.value);
492
+ let totalMs = parseInt(totalHeader.value);
493
493
  const TCPMsHeader = this.responseHeaders.find(item => item.name === HEADER_TCP);
494
494
  const SSLMsHeader = this.responseHeaders.find(item => item.name === HEADER_SSL);
495
495
  const requestMsHeader = this.responseHeaders.find(item => item.name === HEADER_REQ);
@@ -502,11 +502,20 @@ class NetworkRequest {
502
502
  const requestMs = requestMsHeader ? Math.max(0, parseInt(requestMsHeader.value)) : 0;
503
503
  const responseMs = responseMsHeader ? Math.max(0, parseInt(responseMsHeader.value)) : 0;
504
504
 
505
- // Bail if the timings don't add up.
506
- if (TCPMs + requestMs + responseMs !== totalMs) {
505
+ if (Number.isNaN(TCPMs + requestMs + responseMs + totalMs)) {
507
506
  return;
508
507
  }
509
508
 
509
+ // If things don't add up, tweak the total a bit.
510
+ if (TCPMs + requestMs + responseMs !== totalMs) {
511
+ const delta = Math.abs(TCPMs + requestMs + responseMs - totalMs);
512
+ // We didn't see total being more than 5ms less than the total of the components.
513
+ // Allow some discrepancy in the timing, but not too much.
514
+ if (delta >= 25) return;
515
+
516
+ totalMs = TCPMs + requestMs + responseMs;
517
+ }
518
+
510
519
  // Bail if SSL time is > TCP time.
511
520
  if (SSLMs > TCPMs) {
512
521
  return;
@@ -11,6 +11,8 @@ export namespace pageFunctions {
11
11
  export { wrapRequestIdleCallback };
12
12
  export { getBoundingClientRect };
13
13
  export { truncate };
14
+ export { esbuildFunctionWrapperString };
15
+ export { getRuntimeFunctionName };
14
16
  }
15
17
  /**
16
18
  * `typed-query-selector`'s CSS selector parser.
@@ -49,11 +51,11 @@ declare function wrapRuntimeEvalErrorInBrowser(err?: string | Error | undefined)
49
51
  };
50
52
  /**
51
53
  * @template {string} T
52
- * @param {T} selector Optional simple CSS selector to filter nodes on.
54
+ * @param {T=} selector Optional simple CSS selector to filter nodes on.
53
55
  * Combinators are not supported.
54
56
  * @return {Array<ParseSelector<T>>}
55
57
  */
56
- declare function getElementsInDocument<T extends string>(selector: T): import("typed-query-selector/parser").ParseSelector<T, Element>[];
58
+ declare function getElementsInDocument<T extends string>(selector?: T | undefined): import("typed-query-selector/parser").ParseSelector<T, Element>[];
57
59
  /**
58
60
  * Gets the opening tag text of the given node.
59
61
  * @param {Element|ShadowRoot} element
@@ -157,5 +159,11 @@ declare function truncate(string: string, characterLimit: number): string;
157
159
  declare namespace truncate {
158
160
  function toString(): string;
159
161
  }
162
+ declare const esbuildFunctionWrapperString: string;
163
+ /**
164
+ * @param {Function} fn
165
+ * @return {string}
166
+ */
167
+ declare function getRuntimeFunctionName(fn: Function): string;
160
168
  export {};
161
169
  //# sourceMappingURL=page-functions.d.ts.map
@@ -4,6 +4,8 @@
4
4
  * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
5
5
  */
6
6
 
7
+ import {createRequire} from 'module';
8
+
7
9
  import {Util} from '../../shared/util.js';
8
10
 
9
11
  /**
@@ -50,7 +52,7 @@ function wrapRuntimeEvalErrorInBrowser(err) {
50
52
 
51
53
  /**
52
54
  * @template {string} T
53
- * @param {T} selector Optional simple CSS selector to filter nodes on.
55
+ * @param {T=} selector Optional simple CSS selector to filter nodes on.
54
56
  * Combinators are not supported.
55
57
  * @return {Array<ParseSelector<T>>}
56
58
  */
@@ -513,16 +515,89 @@ function truncate(string, characterLimit) {
513
515
  return Util.truncate(string, characterLimit);
514
516
  }
515
517
 
516
- /** @type {string} */
517
- const truncateRawString = truncate.toString();
518
- truncate.toString = () => `function truncate(string, characterLimit) {
518
+ function isBundledEnvironment() {
519
+ // If we're in DevTools or LightRider, we are definitely bundled.
520
+ // TODO: refactor and delete `global.isDevtools`.
521
+ if (global.isDevtools || global.isLightrider) return true;
522
+
523
+ const require = createRequire(import.meta.url);
524
+
525
+ try {
526
+ // Not foolproof, but `lighthouse-logger` is a dependency of lighthouse that should always be resolvable.
527
+ // `require.resolve` will only throw in atypical/bundled environments.
528
+ require.resolve('lighthouse-logger');
529
+ return false;
530
+ } catch (err) {
531
+ return true;
532
+ }
533
+ }
534
+
535
+ // This is to support bundled lighthouse.
536
+ // esbuild calls every function with a builtin `__name` (since we set keepNames: true),
537
+ // whose purpose is to store the real name of the function so that esbuild can rename it to avoid
538
+ // collisions. Anywhere we inject dynamically generated code at runtime for the browser to process,
539
+ // we must manually include this function (because esbuild only does so once at the top scope of
540
+ // the bundle, which is irrelevant for code executed in the browser).
541
+ // When minified, esbuild will mangle the name of this wrapper function, so we need to determine what it
542
+ // is at runtime in order to recreate it within the page.
543
+ const esbuildFunctionWrapperString = createEsbuildFunctionWrapper();
544
+
545
+ function createEsbuildFunctionWrapper() {
546
+ if (!isBundledEnvironment()) {
547
+ return '';
548
+ }
549
+
550
+ const functionAsString = (()=>{
551
+ // eslint-disable-next-line no-unused-vars
552
+ const a = ()=>{};
553
+ }).toString()
554
+ // When not minified, esbuild annotates the call to this function wrapper with PURE.
555
+ // We know further that the name of the wrapper function should be `__name`, but let's not
556
+ // hardcode that. Remove the PURE annotation to simplify the regex.
557
+ .replace('/* @__PURE__ */', '');
558
+ const functionStringMatch = functionAsString.match(/=\s*([\w_]+)\(/);
559
+ if (!functionStringMatch) {
560
+ throw new Error('Could not determine esbuild function wrapper name');
561
+ }
562
+
563
+ /**
564
+ * @param {Function} fn
565
+ * @param {string} value
566
+ */
567
+ const esbuildFunctionWrapper = (fn, value) =>
568
+ Object.defineProperty(fn, 'name', {value, configurable: true});
569
+ const wrapperFnName = functionStringMatch[1];
570
+ return `let ${wrapperFnName}=${esbuildFunctionWrapper}`;
571
+ }
572
+
573
+ /**
574
+ * @param {Function} fn
575
+ * @return {string}
576
+ */
577
+ function getRuntimeFunctionName(fn) {
578
+ const match = fn.toString().match(/function ([\w$]+)/);
579
+ if (!match) throw new Error(`could not find function name for: ${fn}`);
580
+ return match[1];
581
+ }
582
+
583
+ // We setup a number of our page functions to automatically include their dependencies.
584
+ // Because of esbuild bundling, we must refer to the actual (mangled) runtime function name.
585
+ /** @type {Record<string, string>} */
586
+ const names = {
587
+ truncate: getRuntimeFunctionName(truncate),
588
+ getNodeLabel: getRuntimeFunctionName(getNodeLabel),
589
+ getOuterHTMLSnippet: getRuntimeFunctionName(getOuterHTMLSnippet),
590
+ getNodeDetails: getRuntimeFunctionName(getNodeDetails),
591
+ };
592
+
593
+ truncate.toString = () => `function ${names.truncate}(string, characterLimit) {
519
594
  const Util = { ${Util.truncate} };
520
- return (${truncateRawString})(string, characterLimit);
595
+ return Util.truncate(string, characterLimit);
521
596
  }`;
522
597
 
523
598
  /** @type {string} */
524
599
  const getNodeLabelRawString = getNodeLabel.toString();
525
- getNodeLabel.toString = () => `function getNodeLabel(element) {
600
+ getNodeLabel.toString = () => `function ${names.getNodeLabel}(element) {
526
601
  ${truncate};
527
602
  return (${getNodeLabelRawString})(element);
528
603
  }`;
@@ -530,14 +605,14 @@ getNodeLabel.toString = () => `function getNodeLabel(element) {
530
605
  /** @type {string} */
531
606
  const getOuterHTMLSnippetRawString = getOuterHTMLSnippet.toString();
532
607
  // eslint-disable-next-line max-len
533
- getOuterHTMLSnippet.toString = () => `function getOuterHTMLSnippet(element, ignoreAttrs = [], snippetCharacterLimit = 500) {
608
+ getOuterHTMLSnippet.toString = () => `function ${names.getOuterHTMLSnippet}(element, ignoreAttrs = [], snippetCharacterLimit = 500) {
534
609
  ${truncate};
535
610
  return (${getOuterHTMLSnippetRawString})(element, ignoreAttrs, snippetCharacterLimit);
536
611
  }`;
537
612
 
538
613
  /** @type {string} */
539
614
  const getNodeDetailsRawString = getNodeDetails.toString();
540
- getNodeDetails.toString = () => `function getNodeDetails(element) {
615
+ getNodeDetails.toString = () => `function ${names.getNodeDetails}(element) {
541
616
  ${truncate};
542
617
  ${getNodePath};
543
618
  ${getNodeSelector};
@@ -560,4 +635,6 @@ export const pageFunctions = {
560
635
  wrapRequestIdleCallback,
561
636
  getBoundingClientRect,
562
637
  truncate,
638
+ esbuildFunctionWrapperString,
639
+ getRuntimeFunctionName,
563
640
  };
@@ -126,9 +126,16 @@ async function init(opts) {
126
126
  if (opts.tags) {
127
127
  scope.setTags(opts.tags);
128
128
  }
129
- if (opts.extra) {
130
- scope.setExtras(opts.extra);
129
+
130
+ // Add extra details
131
+ let extra;
132
+ if (opts.extra) extra = {...opts.extra};
133
+ // @ts-expect-error Non-standard property
134
+ if (err.extra) extra = {...extra, ...err.extra};
135
+ if (extra) {
136
+ scope.setExtras(extra);
131
137
  }
138
+
132
139
  Sentry.captureException(err);
133
140
  });
134
141
  };
@@ -39,6 +39,10 @@ const stackPacksToInclude = [
39
39
  packId: 'drupal',
40
40
  requiredStacks: ['js:drupal'],
41
41
  },
42
+ {
43
+ packId: 'nitropack',
44
+ requiredStacks: ['js:nitropack'],
45
+ },
42
46
  {
43
47
  packId: 'amp',
44
48
  requiredStacks: ['js:amp'],
package/core/runner.d.ts CHANGED
@@ -1,19 +1,13 @@
1
- export type Connection = import('./legacy/gather/connections/connection.js').Connection;
2
1
  export type ArbitraryEqualityMap = import('./lib/arbitrary-equality-map.js').ArbitraryEqualityMap;
3
- export type Config = LH.Config.LegacyResolvedConfig;
4
- /** @typedef {import('./legacy/gather/connections/connection.js').Connection} Connection */
5
2
  /** @typedef {import('./lib/arbitrary-equality-map.js').ArbitraryEqualityMap} ArbitraryEqualityMap */
6
- /** @typedef {LH.Config.LegacyResolvedConfig} Config */
7
3
  export class Runner {
8
4
  /**
9
- * @template {LH.Config.LegacyResolvedConfig | LH.Config.ResolvedConfig} TConfig
10
5
  * @param {LH.Artifacts} artifacts
11
- * @param {{resolvedConfig: TConfig, driverMock?: Driver, computedCache: Map<string, ArbitraryEqualityMap>}} options
6
+ * @param {{resolvedConfig: LH.Config.ResolvedConfig, computedCache: Map<string, ArbitraryEqualityMap>}} options
12
7
  * @return {Promise<LH.RunnerResult|undefined>}
13
8
  */
14
- static audit<TConfig extends import("../types/config.js").default.ResolvedConfig | import("../types/config.js").default.LegacyResolvedConfig>(artifacts: LH.Artifacts, options: {
15
- resolvedConfig: TConfig;
16
- driverMock?: Driver | undefined;
9
+ static audit(artifacts: LH.Artifacts, options: {
10
+ resolvedConfig: LH.Config.ResolvedConfig;
17
11
  computedCache: Map<string, ArbitraryEqualityMap>;
18
12
  }): Promise<LH.RunnerResult | undefined>;
19
13
  /**
@@ -26,17 +20,14 @@ export class Runner {
26
20
  * -G and -A will run partial lighthouse pipelines,
27
21
  * and -GA will run everything plus save artifacts and lhr to disk.
28
22
  *
29
- * @template {LH.Config.LegacyResolvedConfig | LH.Config.ResolvedConfig} TConfig
30
- * @param {(runnerData: {resolvedConfig: TConfig, driverMock?: Driver}) => Promise<LH.Artifacts>} gatherFn
31
- * @param {{resolvedConfig: TConfig, driverMock?: Driver, computedCache: Map<string, ArbitraryEqualityMap>}} options
23
+ * @param {(runnerData: {resolvedConfig: LH.Config.ResolvedConfig}) => Promise<LH.Artifacts>} gatherFn
24
+ * @param {{resolvedConfig: LH.Config.ResolvedConfig, computedCache: Map<string, ArbitraryEqualityMap>}} options
32
25
  * @return {Promise<LH.Artifacts>}
33
26
  */
34
- static gather<TConfig_1 extends import("../types/config.js").default.ResolvedConfig | import("../types/config.js").default.LegacyResolvedConfig>(gatherFn: (runnerData: {
35
- resolvedConfig: TConfig_1;
36
- driverMock?: Driver | undefined;
27
+ static gather(gatherFn: (runnerData: {
28
+ resolvedConfig: LH.Config.ResolvedConfig;
37
29
  }) => Promise<LH.Artifacts>, options: {
38
- resolvedConfig: TConfig_1;
39
- driverMock?: Driver | undefined;
30
+ resolvedConfig: LH.Config.ResolvedConfig;
40
31
  computedCache: Map<string, ArbitraryEqualityMap>;
41
32
  }): Promise<LH.Artifacts>;
42
33
  /**
@@ -52,18 +43,6 @@ export class Runner {
52
43
  * @return {LH.Result.Timing}
53
44
  */
54
45
  static _getTiming(artifacts: LH.Artifacts): LH.Result.Timing;
55
- /**
56
- * Establish connection, load page and collect all required artifacts
57
- * @param {string} requestedUrl
58
- * @param {{resolvedConfig: Config, computedCache: Map<string, ArbitraryEqualityMap>, driverMock?: Driver}} runnerOpts
59
- * @param {Connection} connection
60
- * @return {Promise<LH.Artifacts>}
61
- */
62
- static _gatherArtifactsFromBrowser(requestedUrl: string, runnerOpts: {
63
- resolvedConfig: Config;
64
- computedCache: Map<string, ArbitraryEqualityMap>;
65
- driverMock?: Driver;
66
- }, connection: Connection): Promise<LH.Artifacts>;
67
46
  /**
68
47
  * Run all audits with specified settings and artifacts.
69
48
  * @param {LH.Config.Settings} settings
@@ -109,6 +88,5 @@ export class Runner {
109
88
  */
110
89
  static _getDataSavePath(settings: LH.Config.Settings): string;
111
90
  }
112
- import { Driver } from './legacy/gather/driver.js';
113
91
  import { Audit } from './audits/audit.js';
114
92
  //# sourceMappingURL=runner.d.ts.map
package/core/runner.js CHANGED
@@ -11,8 +11,6 @@ import path from 'path';
11
11
  import log from 'lighthouse-logger';
12
12
  import isDeepEqual from 'lodash/isEqual.js';
13
13
 
14
- import {Driver} from './legacy/gather/driver.js';
15
- import {GatherRunner} from './legacy/gather/gather-runner.js';
16
14
  import {ReportScoring} from './scoring.js';
17
15
  import {Audit} from './audits/audit.js';
18
16
  import * as format from '../shared/localization/format.js';
@@ -28,15 +26,12 @@ import UrlUtils from './lib/url-utils.js';
28
26
 
29
27
  const moduleDir = getModuleDirectory(import.meta);
30
28
 
31
- /** @typedef {import('./legacy/gather/connections/connection.js').Connection} Connection */
32
29
  /** @typedef {import('./lib/arbitrary-equality-map.js').ArbitraryEqualityMap} ArbitraryEqualityMap */
33
- /** @typedef {LH.Config.LegacyResolvedConfig} Config */
34
30
 
35
31
  class Runner {
36
32
  /**
37
- * @template {LH.Config.LegacyResolvedConfig | LH.Config.ResolvedConfig} TConfig
38
33
  * @param {LH.Artifacts} artifacts
39
- * @param {{resolvedConfig: TConfig, driverMock?: Driver, computedCache: Map<string, ArbitraryEqualityMap>}} options
34
+ * @param {{resolvedConfig: LH.Config.ResolvedConfig, computedCache: Map<string, ArbitraryEqualityMap>}} options
40
35
  * @return {Promise<LH.RunnerResult|undefined>}
41
36
  */
42
37
  static async audit(artifacts, options) {
@@ -153,7 +148,7 @@ class Runner {
153
148
  * @param {LH.Artifacts.ComputedContext} context
154
149
  */
155
150
  static async getEntityClassification(artifacts, context) {
156
- const devtoolsLog = artifacts.devtoolsLogs[Audit.DEFAULT_PASS];
151
+ const devtoolsLog = artifacts.devtoolsLogs?.[Audit.DEFAULT_PASS];
157
152
  if (!devtoolsLog) return;
158
153
  const classifiedEntities = await EntityClassification.request(
159
154
  {URL: artifacts.URL, devtoolsLog}, context);
@@ -188,9 +183,8 @@ class Runner {
188
183
  * -G and -A will run partial lighthouse pipelines,
189
184
  * and -GA will run everything plus save artifacts and lhr to disk.
190
185
  *
191
- * @template {LH.Config.LegacyResolvedConfig | LH.Config.ResolvedConfig} TConfig
192
- * @param {(runnerData: {resolvedConfig: TConfig, driverMock?: Driver}) => Promise<LH.Artifacts>} gatherFn
193
- * @param {{resolvedConfig: TConfig, driverMock?: Driver, computedCache: Map<string, ArbitraryEqualityMap>}} options
186
+ * @param {(runnerData: {resolvedConfig: LH.Config.ResolvedConfig}) => Promise<LH.Artifacts>} gatherFn
187
+ * @param {{resolvedConfig: LH.Config.ResolvedConfig, computedCache: Map<string, ArbitraryEqualityMap>}} options
194
188
  * @return {Promise<LH.Artifacts>}
195
189
  */
196
190
  static async gather(gatherFn, options) {
@@ -217,7 +211,6 @@ class Runner {
217
211
 
218
212
  artifacts = await gatherFn({
219
213
  resolvedConfig: options.resolvedConfig,
220
- driverMock: options.driverMock,
221
214
  });
222
215
 
223
216
  log.timeEnd(runnerStatus);
@@ -291,28 +284,6 @@ class Runner {
291
284
  return {entries: timingEntries, total: gatherTiming + auditTiming};
292
285
  }
293
286
 
294
- /**
295
- * Establish connection, load page and collect all required artifacts
296
- * @param {string} requestedUrl
297
- * @param {{resolvedConfig: Config, computedCache: Map<string, ArbitraryEqualityMap>, driverMock?: Driver}} runnerOpts
298
- * @param {Connection} connection
299
- * @return {Promise<LH.Artifacts>}
300
- */
301
- static async _gatherArtifactsFromBrowser(requestedUrl, runnerOpts, connection) {
302
- if (!runnerOpts.resolvedConfig.passes) {
303
- throw new Error('No browser artifacts are either provided or requested.');
304
- }
305
- const driver = runnerOpts.driverMock || new Driver(connection);
306
- const gatherOpts = {
307
- driver,
308
- requestedUrl,
309
- settings: runnerOpts.resolvedConfig.settings,
310
- computedCache: runnerOpts.computedCache,
311
- };
312
- const artifacts = await GatherRunner.run(runnerOpts.resolvedConfig.passes, gatherOpts);
313
- return artifacts;
314
- }
315
-
316
287
  /**
317
288
  * Run all audits with specified settings and artifacts.
318
289
  * @param {LH.Config.Settings} settings
@@ -396,6 +367,8 @@ class Runner {
396
367
 
397
368
  let auditResult;
398
369
  try {
370
+ if (artifacts.PageLoadError) throw artifacts.PageLoadError;
371
+
399
372
  // Return an early error if an artifact required for the audit is missing or an error.
400
373
  for (const artifactName of audit.meta.requiredArtifacts) {
401
374
  const noArtifact = artifacts[artifactName] === undefined;
@@ -419,15 +392,11 @@ class Runner {
419
392
  // @ts-expect-error: TODO why is this a type error now?
420
393
  const artifactError = artifacts[artifactName];
421
394
 
422
- Sentry.captureException(artifactError, {
423
- tags: {gatherer: artifactName},
424
- level: 'error',
425
- });
426
-
427
395
  log.warn('Runner', `${artifactName} gatherer, required by audit ${audit.meta.id},` +
428
396
  ` encountered an error: ${artifactError.message}`);
429
397
 
430
- // Create a friendlier display error and mark it as expected to avoid duplicates in Sentry
398
+ // Create a friendlier display error and mark it as expected to avoid duplicates in Sentry.
399
+ // The artifact error was already sent to Sentry in `collectPhaseArtifacts`.
431
400
  const error = new LighthouseError(LighthouseError.errors.ERRORED_REQUIRED_ARTIFACT,
432
401
  {artifactName, errorMessage: artifactError.message}, {cause: artifactError});
433
402
  // @ts-expect-error Non-standard property added to Error
@@ -1,4 +1,4 @@
1
- export type GatherStepRunnerOptions = WeakMap<LH.UserFlow.GatherStep, LH.Gatherer.FRGatherResult['runnerOptions']>;
1
+ export type GatherStepRunnerOptions = WeakMap<LH.UserFlow.GatherStep, LH.Gatherer.GatherResult['runnerOptions']>;
2
2
  export class UserFlow {
3
3
  /**
4
4
  * @param {LH.Puppeteer.Page} page
@@ -24,10 +24,10 @@ export class UserFlow {
24
24
  */
25
25
  _getNextNavigationFlags(flags: LH.UserFlow.StepFlags | undefined): LH.UserFlow.StepFlags;
26
26
  /**
27
- * @param {LH.Gatherer.FRGatherResult} gatherResult
27
+ * @param {LH.Gatherer.GatherResult} gatherResult
28
28
  * @param {LH.UserFlow.StepFlags} [flags]
29
29
  */
30
- _addGatherStep(gatherResult: LH.Gatherer.FRGatherResult, flags?: LH.UserFlow.StepFlags | undefined): void;
30
+ _addGatherStep(gatherResult: LH.Gatherer.GatherResult, flags?: LH.UserFlow.StepFlags | undefined): void;
31
31
  /**
32
32
  * @param {LH.NavigationRequestor} requestor
33
33
  * @param {LH.UserFlow.StepFlags} [flags]
@@ -50,7 +50,7 @@ export class UserFlow {
50
50
  startTimespan(flags?: LH.UserFlow.StepFlags | undefined): Promise<void>;
51
51
  currentTimespan: {
52
52
  timespan: {
53
- endTimespanGather(): Promise<LH.Gatherer.FRGatherResult>;
53
+ endTimespanGather(): Promise<LH.Gatherer.GatherResult>;
54
54
  };
55
55
  flags: LH.UserFlow.StepFlags | undefined;
56
56
  } | undefined;
package/core/user-flow.js CHANGED
@@ -15,7 +15,7 @@ import {mergeConfigFragment, deepClone} from './config/config-helpers.js';
15
15
  import * as i18n from './lib/i18n/i18n.js';
16
16
  import * as LH from '../types/lh.js';
17
17
 
18
- /** @typedef {WeakMap<LH.UserFlow.GatherStep, LH.Gatherer.FRGatherResult['runnerOptions']>} GatherStepRunnerOptions */
18
+ /** @typedef {WeakMap<LH.UserFlow.GatherStep, LH.Gatherer.GatherResult['runnerOptions']>} GatherStepRunnerOptions */
19
19
 
20
20
  const UIStrings = {
21
21
  /**
@@ -107,7 +107,7 @@ class UserFlow {
107
107
  }
108
108
 
109
109
  /**
110
- * @param {LH.Gatherer.FRGatherResult} gatherResult
110
+ * @param {LH.Gatherer.GatherResult} gatherResult
111
111
  * @param {LH.UserFlow.StepFlags} [flags]
112
112
  */
113
113
  _addGatherStep(gatherResult, flags) {