lighthouse 9.5.0-dev.20220509 → 9.6.1

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 (259) hide show
  1. package/changelog.md +70 -0
  2. package/dist/report/bundle.esm.js +400 -808
  3. package/dist/report/flow.js +22 -27
  4. package/dist/report/standalone.js +18 -23
  5. package/flow-report/src/summary/category.tsx +1 -1
  6. package/jest.config.js +1 -1
  7. package/lighthouse-cli/.eslintrc.cjs +4 -3
  8. package/lighthouse-cli/bin.js +1 -0
  9. package/lighthouse-cli/cli-flags.js +4 -3
  10. package/lighthouse-cli/commands/commands.js +1 -0
  11. package/lighthouse-cli/commands/list-audits.js +1 -0
  12. package/lighthouse-cli/commands/list-locales.js +1 -0
  13. package/lighthouse-cli/commands/list-trace-categories.js +1 -0
  14. package/lighthouse-cli/index.js +1 -0
  15. package/lighthouse-cli/printer.js +1 -0
  16. package/lighthouse-cli/run.js +24 -9
  17. package/lighthouse-cli/sentry-prompt.js +1 -0
  18. package/lighthouse-cli/test/smokehouse/core-tests.js +1 -0
  19. package/lighthouse-cli/test/smokehouse/frontends/back-compat-util.js +1 -0
  20. package/lighthouse-cli/test/smokehouse/frontends/lib.js +1 -0
  21. package/lighthouse-cli/test/smokehouse/frontends/node.js +1 -0
  22. package/lighthouse-cli/test/smokehouse/frontends/smokehouse-bin.js +1 -0
  23. package/lighthouse-cli/test/smokehouse/lib/child-process-error.js +1 -0
  24. package/lighthouse-cli/test/smokehouse/lib/concurrent-mapper.js +1 -0
  25. package/lighthouse-cli/test/smokehouse/lib/local-console.js +1 -0
  26. package/lighthouse-cli/test/smokehouse/lighthouse-runners/bundle.js +23 -109
  27. package/lighthouse-cli/test/smokehouse/lighthouse-runners/cli.js +3 -2
  28. package/lighthouse-cli/test/smokehouse/lighthouse-runners/devtools.js +19 -28
  29. package/lighthouse-cli/test/smokehouse/report-assert.js +4 -3
  30. package/lighthouse-cli/test/smokehouse/smokehouse.js +1 -1
  31. package/lighthouse-cli/test/smokehouse/version-check-test.js +3 -0
  32. package/lighthouse-cli/test/smokehouse/version-check.js +1 -0
  33. package/lighthouse-core/audits/accessibility/accesskeys.js +1 -1
  34. package/lighthouse-core/audits/accessibility/aria-allowed-attr.js +1 -1
  35. package/lighthouse-core/audits/accessibility/aria-command-name.js +1 -1
  36. package/lighthouse-core/audits/accessibility/aria-hidden-body.js +1 -1
  37. package/lighthouse-core/audits/accessibility/aria-hidden-focus.js +1 -1
  38. package/lighthouse-core/audits/accessibility/aria-input-field-name.js +1 -1
  39. package/lighthouse-core/audits/accessibility/aria-meter-name.js +1 -1
  40. package/lighthouse-core/audits/accessibility/aria-progressbar-name.js +1 -1
  41. package/lighthouse-core/audits/accessibility/aria-required-attr.js +1 -1
  42. package/lighthouse-core/audits/accessibility/aria-required-children.js +1 -1
  43. package/lighthouse-core/audits/accessibility/aria-required-parent.js +1 -1
  44. package/lighthouse-core/audits/accessibility/aria-roles.js +1 -1
  45. package/lighthouse-core/audits/accessibility/aria-toggle-field-name.js +1 -1
  46. package/lighthouse-core/audits/accessibility/aria-tooltip-name.js +1 -1
  47. package/lighthouse-core/audits/accessibility/aria-treeitem-name.js +1 -1
  48. package/lighthouse-core/audits/accessibility/aria-valid-attr-value.js +1 -1
  49. package/lighthouse-core/audits/accessibility/aria-valid-attr.js +1 -1
  50. package/lighthouse-core/audits/accessibility/button-name.js +1 -1
  51. package/lighthouse-core/audits/accessibility/bypass.js +1 -1
  52. package/lighthouse-core/audits/accessibility/color-contrast.js +1 -1
  53. package/lighthouse-core/audits/accessibility/definition-list.js +1 -1
  54. package/lighthouse-core/audits/accessibility/dlitem.js +1 -1
  55. package/lighthouse-core/audits/accessibility/document-title.js +1 -1
  56. package/lighthouse-core/audits/accessibility/duplicate-id-active.js +1 -1
  57. package/lighthouse-core/audits/accessibility/duplicate-id-aria.js +1 -1
  58. package/lighthouse-core/audits/accessibility/form-field-multiple-labels.js +1 -1
  59. package/lighthouse-core/audits/accessibility/frame-title.js +1 -1
  60. package/lighthouse-core/audits/accessibility/heading-order.js +1 -1
  61. package/lighthouse-core/audits/accessibility/html-has-lang.js +1 -1
  62. package/lighthouse-core/audits/accessibility/html-lang-valid.js +1 -1
  63. package/lighthouse-core/audits/accessibility/image-alt.js +1 -1
  64. package/lighthouse-core/audits/accessibility/input-image-alt.js +1 -1
  65. package/lighthouse-core/audits/accessibility/label.js +1 -1
  66. package/lighthouse-core/audits/accessibility/link-name.js +1 -1
  67. package/lighthouse-core/audits/accessibility/list.js +1 -1
  68. package/lighthouse-core/audits/accessibility/listitem.js +5 -5
  69. package/lighthouse-core/audits/accessibility/meta-refresh.js +1 -1
  70. package/lighthouse-core/audits/accessibility/meta-viewport.js +1 -1
  71. package/lighthouse-core/audits/accessibility/object-alt.js +1 -1
  72. package/lighthouse-core/audits/accessibility/tabindex.js +1 -1
  73. package/lighthouse-core/audits/accessibility/td-headers-attr.js +1 -1
  74. package/lighthouse-core/audits/accessibility/th-has-data-cells.js +1 -1
  75. package/lighthouse-core/audits/accessibility/valid-lang.js +1 -1
  76. package/lighthouse-core/audits/accessibility/video-caption.js +1 -1
  77. package/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js +1 -2
  78. package/lighthouse-core/audits/byte-efficiency/duplicated-javascript.js +12 -11
  79. package/lighthouse-core/audits/byte-efficiency/efficient-animated-content.js +1 -1
  80. package/lighthouse-core/audits/byte-efficiency/legacy-javascript.js +24 -22
  81. package/lighthouse-core/audits/byte-efficiency/offscreen-images.js +2 -3
  82. package/lighthouse-core/audits/byte-efficiency/render-blocking-resources.js +3 -2
  83. package/lighthouse-core/audits/byte-efficiency/unminified-css.js +5 -3
  84. package/lighthouse-core/audits/byte-efficiency/unminified-javascript.js +11 -10
  85. package/lighthouse-core/audits/byte-efficiency/unused-css-rules.js +1 -0
  86. package/lighthouse-core/audits/byte-efficiency/unused-javascript.js +8 -11
  87. package/lighthouse-core/audits/byte-efficiency/uses-responsive-images.js +1 -1
  88. package/lighthouse-core/audits/byte-efficiency/uses-text-compression.js +1 -1
  89. package/lighthouse-core/audits/deprecations.js +598 -8
  90. package/lighthouse-core/audits/diagnostics.js +3 -4
  91. package/lighthouse-core/audits/dobetterweb/doctype.js +9 -20
  92. package/lighthouse-core/audits/dobetterweb/geolocation-on-start.js +1 -1
  93. package/lighthouse-core/audits/dobetterweb/no-document-write.js +1 -1
  94. package/lighthouse-core/audits/dobetterweb/notification-on-start.js +1 -1
  95. package/lighthouse-core/audits/dobetterweb/uses-http2.js +1 -2
  96. package/lighthouse-core/audits/dobetterweb/uses-passive-event-listeners.js +1 -1
  97. package/lighthouse-core/audits/errors-in-console.js +2 -2
  98. package/lighthouse-core/audits/long-tasks.js +2 -3
  99. package/lighthouse-core/audits/metrics/experimental-interaction-to-next-paint.js +3 -1
  100. package/lighthouse-core/audits/metrics/first-contentful-paint-3g.js +2 -2
  101. package/lighthouse-core/audits/metrics/first-contentful-paint.js +2 -3
  102. package/lighthouse-core/audits/metrics/first-meaningful-paint.js +2 -3
  103. package/lighthouse-core/audits/metrics/interactive.js +2 -3
  104. package/lighthouse-core/audits/metrics/largest-contentful-paint.js +2 -3
  105. package/lighthouse-core/audits/metrics/max-potential-fid.js +2 -3
  106. package/lighthouse-core/audits/metrics/speed-index.js +2 -3
  107. package/lighthouse-core/audits/metrics/total-blocking-time.js +2 -3
  108. package/lighthouse-core/audits/metrics.js +2 -3
  109. package/lighthouse-core/audits/no-unload-listeners.js +15 -7
  110. package/lighthouse-core/audits/predictive-perf.js +1 -2
  111. package/lighthouse-core/audits/preload-lcp-image.js +3 -3
  112. package/lighthouse-core/audits/redirects.js +1 -1
  113. package/lighthouse-core/audits/script-treemap-data.js +45 -45
  114. package/lighthouse-core/audits/seo/http-status-code.js +4 -2
  115. package/lighthouse-core/audits/seo/link-text.js +0 -2
  116. package/lighthouse-core/audits/server-response-time.js +17 -2
  117. package/lighthouse-core/audits/service-worker.js +2 -7
  118. package/lighthouse-core/audits/timing-budget.js +2 -3
  119. package/lighthouse-core/audits/uses-rel-preconnect.js +1 -1
  120. package/lighthouse-core/audits/uses-rel-preload.js +1 -1
  121. package/lighthouse-core/audits/valid-source-maps.js +14 -12
  122. package/lighthouse-core/audits/violation-audit.js +1 -1
  123. package/lighthouse-core/audits/work-during-interaction.js +280 -0
  124. package/lighthouse-core/computed/critical-request-chains.js +9 -5
  125. package/lighthouse-core/computed/js-bundles.js +11 -11
  126. package/lighthouse-core/computed/main-resource.js +2 -3
  127. package/lighthouse-core/computed/metrics/first-contentful-paint-all-frames.js +1 -1
  128. package/lighthouse-core/computed/metrics/first-contentful-paint.js +1 -1
  129. package/lighthouse-core/computed/metrics/first-meaningful-paint.js +1 -1
  130. package/lighthouse-core/computed/metrics/interactive.js +1 -1
  131. package/lighthouse-core/computed/metrics/lantern-first-contentful-paint.js +1 -1
  132. package/lighthouse-core/computed/metrics/lantern-first-meaningful-paint.js +1 -1
  133. package/lighthouse-core/computed/metrics/lantern-interactive.js +1 -1
  134. package/lighthouse-core/computed/metrics/lantern-largest-contentful-paint.js +1 -1
  135. package/lighthouse-core/computed/metrics/lantern-max-potential-fid.js +1 -1
  136. package/lighthouse-core/computed/metrics/lantern-metric.js +5 -3
  137. package/lighthouse-core/computed/metrics/lantern-speed-index.js +1 -1
  138. package/lighthouse-core/computed/metrics/lantern-total-blocking-time.js +1 -1
  139. package/lighthouse-core/computed/metrics/largest-contentful-paint-all-frames.js +1 -1
  140. package/lighthouse-core/computed/metrics/largest-contentful-paint.js +1 -1
  141. package/lighthouse-core/computed/metrics/max-potential-fid.js +1 -1
  142. package/lighthouse-core/computed/metrics/metric.js +0 -1
  143. package/lighthouse-core/computed/metrics/responsiveness.js +12 -9
  144. package/lighthouse-core/computed/metrics/speed-index.js +1 -1
  145. package/lighthouse-core/computed/metrics/timing-summary.js +6 -13
  146. package/lighthouse-core/computed/metrics/total-blocking-time.js +1 -1
  147. package/lighthouse-core/computed/module-duplication.js +5 -6
  148. package/lighthouse-core/computed/page-dependency-graph.js +28 -55
  149. package/lighthouse-core/computed/resource-summary.js +5 -5
  150. package/lighthouse-core/computed/unused-css.js +7 -6
  151. package/lighthouse-core/computed/unused-javascript-summary.js +36 -16
  152. package/lighthouse-core/config/budget.js +2 -2
  153. package/lighthouse-core/config/default-config.js +1 -2
  154. package/lighthouse-core/config/metrics-to-audits.js +5 -0
  155. package/lighthouse-core/fraggle-rock/api.js +1 -1
  156. package/lighthouse-core/fraggle-rock/config/default-config.js +8 -5
  157. package/lighthouse-core/fraggle-rock/gather/base-artifacts.js +3 -6
  158. package/lighthouse-core/fraggle-rock/gather/driver.js +2 -2
  159. package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +26 -51
  160. package/lighthouse-core/fraggle-rock/gather/runner-helpers.js +3 -0
  161. package/lighthouse-core/fraggle-rock/gather/session.js +2 -2
  162. package/lighthouse-core/fraggle-rock/gather/snapshot-runner.js +4 -5
  163. package/lighthouse-core/fraggle-rock/gather/timespan-runner.js +6 -6
  164. package/lighthouse-core/gather/connections/cri.js +0 -1
  165. package/lighthouse-core/gather/driver/execution-context.js +2 -4
  166. package/lighthouse-core/gather/driver/navigation.js +9 -9
  167. package/lighthouse-core/gather/driver/network-monitor.js +3 -16
  168. package/lighthouse-core/gather/driver.js +1 -6
  169. package/lighthouse-core/gather/fetcher.js +210 -34
  170. package/lighthouse-core/gather/gather-runner.js +17 -13
  171. package/lighthouse-core/gather/gatherers/accessibility.js +4 -16
  172. package/lighthouse-core/gather/gatherers/console-messages.js +2 -4
  173. package/lighthouse-core/gather/gatherers/dobetterweb/doctype.js +2 -4
  174. package/lighthouse-core/gather/gatherers/full-page-screenshot.js +2 -3
  175. package/lighthouse-core/gather/gatherers/js-usage.js +87 -12
  176. package/lighthouse-core/gather/gatherers/link-elements.js +14 -12
  177. package/lighthouse-core/gather/gatherers/main-document-content.js +8 -8
  178. package/lighthouse-core/gather/gatherers/script-elements.js +56 -7
  179. package/lighthouse-core/gather/gatherers/seo/robots-txt.js +30 -2
  180. package/lighthouse-core/gather/gatherers/source-maps.js +1 -3
  181. package/lighthouse-core/gather/gatherers/trace-elements.js +21 -2
  182. package/lighthouse-core/gather/gatherers/web-app-manifest.js +2 -2
  183. package/lighthouse-core/index.js +2 -26
  184. package/lighthouse-core/lib/cdt/generated/SourceMap.js +1 -1
  185. package/lighthouse-core/lib/dependency-graph/simulator/network-analyzer.js +29 -8
  186. package/lighthouse-core/lib/navigation-error.js +4 -13
  187. package/lighthouse-core/lib/script-helpers.js +6 -11
  188. package/lighthouse-core/lib/url-shim.js +2 -2
  189. package/lighthouse-core/runner.js +5 -0
  190. package/lighthouse-core/scripts/manual-chrome-launcher.js +1 -0
  191. package/lighthouse-core/util-commonjs.js +24 -28
  192. package/package.json +12 -12
  193. package/readme.md +1 -1
  194. package/report/.eslintrc.cjs +1 -3
  195. package/report/assets/styles.css +10 -12
  196. package/report/assets/templates.html +9 -10
  197. package/report/clients/bundle.js +1 -0
  198. package/report/clients/standalone.js +1 -0
  199. package/report/generator/report-generator.js +21 -46
  200. package/report/renderer/api.js +1 -0
  201. package/report/renderer/category-renderer.js +1 -0
  202. package/report/renderer/components.js +304 -303
  203. package/report/renderer/crc-details-renderer.js +1 -0
  204. package/report/renderer/details-renderer.js +10 -10
  205. package/report/renderer/dom.js +1 -0
  206. package/report/renderer/drop-down-menu.js +1 -0
  207. package/report/renderer/element-screenshot-renderer.js +4 -0
  208. package/report/renderer/features-util.js +1 -0
  209. package/report/renderer/i18n.js +62 -118
  210. package/report/renderer/logger.js +1 -0
  211. package/report/renderer/open-tab.js +3 -1
  212. package/report/renderer/performance-category-renderer.js +1 -0
  213. package/report/renderer/pwa-category-renderer.js +1 -0
  214. package/report/renderer/report-renderer.js +1 -0
  215. package/report/renderer/report-ui-features.js +1 -0
  216. package/report/renderer/snippet-renderer.js +1 -0
  217. package/report/renderer/swap-locale-feature.js +1 -0
  218. package/report/renderer/text-encoding.js +1 -0
  219. package/report/renderer/topbar-features.js +1 -0
  220. package/report/renderer/util.js +24 -27
  221. package/report/test/clients/bundle-test.js +4 -0
  222. package/report/test/generator/file-namer-test.js +1 -0
  223. package/report/test/generator/report-generator-test.js +20 -25
  224. package/report/test/renderer/category-renderer-test.js +3 -0
  225. package/report/test/renderer/components-test.js +3 -0
  226. package/report/test/renderer/crc-details-renderer-test.js +3 -0
  227. package/report/test/renderer/details-renderer-test.js +12 -58
  228. package/report/test/renderer/dom-test.js +3 -0
  229. package/report/test/renderer/element-screenshot-renderer-test.js +6 -3
  230. package/report/test/renderer/i18n-test.js +25 -70
  231. package/report/test/renderer/performance-category-renderer-test.js +4 -11
  232. package/report/test/renderer/pwa-category-renderer-test.js +3 -0
  233. package/report/test/renderer/report-renderer-axe-test.js +3 -0
  234. package/report/test/renderer/report-renderer-test.js +3 -0
  235. package/report/test/renderer/report-ui-features-test.js +3 -0
  236. package/report/test/renderer/snippet-renderer-test.js +3 -0
  237. package/report/test/renderer/text-encoding-test.js +3 -0
  238. package/report/test/renderer/util-test.js +5 -2
  239. package/report/test-assets/faux-psi.js +1 -2
  240. package/shared/localization/locales/en-US.json +260 -53
  241. package/shared/localization/locales/en-XL.json +260 -53
  242. package/shared/test/localization/format-test.js +2 -0
  243. package/shared/test/localization/locales-test.js +2 -0
  244. package/shared/test/localization/swap-locale-test.js +2 -0
  245. package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +2 -0
  246. package/third-party/chromium-synchronization/installability-errors-test.js +2 -0
  247. package/tsconfig.json +0 -1
  248. package/types/artifacts.d.ts +9 -48
  249. package/types/config.d.ts +0 -2
  250. package/types/externs.d.ts +2 -2
  251. package/types/gatherer.d.ts +2 -1
  252. package/types/global-lh.d.ts +0 -3
  253. package/types/lhr/audit-details.d.ts +3 -1
  254. package/types/lhr/lhr.d.ts +2 -2
  255. package/types/lhr/treemap.d.ts +1 -0
  256. package/lighthouse-core/audits/script-elements-test-audit.js +0 -30
  257. package/lighthouse-core/gather/gatherers/scripts.js +0 -154
  258. package/report/test/.eslintrc.cjs +0 -11
  259. package/shared/test/localization/.eslintrc.cjs +0 -11
