lighthouse 8.0.0-dev.20210709 → 8.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 (299) hide show
  1. package/docs/architecture.md +101 -0
  2. package/docs/authenticated-pages.md +44 -0
  3. package/docs/bug-labels.md +35 -0
  4. package/docs/configuration.md +213 -0
  5. package/docs/emulation.md +32 -0
  6. package/docs/error-reporting.md +42 -0
  7. package/docs/hacking-tips.md +55 -0
  8. package/docs/headless-chrome.md +119 -0
  9. package/docs/lantern.md +55 -0
  10. package/docs/new-audits.md +99 -0
  11. package/docs/performance-budgets.md +187 -0
  12. package/docs/plugins.md +374 -0
  13. package/docs/puppeteer.md +95 -0
  14. package/docs/readme.md +164 -0
  15. package/docs/recipes/auth/README.md +129 -0
  16. package/docs/recipes/auth/example-lh-auth.js +81 -0
  17. package/docs/recipes/auth/package.json +11 -0
  18. package/docs/recipes/auth/server/public/dashboard-unauthenticated.html +21 -0
  19. package/docs/recipes/auth/server/public/dashboard.html +25 -0
  20. package/docs/recipes/auth/server/public/home-unauthenticated.html +27 -0
  21. package/docs/recipes/auth/server/public/home.html +17 -0
  22. package/docs/recipes/auth/server/public/unauthenticated.html +22 -0
  23. package/docs/recipes/auth/server/server.js +85 -0
  24. package/docs/recipes/custom-audit/custom-config.js +36 -0
  25. package/docs/recipes/custom-audit/package.json +8 -0
  26. package/docs/recipes/custom-audit/readme.md +32 -0
  27. package/docs/recipes/custom-audit/searchable-audit.js +46 -0
  28. package/docs/recipes/custom-audit/searchable-gatherer.js +32 -0
  29. package/docs/recipes/custom-gatherer-puppeteer/custom-audit.js +34 -0
  30. package/{root.js → docs/recipes/custom-gatherer-puppeteer/custom-config.js} +23 -2
  31. package/docs/recipes/custom-gatherer-puppeteer/custom-gatherer.js +51 -0
  32. package/docs/recipes/custom-gatherer-puppeteer/package.json +13 -0
  33. package/docs/recipes/custom-gatherer-puppeteer/readme.md +7 -0
  34. package/docs/recipes/custom-gatherer-puppeteer/test.sh +9 -0
  35. package/docs/recipes/gulp/gulpfile.js +79 -0
  36. package/docs/recipes/gulp/package.json +12 -0
  37. package/docs/recipes/gulp/public/index.html +22 -0
  38. package/docs/recipes/gulp/readme.md +6 -0
  39. package/docs/recipes/integration-test/README.md +14 -0
  40. package/docs/recipes/integration-test/example-lh-auth.test.js +160 -0
  41. package/docs/recipes/integration-test/package.json +9 -0
  42. package/docs/recipes/lighthouse-plugin-example/audits/preload-as.js +46 -0
  43. package/docs/recipes/lighthouse-plugin-example/package.json +11 -0
  44. package/docs/recipes/lighthouse-plugin-example/plugin-recipe-screenshot.png +0 -0
  45. package/docs/recipes/lighthouse-plugin-example/plugin.js +24 -0
  46. package/docs/recipes/lighthouse-plugin-example/readme.md +53 -0
  47. package/docs/releasing.md +164 -0
  48. package/docs/scoring.md +79 -0
  49. package/docs/throttling.md +150 -0
  50. package/docs/understanding-results.md +209 -0
  51. package/docs/v8-perf-faq.md +244 -0
  52. package/docs/variability.md +150 -0
  53. package/jest.config.js +0 -3
  54. package/lighthouse-cli/bin.js +8 -6
  55. package/lighthouse-core/audits/accessibility/aria-command-name.js +1 -1
  56. package/lighthouse-core/audits/accessibility/aria-meter-name.js +1 -1
  57. package/lighthouse-core/audits/accessibility/aria-progressbar-name.js +1 -1
  58. package/lighthouse-core/audits/accessibility/aria-tooltip-name.js +1 -1
  59. package/lighthouse-core/audits/accessibility/aria-treeitem-name.js +1 -1
  60. package/lighthouse-core/audits/apple-touch-icon.js +0 -1
  61. package/lighthouse-core/audits/audit.js +3 -3
  62. package/lighthouse-core/audits/autocomplete.js +2 -2
  63. package/lighthouse-core/audits/byte-efficiency/byte-efficiency-audit.js +14 -29
  64. package/lighthouse-core/audits/byte-efficiency/duplicated-javascript.js +2 -3
  65. package/lighthouse-core/audits/byte-efficiency/efficient-animated-content.js +1 -1
  66. package/lighthouse-core/audits/byte-efficiency/legacy-javascript.js +2 -3
  67. package/lighthouse-core/audits/byte-efficiency/modern-image-formats.js +15 -55
  68. package/lighthouse-core/audits/byte-efficiency/offscreen-images.js +4 -8
  69. package/lighthouse-core/audits/byte-efficiency/render-blocking-resources.js +8 -15
  70. package/lighthouse-core/audits/byte-efficiency/total-byte-weight.js +9 -10
  71. package/lighthouse-core/audits/byte-efficiency/unminified-css.js +1 -1
  72. package/lighthouse-core/audits/byte-efficiency/unminified-javascript.js +1 -1
  73. package/lighthouse-core/audits/byte-efficiency/unused-css-rules.js +1 -1
  74. package/lighthouse-core/audits/byte-efficiency/unused-javascript.js +1 -2
  75. package/lighthouse-core/audits/byte-efficiency/uses-long-cache-ttl.js +2 -2
  76. package/lighthouse-core/audits/byte-efficiency/uses-optimized-images.js +1 -2
  77. package/lighthouse-core/audits/byte-efficiency/uses-responsive-images.js +24 -46
  78. package/lighthouse-core/audits/byte-efficiency/uses-text-compression.js +1 -1
  79. package/lighthouse-core/audits/critical-request-chains.js +0 -1
  80. package/lighthouse-core/audits/csp-xss.js +1 -1
  81. package/lighthouse-core/audits/diagnostics.js +0 -1
  82. package/lighthouse-core/audits/dobetterweb/geolocation-on-start.js +0 -1
  83. package/lighthouse-core/audits/dobetterweb/inspector-issues.js +1 -1
  84. package/lighthouse-core/audits/dobetterweb/notification-on-start.js +0 -1
  85. package/lighthouse-core/audits/dobetterweb/uses-http2.js +0 -1
  86. package/lighthouse-core/audits/final-screenshot.js +4 -8
  87. package/lighthouse-core/audits/font-display.js +0 -1
  88. package/lighthouse-core/audits/installable-manifest.js +3 -4
  89. package/lighthouse-core/audits/largest-contentful-paint-element.js +0 -1
  90. package/lighthouse-core/audits/long-tasks.js +1 -1
  91. package/lighthouse-core/audits/maskable-icon.js +0 -1
  92. package/lighthouse-core/audits/metrics/first-contentful-paint-3g.js +2 -4
  93. package/lighthouse-core/audits/metrics/first-contentful-paint.js +2 -4
  94. package/lighthouse-core/audits/metrics/first-meaningful-paint.js +2 -4
  95. package/lighthouse-core/audits/metrics/interactive.js +2 -4
  96. package/lighthouse-core/audits/metrics/largest-contentful-paint.js +2 -4
  97. package/lighthouse-core/audits/metrics/max-potential-fid.js +2 -4
  98. package/lighthouse-core/audits/metrics/speed-index.js +2 -4
  99. package/lighthouse-core/audits/metrics/total-blocking-time.js +2 -10
  100. package/lighthouse-core/audits/metrics.js +2 -4
  101. package/lighthouse-core/audits/performance-budget.js +0 -1
  102. package/lighthouse-core/audits/predictive-perf.js +6 -9
  103. package/lighthouse-core/audits/preload-fonts.js +1 -11
  104. package/lighthouse-core/audits/preload-lcp-image.js +5 -18
  105. package/lighthouse-core/audits/redirects.js +8 -10
  106. package/lighthouse-core/audits/screenshot-thumbnails.js +13 -28
  107. package/lighthouse-core/audits/seo/canonical.js +1 -2
  108. package/lighthouse-core/audits/seo/font-size.js +4 -4
  109. package/lighthouse-core/audits/seo/hreflang.js +2 -3
  110. package/lighthouse-core/audits/seo/http-status-code.js +16 -21
  111. package/lighthouse-core/audits/seo/is-crawlable.js +3 -4
  112. package/lighthouse-core/audits/seo/robots-txt.js +2 -2
  113. package/lighthouse-core/audits/seo/tap-targets.js +5 -5
  114. package/lighthouse-core/audits/server-response-time.js +2 -20
  115. package/lighthouse-core/audits/splash-screen.js +0 -1
  116. package/lighthouse-core/audits/themed-omnibox.js +0 -1
  117. package/lighthouse-core/audits/third-party-facades.js +0 -1
  118. package/lighthouse-core/audits/third-party-summary.js +3 -1
  119. package/lighthouse-core/audits/timing-budget.js +2 -4
  120. package/lighthouse-core/audits/uses-rel-preconnect.js +9 -14
  121. package/lighthouse-core/audits/uses-rel-preload.js +2 -13
  122. package/lighthouse-core/computed/main-thread-tasks.js +2 -2
  123. package/lighthouse-core/computed/metrics/cumulative-layout-shift.js +3 -3
  124. package/lighthouse-core/computed/metrics/first-contentful-paint-all-frames.js +6 -6
  125. package/lighthouse-core/computed/metrics/first-contentful-paint.js +8 -9
  126. package/lighthouse-core/computed/metrics/first-meaningful-paint.js +9 -10
  127. package/lighthouse-core/computed/metrics/interactive.js +24 -25
  128. package/lighthouse-core/computed/metrics/lantern-first-contentful-paint.js +6 -6
  129. package/lighthouse-core/computed/metrics/lantern-first-meaningful-paint.js +6 -6
  130. package/lighthouse-core/computed/metrics/lantern-largest-contentful-paint.js +6 -6
  131. package/lighthouse-core/computed/metrics/lantern-metric.js +8 -16
  132. package/lighthouse-core/computed/metrics/largest-contentful-paint-all-frames.js +7 -7
  133. package/lighthouse-core/computed/metrics/largest-contentful-paint.js +9 -10
  134. package/lighthouse-core/computed/metrics/max-potential-fid.js +11 -8
  135. package/lighthouse-core/computed/metrics/metric.js +5 -32
  136. package/lighthouse-core/computed/metrics/speed-index.js +5 -6
  137. package/lighthouse-core/computed/metrics/timing-summary.js +45 -55
  138. package/lighthouse-core/computed/metrics/total-blocking-time.js +29 -36
  139. package/lighthouse-core/computed/page-dependency-graph.js +14 -14
  140. package/lighthouse-core/computed/resource-summary.js +7 -3
  141. package/lighthouse-core/computed/speedline.js +3 -3
  142. package/lighthouse-core/computed/trace-of-tab.js +86 -15
  143. package/lighthouse-core/computed/user-timings.js +5 -5
  144. package/lighthouse-core/config/default-config.js +0 -1
  145. package/lighthouse-core/fraggle-rock/config/config.js +7 -9
  146. package/lighthouse-core/fraggle-rock/config/default-config.js +2 -40
  147. package/lighthouse-core/fraggle-rock/config/filters.js +6 -39
  148. package/lighthouse-core/fraggle-rock/config/validation.js +4 -4
  149. package/lighthouse-core/fraggle-rock/gather/base-artifacts.js +19 -54
  150. package/lighthouse-core/fraggle-rock/gather/navigation-runner.js +10 -21
  151. package/lighthouse-core/fraggle-rock/gather/runner-helpers.js +2 -2
  152. package/lighthouse-core/fraggle-rock/gather/snapshot-runner.js +2 -2
  153. package/lighthouse-core/fraggle-rock/gather/timespan-runner.js +2 -2
  154. package/lighthouse-core/gather/driver/prepare.js +0 -3
  155. package/lighthouse-core/gather/fetcher.js +2 -0
  156. package/lighthouse-core/gather/gather-runner.js +14 -2
  157. package/lighthouse-core/gather/gatherers/image-elements.js +61 -24
  158. package/lighthouse-core/gather/gatherers/inspector-issues.js +2 -2
  159. package/lighthouse-core/gather/gatherers/script-elements.js +12 -45
  160. package/lighthouse-core/gather/gatherers/seo/font-size.js +5 -5
  161. package/lighthouse-core/gather/gatherers/seo/tap-targets.js +12 -64
  162. package/lighthouse-core/gather/gatherers/service-worker.js +3 -20
  163. package/lighthouse-core/gather/gatherers/trace-compat.js +1 -1
  164. package/lighthouse-core/gather/gatherers/trace-elements.js +3 -15
  165. package/lighthouse-core/gather/gatherers/trace.js +4 -13
  166. package/lighthouse-core/gather/gatherers/viewport-dimensions.js +1 -1
  167. package/lighthouse-core/lib/dependency-graph/simulator/network-analyzer.js +2 -13
  168. package/lighthouse-core/lib/emulation.js +2 -0
  169. package/lighthouse-core/lib/i18n/i18n.js +2 -2
  170. package/lighthouse-core/lib/i18n/locales/ar-XB.json +141 -141
  171. package/lighthouse-core/lib/i18n/locales/ar.json +143 -143
  172. package/lighthouse-core/lib/i18n/locales/bg.json +143 -143
  173. package/lighthouse-core/lib/i18n/locales/ca.json +141 -141
  174. package/lighthouse-core/lib/i18n/locales/cs.json +141 -141
  175. package/lighthouse-core/lib/i18n/locales/da.json +141 -141
  176. package/lighthouse-core/lib/i18n/locales/de.json +142 -142
  177. package/lighthouse-core/lib/i18n/locales/el.json +141 -141
  178. package/lighthouse-core/lib/i18n/locales/en-GB.json +141 -141
  179. package/lighthouse-core/lib/i18n/locales/en-US.ctc.json +6659 -0
  180. package/lighthouse-core/lib/i18n/locales/en-US.json +144 -150
  181. package/lighthouse-core/lib/i18n/locales/en-XA.json +141 -141
  182. package/lighthouse-core/lib/i18n/locales/en-XL.ctc.json +6628 -0
  183. package/lighthouse-core/lib/i18n/locales/en-XL.json +144 -150
  184. package/lighthouse-core/lib/i18n/locales/es-419.json +141 -141
  185. package/lighthouse-core/lib/i18n/locales/es.json +141 -141
  186. package/lighthouse-core/lib/i18n/locales/fi.json +143 -143
  187. package/lighthouse-core/lib/i18n/locales/fil.json +142 -142
  188. package/lighthouse-core/lib/i18n/locales/fr.json +141 -141
  189. package/lighthouse-core/lib/i18n/locales/he.json +142 -142
  190. package/lighthouse-core/lib/i18n/locales/hi.json +143 -143
  191. package/lighthouse-core/lib/i18n/locales/hr.json +141 -141
  192. package/lighthouse-core/lib/i18n/locales/hu.json +143 -143
  193. package/lighthouse-core/lib/i18n/locales/id.json +143 -143
  194. package/lighthouse-core/lib/i18n/locales/it.json +143 -143
  195. package/lighthouse-core/lib/i18n/locales/ja.json +143 -143
  196. package/lighthouse-core/lib/i18n/locales/ko.json +143 -143
  197. package/lighthouse-core/lib/i18n/locales/lt.json +143 -143
  198. package/lighthouse-core/lib/i18n/locales/lv.json +143 -143
  199. package/lighthouse-core/lib/i18n/locales/nl.json +141 -141
  200. package/lighthouse-core/lib/i18n/locales/no.json +141 -141
  201. package/lighthouse-core/lib/i18n/locales/pl.json +141 -141
  202. package/lighthouse-core/lib/i18n/locales/pt-PT.json +141 -141
  203. package/lighthouse-core/lib/i18n/locales/pt.json +141 -141
  204. package/lighthouse-core/lib/i18n/locales/ro.json +144 -144
  205. package/lighthouse-core/lib/i18n/locales/ru.json +143 -143
  206. package/lighthouse-core/lib/i18n/locales/sk.json +142 -142
  207. package/lighthouse-core/lib/i18n/locales/sl.json +141 -141
  208. package/lighthouse-core/lib/i18n/locales/sr-Latn.json +143 -143
  209. package/lighthouse-core/lib/i18n/locales/sr.json +143 -143
  210. package/lighthouse-core/lib/i18n/locales/sv.json +142 -142
  211. package/lighthouse-core/lib/i18n/locales/ta.json +141 -141
  212. package/lighthouse-core/lib/i18n/locales/te.json +143 -143
  213. package/lighthouse-core/lib/i18n/locales/th.json +143 -143
  214. package/lighthouse-core/lib/i18n/locales/tr.json +143 -143
  215. package/lighthouse-core/lib/i18n/locales/uk.json +141 -141
  216. package/lighthouse-core/lib/i18n/locales/vi.json +143 -143
  217. package/lighthouse-core/lib/i18n/locales/zh-HK.json +141 -141
  218. package/lighthouse-core/lib/i18n/locales/zh-TW.json +143 -143
  219. package/lighthouse-core/lib/i18n/locales/zh.json +143 -143
  220. package/lighthouse-core/lib/lh-error.js +2 -2
  221. package/lighthouse-core/lib/minify-trace.js +1 -1
  222. package/lighthouse-core/lib/network-request.js +1 -17
  223. package/lighthouse-core/lib/page-functions.js +5 -6
  224. package/lighthouse-core/lib/rect-helpers.js +3 -3
  225. package/lighthouse-core/lib/sd-validation/assets/jsonldcontext.json +7137 -0
  226. package/lighthouse-core/lib/sd-validation/assets/schema-tree.json +9900 -0
  227. package/{report/report-assets.js → lighthouse-core/lib/sd-validation/helpers/walk-object.js} +20 -12
  228. package/lighthouse-core/lib/sd-validation/json-expander.js +56 -0
  229. package/lighthouse-core/lib/sd-validation/json-linter.js +49 -0
  230. package/lighthouse-core/lib/sd-validation/jsonld-keyword-validator.js +50 -0
  231. package/lighthouse-core/lib/sd-validation/line-number-from-jsonld-path.js +60 -0
  232. package/lighthouse-core/lib/sd-validation/schema-validator.js +146 -0
  233. package/lighthouse-core/lib/sd-validation/scripts/download-jsonldcontext.js +30 -0
  234. package/lighthouse-core/lib/sd-validation/scripts/generate-schema-tree.js +97 -0
  235. package/lighthouse-core/lib/sd-validation/sd-validation.js +77 -0
  236. package/lighthouse-core/lib/tappable-rects.js +1 -1
  237. package/lighthouse-core/lib/tracehouse/trace-processor.js +42 -116
  238. package/lighthouse-core/lib/url-shim.js +2 -29
  239. package/lighthouse-core/report/html/html-report-assets.js +38 -0
  240. package/{report/README.md → lighthouse-core/report/html/readme.md} +11 -7
  241. package/{report → lighthouse-core/report/html}/renderer/category-renderer.js +0 -0
  242. package/{report → lighthouse-core/report/html}/renderer/crc-details-renderer.js +0 -0
  243. package/{report → lighthouse-core/report/html}/renderer/details-renderer.js +1 -1
  244. package/{report → lighthouse-core/report/html}/renderer/dom.js +0 -0
  245. package/{report → lighthouse-core/report/html}/renderer/element-screenshot-renderer.js +0 -0
  246. package/{report → lighthouse-core/report/html}/renderer/i18n.js +1 -1
  247. package/{report → lighthouse-core/report/html}/renderer/logger.js +0 -0
  248. package/{report → lighthouse-core/report/html}/renderer/performance-category-renderer.js +0 -0
  249. package/{report → lighthouse-core/report/html}/renderer/psi.js +0 -0
  250. package/{report → lighthouse-core/report/html}/renderer/pwa-category-renderer.js +0 -0
  251. package/{report → lighthouse-core/report/html}/renderer/report-renderer.js +0 -0
  252. package/{report → lighthouse-core/report/html}/renderer/report-ui-features.js +3 -3
  253. package/{report → lighthouse-core/report/html}/renderer/snippet-renderer.js +0 -0
  254. package/{report → lighthouse-core/report/html}/renderer/text-encoding.js +0 -0
  255. package/{report → lighthouse-core/report/html}/renderer/util.js +4 -7
  256. package/{report/assets/styles.css → lighthouse-core/report/html/report-styles.css} +0 -0
  257. package/{report/assets/standalone-template.html → lighthouse-core/report/html/report-template.html} +41 -1
  258. package/{report/assets → lighthouse-core/report/html}/templates.html +0 -0
  259. package/{report → lighthouse-core/report}/report-generator.js +1 -1
  260. package/lighthouse-core/runner.js +1 -1
  261. package/package.json +12 -13
  262. package/readme.md +2 -2
  263. package/third-party/chromium-synchronization/inspector-issueAdded-types-test.js +2 -3
  264. package/third-party/chromium-synchronization/installability-errors-test.js +2 -2
  265. package/third-party/download-content-shell/download-content-shell.js +1 -2
  266. package/third-party/snyk/snapshot.json +1 -1
  267. package/tsconfig.json +1 -0
  268. package/types/artifacts.d.ts +21 -41
  269. package/types/audit.d.ts +0 -2
  270. package/types/config.d.ts +2 -16
  271. package/types/externs.d.ts +0 -1
  272. package/types/gatherer.d.ts +13 -13
  273. package/types/html-renderer.d.ts +14 -14
  274. package/types/i18n.d.ts +1 -1
  275. package/lighthouse-core/audits/byte-efficiency/uses-responsive-images-snapshot.js +0 -94
  276. package/lighthouse-core/computed/image-records.js +0 -62
  277. package/lighthouse-core/computed/metrics/navigation-metric.js +0 -46
  278. package/lighthouse-core/computed/processed-navigation.js +0 -21
  279. package/lighthouse-core/computed/processed-trace.js +0 -21
  280. package/lighthouse-core/gather/gatherers/gather-context.js +0 -25
  281. package/lighthouse-core/gather/gatherers/host-form-factor.js +0 -31
  282. package/lighthouse-core/gather/gatherers/host-user-agent.js +0 -29
  283. package/lighthouse-core/lib/lh-trace-processor.js +0 -46
  284. package/report/clients/standalone.js +0 -52
  285. package/report/test/renderer/category-renderer-test.js +0 -488
  286. package/report/test/renderer/crc-details-renderer-test.js +0 -115
  287. package/report/test/renderer/details-renderer-test.js +0 -843
  288. package/report/test/renderer/dom-test.js +0 -157
  289. package/report/test/renderer/element-screenshot-renderer-test.js +0 -189
  290. package/report/test/renderer/i18n-test.js +0 -146
  291. package/report/test/renderer/performance-category-renderer-test.js +0 -332
  292. package/report/test/renderer/psi-test.js +0 -152
  293. package/report/test/renderer/pwa-category-renderer-test.js +0 -303
  294. package/report/test/renderer/report-renderer-test.js +0 -325
  295. package/report/test/renderer/report-ui-features-test.js +0 -572
  296. package/report/test/renderer/snippet-renderer-test.js +0 -291
  297. package/report/test/renderer/text-encoding-test.js +0 -41
  298. package/report/test/renderer/util-test.js +0 -388
  299. package/report/test/report-generator-test.js +0 -145
