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
@@ -1,590 +0,0 @@
1
- /**
2
- * @license Copyright 2016 The Lighthouse Authors. All Rights Reserved.
3
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
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
- */
6
-
7
- import log from 'lighthouse-logger';
8
-
9
- import {NetworkRecords} from '../../computed/network-records.js';
10
- import {getPageLoadError} from '../../lib/navigation-error.js';
11
- import * as emulation from '../../lib/emulation.js';
12
- import * as constants from '../../config/constants.js';
13
- import * as format from '../../../shared/localization/format.js';
14
- import {getBenchmarkIndex, getEnvironmentWarnings} from '../../gather/driver/environment.js';
15
- import * as prepare from '../../gather/driver/prepare.js';
16
- import * as storage from '../../gather/driver/storage.js';
17
- import * as navigation from '../../gather/driver/navigation.js';
18
- import * as serviceWorkers from '../../gather/driver/service-workers.js';
19
- import NetworkUserAgent from '../../gather/gatherers/network-user-agent.js';
20
- import {finalizeArtifacts} from '../../gather/base-artifacts.js';
21
- import UrlUtils from '../../lib/url-utils.js';
22
-
23
- /** @typedef {import('./driver.js').Driver} Driver */
24
- /** @typedef {import('../../lib/arbitrary-equality-map.js').ArbitraryEqualityMap} ArbitraryEqualityMap */
25
-
26
- /**
27
- * Each entry in each gatherer result array is the output of a gatherer phase:
28
- * `beforePass`, `pass`, and `afterPass`. Flattened into an `LH.Artifacts` in
29
- * `collectArtifacts`.
30
- * @typedef {Record<keyof LH.GathererArtifacts, Array<LH.Gatherer.PhaseResult>>} GathererResults
31
- */
32
- /** @typedef {Array<[keyof GathererResults, GathererResults[keyof GathererResults]]>} GathererResultsEntries */
33
-
34
- /**
35
- * Class that drives browser to load the page and runs gatherer lifecycle hooks.
36
- */
37
- class GatherRunner {
38
- /**
39
- * Loads about:blank and waits there briefly. Since a Page.reload command does
40
- * not let a service worker take over, we navigate away and then come back to
41
- * reload. We do not `waitForLoad` on about:blank since a page load event is
42
- * never fired on it.
43
- * @param {Driver} driver
44
- * @param {string=} url
45
- * @return {Promise<void>}
46
- */
47
- static async loadBlank(driver, url = constants.defaultPassConfig.blankPage) {
48
- const status = {msg: 'Resetting state with about:blank', id: 'lh:gather:loadBlank'};
49
- log.time(status);
50
- await navigation.gotoURL(driver, url, {waitUntil: ['navigated']});
51
- log.timeEnd(status);
52
- }
53
-
54
- /**
55
- * Loads options.url with specified options. If the main document URL
56
- * redirects, options.url will be updated accordingly. As such, options.url
57
- * will always represent the post-redirected URL. options.requestedUrl is the
58
- * pre-redirect starting URL. If the navigation errors with "expected" errors such as
59
- * NO_FCP, a `navigationError` is returned.
60
- * @param {Driver} driver
61
- * @param {LH.Gatherer.PassContext} passContext
62
- * @return {Promise<{navigationError?: LH.LighthouseError}>}
63
- */
64
- static async loadPage(driver, passContext) {
65
- const status = {
66
- msg: 'Loading page & waiting for onload',
67
- id: `lh:gather:loadPage-${passContext.passConfig.passName}`,
68
- };
69
- log.time(status);
70
- try {
71
- const requestedUrl = passContext.url;
72
- const {mainDocumentUrl, warnings} = await navigation.gotoURL(driver, requestedUrl, {
73
- waitUntil: passContext.passConfig.recordTrace ?
74
- ['load', 'fcp'] : ['load'],
75
- debugNavigation: passContext.settings.debugNavigation,
76
- maxWaitForFcp: passContext.settings.maxWaitForFcp,
77
- maxWaitForLoad: passContext.settings.maxWaitForLoad,
78
- ...passContext.passConfig,
79
- });
80
- passContext.url = mainDocumentUrl;
81
- const {URL} = passContext.baseArtifacts;
82
- if (!URL.finalDisplayedUrl || !URL.mainDocumentUrl) {
83
- URL.mainDocumentUrl = mainDocumentUrl;
84
- URL.finalDisplayedUrl = await passContext.driver.url();
85
- }
86
- if (passContext.passConfig.loadFailureMode === 'fatal') {
87
- passContext.LighthouseRunWarnings.push(...warnings);
88
- }
89
- } catch (err) {
90
- // If it's one of our loading-based LighthouseErrors, we'll treat it as a page load error.
91
- if (err.code === 'NO_FCP' || err.code === 'PAGE_HUNG') {
92
- return {navigationError: err};
93
- }
94
-
95
- throw err;
96
- } finally {
97
- log.timeEnd(status);
98
- }
99
-
100
- return {};
101
- }
102
-
103
- /**
104
- * Rejects if any open tabs would share a service worker with the target URL.
105
- * This includes the target tab, so navigation to something like about:blank
106
- * should be done before calling.
107
- * @param {LH.Gatherer.FRProtocolSession} session
108
- * @param {string} pageUrl
109
- * @return {Promise<void>}
110
- */
111
- static assertNoSameOriginServiceWorkerClients(session, pageUrl) {
112
- /** @type {Array<LH.Crdp.ServiceWorker.ServiceWorkerRegistration>} */
113
- let registrations;
114
- /** @type {Array<LH.Crdp.ServiceWorker.ServiceWorkerVersion>} */
115
- let versions;
116
-
117
- return serviceWorkers.getServiceWorkerRegistrations(session)
118
- .then(data => {
119
- registrations = data.registrations;
120
- })
121
- .then(_ => serviceWorkers.getServiceWorkerVersions(session))
122
- .then(data => {
123
- versions = data.versions;
124
- })
125
- .then(_ => {
126
- const origin = new URL(pageUrl).origin;
127
-
128
- registrations
129
- .filter(reg => {
130
- const swOrigin = new URL(reg.scopeURL).origin;
131
-
132
- return origin === swOrigin;
133
- })
134
- .forEach(reg => {
135
- versions.forEach(ver => {
136
- // Ignore workers unaffiliated with this registration
137
- if (ver.registrationId !== reg.registrationId) {
138
- return;
139
- }
140
-
141
- // Throw if service worker for this origin has active controlledClients.
142
- if (ver.controlledClients && ver.controlledClients.length > 0) {
143
- throw new Error('You probably have multiple tabs open to the same origin.');
144
- }
145
- });
146
- });
147
- });
148
- }
149
-
150
- /**
151
- * @param {Driver} driver
152
- * @param {{requestedUrl: string, settings: LH.Config.Settings}} options
153
- * @return {Promise<void>}
154
- */
155
- static async setupDriver(driver, options) {
156
- const status = {msg: 'Initializing…', id: 'lh:gather:setupDriver'};
157
- log.time(status);
158
- const session = driver.defaultSession;
159
-
160
- // Assert no service workers are still installed, so we test that they would actually be installed for a new user.
161
- await GatherRunner.assertNoSameOriginServiceWorkerClients(session, options.requestedUrl);
162
-
163
- await prepare.prepareTargetForNavigationMode(driver, options.settings);
164
-
165
- log.timeEnd(status);
166
- }
167
-
168
- /**
169
- * Reset browser state where needed and release the connection.
170
- * @param {Driver} driver
171
- * @param {{requestedUrl: string, settings: LH.Config.Settings}} options
172
- * @return {Promise<void>}
173
- */
174
- static async disposeDriver(driver, options) {
175
- const status = {msg: 'Disconnecting from browser...', id: 'lh:gather:disconnect'};
176
-
177
- log.time(status);
178
- try {
179
- // If storage was cleared for the run, clear at the end so Lighthouse specifics aren't cached.
180
- const session = driver.defaultSession;
181
- const resetStorage = !options.settings.disableStorageReset;
182
- if (resetStorage) await storage.clearDataForOrigin(session, options.requestedUrl);
183
-
184
- await driver.disconnect();
185
- } catch (err) {
186
- // Ignore disconnecting error if browser was already closed.
187
- // See https://github.com/GoogleChrome/lighthouse/issues/1583
188
- if (!(/close\/.*status: (500|404)$/.test(err.message))) {
189
- log.error('GatherRunner disconnect', err.message);
190
- }
191
- }
192
- log.timeEnd(status);
193
- }
194
-
195
- /**
196
- * Beging recording devtoolsLog and trace (if requested).
197
- * @param {LH.Gatherer.PassContext} passContext
198
- * @return {Promise<void>}
199
- */
200
- static async beginRecording(passContext) {
201
- const status = {msg: 'Beginning devtoolsLog and trace', id: 'lh:gather:beginRecording'};
202
- log.time(status);
203
-
204
- const {driver, passConfig, settings} = passContext;
205
-
206
- // Always record devtoolsLog
207
- await driver.beginDevtoolsLog();
208
-
209
- if (passConfig.recordTrace) {
210
- await driver.beginTrace(settings);
211
- }
212
-
213
- log.timeEnd(status);
214
- }
215
-
216
- /**
217
- * End recording devtoolsLog and trace (if requested), returning an
218
- * `LH.Gatherer.LoadData` with the recorded data.
219
- * @param {LH.Gatherer.PassContext} passContext
220
- * @return {Promise<LH.Gatherer.LoadData>}
221
- */
222
- static async endRecording(passContext) {
223
- const {driver, passConfig} = passContext;
224
-
225
- let trace;
226
- if (passConfig.recordTrace) {
227
- const status = {msg: 'Gathering trace', id: `lh:gather:getTrace`};
228
- log.time(status);
229
- trace = await driver.endTrace();
230
- log.timeEnd(status);
231
- }
232
-
233
- const status = {
234
- msg: 'Gathering devtoolsLog & network records',
235
- id: `lh:gather:getDevtoolsLog`,
236
- };
237
- log.time(status);
238
- const devtoolsLog = await driver.endDevtoolsLog();
239
- const networkRecords = await NetworkRecords.request(devtoolsLog, passContext);
240
- log.timeEnd(status);
241
-
242
- return {
243
- networkRecords,
244
- devtoolsLog,
245
- trace,
246
- };
247
- }
248
-
249
- /**
250
- * Run beforePass() on gatherers.
251
- * @param {LH.Gatherer.PassContext} passContext
252
- * @param {Partial<GathererResults>} gathererResults
253
- * @return {Promise<void>}
254
- */
255
- static async beforePass(passContext, gathererResults) {
256
- const bpStatus = {msg: `Running beforePass methods`, id: `lh:gather:beforePass`};
257
- log.time(bpStatus, 'verbose');
258
-
259
- for (const gathererDefn of passContext.passConfig.gatherers) {
260
- const gatherer = gathererDefn.instance;
261
- const status = {
262
- msg: `Gathering setup: ${gatherer.name}`,
263
- id: `lh:gather:beforePass:${gatherer.name}`,
264
- };
265
- log.time(status, 'verbose');
266
- const artifactPromise = Promise.resolve().then(_ => gatherer.beforePass(passContext));
267
- gathererResults[gatherer.name] = [artifactPromise];
268
- await artifactPromise.catch(() => {});
269
- log.timeEnd(status);
270
- }
271
- log.timeEnd(bpStatus);
272
- }
273
-
274
- /**
275
- * Run pass() on gatherers.
276
- * @param {LH.Gatherer.PassContext} passContext
277
- * @param {Partial<GathererResults>} gathererResults
278
- * @return {Promise<void>}
279
- */
280
- static async pass(passContext, gathererResults) {
281
- const config = passContext.passConfig;
282
- const gatherers = config.gatherers;
283
-
284
- const pStatus = {msg: `Running pass methods`, id: `lh:gather:pass`};
285
- log.time(pStatus, 'verbose');
286
-
287
- for (const gathererDefn of gatherers) {
288
- const gatherer = gathererDefn.instance;
289
- const status = {
290
- msg: `Gathering in-page: ${gatherer.name}`,
291
- id: `lh:gather:pass:${gatherer.name}`,
292
- };
293
- log.time(status);
294
- const artifactPromise = Promise.resolve().then(_ => gatherer.pass(passContext));
295
-
296
- const gathererResult = gathererResults[gatherer.name] || [];
297
- gathererResult.push(artifactPromise);
298
- gathererResults[gatherer.name] = gathererResult;
299
- await artifactPromise.catch(() => {});
300
- }
301
-
302
- log.timeEnd(pStatus);
303
- }
304
-
305
- /**
306
- * Run afterPass() on gatherers.
307
- * @param {LH.Gatherer.PassContext} passContext
308
- * @param {LH.Gatherer.LoadData} loadData
309
- * @param {Partial<GathererResults>} gathererResults
310
- * @return {Promise<void>}
311
- */
312
- static async afterPass(passContext, loadData, gathererResults) {
313
- const config = passContext.passConfig;
314
- const gatherers = config.gatherers;
315
-
316
- const apStatus = {msg: `Running afterPass methods`, id: `lh:gather:afterPass`};
317
- log.time(apStatus, 'verbose');
318
-
319
- for (const gathererDefn of gatherers) {
320
- const gatherer = gathererDefn.instance;
321
- const status = {
322
- msg: `Gathering: ${gatherer.name}`,
323
- id: `lh:gather:afterPass:${gatherer.name}`,
324
- };
325
- log.time(status);
326
-
327
- const artifactPromise = Promise.resolve()
328
- .then(_ => gatherer.afterPass(passContext, loadData));
329
-
330
- const gathererResult = gathererResults[gatherer.name] || [];
331
- gathererResult.push(artifactPromise);
332
- gathererResults[gatherer.name] = gathererResult;
333
- await artifactPromise.catch(() => {});
334
- log.timeEnd(status);
335
- }
336
- log.timeEnd(apStatus);
337
- }
338
-
339
- /**
340
- * Takes the results of each gatherer phase for each gatherer and uses the
341
- * last produced value (that's not undefined) as the artifact for that
342
- * gatherer. If an error was rejected from a gatherer phase,
343
- * uses that error object as the artifact instead.
344
- * @param {Partial<GathererResults>} gathererResults
345
- * @return {Promise<{artifacts: Partial<LH.GathererArtifacts>}>}
346
- */
347
- static async collectArtifacts(gathererResults) {
348
- /** @type {Partial<LH.GathererArtifacts>} */
349
- const gathererArtifacts = {};
350
-
351
- const resultsEntries = /** @type {GathererResultsEntries} */ (Object.entries(gathererResults));
352
- for (const [gathererName, phaseResultsPromises] of resultsEntries) {
353
- try {
354
- const phaseResults = await Promise.all(phaseResultsPromises);
355
- // Take the last defined pass result as artifact. If none are defined, the undefined check below handles it.
356
- const definedResults = phaseResults.filter(element => element !== undefined);
357
- const artifact = definedResults[definedResults.length - 1];
358
- // @ts-expect-error tsc can't yet express that gathererName is only a single type in each iteration, not a union of types.
359
- gathererArtifacts[gathererName] = artifact;
360
- } catch (err) {
361
- // Return error to runner to handle turning it into an error audit.
362
- gathererArtifacts[gathererName] = err;
363
- }
364
-
365
- if (gathererArtifacts[gathererName] === undefined) {
366
- throw new Error(`${gathererName} failed to provide an artifact.`);
367
- }
368
- }
369
-
370
- return {
371
- artifacts: gathererArtifacts,
372
- };
373
- }
374
-
375
- /**
376
- * Return an initialized but mostly empty set of base artifacts, to be
377
- * populated as the run continues.
378
- * @param {{driver: Driver, requestedUrl: string, settings: LH.Config.Settings}} options
379
- * @return {Promise<LH.BaseArtifacts>}
380
- */
381
- static async initializeBaseArtifacts(options) {
382
- const hostUserAgent = (await options.driver.getBrowserVersion()).userAgent;
383
-
384
- // Whether Lighthouse was run on a mobile device (i.e. not on a desktop machine).
385
- const HostFormFactor = hostUserAgent.includes('Android') || hostUserAgent.includes('Mobile') ?
386
- 'mobile' : 'desktop';
387
-
388
- return {
389
- fetchTime: (new Date()).toJSON(),
390
- LighthouseRunWarnings: [],
391
- HostFormFactor,
392
- HostUserAgent: hostUserAgent,
393
- NetworkUserAgent: '', // updated later
394
- BenchmarkIndex: 0, // updated later
395
- traces: {},
396
- devtoolsLogs: {},
397
- settings: options.settings,
398
- GatherContext: {gatherMode: 'navigation'},
399
- URL: {
400
- requestedUrl: options.requestedUrl,
401
- mainDocumentUrl: '',
402
- finalDisplayedUrl: '',
403
- },
404
- Timing: [],
405
- PageLoadError: null,
406
- };
407
- }
408
-
409
- /**
410
- * Populates the important base artifacts from a fully loaded test page.
411
- * Currently must be run before `start-url` gatherer so that `WebAppManifest`
412
- * will be available to it.
413
- * @param {LH.Gatherer.PassContext} passContext
414
- */
415
- static async populateBaseArtifacts(passContext) {
416
- const status = {msg: 'Populate base artifacts', id: 'lh:gather:populateBaseArtifacts'};
417
- log.time(status);
418
-
419
- const baseArtifacts = passContext.baseArtifacts;
420
-
421
- // Find the NetworkUserAgent actually used in the devtoolsLogs.
422
- const devtoolsLog = baseArtifacts.devtoolsLogs[passContext.passConfig.passName];
423
- baseArtifacts.NetworkUserAgent = NetworkUserAgent.getNetworkUserAgent(devtoolsLog);
424
-
425
- const environmentWarnings = getEnvironmentWarnings(passContext);
426
- baseArtifacts.LighthouseRunWarnings.push(...environmentWarnings);
427
-
428
- log.timeEnd(status);
429
- }
430
-
431
- /**
432
- * @param {Array<LH.Config.Pass>} passConfigs
433
- * @param {{driver: Driver, requestedUrl: string, settings: LH.Config.Settings, computedCache: Map<string, ArbitraryEqualityMap>}} options
434
- * @return {Promise<LH.Artifacts>}
435
- */
436
- static async run(passConfigs, options) {
437
- const driver = options.driver;
438
-
439
- /** @type {Partial<LH.GathererArtifacts>} */
440
- const artifacts = {};
441
-
442
- try {
443
- await driver.connect();
444
- // In the devtools/extension case, we can't still be on the site while trying to clear state
445
- // So we first navigate to about:blank, then apply our emulation & setup
446
- await GatherRunner.loadBlank(driver);
447
-
448
- const baseArtifacts = await GatherRunner.initializeBaseArtifacts(options);
449
- baseArtifacts.BenchmarkIndex = await getBenchmarkIndex(driver.executionContext);
450
-
451
- // Hack for running benchmarkIndex extra times.
452
- // Add a `bidx=20` query param, eg: https://www.example.com/?bidx=50
453
- const parsedUrl = UrlUtils.isValid(options.requestedUrl) && new URL(options.requestedUrl);
454
- if (options.settings.channel === 'lr' && parsedUrl && parsedUrl.searchParams.has('bidx')) {
455
- const bidxRunCount = Number(parsedUrl.searchParams.get('bidx')) || 0;
456
- // Add the first bidx into the new set
457
- const indexes = [baseArtifacts.BenchmarkIndex];
458
- for (let i = 0; i < bidxRunCount; i++) {
459
- const bidx = await getBenchmarkIndex(driver.executionContext);
460
- indexes.push(bidx);
461
- }
462
- baseArtifacts.BenchmarkIndexes = indexes;
463
- }
464
-
465
- await GatherRunner.setupDriver(driver, options);
466
-
467
- let isFirstPass = true;
468
- for (const passConfig of passConfigs) {
469
- /** @type {LH.Gatherer.PassContext} */
470
- const passContext = {
471
- gatherMode: 'navigation',
472
- driver,
473
- url: options.requestedUrl,
474
- settings: options.settings,
475
- passConfig,
476
- baseArtifacts,
477
- computedCache: options.computedCache,
478
- LighthouseRunWarnings: baseArtifacts.LighthouseRunWarnings,
479
- };
480
- const passResults = await GatherRunner.runPass(passContext);
481
- Object.assign(artifacts, passResults.artifacts);
482
-
483
- // If we encountered a pageLoadError, don't try to keep loading the page in future passes.
484
- if (passResults.pageLoadError && passConfig.loadFailureMode === 'fatal') {
485
- baseArtifacts.PageLoadError = passResults.pageLoadError;
486
- break;
487
- }
488
-
489
- if (isFirstPass) {
490
- await GatherRunner.populateBaseArtifacts(passContext);
491
- isFirstPass = false;
492
- }
493
- }
494
-
495
- await GatherRunner.disposeDriver(driver, options);
496
- return finalizeArtifacts(baseArtifacts, artifacts);
497
- } catch (err) {
498
- // Clean up on error. Don't await so that the root error, not a disposal error, is shown.
499
- GatherRunner.disposeDriver(driver, options);
500
-
501
- throw err;
502
- }
503
- }
504
-
505
- /**
506
- * Save the devtoolsLog and trace (if applicable) to baseArtifacts.
507
- * @param {LH.Gatherer.PassContext} passContext
508
- * @param {LH.Gatherer.LoadData} loadData
509
- * @param {string} passName
510
- */
511
- static _addLoadDataToBaseArtifacts(passContext, loadData, passName) {
512
- const baseArtifacts = passContext.baseArtifacts;
513
- baseArtifacts.devtoolsLogs[passName] = loadData.devtoolsLog;
514
- if (loadData.trace) baseArtifacts.traces[passName] = loadData.trace;
515
- }
516
-
517
- /**
518
- * Starting from about:blank, load the page and run gatherers for this pass.
519
- * @param {LH.Gatherer.PassContext} passContext
520
- * @return {Promise<{artifacts: Partial<LH.GathererArtifacts>, pageLoadError?: LH.LighthouseError}>}
521
- */
522
- static async runPass(passContext) {
523
- const status = {
524
- msg: `Running ${passContext.passConfig.passName} pass`,
525
- id: `lh:gather:runPass-${passContext.passConfig.passName}`,
526
- args: [passContext.passConfig.gatherers.map(g => g.instance.name).join(', ')],
527
- };
528
- log.time(status);
529
-
530
- /** @type {Partial<GathererResults>} */
531
- const gathererResults = {};
532
- const {driver, passConfig} = passContext;
533
-
534
- // Go to about:blank, set up, and run `beforePass()` on gatherers.
535
- await GatherRunner.loadBlank(driver, passConfig.blankPage);
536
- const {warnings} = await prepare.prepareTargetForIndividualNavigation(
537
- driver.defaultSession,
538
- passContext.settings,
539
- {
540
- requestor: passContext.url,
541
- disableStorageReset: !passConfig.useThrottling,
542
- disableThrottling: !passConfig.useThrottling,
543
- blockedUrlPatterns: passConfig.blockedUrlPatterns,
544
- }
545
- );
546
- passContext.LighthouseRunWarnings.push(...warnings);
547
- await GatherRunner.beforePass(passContext, gathererResults);
548
-
549
- // Navigate, start recording, and run `pass()` on gatherers.
550
- await GatherRunner.beginRecording(passContext);
551
- const {navigationError: possibleNavError} = await GatherRunner.loadPage(driver, passContext);
552
- await GatherRunner.pass(passContext, gathererResults);
553
- const loadData = await GatherRunner.endRecording(passContext);
554
-
555
- // Disable throttling so the afterPass analysis isn't throttled.
556
- await emulation.clearThrottling(driver.defaultSession);
557
-
558
- // In case of load error, save log and trace with an error prefix, return no artifacts for this pass.
559
- const pageLoadError = getPageLoadError(possibleNavError, {
560
- url: passContext.url,
561
- loadFailureMode: passConfig.loadFailureMode,
562
- networkRecords: loadData.networkRecords,
563
- warnings: passContext.LighthouseRunWarnings,
564
- });
565
- if (pageLoadError) {
566
- const localizedMessage = format.getFormatted(pageLoadError.friendlyMessage,
567
- passContext.settings.locale);
568
- log.error('GatherRunner', localizedMessage, passContext.url);
569
-
570
- passContext.LighthouseRunWarnings.push(pageLoadError.friendlyMessage);
571
- GatherRunner._addLoadDataToBaseArtifacts(passContext, loadData,
572
- `pageLoadError-${passConfig.passName}`);
573
-
574
- log.timeEnd(status);
575
- return {artifacts: {}, pageLoadError};
576
- }
577
-
578
- // If no error, save devtoolsLog and trace.
579
- GatherRunner._addLoadDataToBaseArtifacts(passContext, loadData, passConfig.passName);
580
-
581
- // Run `afterPass()` on gatherers and return collected artifacts.
582
- await GatherRunner.afterPass(passContext, loadData, gathererResults);
583
- const artifacts = GatherRunner.collectArtifacts(gathererResults);
584
-
585
- log.timeEnd(status);
586
- return artifacts;
587
- }
588
- }
589
-
590
- export {GatherRunner};
@@ -1,34 +0,0 @@
1
- /**
2
- * @license Copyright 2017 The Lighthouse Authors. All Rights Reserved.
3
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
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
- */
6
-
7
- declare module 'lighthouse-logger' {
8
- interface Status {
9
- msg: string;
10
- id: string;
11
- args?: any[];
12
- }
13
- export function setLevel(level: string): void;
14
- export function isVerbose(): boolean;
15
- export function formatProtocol(prefix: string, data: Object, level?: string): void;
16
- export function log(title: string, ...args: any[]): void;
17
- export function warn(title: string, ...args: any[]): void;
18
- export function error(title: string, ...args: any[]): void;
19
- export function verbose(title: string, ...args: any[]): void;
20
- export function time(status: Status, level?: string): void;
21
- export function timeEnd(status: Status, level?: string): void;
22
- export function reset(): string;
23
- export const cross: string;
24
- export const dim: string;
25
- export const tick: string;
26
- export const bold: string;
27
- export const purple: string;
28
- export function redify(message: any): string;
29
- export function greenify(message: any): string;
30
- /** Retrieves and clears all stored time entries */
31
- export function takeTimeEntries(): PerformanceEntry[];
32
- export function getTimeEntries(): PerformanceEntry[];
33
- export const events: import('events').EventEmitter;
34
- }