@@ -35,10 +35,7 @@ async function getBaseArtifacts(config, driver, context) {
35
35
  HostFormFactor: userAgent.includes('Android') || userAgent.includes('Mobile') ?
36
36
  'mobile' : 'desktop',
37
37
  // Contextual artifacts whose collection changes based on gather mode.
38
- URL: {
39
- initialUrl: '',
40
- finalUrl: '',
41
- },
38
+ URL: {requestedUrl: '', finalUrl: ''},
42
39
  PageLoadError: null,
43
40
  GatherContext: context,
44
41
  // Artifacts that have been replaced by regular gatherers in Fraggle Rock.
@@ -86,11 +83,11 @@ function finalizeArtifacts(baseArtifacts, gathererArtifacts) {
86
83
  artifacts.LighthouseRunWarnings = deduplicateWarnings(warnings);
87
84
 
88
85
  if (artifacts.PageLoadError && !artifacts.URL.finalUrl) {
89
- artifacts.URL.finalUrl = artifacts.URL.requestedUrl || artifacts.URL.initialUrl;
86
+ artifacts.URL.finalUrl = artifacts.URL.requestedUrl;
90
87
  }
91
88
 
92
89
  // Check that the runner remembered to mutate the special-case URL artifact.
93
- if (!artifacts.URL.initialUrl) throw new Error('Runner did not set initialUrl');
90
+ if (!artifacts.URL.requestedUrl) throw new Error('Runner did not set requestedUrl');
94
91
  if (!artifacts.URL.finalUrl) throw new Error('Runner did not set finalUrl');
95
92
 
96
93
  return artifacts;
@@ -35,7 +35,7 @@ const defaultSession = {
35
35
  /** @implements {LH.Gatherer.FRTransitionalDriver} */
36
36
  class Driver {
37
37
  /**
38
- * @param {LH.Puppeteer.Page} page
38
+ * @param {import('puppeteer').Page} page
39
39
  */
40
40
  constructor(page) {
41
41
  this._page = page;
@@ -74,7 +74,7 @@ class Driver {
74
74
  const session = await this._page.target().createCDPSession();
75
75
  this._session = this.defaultSession = new ProtocolSession(session);
76
76
  this._executionContext = new ExecutionContext(this._session);
77
- this._fetcher = new Fetcher(this._session);
77
+ this._fetcher = new Fetcher(this._session, this._executionContext);
78
78
  log.timeEnd(status);
79
79
  }
80
80
 
@@ -5,7 +5,6 @@
5
5
  */
6
6
  'use strict';
7
7
 
8
- const puppeteer = require('puppeteer-core');
9
8
  const log = require('lighthouse-logger');
10
9
  const Driver = require('./driver.js');
11
10
  const Runner = require('../../runner.js');
@@ -44,20 +43,18 @@ const NetworkRecords = require('../../computed/network-records.js');
44
43
 
45
44
  /** @typedef {Omit<Parameters<typeof collectPhaseArtifacts>[0], 'phase'>} PhaseState */
46
45
 
47
- const DEFAULT_HOSTNAME = '127.0.0.1';
48
- const DEFAULT_PORT = 9222;
49
-
50
46
  /**
51
- * @param {{driver: Driver, config: LH.Config.FRConfig, options?: InternalOptions}} args
47
+ * @param {{driver: Driver, config: LH.Config.FRConfig, requestor: LH.NavigationRequestor, options?: InternalOptions}} args
52
48
  * @return {Promise<{baseArtifacts: LH.FRBaseArtifacts}>}
53
49
  */
54
- async function _setup({driver, config, options}) {
50
+ async function _setup({driver, config, requestor, options}) {
55
51
  await driver.connect();
56
52
  if (!options?.skipAboutBlank) {
57
53
  await gotoURL(driver, defaultNavigationConfig.blankPage, {waitUntil: ['navigated']});
58
54
  }
59
55
 
60
56
  const baseArtifacts = await getBaseArtifacts(config, driver, {gatherMode: 'navigation'});
57
+ if (typeof requestor === 'string') baseArtifacts.URL.requestedUrl = requestor;
61
58
 
62
59
  await prepare.prepareTargetForNavigationMode(driver, config.settings);
63
60
 
@@ -93,32 +90,25 @@ async function _cleanupNavigation({driver}) {
93
90
 
94
91
  /**
95
92
  * @param {NavigationContext} navigationContext
96
- * @return {Promise<{requestedUrl: string, mainDocumentUrl: string, navigationError: LH.LighthouseError | undefined, warnings: Array<LH.IcuMessage>}>}
93
+ * @return {Promise<{requestedUrl: string, finalUrl: string, navigationError: LH.LighthouseError | undefined, warnings: Array<LH.IcuMessage>}>}
97
94
  */
98
95
  async function _navigate(navigationContext) {
99
96
  const {driver, config, requestor} = navigationContext;
100
97
 
101
98
  try {
102
- const {requestedUrl, mainDocumentUrl, warnings} = await gotoURL(driver, requestor, {
99
+ const {requestedUrl, finalUrl, warnings} = await gotoURL(driver, requestor, {
103
100
  ...navigationContext.navigation,
104
101
  debugNavigation: config.settings.debugNavigation,
105
102
  maxWaitForFcp: config.settings.maxWaitForFcp,
106
103
  maxWaitForLoad: config.settings.maxWaitForLoad,
107
104
  waitUntil: navigationContext.navigation.pauseAfterFcpMs ? ['fcp', 'load'] : ['load'],
108
105
  });
109
- return {requestedUrl, mainDocumentUrl, navigationError: undefined, warnings};
106
+ return {requestedUrl, finalUrl, navigationError: undefined, warnings};
110
107
  } catch (err) {
111
108
  if (!(err instanceof LighthouseError)) throw err;
112
109
  if (err.code !== 'NO_FCP' && err.code !== 'PAGE_HUNG') throw err;
113
110
  if (typeof requestor !== 'string') throw err;
114
-
115
- // TODO: Make the urls optional here so we don't need to throw an error with a callback requestor.
116
- return {
117
- requestedUrl: requestor,
118
- mainDocumentUrl: requestor,
119
- navigationError: err,
120
- warnings: [],
121
- };
111
+ return {requestedUrl: requestor, finalUrl: requestor, navigationError: err, warnings: []};
122
112
  }
123
113
  }
124
114
 
@@ -162,7 +152,7 @@ async function _collectDebugData(navigationContext, phaseState) {
162
152
  * @param {PhaseState} phaseState
163
153
  * @param {Awaited<ReturnType<typeof _setupNavigation>>} setupResult
164
154
  * @param {Awaited<ReturnType<typeof _navigate>>} navigateResult
165
- * @return {Promise<{artifacts: Partial<LH.GathererArtifacts>, warnings: Array<LH.IcuMessage>, pageLoadError: LH.LighthouseError | undefined}>}
155
+ * @return {Promise<{requestedUrl: string, finalUrl: string, artifacts: Partial<LH.GathererArtifacts>, warnings: Array<LH.IcuMessage>, pageLoadError: LH.LighthouseError | undefined}>}
166
156
  */
167
157
  async function _computeNavigationResult(
168
158
  navigationContext,
@@ -170,12 +160,12 @@ async function _computeNavigationResult(
170
160
  setupResult,
171
161
  navigateResult
172
162
  ) {
173
- const {navigationError, mainDocumentUrl} = navigateResult;
163
+ const {navigationError, finalUrl} = navigateResult;
174
164
  const warnings = [...setupResult.warnings, ...navigateResult.warnings];
175
165
  const debugData = await _collectDebugData(navigationContext, phaseState);
176
166
  const pageLoadError = debugData.records
177
167
  ? getPageLoadError(navigationError, {
178
- url: mainDocumentUrl,
168
+ url: finalUrl,
179
169
  loadFailureMode: navigationContext.navigation.loadFailureMode,
180
170
  networkRecords: debugData.records,
181
171
  })
@@ -193,6 +183,8 @@ async function _computeNavigationResult(
193
183
  if (debugData.trace) artifacts.traces = {[pageLoadErrorId]: debugData.trace};
194
184
 
195
185
  return {
186
+ requestedUrl: navigateResult.requestedUrl,
187
+ finalUrl,
196
188
  pageLoadError,
197
189
  artifacts,
198
190
  warnings: [...warnings, pageLoadError.friendlyMessage],
@@ -202,6 +194,8 @@ async function _computeNavigationResult(
202
194
 
203
195
  const artifacts = await awaitArtifacts(phaseState.artifactState);
204
196
  return {
197
+ requestedUrl: navigateResult.requestedUrl,
198
+ finalUrl,
205
199
  artifacts,
206
200
  warnings,
207
201
  pageLoadError: undefined,
@@ -215,9 +209,8 @@ async function _computeNavigationResult(
215
209
  */
216
210
  async function _navigation(navigationContext) {
217
211
  const artifactState = getEmptyArtifactState();
218
- const initialUrl = await navigationContext.driver.url();
219
212
  const phaseState = {
220
- url: initialUrl,
213
+ url: await navigationContext.driver.url(),
221
214
  gatherMode: /** @type {const} */ ('navigation'),
222
215
  driver: navigationContext.driver,
223
216
  computedCache: navigationContext.computedCache,
@@ -231,19 +224,7 @@ async function _navigation(navigationContext) {
231
224
  await collectPhaseArtifacts({phase: 'startInstrumentation', ...phaseState});
232
225
  await collectPhaseArtifacts({phase: 'startSensitiveInstrumentation', ...phaseState});
233
226
  const navigateResult = await _navigate(navigationContext);
234
-
235
- // Every required url is initialized to an empty string in `getBaseArtifacts`.
236
- // If we haven't set all the required urls yet, set them here.
237
- if (!Object.values(phaseState.baseArtifacts).every(Boolean)) {
238
- phaseState.baseArtifacts.URL = {
239
- initialUrl,
240
- requestedUrl: navigateResult.requestedUrl,
241
- mainDocumentUrl: navigateResult.mainDocumentUrl,
242
- finalUrl: navigateResult.mainDocumentUrl,
243
- };
244
- }
245
- phaseState.url = navigateResult.mainDocumentUrl;
246
-
227
+ phaseState.url = navigateResult.finalUrl;
247
228
  await collectPhaseArtifacts({phase: 'stopSensitiveInstrumentation', ...phaseState});
248
229
  await collectPhaseArtifacts({phase: 'stopInstrumentation', ...phaseState});
249
230
  await _cleanupNavigation(navigationContext);
@@ -281,6 +262,11 @@ async function _navigations({driver, config, requestor, baseArtifacts, computedC
281
262
  artifacts.PageLoadError = navigationResult.pageLoadError;
282
263
  shouldHaltNavigations = true;
283
264
  }
265
+
266
+ artifacts.URL = {
267
+ requestedUrl: navigationResult.requestedUrl,
268
+ finalUrl: navigationResult.finalUrl,
269
+ };
284
270
  }
285
271
 
286
272
  LighthouseRunWarnings.push(...navigationResult.warnings);
@@ -302,12 +288,12 @@ async function _cleanup({requestedUrl, driver, config}) {
302
288
  }
303
289
 
304
290
  /**
305
- * @param {LH.NavigationRequestor|undefined} requestor
306
- * @param {{page?: LH.Puppeteer.Page, config?: LH.Config.Json, configContext?: LH.Config.FRContext}} options
291
+ * @param {LH.NavigationRequestor} requestor
292
+ * @param {{page: import('puppeteer').Page, config?: LH.Config.Json, configContext?: LH.Config.FRContext}} options
307
293
  * @return {Promise<LH.Gatherer.FRGatherResult>}
308
294
  */
309
295
  async function navigationGather(requestor, options) {
310
- const {configContext = {}} = options;
296
+ const {page, configContext = {}} = options;
311
297
  log.setLevel(configContext.logLevel || 'error');
312
298
 
313
299
  const {config} = initializeConfig(options.config, {...configContext, gatherMode: 'navigation'});
@@ -317,29 +303,18 @@ async function navigationGather(requestor, options) {
317
303
  };
318
304
 
319
305
  // We can't trigger the navigation through user interaction if we reset the page before starting.
320
- const isCallback = typeof requestor === 'function';
321
- if (isCallback) {
306
+ if (typeof requestor !== 'string') {
322
307
  internalOptions.skipAboutBlank = true;
323
308
  }
324
309
 
325
310
  const runnerOptions = {config, computedCache};
326
311
  const artifacts = await Runner.gather(
327
312
  async () => {
328
- let {page} = options;
329
-
330
- // For navigation mode, we shouldn't connect to a browser in audit mode,
331
- // therefore we connect to the browser in the gatherFn callback.
332
- if (!page) {
333
- const {hostname = DEFAULT_HOSTNAME, port = DEFAULT_PORT} = configContext;
334
- const browser = await puppeteer.connect({browserURL: `http://${hostname}:${port}`});
335
- page = await browser.newPage();
336
- }
337
-
338
313
  const driver = new Driver(page);
339
314
  const context = {
340
315
  driver,
341
316
  config,
342
- requestor: isCallback ? requestor : URL.normalizeUrl(requestor),
317
+ requestor: typeof requestor === 'string' ? URL.normalizeUrl(requestor) : requestor,
343
318
  options: internalOptions,
344
319
  };
345
320
  const {baseArtifacts} = await _setup(context);
@@ -15,6 +15,7 @@
15
15
  * @property {LH.Gatherer.GatherMode} gatherMode
16
16
  * @property {Map<string, LH.ArbitraryEqualityMap>} computedCache
17
17
  * @property {LH.Config.Settings} settings
18
+ * @property {string} url
18
19
  */
19
20
 
20
21
  /** @typedef {Record<string, Promise<any>>} IntermediateArtifacts */
@@ -74,6 +75,7 @@ async function collectPhaseArtifacts(options) {
74
75
  gatherMode,
75
76
  computedCache,
76
77
  settings,
78
+ url,
77
79
  } = options;
78
80
  const priorPhase = phaseToPriorPhase[phase];
79
81
  const priorPhaseArtifacts = (priorPhase && artifactState[priorPhase]) || {};
@@ -90,6 +92,7 @@ async function collectPhaseArtifacts(options) {
90
92
  : /** @type {Dependencies} */ ({});
91
93
 
92
94
  return gatherer[phase]({
95
+ url,
93
96
  gatherMode,
94
97
  driver,
95
98
  baseArtifacts,
@@ -14,7 +14,7 @@ const DEFAULT_PROTOCOL_TIMEOUT = 30000;
14
14
  /** @implements {LH.Gatherer.FRProtocolSession} */
15
15
  class ProtocolSession {
16
16
  /**
17
- * @param {LH.Puppeteer.CDPSession} session
17
+ * @param {import('puppeteer').CDPSession} session
18
18
  */
19
19
  constructor(session) {
20
20
  this._session = session;
@@ -93,7 +93,7 @@ class ProtocolSession {
93
93
  * @param {(session: ProtocolSession) => void} callback
94
94
  */
95
95
  addSessionAttachedListener(callback) {
96
- /** @param {LH.Puppeteer.CDPSession} session */
96
+ /** @param {import('puppeteer').CDPSession} session */
97
97
  const listener = session => callback(new ProtocolSession(session));
98
98
  this._callbackMap.set(callback, listener);
99
99
  this._getConnection().on('sessionattached', listener);
@@ -17,7 +17,7 @@ const {initializeConfig} = require('../config/config.js');
17
17
  const {getBaseArtifacts, finalizeArtifacts} = require('./base-artifacts.js');
18
18
 
19
19
  /**
20
- * @param {{page: LH.Puppeteer.Page, config?: LH.Config.Json, configContext?: LH.Config.FRContext}} options
20
+ * @param {{page: import('puppeteer').Page, config?: LH.Config.Json, configContext?: LH.Config.FRContext}} options
21
21
  * @return {Promise<LH.Gatherer.FRGatherResult>}
22
22
  */
23
23
  async function snapshotGather(options) {
@@ -36,14 +36,13 @@ async function snapshotGather(options) {
36
36
  const artifacts = await Runner.gather(
37
37
  async () => {
38
38
  const baseArtifacts = await getBaseArtifacts(config, driver, {gatherMode: 'snapshot'});
39
- baseArtifacts.URL = {
40
- initialUrl: url,
41
- finalUrl: url,
42
- };
39
+ baseArtifacts.URL.requestedUrl = url;
40
+ baseArtifacts.URL.finalUrl = url;
43
41
 
44
42
  const artifactDefinitions = config.artifacts || [];
45
43
  const artifactState = getEmptyArtifactState();
46
44
  await collectPhaseArtifacts({
45
+ url,
47
46
  phase: 'getArtifact',
48
47
  gatherMode: 'snapshot',
49
48
  driver,
@@ -18,7 +18,7 @@ const {initializeConfig} = require('../config/config.js');
18
18
  const {getBaseArtifacts, finalizeArtifacts} = require('./base-artifacts.js');
19
19
 
20
20
  /**
21
- * @param {{page: LH.Puppeteer.Page, config?: LH.Config.Json, configContext?: LH.Config.FRContext}} options
21
+ * @param {{page: import('puppeteer').Page, config?: LH.Config.Json, configContext?: LH.Config.FRContext}} options
22
22
  * @return {Promise<{endTimespanGather(): Promise<LH.Gatherer.FRGatherResult>}>}
23
23
  */
24
24
  async function startTimespanGather(options) {
@@ -32,11 +32,12 @@ async function startTimespanGather(options) {
32
32
  /** @type {Map<string, LH.ArbitraryEqualityMap>} */
33
33
  const computedCache = new Map();
34
34
  const artifactDefinitions = config.artifacts || [];
35
- const initialUrl = await driver.url();
35
+ const requestedUrl = await driver.url();
36
36
  const baseArtifacts = await getBaseArtifacts(config, driver, {gatherMode: 'timespan'});
37
37
  const artifactState = getEmptyArtifactState();
38
38
  /** @type {Omit<import('./runner-helpers.js').CollectPhaseArtifactOptions, 'phase'>} */
39
39
  const phaseOptions = {
40
+ url: requestedUrl,
40
41
  driver,
41
42
  artifactDefinitions,
42
43
  artifactState,
@@ -53,14 +54,13 @@ async function startTimespanGather(options) {
53
54
  return {
54
55
  async endTimespanGather() {
55
56
  const finalUrl = await driver.url();
57
+ phaseOptions.url = finalUrl;
56
58
 
57
59
  const runnerOptions = {config, computedCache};
58
60
  const artifacts = await Runner.gather(
59
61
  async () => {
60
- baseArtifacts.URL = {
61
- initialUrl,
62
- finalUrl,
63
- };
62
+ baseArtifacts.URL.requestedUrl = requestedUrl;
63
+ baseArtifacts.URL.finalUrl = finalUrl;
64
64
 
65
65
  await collectPhaseArtifacts({phase: 'stopSensitiveInstrumentation', ...phaseOptions});
66
66
  await collectPhaseArtifacts({phase: 'stopInstrumentation', ...phaseOptions});
@@ -88,7 +88,6 @@ class CriConnection extends Connection {
88
88
  path: '/json/' + command,
89
89
  }, response => {
90
90
  let data = '';
91
- response.setEncoding('utf8');
92
91
  response.on('data', chunk => {
93
92
  data += chunk;
94
93
  });
@@ -97,8 +97,7 @@ class ExecutionContext {
97
97
  .catch(${pageFunctions.wrapRuntimeEvalErrorInBrowserString})
98
98
  .then(resolve);
99
99
  });
100
- }())
101
- //# sourceURL=_lighthouse-eval.js`,
100
+ }())`,
102
101
  includeCommandLineAPI: true,
103
102
  awaitPromise: true,
104
103
  returnByValue: true,
@@ -196,8 +195,7 @@ class ExecutionContext {
196
195
  ${ExecutionContext._cachedNativesPreamble};
197
196
  ${depsSerialized};
198
197
  (${mainFn})(${argsSerialized});
199
- })()
200
- //# sourceURL=_lighthouse-eval.js`;
198
+ })()`;
201
199
 
202
200
  await this._session.sendCommand('Page.addScriptToEvaluateOnNewDocument', {source: expression});
203
201
  }
@@ -80,7 +80,7 @@ function resolveWaitForFullyLoadedOptions(options) {
80
80
  * @param {LH.Gatherer.FRTransitionalDriver} driver
81
81
  * @param {LH.NavigationRequestor} requestor
82
82
  * @param {NavigationOptions} options
83
- * @return {Promise<{requestedUrl: string, mainDocumentUrl: string, warnings: Array<LH.IcuMessage>}>}
83
+ * @return {Promise<{requestedUrl: string, finalUrl: string, warnings: Array<LH.IcuMessage>}>}
84
84
  */
85
85
  async function gotoURL(driver, requestor, options) {
86
86
  const status = typeof requestor === 'string' ?
@@ -130,14 +130,14 @@ async function gotoURL(driver, requestor, options) {
130
130
 
131
131
  let requestedUrl = navigationUrls.requestedUrl;
132
132
  if (typeof requestor === 'string') {
133
- if (requestedUrl && !URL.equalWithExcludedFragments(requestor, requestedUrl)) {
133
+ if (requestor !== requestedUrl) {
134
134
  log.error('Navigation', 'Provided URL did not match initial navigation URL');
135
135
  }
136
136
  requestedUrl = requestor;
137
137
  }
138
138
  if (!requestedUrl) throw Error('No navigations detected when running user defined requestor.');
139
139
 
140
- const mainDocumentUrl = navigationUrls.mainDocumentUrl || requestedUrl;
140
+ const finalUrl = navigationUrls.finalUrl || requestedUrl;
141
141
 
142
142
  // Bring `Page.navigate` errors back into the promise chain. See https://github.com/GoogleChrome/lighthouse/pull/6739.
143
143
  await waitForNavigationTriggered;
@@ -150,26 +150,26 @@ async function gotoURL(driver, requestor, options) {
150
150
  log.timeEnd(status);
151
151
  return {
152
152
  requestedUrl,
153
- mainDocumentUrl,
154
- warnings: getNavigationWarnings({timedOut, mainDocumentUrl, requestedUrl}),
153
+ finalUrl,
154
+ warnings: getNavigationWarnings({timedOut, finalUrl, requestedUrl}),
155
155
  };
156
156
  }
157
157
 
158
158
  /**
159
- * @param {{timedOut: boolean, requestedUrl: string, mainDocumentUrl: string; }} navigation
159
+ * @param {{timedOut: boolean, requestedUrl: string, finalUrl: string; }} navigation
160
160
  * @return {Array<LH.IcuMessage>}
161
161
  */
162
162
  function getNavigationWarnings(navigation) {
163
- const {requestedUrl, mainDocumentUrl} = navigation;
163
+ const {requestedUrl, finalUrl} = navigation;
164
164
  /** @type {Array<LH.IcuMessage>} */
165
165
  const warnings = [];
166
166
 
167
167
  if (navigation.timedOut) warnings.push(str_(UIStrings.warningTimeout));
168
168
 
169
- if (!URL.equalWithExcludedFragments(requestedUrl, mainDocumentUrl)) {
169
+ if (!URL.equalWithExcludedFragments(requestedUrl, finalUrl)) {
170
170
  warnings.push(str_(UIStrings.warningRedirected, {
171
171
  requested: requestedUrl,
172
- final: mainDocumentUrl,
172
+ final: finalUrl,
173
173
  }));
174
174
  }
175
175
 
@@ -133,7 +133,7 @@ class NetworkMonitor {
133
133
  this._sessions = new Map();
134
134
  }
135
135
 
136
- /** @return {Promise<{requestedUrl?: string, mainDocumentUrl?: string}>} */
136
+ /** @return {Promise<{requestedUrl?: string, finalUrl?: string}>} */
137
137
  async getNavigationUrls() {
138
138
  const frameNavigations = this._frameNavigations;
139
139
  if (!frameNavigations.length) return {};
@@ -143,22 +143,9 @@ class NetworkMonitor {
143
143
  const mainFrameNavigations = frameNavigations.filter(frame => frame.id === mainFrameId);
144
144
  if (!mainFrameNavigations.length) log.warn('NetworkMonitor', 'No detected navigations');
145
145
 
146
- // The requested URL is the initiator request for the first frame navigation.
147
- /** @type {string|undefined} */
148
- let requestedUrl = mainFrameNavigations[0]?.url;
149
- if (this._networkRecorder) {
150
- const records = this._networkRecorder.getRawRecords();
151
-
152
- let initialUrlRequest = records.find(record => record.url === requestedUrl);
153
- while (initialUrlRequest?.redirectSource) {
154
- initialUrlRequest = initialUrlRequest.redirectSource;
155
- requestedUrl = initialUrlRequest.url;
156
- }
157
- }
158
-
159
146
  return {
160
- requestedUrl,
161
- mainDocumentUrl: mainFrameNavigations[mainFrameNavigations.length - 1]?.url,
147
+ requestedUrl: mainFrameNavigations[0]?.url,
148
+ finalUrl: mainFrameNavigations[mainFrameNavigations.length - 1]?.url,
162
149
  };
163
150
  }
164
151
 
@@ -64,7 +64,7 @@ class Driver {
64
64
  defaultSession = this;
65
65
 
66
66
  // eslint-disable-next-line no-invalid-this
67
- fetcher = new Fetcher(this.defaultSession);
67
+ fetcher = new Fetcher(this.defaultSession, this.executionContext);
68
68
 
69
69
  /**
70
70
  * @param {Connection} connection
@@ -470,11 +470,6 @@ class Driver {
470
470
  this._devtoolsLog.endRecording();
471
471
  return this._devtoolsLog.messages;
472
472
  }
473
-
474
- async url() {
475
- const {frameTree} = await this.sendCommand('Page.getFrameTree');
476
- return `${frameTree.frame.url}${frameTree.frame.urlFragment || ''}`;
477
- }
478
473
  }
479
474
 
480
475
  module.exports = Driver;