@@ -6,8 +6,8 @@
6
6
  'use strict';
7
7
 
8
8
  /**
9
- * @param {LH.Config.GathererDefn | LH.Config.AnyFRGathererDefn} gathererDefn
10
- * @return {gathererDefn is LH.Config.AnyFRGathererDefn}
9
+ * @param {LH.Config.GathererDefn | LH.Config.FRGathererDefn} gathererDefn
10
+ * @return {gathererDefn is LH.Config.FRGathererDefn}
11
11
  */
12
12
  function isFRGathererDefn(gathererDefn) {
13
13
  return 'meta' in gathererDefn.instance;
@@ -17,8 +17,8 @@ function isFRGathererDefn(gathererDefn) {
17
17
  * Determines if the artifact dependency direction is valid. The dependency's minimum supported mode
18
18
  * must be less than or equal to the dependent's.
19
19
  *
20
- * @param {LH.Config.AnyFRGathererDefn} dependent The artifact that depends on the other.
21
- * @param {LH.Config.AnyFRGathererDefn} dependency The artifact that is being depended on by the other.
20
+ * @param {LH.Config.FRGathererDefn} dependent The artifact that depends on the other.
21
+ * @param {LH.Config.FRGathererDefn} dependency The artifact that is being depended on by the other.
22
22
  * @return {boolean}
23
23
  */
24
24
  function isValidArtifactDependency(dependent, dependency) {
@@ -5,12 +5,7 @@
5
5
  */
6
6
  'use strict';
7
7
 
8
- const log = require('lighthouse-logger');
9
- const isEqual = require('lodash.isequal');
10
- const {
11
- getBenchmarkIndex,
12
- getEnvironmentWarnings,
13
- } = require('../../gather/driver/environment.js');
8
+ const {getBrowserVersion, getBenchmarkIndex} = require('../../gather/driver/environment.js');
14
9
 
15
10
  /**
16
11
  * @param {LH.Config.FRConfig} config
@@ -18,73 +13,43 @@ const {
18
13
  * @return {Promise<LH.BaseArtifacts>}
19
14
  */
20
15
  async function getBaseArtifacts(config, driver) {
16
+ const HostUserAgent = (await getBrowserVersion(driver.defaultSession)).userAgent;
17
+
18
+ // Whether Lighthouse was run on a mobile device (i.e. not on a desktop machine).
19
+ const HostFormFactor =
20
+ HostUserAgent.includes('Android') || HostUserAgent.includes('Mobile') ? 'mobile' : 'desktop';
21
+
21
22
  const BenchmarkIndex = await getBenchmarkIndex(driver.executionContext);
22
23
 
24
+ /** @type {Array<string | LH.IcuMessage>} */
25
+ const LighthouseRunWarnings = [];
26
+
27
+ // TODO(FR-COMPAT): support slow host CPU warning
28
+ // TODO(FR-COMPAT): support redirected URL warning
29
+
23
30
  return {
24
31
  // Meta artifacts.
25
32
  fetchTime: new Date().toJSON(),
26
33
  Timing: [],
27
- LighthouseRunWarnings: [],
34
+ LighthouseRunWarnings,
28
35
  settings: config.settings,
29
36
  // Environment artifacts that can always be computed.
37
+ HostFormFactor,
38
+ HostUserAgent,
30
39
  BenchmarkIndex,
31
40
  // Contextual artifacts whose collection changes based on gather mode.
32
41
  URL: {requestedUrl: '', finalUrl: ''},
33
- PageLoadError: null,
42
+ PageLoadError: null, // TODO(FR-COMPAT): support PageLoadError
34
43
  // Artifacts that have been replaced by regular gatherers in Fraggle Rock.
35
- HostFormFactor: 'mobile',
36
- HostUserAgent: '',
37
44
  Stacks: [],
38
45
  NetworkUserAgent: '',
39
- WebAppManifest: null,
40
- InstallabilityErrors: {errors: []},
46
+ WebAppManifest: null, // replaced by standard gatherer
47
+ InstallabilityErrors: {errors: []}, // replaced by standard gatherer
41
48
  traces: {},
42
49
  devtoolsLogs: {},
43
50
  };
44
51
  }
45
52
 
46
- /**
47
- * Deduplicates identical warnings.
48
- * @param {Array<string | LH.IcuMessage>} warnings
49
- * @return {Array<string | LH.IcuMessage>}
50
- */
51
- function deduplicateWarnings(warnings) {
52
- /** @type {Array<string | LH.IcuMessage>} */
53
- const unique = [];
54
-
55
- for (const warning of warnings) {
56
- if (unique.some(existing => isEqual(warning, existing))) continue;
57
- unique.push(warning);
58
- }
59
-
60
- return unique;
61
- }
62
-
63
- /**
64
- * @param {LH.FRBaseArtifacts} baseArtifacts
65
- * @param {Partial<LH.Artifacts>} gathererArtifacts
66
- * @return {LH.Artifacts}
67
- */
68
- function finalizeArtifacts(baseArtifacts, gathererArtifacts) {
69
- const warnings = baseArtifacts.LighthouseRunWarnings
70
- .concat(gathererArtifacts.LighthouseRunWarnings || [])
71
- .concat(getEnvironmentWarnings({settings: baseArtifacts.settings, baseArtifacts}));
72
-
73
- // Cast to remove the partial from gathererArtifacts.
74
- const artifacts = /** @type {LH.Artifacts} */ ({...baseArtifacts, ...gathererArtifacts});
75
-
76
- // Set the post-run meta artifacts.
77
- artifacts.Timing = log.getTimeEntries();
78
- artifacts.LighthouseRunWarnings = deduplicateWarnings(warnings);
79
-
80
- // Check that the runner remembered to mutate the special-case URL artifact.
81
- if (!artifacts.URL.requestedUrl) throw new Error('Runner did not set requestedUrl');
82
- if (!artifacts.URL.finalUrl) throw new Error('Runner did not set finalUrl');
83
-
84
- return artifacts;
85
- }
86
-
87
53
  module.exports = {
88
54
  getBaseArtifacts,
89
- finalizeArtifacts,
90
55
  };
@@ -19,7 +19,7 @@ const storage = require('../../gather/driver/storage.js');
19
19
  const emulation = require('../../lib/emulation.js');
20
20
  const {defaultNavigationConfig} = require('../../config/constants.js');
21
21
  const {initializeConfig} = require('../config/config.js');
22
- const {getBaseArtifacts, finalizeArtifacts} = require('./base-artifacts.js');
22
+ const {getBaseArtifacts} = require('./base-artifacts.js');
23
23
  const i18n = require('../../lib/i18n/i18n.js');
24
24
  const LighthouseError = require('../../lib/lh-error.js');
25
25
  const {getPageLoadError} = require('../../lib/navigation-error.js');
@@ -126,7 +126,7 @@ async function _collectNetworkRecords(navigationContext, phaseState) {
126
126
  * @param {PhaseState} phaseState
127
127
  * @param {UnPromise<ReturnType<typeof _setupNavigation>>} setupResult
128
128
  * @param {UnPromise<ReturnType<typeof _navigate>>} navigateResult
129
- * @return {Promise<{finalUrl: string, artifacts: Partial<LH.GathererArtifacts>, warnings: Array<LH.IcuMessage>, pageLoadError: LH.LighthouseError | undefined}>}
129
+ * @return {Promise<{artifacts: Partial<LH.GathererArtifacts>, warnings: Array<LH.IcuMessage>, pageLoadError: LH.LighthouseError | undefined}>}
130
130
  */
131
131
  async function _computeNavigationResult(
132
132
  navigationContext,
@@ -150,17 +150,12 @@ async function _computeNavigationResult(
150
150
  const localizedMessage = i18n.getFormatted(pageLoadError.friendlyMessage, locale);
151
151
  log.error('NavigationRunner', localizedMessage, navigationContext.requestedUrl);
152
152
 
153
- return {
154
- finalUrl,
155
- pageLoadError,
156
- artifacts: {},
157
- warnings: [...warnings, pageLoadError.friendlyMessage],
158
- };
153
+ return {artifacts: {}, warnings: [...warnings, pageLoadError.friendlyMessage], pageLoadError};
159
154
  } else {
160
155
  await collectPhaseArtifacts({phase: 'getArtifact', ...phaseState});
161
156
 
162
157
  const artifacts = await awaitArtifacts(phaseState.artifactState);
163
- return {finalUrl, artifacts, warnings, pageLoadError: undefined};
158
+ return {artifacts, warnings, pageLoadError: undefined};
164
159
  }
165
160
  }
166
161
 
@@ -199,8 +194,6 @@ async function _navigations({driver, config, requestedUrl, computedCache}) {
199
194
 
200
195
  /** @type {Partial<LH.FRArtifacts & LH.FRBaseArtifacts>} */
201
196
  const artifacts = {};
202
- /** @type {Array<LH.IcuMessage>} */
203
- const LighthouseRunWarnings = [];
204
197
 
205
198
  for (const navigation of config.navigations) {
206
199
  const navigationContext = {
@@ -212,20 +205,16 @@ async function _navigations({driver, config, requestedUrl, computedCache}) {
212
205
  };
213
206
 
214
207
  const navigationResult = await _navigation(navigationContext);
215
- if (navigation.loadFailureMode === 'fatal') {
216
- if (navigationResult.pageLoadError) {
217
- artifacts.PageLoadError = navigationResult.pageLoadError;
218
- break;
219
- }
220
-
221
- artifacts.URL = {requestedUrl, finalUrl: navigationResult.finalUrl};
208
+ if (navigationResult.pageLoadError && navigation.loadFailureMode === 'fatal') {
209
+ artifacts.PageLoadError = navigationResult.pageLoadError;
210
+ break;
222
211
  }
223
212
 
224
- LighthouseRunWarnings.push(...navigationResult.warnings);
213
+ // TODO(FR-COMPAT): merge RunWarnings between navigations
225
214
  Object.assign(artifacts, navigationResult.artifacts);
226
215
  }
227
216
 
228
- return {artifacts: {...artifacts, LighthouseRunWarnings}};
217
+ return {artifacts};
229
218
  }
230
219
 
231
220
  /**
@@ -254,7 +243,7 @@ async function navigation(options) {
254
243
  const {artifacts} = await _navigations({driver, config, requestedUrl, computedCache});
255
244
  await _cleanup({driver, config, requestedUrl});
256
245
 
257
- return finalizeArtifacts(baseArtifacts, artifacts);
246
+ return /** @type {LH.Artifacts} */ ({...baseArtifacts, ...artifacts}); // Cast to drop Partial<>
258
247
  },
259
248
  {
260
249
  url: requestedUrl,
@@ -8,7 +8,7 @@
8
8
  /**
9
9
  * @typedef CollectPhaseArtifactOptions
10
10
  * @property {import('./driver.js')} driver
11
- * @property {Array<LH.Config.AnyArtifactDefn>} artifactDefinitions
11
+ * @property {Array<LH.Config.ArtifactDefn>} artifactDefinitions
12
12
  * @property {ArtifactState} artifactState
13
13
  * @property {LH.Gatherer.FRGatherPhase} phase
14
14
  * @property {LH.Gatherer.GatherMode} gatherMode
@@ -99,7 +99,7 @@ async function collectPhaseArtifacts(options) {
99
99
  }
100
100
 
101
101
  /**
102
- * @param {LH.Config.AnyArtifactDefn} artifact
102
+ * @param {LH.Config.ArtifactDefn} artifact
103
103
  * @param {Record<string, LH.Gatherer.PhaseResult>} artifactsById
104
104
  * @return {Promise<Dependencies>}
105
105
  */
@@ -13,7 +13,7 @@ const {
13
13
  awaitArtifacts,
14
14
  } = require('./runner-helpers.js');
15
15
  const {initializeConfig} = require('../config/config.js');
16
- const {getBaseArtifacts, finalizeArtifacts} = require('./base-artifacts.js');
16
+ const {getBaseArtifacts} = require('./base-artifacts.js');
17
17
 
18
18
  /** @param {{page: import('puppeteer').Page, config?: LH.Config.Json}} options */
19
19
  async function snapshot(options) {
@@ -44,7 +44,7 @@ async function snapshot(options) {
44
44
  });
45
45
 
46
46
  const artifacts = await awaitArtifacts(artifactState);
47
- return finalizeArtifacts(baseArtifacts, artifacts);
47
+ return /** @type {LH.Artifacts} */ ({...baseArtifacts, ...artifacts}); // Cast to drop Partial<>
48
48
  },
49
49
  {
50
50
  url,
@@ -13,7 +13,7 @@ const {
13
13
  awaitArtifacts,
14
14
  } = require('./runner-helpers.js');
15
15
  const {initializeConfig} = require('../config/config.js');
16
- const {getBaseArtifacts, finalizeArtifacts} = require('./base-artifacts.js');
16
+ const {getBaseArtifacts} = require('./base-artifacts.js');
17
17
 
18
18
  /**
19
19
  * @param {{page: import('puppeteer').Page, config?: LH.Config.Json}} options
@@ -56,7 +56,7 @@ async function startTimespan(options) {
56
56
  await collectPhaseArtifacts({phase: 'getArtifact', ...phaseOptions});
57
57
 
58
58
  const artifacts = await awaitArtifacts(artifactState);
59
- return finalizeArtifacts(baseArtifacts, artifacts);
59
+ return /** @type {LH.Artifacts} */ ({...baseArtifacts, ...artifacts}); // Cast to drop Partial<>
60
60
  },
61
61
  {
62
62
  url: finalUrl,
@@ -127,9 +127,6 @@ async function prepareNetworkForNavigation(session, settings, navigation) {
127
127
  * @param {LH.Config.Settings} settings
128
128
  */
129
129
  async function prepareTargetForNavigationMode(driver, settings) {
130
- // Enable network domain here so future calls to `emulate()` don't clear cache (#12631)
131
- await driver.defaultSession.sendCommand('Network.enable');
132
-
133
130
  // Emulate our target device screen and user agent.
134
131
  await emulation.emulate(driver.defaultSession, settings);
135
132
 
@@ -146,6 +146,7 @@ class Fetcher {
146
146
  * @return {Promise<{stream: LH.Crdp.IO.StreamHandle|null, status: number|null}>}
147
147
  */
148
148
  async _loadNetworkResource(url) {
149
+ await this.session.sendCommand('Network.enable');
149
150
  const frameTreeResponse = await this.session.sendCommand('Page.getFrameTree');
150
151
  const networkResponse = await this.session.sendCommand('Network.loadNetworkResource', {
151
152
  frameId: frameTreeResponse.frameTree.frame.id,
@@ -155,6 +156,7 @@ class Fetcher {
155
156
  includeCredentials: true,
156
157
  },
157
158
  });
159
+ await this.session.sendCommand('Network.disable');
158
160
 
159
161
  return {
160
162
  stream: networkResponse.resource.success ? (networkResponse.resource.stream || null) : null,
@@ -20,7 +20,6 @@ const WebAppManifest = require('./gatherers/web-app-manifest.js');
20
20
  const InstallabilityErrors = require('./gatherers/installability-errors.js');
21
21
  const NetworkUserAgent = require('./gatherers/network-user-agent.js');
22
22
  const Stacks = require('./gatherers/stacks.js');
23
- const {finalizeArtifacts} = require('../fraggle-rock/gather/base-artifacts.js');
24
23
 
25
24
  /** @typedef {import('../gather/driver.js')} Driver */
26
25
  /** @typedef {import('../lib/arbitrary-equality-map.js')} ArbitraryEqualityMap */
@@ -447,6 +446,18 @@ class GatherRunner {
447
446
  log.timeEnd(status);
448
447
  }
449
448
 
449
+ /**
450
+ * Finalize baseArtifacts after gathering is fully complete.
451
+ * @param {LH.BaseArtifacts} baseArtifacts
452
+ */
453
+ static finalizeBaseArtifacts(baseArtifacts) {
454
+ // Take only unique LighthouseRunWarnings.
455
+ baseArtifacts.LighthouseRunWarnings = Array.from(new Set(baseArtifacts.LighthouseRunWarnings));
456
+
457
+ // Take the timing entries we've gathered so far.
458
+ baseArtifacts.Timing = log.getTimeEntries();
459
+ }
460
+
450
461
  /**
451
462
  * @param {Array<LH.Config.Pass>} passConfigs
452
463
  * @param {{driver: Driver, requestedUrl: string, settings: LH.Config.Settings, computedCache: Map<string, ArbitraryEqualityMap>}} options
@@ -504,7 +515,8 @@ class GatherRunner {
504
515
  }
505
516
 
506
517
  await GatherRunner.disposeDriver(driver, options);
507
- return finalizeArtifacts(baseArtifacts, artifacts);
518
+ GatherRunner.finalizeBaseArtifacts(baseArtifacts);
519
+ return /** @type {LH.Artifacts} */ ({...baseArtifacts, ...artifacts}); // Cast to drop Partial<>.
508
520
  } catch (err) {
509
521
  // Clean up on error. Don't await so that the root error, not a disposal error, is shown.
510
522
  GatherRunner.disposeDriver(driver, options);
@@ -12,8 +12,9 @@
12
12
  const log = require('lighthouse-logger');
13
13
  const FRGatherer = require('../../fraggle-rock/gather/base-gatherer.js');
14
14
  const pageFunctions = require('../../lib/page-functions.js');
15
- const URL = require('../../lib/url-shim.js');
15
+ const DevtoolsLog = require('./devtools-log.js');
16
16
  const FontSize = require('./seo/font-size.js');
17
+ const NetworkRecords = require('../../computed/network-records.js');
17
18
 
18
19
  /* global window, getElementsInDocument, Image, getNodeDetails, ShadowRoot */
19
20
 
@@ -190,7 +191,7 @@ function findSizeDeclaration(rule, property) {
190
191
  *
191
192
  * @param {Array<LH.Crdp.CSS.RuleMatch>|undefined} matchedCSSRules
192
193
  * @param {string} property
193
- * @return {string | undefined}
194
+ * @returns {string | undefined}
194
195
  */
195
196
  function findMostSpecificCSSRule(matchedCSSRules, property) {
196
197
  /** @param {LH.Crdp.CSS.CSSStyle} declaration */
@@ -204,7 +205,7 @@ function findMostSpecificCSSRule(matchedCSSRules, property) {
204
205
  /**
205
206
  * @param {LH.Crdp.CSS.GetMatchedStylesForNodeResponse} matched CSS rules}
206
207
  * @param {string} property
207
- * @return {string | null}
208
+ * @returns {string | null}
208
209
  */
209
210
  function getEffectiveSizingRule({attributesStyle, inlineStyle, matchedCSSRules}, property) {
210
211
  // CSS sizing can't be inherited.
@@ -223,21 +224,11 @@ function getEffectiveSizingRule({attributesStyle, inlineStyle, matchedCSSRules},
223
224
  return null;
224
225
  }
225
226
 
226
- /**
227
- * @param {LH.Artifacts.ImageElement} element
228
- * @return {number}
229
- */
230
- function getPixelArea(element) {
231
- if (element.naturalDimensions) {
232
- return element.naturalDimensions.height * element.naturalDimensions.width;
233
- }
234
- return element.displayedHeight * element.displayedWidth;
235
- }
236
-
237
227
  class ImageElements extends FRGatherer {
238
- /** @type {LH.Gatherer.GathererMeta} */
228
+ /** @type {LH.Gatherer.GathererMeta<'DevtoolsLog'>} */
239
229
  meta = {
240
- supportedModes: ['snapshot', 'timespan', 'navigation'],
230
+ supportedModes: ['navigation'],
231
+ dependencies: {DevtoolsLog: DevtoolsLog.symbol},
241
232
  };
242
233
 
243
234
  constructor() {
@@ -298,19 +289,40 @@ class ImageElements extends FRGatherer {
298
289
  }
299
290
  }
300
291
 
292
+ /**
293
+ * @param {LH.Artifacts.NetworkRequest[]} networkRecords
294
+ */
295
+ indexNetworkRecords(networkRecords) {
296
+ return networkRecords.reduce((map, record) => {
297
+ // An image response in newer formats is sometimes incorrectly marked as "application/octet-stream",
298
+ // so respect the extension too.
299
+ const isImage = /^image/.test(record.mimeType) || /\.(avif|webp)$/i.test(record.url);
300
+ // The network record is only valid for size information if it finished with a successful status
301
+ // code that indicates a complete image response.
302
+ if (isImage && record.finished && record.statusCode === 200) {
303
+ map[record.url] = record;
304
+ }
305
+
306
+ return map;
307
+ }, /** @type {Record<string, LH.Artifacts.NetworkRequest>} */ ({}));
308
+ }
309
+
301
310
  /**
302
311
  *
303
312
  * @param {LH.Gatherer.FRTransitionalDriver} driver
304
313
  * @param {LH.Artifacts.ImageElement[]} elements
314
+ * @param {Record<string, LH.Artifacts.NetworkRequest>} indexedNetworkRecords
305
315
  */
306
- async collectExtraDetails(driver, elements) {
316
+ async collectExtraDetails(driver, elements, indexedNetworkRecords) {
307
317
  // Don't do more than 5s of this expensive devtools protocol work. See #11289
308
318
  let reachedGatheringBudget = false;
309
319
  setTimeout(_ => (reachedGatheringBudget = true), 5000);
310
320
  let skippedCount = 0;
311
321
 
312
322
  for (const element of elements) {
313
- element.mimeType = URL.guessMimeType(element.src);
323
+ // Pull some of our information directly off the network record.
324
+ const networkRecord = indexedNetworkRecords[element.src];
325
+ element.mimeType = networkRecord && networkRecord.mimeType;
314
326
 
315
327
  if (reachedGatheringBudget) {
316
328
  skippedCount++;
@@ -323,7 +335,8 @@ class ImageElements extends FRGatherer {
323
335
  }
324
336
  // Images within `picture` behave strangely and natural size information isn't accurate,
325
337
  // CSS images have no natural size information at all. Try to get the actual size if we can.
326
- if (element.isPicture || element.isCss || element.srcset) {
338
+ // Additional fetch is expensive; don't bother if we don't have a networkRecord for the image.
339
+ if ((element.isPicture || element.isCss || element.srcset) && networkRecord) {
327
340
  await this.fetchElementWithSizeInformation(driver, element);
328
341
  }
329
342
  }
@@ -335,11 +348,13 @@ class ImageElements extends FRGatherer {
335
348
 
336
349
  /**
337
350
  * @param {LH.Gatherer.FRTransitionalContext} context
351
+ * @param {LH.Artifacts.NetworkRequest[]} networkRecords
338
352
  * @return {Promise<LH.Artifacts['ImageElements']>}
339
353
  */
340
- async getArtifact(context) {
354
+ async _getArtifact(context, networkRecords) {
341
355
  const session = context.driver.defaultSession;
342
356
  const executionContext = context.driver.executionContext;
357
+ const indexedNetworkRecords = this.indexNetworkRecords(networkRecords);
343
358
 
344
359
  const elements = await executionContext.evaluate(collectImageElementInfo, {
345
360
  args: [],
@@ -360,11 +375,14 @@ class ImageElements extends FRGatherer {
360
375
  session.sendCommand('DOM.getDocument', {depth: -1, pierce: true}),
361
376
  ]);
362
377
 
363
- // Spend our extra details budget on highest impact images.
364
- // Our best approximation of impact without network records is to use pixel area.
365
- elements.sort((a, b) => getPixelArea(b) - getPixelArea(a));
378
+ // Sort (in-place) as largest images descending.
379
+ elements.sort((a, b) => {
380
+ const aRecord = indexedNetworkRecords[a.src] || {};
381
+ const bRecord = indexedNetworkRecords[b.src] || {};
382
+ return bRecord.resourceSize - aRecord.resourceSize;
383
+ });
366
384
 
367
- await this.collectExtraDetails(context.driver, elements);
385
+ await this.collectExtraDetails(context.driver, elements, indexedNetworkRecords);
368
386
 
369
387
  await Promise.all([
370
388
  session.sendCommand('DOM.disable'),
@@ -373,6 +391,25 @@ class ImageElements extends FRGatherer {
373
391
 
374
392
  return elements;
375
393
  }
394
+
395
+ /**
396
+ * @param {LH.Gatherer.FRTransitionalContext<'DevtoolsLog'>} context
397
+ * @return {Promise<LH.Artifacts['ImageElements']>}
398
+ */
399
+ async getArtifact(context) {
400
+ const devtoolsLog = context.dependencies.DevtoolsLog;
401
+ const networkRecords = await NetworkRecords.request(devtoolsLog, context);
402
+ return this._getArtifact(context, networkRecords);
403
+ }
404
+
405
+ /**
406
+ * @param {LH.Gatherer.PassContext} passContext
407
+ * @param {LH.Gatherer.LoadData} loadData
408
+ * @return {Promise<LH.Artifacts['ImageElements']>}
409
+ */
410
+ async afterPass(passContext, loadData) {
411
+ return this._getArtifact({...passContext, dependencies: {}}, loadData.networkRecords);
412
+ }
376
413
  }
377
414
 
378
415
  module.exports = ImageElements;
@@ -112,7 +112,7 @@ class InspectorIssues extends FRGatherer {
112
112
 
113
113
  /**
114
114
  * @param {LH.Gatherer.FRTransitionalContext<'DevtoolsLog'>} context
115
- * @return {Promise<LH.Artifacts['InspectorIssues']>}
115
+ * @returns {Promise<LH.Artifacts['InspectorIssues']>}
116
116
  */
117
117
  async getArtifact(context) {
118
118
  const devtoolsLog = context.dependencies.DevtoolsLog;
@@ -123,7 +123,7 @@ class InspectorIssues extends FRGatherer {
123
123
  /**
124
124
  * @param {LH.Gatherer.PassContext} passContext
125
125
  * @param {LH.Gatherer.LoadData} loadData
126
- * @return {Promise<LH.Artifacts['InspectorIssues']>}
126
+ * @returns {Promise<LH.Artifacts['InspectorIssues']>}
127
127
  */
128
128
  async afterPass(passContext, loadData) {
129
129
  await this.stopInstrumentation({...passContext, dependencies: {}});
@@ -5,14 +5,10 @@
5
5
  */
6
6
  'use strict';
7
7
 
8
- const FRGatherer = require('../../fraggle-rock/gather/base-gatherer.js');
9
- const NetworkRecords = require('../../computed/network-records.js');
8
+ const Gatherer = require('./gatherer.js');
10
9
  const NetworkAnalyzer = require('../../lib/dependency-graph/simulator/network-analyzer.js');
11
10
  const NetworkRequest = require('../../lib/network-request.js');
12
11
  const pageFunctions = require('../../lib/page-functions.js');
13
- const {fetchResponseBodyFromCache} = require('../driver/network.js');
14
- const DevtoolsLog = require('./devtools-log.js');
15
- const HostFormFactor = require('./host-form-factor.js');
16
12
 
17
13
  /* global getNodeDetails */
18
14
 
@@ -66,25 +62,17 @@ async function runInSeriesOrParallel(values, promiseMapper, runInSeries) {
66
62
  /**
67
63
  * @fileoverview Gets JavaScript file contents.
68
64
  */
69
- class ScriptElements extends FRGatherer {
70
- /** @type {LH.Gatherer.GathererMeta<'DevtoolsLog'|'HostFormFactor'>} */
71
- meta = {
72
- supportedModes: ['timespan', 'navigation'],
73
- dependencies: {DevtoolsLog: DevtoolsLog.symbol, HostFormFactor: HostFormFactor.symbol},
74
- }
75
-
65
+ class ScriptElements extends Gatherer {
76
66
  /**
77
- * @param {LH.Gatherer.FRTransitionalContext} context
78
- * @param {LH.Artifacts.NetworkRequest[]} networkRecords
79
- * @param {LH.Artifacts['HostFormFactor']} formFactor
67
+ * @param {LH.Gatherer.PassContext} passContext
68
+ * @param {LH.Gatherer.LoadData} loadData
80
69
  * @return {Promise<LH.Artifacts['ScriptElements']>}
81
70
  */
82
- async _getArtifact(context, networkRecords, formFactor) {
83
- const session = context.driver.defaultSession;
84
- const executionContext = context.driver.executionContext;
85
- const mainResource = NetworkAnalyzer.findOptionalMainDocument(networkRecords, context.url);
71
+ async afterPass(passContext, loadData) {
72
+ const driver = passContext.driver;
73
+ const mainResource = NetworkAnalyzer.findMainDocument(loadData.networkRecords, passContext.url);
86
74
 
87
- const scripts = await executionContext.evaluate(collectAllScriptElements, {
75
+ const scripts = await driver.executionContext.evaluate(collectAllScriptElements, {
88
76
  args: [],
89
77
  useIsolation: true,
90
78
  deps: [
@@ -94,10 +82,10 @@ class ScriptElements extends FRGatherer {
94
82
  });
95
83
 
96
84
  for (const script of scripts) {
97
- if (mainResource && script.content) script.requestId = mainResource.requestId;
85
+ if (script.content) script.requestId = mainResource.requestId;
98
86
  }
99
87
 
100
- const scriptRecords = networkRecords
88
+ const scriptRecords = loadData.networkRecords
101
89
  // Ignore records from OOPIFs
102
90
  .filter(record => !record.sessionId)
103
91
  // Only get the content of script requests
@@ -107,9 +95,8 @@ class ScriptElements extends FRGatherer {
107
95
  // record at a time.
108
96
  const scriptRecordContents = await runInSeriesOrParallel(
109
97
  scriptRecords,
110
- record => fetchResponseBodyFromCache(session, record.requestId).catch(() => ''),
111
- formFactor === 'mobile' /* runInSeries */
112
- );
98
+ record => driver.getRequestContent(record.requestId).catch(() => ''),
99
+ passContext.baseArtifacts.HostFormFactor === 'mobile' /* runInSeries*/ );
113
100
 
114
101
  for (let i = 0; i < scriptRecords.length; i++) {
115
102
  const record = scriptRecords[i];
@@ -136,26 +123,6 @@ class ScriptElements extends FRGatherer {
136
123
  }
137
124
  return scripts;
138
125
  }
139
-
140
- /**
141
- * @param {LH.Gatherer.FRTransitionalContext<'DevtoolsLog'|'HostFormFactor'>} context
142
- */
143
- async getArtifact(context) {
144
- const devtoolsLog = context.dependencies.DevtoolsLog;
145
- const formFactor = context.dependencies.HostFormFactor;
146
- const networkRecords = await NetworkRecords.request(devtoolsLog, context);
147
- return this._getArtifact(context, networkRecords, formFactor);
148
- }
149
-
150
- /**
151
- * @param {LH.Gatherer.PassContext} passContext
152
- * @param {LH.Gatherer.LoadData} loadData
153
- */
154
- async afterPass(passContext, loadData) {
155
- const networkRecords = loadData.networkRecords;
156
- const formFactor = passContext.baseArtifacts.HostFormFactor;
157
- return this._getArtifact({...passContext, dependencies: {}}, networkRecords, formFactor);
158
- }
159
126
  }
160
127
 
161
128
  module.exports = ScriptElements;
@@ -68,7 +68,7 @@ function computeSelectorSpecificity(selector) {
68
68
  *
69
69
  * @param {Array<LH.Crdp.CSS.RuleMatch>} matchedCSSRules
70
70
  * @param {function(LH.Crdp.CSS.CSSStyle):boolean|string|undefined} isDeclarationOfInterest
71
- * @return {NodeFontData['cssRule']|undefined}
71
+ * @returns {NodeFontData['cssRule']|undefined}
72
72
  */
73
73
  function findMostSpecificMatchedCSSRule(matchedCSSRules = [], isDeclarationOfInterest) {
74
74
  let maxSpecificity = -Infinity;
@@ -105,7 +105,7 @@ function findMostSpecificMatchedCSSRule(matchedCSSRules = [], isDeclarationOfInt
105
105
  * Finds the most specific directly matched CSS font-size rule from the list.
106
106
  *
107
107
  * @param {Array<LH.Crdp.CSS.InheritedStyleEntry>} [inheritedEntries]
108
- * @return {NodeFontData['cssRule']|undefined}
108
+ * @returns {NodeFontData['cssRule']|undefined}
109
109
  */
110
110
  function findInheritedCSSRule(inheritedEntries = []) {
111
111
  // The inherited array contains the array of matched rules for all parents in ascending tree order.
@@ -126,7 +126,7 @@ function findInheritedCSSRule(inheritedEntries = []) {
126
126
  *
127
127
  * @see https://cs.chromium.org/chromium/src/third_party/blink/renderer/devtools/front_end/sdk/CSSMatchedStyles.js?q=CSSMatchedStyles+f:devtools+-f:out&sq=package:chromium&dr=C&l=59-134
128
128
  * @param {LH.Crdp.CSS.GetMatchedStylesForNodeResponse} matched CSS rules
129
- * @return {NodeFontData['cssRule']|undefined}
129
+ * @returns {NodeFontData['cssRule']|undefined}
130
130
  */
131
131
  function getEffectiveFontRule({attributesStyle, inlineStyle, matchedCSSRules, inherited}) {
132
132
  // Inline styles have highest priority
@@ -148,7 +148,7 @@ function getEffectiveFontRule({attributesStyle, inlineStyle, matchedCSSRules, in
148
148
 
149
149
  /**
150
150
  * @param {string} text
151
- * @return {number}
151
+ * @returns {number}
152
152
  */
153
153
  function getTextLength(text) {
154
154
  // Array.from to count symbols not unicode code points. See: #6973
@@ -158,7 +158,7 @@ function getTextLength(text) {
158
158
  /**
159
159
  * @param {LH.Gatherer.FRProtocolSession} session
160
160
  * @param {number} nodeId text node
161
- * @return {Promise<NodeFontData['cssRule']|undefined>}
161
+ * @returns {Promise<NodeFontData['cssRule']|undefined>}
162
162
  */
163
163
  async function fetchSourceRule(session, nodeId) {
164
164
  const matchedRules = await session.sendCommand('CSS.getMatchedStylesForNode', {