chrome-devtools-frontend 1.0.1380117 → 1.0.1386602

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 (595) hide show
  1. package/.stylelintrc.json +2 -1
  2. package/config/gni/devtools_grd_files.gni +25 -4
  3. package/config/gni/devtools_image_files.gni +2 -0
  4. package/docs/README.md +4 -0
  5. package/docs/contributing/issues.md +13 -10
  6. package/docs/get_the_code.md +4 -1
  7. package/docs/policy/README.md +6 -0
  8. package/docs/policy/slow-close.md +52 -0
  9. package/docs/styleguide/ux/README.md +1 -0
  10. package/docs/styleguide/ux/numbers.md +106 -0
  11. package/front_end/Images/src/cookie_off.svg +3 -0
  12. package/front_end/Images/src/domain.svg +3 -0
  13. package/front_end/core/common/Color.ts +3 -3
  14. package/front_end/core/common/SettingRegistration.ts +7 -0
  15. package/front_end/core/host/AidaClient.ts +3 -3
  16. package/front_end/core/host/InspectorFrontendHostAPI.ts +0 -1
  17. package/front_end/core/host/UserMetrics.ts +0 -8
  18. package/front_end/core/i18n/locales/af.json +1031 -887
  19. package/front_end/core/i18n/locales/am.json +1036 -892
  20. package/front_end/core/i18n/locales/ar.json +1039 -895
  21. package/front_end/core/i18n/locales/as.json +1032 -888
  22. package/front_end/core/i18n/locales/az.json +1034 -890
  23. package/front_end/core/i18n/locales/be.json +1031 -887
  24. package/front_end/core/i18n/locales/bg.json +1031 -887
  25. package/front_end/core/i18n/locales/bn.json +1033 -889
  26. package/front_end/core/i18n/locales/bs.json +1036 -892
  27. package/front_end/core/i18n/locales/ca.json +1031 -887
  28. package/front_end/core/i18n/locales/cs.json +1030 -886
  29. package/front_end/core/i18n/locales/cy.json +1032 -888
  30. package/front_end/core/i18n/locales/da.json +1031 -887
  31. package/front_end/core/i18n/locales/de.json +1033 -889
  32. package/front_end/core/i18n/locales/el.json +1031 -887
  33. package/front_end/core/i18n/locales/en-GB.json +1033 -889
  34. package/front_end/core/i18n/locales/es-419.json +1029 -885
  35. package/front_end/core/i18n/locales/es.json +1032 -888
  36. package/front_end/core/i18n/locales/et.json +1033 -889
  37. package/front_end/core/i18n/locales/eu.json +1031 -887
  38. package/front_end/core/i18n/locales/fa.json +1035 -891
  39. package/front_end/core/i18n/locales/fi.json +1035 -891
  40. package/front_end/core/i18n/locales/fil.json +1034 -890
  41. package/front_end/core/i18n/locales/fr-CA.json +1031 -887
  42. package/front_end/core/i18n/locales/fr.json +1049 -905
  43. package/front_end/core/i18n/locales/gl.json +1032 -888
  44. package/front_end/core/i18n/locales/gu.json +1035 -891
  45. package/front_end/core/i18n/locales/he.json +1031 -887
  46. package/front_end/core/i18n/locales/hi.json +1034 -890
  47. package/front_end/core/i18n/locales/hr.json +1031 -887
  48. package/front_end/core/i18n/locales/hu.json +1033 -889
  49. package/front_end/core/i18n/locales/hy.json +1046 -902
  50. package/front_end/core/i18n/locales/id.json +1023 -879
  51. package/front_end/core/i18n/locales/is.json +1032 -888
  52. package/front_end/core/i18n/locales/it.json +1031 -887
  53. package/front_end/core/i18n/locales/ja.json +1042 -898
  54. package/front_end/core/i18n/locales/ka.json +1034 -890
  55. package/front_end/core/i18n/locales/kk.json +1035 -891
  56. package/front_end/core/i18n/locales/km.json +1035 -891
  57. package/front_end/core/i18n/locales/kn.json +1036 -892
  58. package/front_end/core/i18n/locales/ko.json +1031 -887
  59. package/front_end/core/i18n/locales/ky.json +1032 -888
  60. package/front_end/core/i18n/locales/lo.json +1030 -886
  61. package/front_end/core/i18n/locales/lt.json +1032 -888
  62. package/front_end/core/i18n/locales/lv.json +1032 -888
  63. package/front_end/core/i18n/locales/mk.json +1032 -888
  64. package/front_end/core/i18n/locales/ml.json +1033 -889
  65. package/front_end/core/i18n/locales/mn.json +1034 -890
  66. package/front_end/core/i18n/locales/mr.json +1035 -891
  67. package/front_end/core/i18n/locales/ms.json +1033 -889
  68. package/front_end/core/i18n/locales/my.json +1033 -889
  69. package/front_end/core/i18n/locales/ne.json +1036 -892
  70. package/front_end/core/i18n/locales/nl.json +1033 -889
  71. package/front_end/core/i18n/locales/no.json +1036 -892
  72. package/front_end/core/i18n/locales/or.json +1043 -899
  73. package/front_end/core/i18n/locales/pa.json +1030 -886
  74. package/front_end/core/i18n/locales/pl.json +1032 -888
  75. package/front_end/core/i18n/locales/pt-PT.json +1033 -889
  76. package/front_end/core/i18n/locales/pt.json +1033 -889
  77. package/front_end/core/i18n/locales/ro.json +1029 -885
  78. package/front_end/core/i18n/locales/ru.json +1026 -882
  79. package/front_end/core/i18n/locales/si.json +1031 -887
  80. package/front_end/core/i18n/locales/sk.json +1033 -889
  81. package/front_end/core/i18n/locales/sl.json +1031 -887
  82. package/front_end/core/i18n/locales/sq.json +1061 -917
  83. package/front_end/core/i18n/locales/sr-Latn.json +1033 -889
  84. package/front_end/core/i18n/locales/sr.json +1033 -889
  85. package/front_end/core/i18n/locales/sv.json +1031 -887
  86. package/front_end/core/i18n/locales/sw.json +1033 -889
  87. package/front_end/core/i18n/locales/ta.json +1058 -914
  88. package/front_end/core/i18n/locales/te.json +1037 -893
  89. package/front_end/core/i18n/locales/th.json +1032 -888
  90. package/front_end/core/i18n/locales/tr.json +1031 -887
  91. package/front_end/core/i18n/locales/uk.json +1030 -886
  92. package/front_end/core/i18n/locales/ur.json +1031 -887
  93. package/front_end/core/i18n/locales/uz.json +1023 -879
  94. package/front_end/core/i18n/locales/vi.json +1032 -888
  95. package/front_end/core/i18n/locales/zh-HK.json +1032 -888
  96. package/front_end/core/i18n/locales/zh-TW.json +1032 -888
  97. package/front_end/core/i18n/locales/zh.json +1033 -889
  98. package/front_end/core/i18n/locales/zu.json +1032 -888
  99. package/front_end/core/root/Runtime.ts +0 -1
  100. package/front_end/core/sdk/NetworkManager.test.ts +50 -0
  101. package/front_end/core/sdk/NetworkManager.ts +6 -4
  102. package/front_end/core/sdk/SourceMap.test.ts +5 -5
  103. package/front_end/core/sdk/SourceMapScopeChainEntry.test.ts +7 -2
  104. package/front_end/core/sdk/SourceMapScopeChainEntry.ts +2 -2
  105. package/front_end/core/sdk/SourceMapScopes.test.ts +112 -45
  106. package/front_end/core/sdk/SourceMapScopes.ts +39 -14
  107. package/front_end/core/sdk/SourceMapScopesInfo.test.ts +51 -50
  108. package/front_end/core/sdk/SourceMapScopesInfo.ts +1 -1
  109. package/front_end/core/sdk/sdk-meta.ts +27 -0
  110. package/front_end/devtools_compatibility.js +0 -1
  111. package/front_end/entrypoints/devtools_app/devtools_app.ts +1 -0
  112. package/front_end/entrypoints/inspector_main/renderingOptions.css +1 -1
  113. package/front_end/entrypoints/main/ExecutionContextSelector.test.ts +13 -3
  114. package/front_end/entrypoints/main/ExecutionContextSelector.ts +23 -1
  115. package/front_end/entrypoints/main/MainImpl.ts +0 -5
  116. package/front_end/generated/Deprecation.ts +0 -15
  117. package/front_end/generated/InspectorBackendCommands.js +1 -1
  118. package/front_end/generated/SupportedCSSProperties.js +0 -40
  119. package/front_end/generated/protocol.ts +1 -0
  120. package/front_end/models/bindings/IgnoreListManager.ts +25 -2
  121. package/front_end/models/crux-manager/CrUXManager.test.ts +25 -6
  122. package/front_end/models/crux-manager/CrUXManager.ts +23 -4
  123. package/front_end/models/extensions/ExtensionServer.test.ts +14 -0
  124. package/front_end/models/extensions/ExtensionServer.ts +28 -15
  125. package/front_end/models/issues_manager/CookieIssue.ts +79 -2
  126. package/front_end/models/issues_manager/IssuesManager.ts +1 -1
  127. package/front_end/models/issues_manager/descriptions/cookieExcludePortMismatch.md +8 -0
  128. package/front_end/models/issues_manager/descriptions/cookieExcludeSchemeMismatch.md +7 -0
  129. package/front_end/models/javascript_metadata/NativeFunctions.js +14 -4
  130. package/front_end/models/persistence/EditFileSystemView.ts +2 -2
  131. package/front_end/models/persistence/editFileSystemView.css +6 -3
  132. package/front_end/models/persistence/workspaceSettingsTab.css +2 -2
  133. package/front_end/models/trace/extras/Metadata.test.ts +35 -2
  134. package/front_end/models/trace/extras/Metadata.ts +24 -5
  135. package/front_end/models/trace/extras/TraceTree.ts +28 -18
  136. package/front_end/models/trace/extras/URLForEntry.ts +6 -5
  137. package/front_end/models/trace/handlers/ImagePaintingHandler.ts +12 -0
  138. package/front_end/models/trace/helpers/Timing.ts +8 -0
  139. package/front_end/models/trace/insights/CLSCulprits.ts +11 -3
  140. package/front_end/models/trace/insights/DocumentLatency.ts +16 -3
  141. package/front_end/models/trace/insights/FontDisplay.ts +10 -3
  142. package/front_end/models/trace/insights/ImageDelivery.test.ts +98 -0
  143. package/front_end/models/trace/insights/ImageDelivery.ts +183 -0
  144. package/front_end/models/trace/insights/InteractionToNextPaint.ts +9 -3
  145. package/front_end/models/trace/insights/LCPDiscovery.ts +24 -3
  146. package/front_end/models/trace/insights/LCPPhases.ts +25 -3
  147. package/front_end/models/trace/insights/Models.ts +1 -0
  148. package/front_end/models/trace/insights/RenderBlocking.ts +10 -2
  149. package/front_end/models/trace/insights/SlowCSSSelector.ts +10 -3
  150. package/front_end/models/trace/insights/ThirdParties.ts +11 -3
  151. package/front_end/models/trace/insights/Viewport.ts +16 -3
  152. package/front_end/models/trace/insights/types.ts +13 -2
  153. package/front_end/models/trace/types/File.ts +7 -0
  154. package/front_end/models/trace/types/TraceEvents.ts +9 -2
  155. package/front_end/panels/animation/AnimationTimeline.ts +2 -4
  156. package/front_end/panels/application/ApplicationPanelSidebar.test.ts +0 -5
  157. package/front_end/panels/application/ApplicationPanelSidebar.ts +15 -21
  158. package/front_end/panels/application/IndexedDBViews.ts +4 -1
  159. package/front_end/panels/application/ServiceWorkerCacheViews.ts +4 -1
  160. package/front_end/panels/application/StorageView.test.ts +1 -1
  161. package/front_end/panels/application/resourcesSidebar.css +1 -1
  162. package/front_end/panels/browser_debugger/CategorizedBreakpointsSidebarPane.ts +1 -1
  163. package/front_end/panels/browser_debugger/DOMBreakpointsSidebarPane.ts +1 -1
  164. package/front_end/panels/browser_debugger/XHRBreakpointsSidebarPane.ts +1 -1
  165. package/front_end/panels/browser_debugger/categorizedBreakpointsSidebarPane.css +1 -1
  166. package/front_end/panels/browser_debugger/xhrBreakpointsSidebarPane.css +1 -1
  167. package/front_end/panels/console/ConsoleViewMessage.test.ts +25 -0
  168. package/front_end/panels/console/ConsoleViewMessage.ts +23 -0
  169. package/front_end/panels/coverage/CoverageListView.ts +1 -1
  170. package/front_end/panels/developer_resources/DeveloperResourcesListView.ts +1 -1
  171. package/front_end/panels/elements/ClassesPaneWidget.ts +1 -1
  172. package/front_end/panels/elements/ElementStatePaneWidget.test.ts +3 -2
  173. package/front_end/panels/elements/ElementStatePaneWidget.ts +7 -2
  174. package/front_end/panels/elements/ElementsSidebarPane.ts +3 -3
  175. package/front_end/panels/elements/ElementsTreeElement.ts +1 -0
  176. package/front_end/panels/elements/LayersWidget.ts +1 -1
  177. package/front_end/panels/elements/PropertyMatchers.test.ts +7 -0
  178. package/front_end/panels/elements/PropertyMatchers.ts +3 -0
  179. package/front_end/panels/elements/classesPaneWidget.css +1 -1
  180. package/front_end/panels/emulation/DeviceModeView.ts +1 -1
  181. package/front_end/panels/emulation/DeviceModeWrapper.ts +1 -1
  182. package/front_end/panels/emulation/InspectedPagePlaceholder.ts +1 -1
  183. package/front_end/panels/freestyler/AiAgent.test.ts +319 -50
  184. package/front_end/panels/freestyler/AiAgent.ts +193 -141
  185. package/front_end/panels/freestyler/AiHistoryStorage.test.ts +159 -0
  186. package/front_end/panels/freestyler/AiHistoryStorage.ts +73 -0
  187. package/front_end/panels/freestyler/DrJonesFileAgent.test.ts +14 -15
  188. package/front_end/panels/freestyler/DrJonesFileAgent.ts +3 -14
  189. package/front_end/panels/freestyler/DrJonesNetworkAgent.test.ts +14 -13
  190. package/front_end/panels/freestyler/DrJonesNetworkAgent.ts +3 -3
  191. package/front_end/panels/freestyler/DrJonesPerformanceAgent.test.ts +38 -36
  192. package/front_end/panels/freestyler/DrJonesPerformanceAgent.ts +3 -14
  193. package/front_end/panels/freestyler/FreestylerAgent.test.ts +195 -14
  194. package/front_end/panels/freestyler/FreestylerAgent.ts +13 -18
  195. package/front_end/panels/freestyler/FreestylerPanel.test.ts +71 -0
  196. package/front_end/panels/freestyler/FreestylerPanel.ts +99 -74
  197. package/front_end/panels/freestyler/components/FreestylerChatUi.ts +128 -29
  198. package/front_end/panels/freestyler/components/UserActionRow.ts +1 -0
  199. package/front_end/panels/freestyler/components/freestylerChatUi.css +21 -1
  200. package/front_end/panels/freestyler/components/userActionRow.css +2 -1
  201. package/front_end/panels/freestyler/freestyler.ts +1 -0
  202. package/front_end/panels/issues/IssueAggregator.test.ts +50 -0
  203. package/front_end/panels/issues/IssueAggregator.ts +10 -10
  204. package/front_end/panels/issues/issuesTree.css +1 -1
  205. package/front_end/panels/layer_viewer/LayerDetailsView.ts +1 -1
  206. package/front_end/panels/layer_viewer/Layers3DView.ts +1 -1
  207. package/front_end/panels/layer_viewer/PaintProfilerView.ts +1 -1
  208. package/front_end/panels/layers/LayersPanel.ts +1 -1
  209. package/front_end/panels/lighthouse/lighthouseStartView.css +1 -1
  210. package/front_end/panels/media/TickingFlameChart.ts +1 -1
  211. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +1 -1
  212. package/front_end/panels/network/BlockedURLsPane.ts +1 -1
  213. package/front_end/panels/network/NetworkDataGridNode.ts +1 -0
  214. package/front_end/panels/network/NetworkLogView.test.ts +1 -1
  215. package/front_end/panels/network/NetworkPanel.ts +40 -32
  216. package/front_end/panels/network/NetworkWaterfallColumn.ts +1 -1
  217. package/front_end/panels/profiler/HeapProfileView.ts +9 -9
  218. package/front_end/panels/profiler/HeapTimelineOverview.ts +1 -1
  219. package/front_end/panels/profiler/IsolateSelector.ts +1 -1
  220. package/front_end/panels/profiler/LiveHeapProfileView.ts +3 -1
  221. package/front_end/panels/profiler/ProfileFlameChartDataProvider.ts +3 -3
  222. package/front_end/panels/profiler/ProfileView.ts +2 -2
  223. package/front_end/panels/profiler/profileLauncherView.css +1 -1
  224. package/front_end/panels/profiler/profilesSidebarTree.css +1 -1
  225. package/front_end/panels/recorder/recorderController.css +1 -1
  226. package/front_end/panels/security/CookieControlsTreeElement.ts +18 -0
  227. package/front_end/panels/security/CookieControlsView.test.ts +29 -0
  228. package/front_end/panels/security/CookieControlsView.ts +265 -0
  229. package/front_end/panels/security/CookieReportView.test.ts +157 -0
  230. package/front_end/panels/security/CookieReportView.ts +208 -12
  231. package/front_end/panels/security/SecurityPanel.ts +5 -3
  232. package/front_end/panels/security/SecurityPanelSidebar.ts +6 -1
  233. package/front_end/panels/security/cookieControlsView.css +101 -0
  234. package/front_end/panels/security/cookieReportView.css +26 -3
  235. package/front_end/panels/security/security.ts +4 -0
  236. package/front_end/panels/security/sidebar.css +1 -1
  237. package/front_end/panels/settings/KeybindsSettingsTab.ts +3 -2
  238. package/front_end/panels/settings/SettingsScreen.ts +5 -1
  239. package/front_end/panels/settings/frameworkIgnoreListSettingsTab.css +1 -1
  240. package/front_end/panels/settings/keybindsSettingsTab.css +6 -1
  241. package/front_end/panels/settings/settings-meta.ts +3 -1
  242. package/front_end/panels/settings/settingsScreen.css +10 -0
  243. package/front_end/panels/sources/CallStackSidebarPane.ts +2 -2
  244. package/front_end/panels/sources/NavigatorView.ts +1 -0
  245. package/front_end/panels/sources/navigatorTree.css +1 -1
  246. package/front_end/panels/sources/sourcesPanel.css +2 -2
  247. package/front_end/panels/timeline/AnimationsTrackAppender.ts +1 -7
  248. package/front_end/panels/timeline/AppenderUtils.ts +1 -1
  249. package/front_end/panels/timeline/CompatibilityTracksAppender.ts +38 -41
  250. package/front_end/panels/timeline/ExtensionTrackAppender.ts +4 -13
  251. package/front_end/panels/timeline/InteractionsTrackAppender.ts +3 -4
  252. package/front_end/panels/timeline/LayoutShiftsTrackAppender.ts +6 -12
  253. package/front_end/panels/timeline/ServerTimingsTrackAppender.ts +1 -10
  254. package/front_end/panels/timeline/ThreadAppender.ts +9 -12
  255. package/front_end/panels/timeline/TimelineController.ts +1 -1
  256. package/front_end/panels/timeline/TimelineDetailsView.test.ts +3 -2
  257. package/front_end/panels/timeline/TimelineDetailsView.ts +18 -17
  258. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +55 -36
  259. package/front_end/panels/timeline/TimelineFlameChartNetworkDataProvider.ts +1 -1
  260. package/front_end/panels/timeline/TimelineFlameChartView.ts +33 -14
  261. package/front_end/panels/timeline/TimelineHistoryManager.test.ts +20 -15
  262. package/front_end/panels/timeline/TimelineHistoryManager.ts +46 -58
  263. package/front_end/panels/timeline/TimelineLayersView.ts +1 -1
  264. package/front_end/panels/timeline/TimelineLoader.ts +16 -0
  265. package/front_end/panels/timeline/TimelineMiniMap.ts +2 -2
  266. package/front_end/panels/timeline/TimelinePaintProfilerView.ts +1 -1
  267. package/front_end/panels/timeline/TimelinePanel.ts +145 -28
  268. package/front_end/panels/timeline/TimelineTreeView.ts +65 -16
  269. package/front_end/panels/timeline/TimelineUIUtils.ts +44 -0
  270. package/front_end/panels/timeline/TimingsTrackAppender.ts +6 -13
  271. package/front_end/panels/timeline/components/FieldSettingsDialog.test.ts +1 -0
  272. package/front_end/panels/timeline/components/FieldSettingsDialog.ts +6 -1
  273. package/front_end/panels/timeline/components/LiveMetricsView.test.ts +12 -0
  274. package/front_end/panels/timeline/components/LiveMetricsView.ts +13 -18
  275. package/front_end/panels/timeline/components/Sidebar.ts +1 -4
  276. package/front_end/panels/timeline/components/SidebarAnnotationsTab.test.ts +1 -1
  277. package/front_end/panels/timeline/components/SidebarInsightsTab.ts +1 -1
  278. package/front_end/panels/timeline/components/SidebarSingleInsightSet.test.ts +21 -35
  279. package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +16 -9
  280. package/front_end/panels/timeline/components/TimelineSummary.test.ts +75 -0
  281. package/front_end/panels/timeline/components/TimelineSummary.ts +101 -0
  282. package/front_end/panels/timeline/components/Utils.test.ts +49 -0
  283. package/front_end/panels/timeline/components/Utils.ts +2 -2
  284. package/front_end/panels/timeline/components/components.ts +2 -0
  285. package/front_end/panels/timeline/components/insights/BaseInsightComponent.test.ts +84 -0
  286. package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +291 -0
  287. package/front_end/panels/timeline/components/insights/CLSCulprits.ts +17 -41
  288. package/front_end/panels/timeline/components/insights/DocumentLatency.ts +28 -46
  289. package/front_end/panels/timeline/components/insights/EventRef.ts +70 -2
  290. package/front_end/panels/timeline/components/insights/FontDisplay.ts +28 -46
  291. package/front_end/panels/timeline/components/insights/Helpers.ts +5 -208
  292. package/front_end/panels/timeline/components/insights/ImageDelivery.ts +142 -0
  293. package/front_end/panels/timeline/components/insights/InteractionToNextPaint.ts +30 -53
  294. package/front_end/panels/timeline/components/insights/LCPDiscovery.ts +36 -75
  295. package/front_end/panels/timeline/components/insights/LCPPhases.ts +15 -49
  296. package/front_end/panels/timeline/components/insights/RenderBlocking.ts +27 -44
  297. package/front_end/panels/timeline/components/insights/SidebarInsight.ts +3 -197
  298. package/front_end/panels/timeline/components/insights/SlowCSSSelector.ts +51 -74
  299. package/front_end/panels/timeline/components/insights/Table.ts +6 -5
  300. package/front_end/panels/timeline/components/insights/ThirdParties.ts +41 -61
  301. package/front_end/panels/timeline/components/insights/Viewport.ts +20 -31
  302. package/front_end/panels/timeline/components/insights/{sidebarInsight.css → baseInsightComponent.css} +9 -9
  303. package/front_end/panels/timeline/components/insights/insights.ts +4 -0
  304. package/front_end/panels/timeline/components/insights/types.ts +0 -7
  305. package/front_end/panels/timeline/components/liveMetricsView.css +5 -5
  306. package/front_end/panels/timeline/components/timelineSummary.css +67 -0
  307. package/front_end/panels/timeline/docs/flame_chart_migration.md +1 -1
  308. package/front_end/panels/timeline/fixtures/traces/README.md +4 -0
  309. package/front_end/panels/timeline/fixtures/traces/image-delivery.json.gz +0 -0
  310. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +22 -0
  311. package/front_end/panels/timeline/timeline-meta.ts +1 -1
  312. package/front_end/panels/timeline/timelineFlamechartPopover.css +14 -4
  313. package/front_end/panels/timeline/timelineHistoryManager.css +7 -3
  314. package/front_end/panels/timeline/timelinePanel.css +0 -1
  315. package/front_end/panels/timeline/track_appenders/CompatibilityTracksAppender.test.ts +5 -5
  316. package/front_end/panels/timeline/track_appenders/ExtensionTrackAppender.test.ts +5 -6
  317. package/front_end/panels/timeline/track_appenders/LayoutShiftsTrackAppender.test.ts +11 -2
  318. package/front_end/panels/timeline/track_appenders/ServerTimingsTrackAppender.test.ts +0 -9
  319. package/front_end/panels/timeline/track_appenders/ThreadAppender.test.ts +37 -44
  320. package/front_end/panels/timeline/track_appenders/TimingsTrackAppender.test.ts +44 -30
  321. package/front_end/panels/timeline/utils/EntryName.ts +1 -2
  322. package/front_end/panels/timeline/utils/Helpers.ts +19 -0
  323. package/front_end/panels/timeline/utils/IgnoreList.test.ts +52 -0
  324. package/front_end/panels/timeline/utils/IgnoreList.ts +68 -7
  325. package/front_end/panels/timeline/utils/SourceMapsResolver.ts +2 -0
  326. package/front_end/panels/webauthn/webauthnPane.css +1 -1
  327. package/front_end/panels/whats_new/ReleaseNote.test.ts +90 -0
  328. package/front_end/panels/whats_new/ReleaseNoteText.ts +52 -0
  329. package/front_end/panels/whats_new/ReleaseNoteView.ts +157 -0
  330. package/front_end/panels/whats_new/WhatsNewImpl.ts +102 -0
  331. package/front_end/panels/whats_new/releaseNoteView.css +121 -0
  332. package/front_end/panels/whats_new/resources/WNDT.md +6 -0
  333. package/front_end/panels/whats_new/resources/whatsnew.avif +0 -0
  334. package/front_end/panels/whats_new/whats_new-meta.ts +142 -0
  335. package/front_end/panels/whats_new/whats_new.ts +13 -0
  336. package/front_end/services/puppeteer/PuppeteerConnection.ts +4 -3
  337. package/front_end/testing/EnvironmentHelpers.ts +1 -2
  338. package/front_end/testing/SourceMapEncoder.ts +27 -11
  339. package/front_end/testing/TraceHelpers.ts +2 -1
  340. package/front_end/testing/TraceLoader.ts +6 -2
  341. package/front_end/third_party/lighthouse/README.chromium +2 -2
  342. package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1380 -1369
  343. package/front_end/third_party/lighthouse/locales/ar-XB.json +88 -85
  344. package/front_end/third_party/lighthouse/locales/ar.json +98 -95
  345. package/front_end/third_party/lighthouse/locales/bg.json +88 -85
  346. package/front_end/third_party/lighthouse/locales/ca.json +91 -88
  347. package/front_end/third_party/lighthouse/locales/cs.json +91 -88
  348. package/front_end/third_party/lighthouse/locales/da.json +94 -91
  349. package/front_end/third_party/lighthouse/locales/de.json +92 -89
  350. package/front_end/third_party/lighthouse/locales/el.json +92 -89
  351. package/front_end/third_party/lighthouse/locales/en-GB.json +89 -86
  352. package/front_end/third_party/lighthouse/locales/en-US.json +23 -20
  353. package/front_end/third_party/lighthouse/locales/en-XA.json +88 -85
  354. package/front_end/third_party/lighthouse/locales/en-XL.json +23 -20
  355. package/front_end/third_party/lighthouse/locales/es-419.json +92 -89
  356. package/front_end/third_party/lighthouse/locales/es.json +91 -88
  357. package/front_end/third_party/lighthouse/locales/fi.json +92 -89
  358. package/front_end/third_party/lighthouse/locales/fil.json +93 -90
  359. package/front_end/third_party/lighthouse/locales/fr.json +94 -91
  360. package/front_end/third_party/lighthouse/locales/he.json +97 -94
  361. package/front_end/third_party/lighthouse/locales/hi.json +92 -89
  362. package/front_end/third_party/lighthouse/locales/hr.json +90 -87
  363. package/front_end/third_party/lighthouse/locales/hu.json +90 -87
  364. package/front_end/third_party/lighthouse/locales/id.json +91 -88
  365. package/front_end/third_party/lighthouse/locales/it.json +90 -87
  366. package/front_end/third_party/lighthouse/locales/ja.json +90 -87
  367. package/front_end/third_party/lighthouse/locales/ko.json +90 -87
  368. package/front_end/third_party/lighthouse/locales/lt.json +90 -87
  369. package/front_end/third_party/lighthouse/locales/lv.json +91 -88
  370. package/front_end/third_party/lighthouse/locales/nl.json +90 -87
  371. package/front_end/third_party/lighthouse/locales/no.json +92 -89
  372. package/front_end/third_party/lighthouse/locales/pl.json +90 -87
  373. package/front_end/third_party/lighthouse/locales/pt-PT.json +111 -108
  374. package/front_end/third_party/lighthouse/locales/pt.json +97 -94
  375. package/front_end/third_party/lighthouse/locales/ro.json +94 -91
  376. package/front_end/third_party/lighthouse/locales/ru.json +93 -90
  377. package/front_end/third_party/lighthouse/locales/sk.json +93 -90
  378. package/front_end/third_party/lighthouse/locales/sl.json +91 -88
  379. package/front_end/third_party/lighthouse/locales/sr-Latn.json +91 -88
  380. package/front_end/third_party/lighthouse/locales/sr.json +91 -88
  381. package/front_end/third_party/lighthouse/locales/sv.json +92 -89
  382. package/front_end/third_party/lighthouse/locales/ta.json +101 -98
  383. package/front_end/third_party/lighthouse/locales/te.json +92 -89
  384. package/front_end/third_party/lighthouse/locales/th.json +95 -92
  385. package/front_end/third_party/lighthouse/locales/tr.json +91 -88
  386. package/front_end/third_party/lighthouse/locales/uk.json +93 -90
  387. package/front_end/third_party/lighthouse/locales/vi.json +95 -92
  388. package/front_end/third_party/lighthouse/locales/zh-HK.json +92 -89
  389. package/front_end/third_party/lighthouse/locales/zh-TW.json +98 -95
  390. package/front_end/third_party/lighthouse/locales/zh.json +96 -93
  391. package/front_end/third_party/puppeteer/README.chromium +2 -2
  392. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Browser.d.ts +8 -0
  393. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Browser.d.ts.map +1 -1
  394. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Browser.js.map +1 -1
  395. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Frame.d.ts.map +1 -1
  396. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Frame.js +3 -1
  397. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Frame.js.map +1 -1
  398. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/HTTPRequest.d.ts +1 -0
  399. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/HTTPRequest.d.ts.map +1 -1
  400. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/HTTPRequest.js +1 -0
  401. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/HTTPRequest.js.map +1 -1
  402. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts +4 -0
  403. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.d.ts.map +1 -1
  404. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/api/Page.js.map +1 -1
  405. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts +1 -0
  406. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.d.ts.map +1 -1
  407. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js +3 -0
  408. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/bidi/Page.js.map +1 -1
  409. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.d.ts +3 -2
  410. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.d.ts.map +1 -1
  411. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js +10 -4
  412. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Browser.js.map +1 -1
  413. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserConnector.d.ts.map +1 -1
  414. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserConnector.js +2 -2
  415. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserConnector.js.map +1 -1
  416. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserContext.d.ts +2 -0
  417. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserContext.d.ts.map +1 -1
  418. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserContext.js +7 -0
  419. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/BrowserContext.js.map +1 -1
  420. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPRequest.d.ts +1 -0
  421. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPRequest.d.ts.map +1 -1
  422. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPRequest.js +3 -0
  423. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPRequest.js.map +1 -1
  424. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPResponse.d.ts +1 -2
  425. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPResponse.d.ts.map +1 -1
  426. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPResponse.js +4 -4
  427. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/HTTPResponse.js.map +1 -1
  428. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  429. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js +24 -12
  430. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/NetworkManager.js.map +1 -1
  431. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts +1 -0
  432. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.d.ts.map +1 -1
  433. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js +3 -0
  434. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/cdp/Page.js.map +1 -1
  435. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConnectOptions.d.ts +5 -0
  436. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/ConnectOptions.d.ts.map +1 -1
  437. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DownloadBehavior.d.ts +30 -0
  438. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DownloadBehavior.d.ts.map +1 -0
  439. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DownloadBehavior.js +8 -0
  440. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/DownloadBehavior.js.map +1 -0
  441. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/common.d.ts +1 -0
  442. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/common/common.d.ts.map +1 -1
  443. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.d.ts +1 -1
  444. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/generated/version.js +1 -1
  445. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/injected/injected.d.ts +1 -1
  446. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  447. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js +2 -2
  448. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/node/BrowserLauncher.js.map +1 -1
  449. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.d.ts +3 -3
  450. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js +3 -3
  451. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/revisions.js.map +1 -1
  452. package/front_end/third_party/puppeteer/package/lib/cjs/puppeteer/util/Mutex.d.ts +2 -2
  453. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.d.ts +49 -0
  454. package/front_end/third_party/puppeteer/package/lib/es5-iife/puppeteer-core-browser.js +118 -88
  455. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.d.ts +8 -0
  456. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.d.ts.map +1 -1
  457. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Browser.js.map +1 -1
  458. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Frame.d.ts.map +1 -1
  459. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Frame.js +3 -1
  460. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Frame.js.map +1 -1
  461. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/HTTPRequest.d.ts +1 -0
  462. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/HTTPRequest.d.ts.map +1 -1
  463. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/HTTPRequest.js +1 -0
  464. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/HTTPRequest.js.map +1 -1
  465. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts +4 -0
  466. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.d.ts.map +1 -1
  467. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/api/Page.js.map +1 -1
  468. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts +1 -0
  469. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.d.ts.map +1 -1
  470. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js +3 -0
  471. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/bidi/Page.js.map +1 -1
  472. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.d.ts +3 -2
  473. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.d.ts.map +1 -1
  474. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js +10 -4
  475. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Browser.js.map +1 -1
  476. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserConnector.d.ts.map +1 -1
  477. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserConnector.js +2 -2
  478. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserConnector.js.map +1 -1
  479. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserContext.d.ts +2 -0
  480. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserContext.d.ts.map +1 -1
  481. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserContext.js +7 -0
  482. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/BrowserContext.js.map +1 -1
  483. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPRequest.d.ts +1 -0
  484. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPRequest.d.ts.map +1 -1
  485. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPRequest.js +3 -0
  486. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPRequest.js.map +1 -1
  487. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPResponse.d.ts +1 -2
  488. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPResponse.d.ts.map +1 -1
  489. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPResponse.js +4 -4
  490. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/HTTPResponse.js.map +1 -1
  491. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.d.ts.map +1 -1
  492. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js +24 -12
  493. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/NetworkManager.js.map +1 -1
  494. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts +1 -0
  495. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.d.ts.map +1 -1
  496. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js +3 -0
  497. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/cdp/Page.js.map +1 -1
  498. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/ConnectOptions.d.ts +5 -0
  499. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/ConnectOptions.d.ts.map +1 -1
  500. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/DownloadBehavior.d.ts +30 -0
  501. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/DownloadBehavior.d.ts.map +1 -0
  502. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/DownloadBehavior.js +7 -0
  503. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/DownloadBehavior.js.map +1 -0
  504. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/common.d.ts +1 -0
  505. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/common/common.d.ts.map +1 -1
  506. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.d.ts +1 -1
  507. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/generated/version.js +1 -1
  508. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.d.ts.map +1 -1
  509. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js +2 -2
  510. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/node/BrowserLauncher.js.map +1 -1
  511. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.d.ts +3 -3
  512. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js +3 -3
  513. package/front_end/third_party/puppeteer/package/lib/esm/puppeteer/revisions.js.map +1 -1
  514. package/front_end/third_party/puppeteer/package/lib/types.d.ts +49 -0
  515. package/front_end/third_party/puppeteer/package/package.json +3 -3
  516. package/front_end/third_party/puppeteer/package/src/api/Browser.ts +8 -0
  517. package/front_end/third_party/puppeteer/package/src/api/Frame.ts +3 -1
  518. package/front_end/third_party/puppeteer/package/src/api/HTTPRequest.ts +1 -0
  519. package/front_end/third_party/puppeteer/package/src/api/Page.ts +5 -0
  520. package/front_end/third_party/puppeteer/package/src/bidi/Page.ts +4 -0
  521. package/front_end/third_party/puppeteer/package/src/cdp/Browser.ts +11 -3
  522. package/front_end/third_party/puppeteer/package/src/cdp/BrowserConnector.ts +2 -0
  523. package/front_end/third_party/puppeteer/package/src/cdp/BrowserContext.ts +11 -0
  524. package/front_end/third_party/puppeteer/package/src/cdp/HTTPRequest.ts +4 -0
  525. package/front_end/third_party/puppeteer/package/src/cdp/HTTPResponse.ts +3 -5
  526. package/front_end/third_party/puppeteer/package/src/cdp/NetworkManager.ts +34 -17
  527. package/front_end/third_party/puppeteer/package/src/cdp/Page.ts +4 -0
  528. package/front_end/third_party/puppeteer/package/src/common/ConnectOptions.ts +5 -0
  529. package/front_end/third_party/puppeteer/package/src/common/DownloadBehavior.ts +31 -0
  530. package/front_end/third_party/puppeteer/package/src/common/common.ts +1 -0
  531. package/front_end/third_party/puppeteer/package/src/generated/version.ts +1 -1
  532. package/front_end/third_party/puppeteer/package/src/node/BrowserLauncher.ts +2 -0
  533. package/front_end/third_party/puppeteer/package/src/revisions.ts +3 -3
  534. package/front_end/third_party/puppeteer/puppeteer-tsconfig.json +1 -0
  535. package/front_end/ui/components/data_grid/DataGridControllerIntegrator.ts +4 -1
  536. package/front_end/ui/components/dialogs/ButtonDialog.test.ts +78 -0
  537. package/front_end/ui/components/dialogs/ButtonDialog.ts +131 -0
  538. package/front_end/ui/components/dialogs/Dialog.test.ts +43 -0
  539. package/front_end/ui/components/dialogs/Dialog.ts +64 -2
  540. package/front_end/ui/components/dialogs/ShortcutDialog.test.ts +15 -1
  541. package/front_end/ui/components/dialogs/ShortcutDialog.ts +28 -20
  542. package/front_end/ui/components/dialogs/buttonDialog.css +9 -0
  543. package/front_end/ui/components/dialogs/dialog.css +15 -0
  544. package/front_end/ui/components/dialogs/dialogs.ts +2 -0
  545. package/front_end/ui/components/dialogs/shortcutDialog.css +34 -6
  546. package/front_end/ui/components/docs/dialog/button_dialog.html +28 -0
  547. package/front_end/ui/components/docs/dialog/button_dialog.ts +29 -0
  548. package/front_end/ui/components/docs/performance_panel/basic.ts +1 -1
  549. package/front_end/ui/components/docs/performance_panel/timeline_history_manager.ts +6 -4
  550. package/front_end/ui/components/floating_button/FloatingButton.ts +3 -2
  551. package/front_end/ui/components/icon_button/fileSourceIcon.css +7 -3
  552. package/front_end/ui/components/issue_counter/IssueCounter.ts +15 -2
  553. package/front_end/ui/components/legacy_wrapper/LegacyWrapper.ts +1 -1
  554. package/front_end/ui/components/markdown_view/MarkdownView.ts +15 -0
  555. package/front_end/ui/components/markdown_view/markdownView.css +1 -1
  556. package/front_end/ui/components/render_coordinator/RenderCoordinator.ts +24 -18
  557. package/front_end/ui/components/switch/SwitchImpl.ts +2 -2
  558. package/front_end/ui/legacy/Infobar.ts +6 -0
  559. package/front_end/ui/legacy/InspectorView.ts +40 -0
  560. package/front_end/ui/legacy/ListWidget.ts +4 -2
  561. package/front_end/ui/legacy/ThrottledWidget.ts +2 -2
  562. package/front_end/ui/legacy/Toolbar.ts +3 -3
  563. package/front_end/ui/legacy/UIUtils.ts +8 -6
  564. package/front_end/ui/legacy/Widget.ts +32 -0
  565. package/front_end/ui/legacy/components/data_grid/DataGrid.test.ts +6 -9
  566. package/front_end/ui/legacy/components/data_grid/DataGrid.ts +35 -34
  567. package/front_end/ui/legacy/components/data_grid/ViewportDataGrid.ts +1 -1
  568. package/front_end/ui/legacy/components/perf_ui/ChartViewport.ts +2 -2
  569. package/front_end/ui/legacy/components/perf_ui/FilmStripView.ts +1 -1
  570. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +32 -25
  571. package/front_end/ui/legacy/components/perf_ui/TimelineOverviewCalculator.ts +18 -4
  572. package/front_end/ui/legacy/components/perf_ui/TimelineOverviewPane.ts +80 -39
  573. package/front_end/ui/legacy/components/perf_ui/perf_ui-meta.ts +4 -4
  574. package/front_end/ui/legacy/components/utils/jsUtils.css +8 -0
  575. package/front_end/ui/legacy/filter.css +1 -1
  576. package/front_end/ui/legacy/inspectorCommon.css +1 -1
  577. package/front_end/ui/legacy/listWidget.css +4 -1
  578. package/front_end/ui/legacy/reportView.css +1 -1
  579. package/front_end/ui/legacy/toolbar.css +3 -6
  580. package/front_end/ui/legacy/treeoutline.css +3 -1
  581. package/front_end/ui/visual_logging/KnownContextValues.ts +12 -1
  582. package/front_end/ui/visual_logging/LoggingDriver.test.ts +27 -1
  583. package/front_end/ui/visual_logging/LoggingDriver.ts +7 -4
  584. package/package.json +2 -3
  585. package/scripts/build/wasm-as.py +1 -1
  586. package/scripts/freestyler/auto_freestyler.js +12 -4
  587. package/scripts/freestyler/to_tsv.mjs +40 -0
  588. package/scripts/tools/update_goldens.py +11 -13
  589. package/front_end/panels/timeline/components/insights/SidebarInsight.test.ts +0 -72
  590. package/front_end/ui/components/docs/two_states_counter/basic.html +0 -27
  591. package/front_end/ui/components/docs/two_states_counter/basic.ts +0 -45
  592. package/front_end/ui/components/two_states_counter/TwoStatesCounter.test.ts +0 -73
  593. package/front_end/ui/components/two_states_counter/TwoStatesCounter.ts +0 -104
  594. package/front_end/ui/components/two_states_counter/twoStatesCounter.css +0 -37
  595. package/front_end/ui/components/two_states_counter/two_states_counter.ts +0 -9
@@ -13,17 +13,23 @@ export class Node {
13
13
  totalTime: number;
14
14
  selfTime: number;
15
15
  id: string|symbol;
16
- event: Types.Events.Event|null;
16
+ /** The first trace event encountered that necessitated the creation of this tree node. */
17
+ event: Types.Events.Event;
18
+ /** All of the trace events associated with this aggregate node.
19
+ * Minor: In the case of Event Log (EventsTimelineTreeView), the node is not aggregate and this will only hold 1 event, the same that's in this.event
20
+ */
21
+ events: Types.Events.Event[];
17
22
  parent!: Node|null;
18
23
  groupId: string;
19
24
  isGroupNodeInternal: boolean;
20
25
  depth: number;
21
26
 
22
- constructor(id: string|symbol, event: Types.Events.Event|null) {
27
+ constructor(id: string|symbol, event: Types.Events.Event) {
23
28
  this.totalTime = 0;
24
29
  this.selfTime = 0;
25
30
  this.id = id;
26
31
  this.event = event;
32
+ this.events = [event];
27
33
 
28
34
  this.groupId = '';
29
35
  this.isGroupNodeInternal = false;
@@ -67,7 +73,7 @@ export class TopDownNode extends Node {
67
73
  childrenInternal: ChildrenCache|null;
68
74
  override parent: TopDownNode|null;
69
75
 
70
- constructor(id: string|symbol, event: Types.Events.Event|null, parent: TopDownNode|null) {
76
+ constructor(id: string|symbol, event: Types.Events.Event, parent: TopDownNode|null) {
71
77
  super(id, event);
72
78
  this.root = parent && parent.root;
73
79
  this.hasChildrenInternal = false;
@@ -180,6 +186,8 @@ export class TopDownNode extends Node {
180
186
  node = new TopDownNode(id, e, self);
181
187
  node.groupId = groupId;
182
188
  children.set(id, node);
189
+ } else {
190
+ node.events.push(e);
183
191
  }
184
192
  node.selfTime += duration;
185
193
  node.totalTime += duration;
@@ -238,8 +246,6 @@ export class TopDownNode extends Node {
238
246
 
239
247
  export class TopDownRootNode extends TopDownNode {
240
248
  readonly filter: (e: Types.Events.Event) => boolean;
241
- /** This is all events passed in to create the tree, and it's very likely that it included events outside of the passed startTime/endTime as that filtering is done in `Helpers.Trace.forEachEvent` */
242
- readonly events: Types.Events.Event[];
243
249
  readonly startTime: Types.Timing.MilliSeconds;
244
250
  readonly endTime: Types.Timing.MilliSeconds;
245
251
  eventGroupIdCallback: ((arg0: Types.Events.Event) => string)|null|undefined;
@@ -253,7 +259,8 @@ export class TopDownRootNode extends TopDownNode {
253
259
  events: Types.Events.Event[], filters: TraceFilter[], startTime: Types.Timing.MilliSeconds,
254
260
  endTime: Types.Timing.MilliSeconds, doNotAggregate?: boolean,
255
261
  eventGroupIdCallback?: ((arg0: Types.Events.Event) => string)|null, includeInstantEvents?: boolean) {
256
- super('', null, null);
262
+ super('', events[0], null);
263
+ this.event = events[0];
257
264
  this.root = this;
258
265
  this.events = events;
259
266
  this.filter = (e: Types.Events.Event): boolean => filters.every(f => f.accept(e));
@@ -281,14 +288,13 @@ export class TopDownRootNode extends TopDownNode {
281
288
  }
282
289
  const groupNodes = new Map<string, GroupNode>();
283
290
  for (const node of flatNodes.values()) {
284
- if (!node.event) {
285
- continue;
286
- }
287
291
  const groupId = this.eventGroupIdCallback(node.event);
288
292
  let groupNode = groupNodes.get(groupId);
289
293
  if (!groupNode) {
290
- groupNode = new GroupNode(groupId, this, node.event);
294
+ groupNode = new GroupNode(groupId, this, node.events);
291
295
  groupNodes.set(groupId, groupNode);
296
+ } else {
297
+ groupNode.events.push(...node.events);
292
298
  }
293
299
  groupNode.addChild(node as BottomUpNode, node.selfTime, node.totalTime);
294
300
  }
@@ -303,7 +309,6 @@ export class TopDownRootNode extends TopDownNode {
303
309
 
304
310
  export class BottomUpRootNode extends Node {
305
311
  private childrenInternal: ChildrenCache|null;
306
- readonly events: Types.Events.Event[];
307
312
  private textFilter: TraceFilter;
308
313
  readonly filter: (e: Types.Events.Event) => boolean;
309
314
  readonly startTime: Types.Timing.MilliSeconds;
@@ -315,7 +320,7 @@ export class BottomUpRootNode extends Node {
315
320
  events: Types.Events.Event[], textFilter: TraceFilter, filters: TraceFilter[],
316
321
  startTime: Types.Timing.MilliSeconds, endTime: Types.Timing.MilliSeconds,
317
322
  eventGroupIdCallback: ((arg0: Types.Events.Event) => string)|null) {
318
- super('', null);
323
+ super('', events[0]);
319
324
  this.childrenInternal = null;
320
325
  this.events = events;
321
326
  this.textFilter = textFilter;
@@ -388,6 +393,8 @@ export class BottomUpRootNode extends Node {
388
393
  if (!node) {
389
394
  node = new BottomUpNode(root, id, event, false, root);
390
395
  nodeById.set(id, node);
396
+ } else {
397
+ node.events.push(event);
391
398
  }
392
399
  node.selfTime += selfTimeStack.pop() || 0;
393
400
  if (firstNodeStack.pop()) {
@@ -415,14 +422,13 @@ export class BottomUpRootNode extends Node {
415
422
  }
416
423
  const groupNodes = new Map<string, GroupNode>();
417
424
  for (const node of flatNodes.values()) {
418
- if (!node.event) {
419
- continue;
420
- }
421
425
  const groupId = this.eventGroupIdCallback(node.event);
422
426
  let groupNode = groupNodes.get(groupId);
423
427
  if (!groupNode) {
424
- groupNode = new GroupNode(groupId, this, node.event);
428
+ groupNode = new GroupNode(groupId, this, node.events);
425
429
  groupNodes.set(groupId, groupNode);
430
+ } else {
431
+ groupNode.events.push(...node.events);
426
432
  }
427
433
  groupNode.addChild(node as BottomUpNode, node.selfTime, node.selfTime);
428
434
  }
@@ -433,9 +439,11 @@ export class BottomUpRootNode extends Node {
433
439
  export class GroupNode extends Node {
434
440
  private readonly childrenInternal: ChildrenCache;
435
441
  override isGroupNodeInternal: boolean;
442
+ override events: Types.Events.Event[];
436
443
 
437
- constructor(id: string, parent: BottomUpRootNode|TopDownRootNode, event: Types.Events.Event) {
438
- super(id, event);
444
+ constructor(id: string, parent: BottomUpRootNode|TopDownRootNode, events: Types.Events.Event[]) {
445
+ super(id, events[0]);
446
+ this.events = events;
439
447
  this.childrenInternal = new Map();
440
448
  this.parent = parent;
441
449
  this.isGroupNodeInternal = true;
@@ -539,6 +547,8 @@ export class BottomUpNode extends Node {
539
547
  const hasChildren = eventStack.length > self.depth;
540
548
  node = new BottomUpNode(self.root, childId, event, hasChildren, self);
541
549
  nodeById.set(childId, node);
550
+ } else {
551
+ node.events.push(e);
542
552
  }
543
553
  const actualEndTime = currentEndTime !== undefined ? Math.min(currentEndTime, endTime) : endTime;
544
554
  const totalTime = actualEndTime - Math.max(currentStartTime, lastTimeMarker);
@@ -7,12 +7,13 @@ import type * as Handlers from '../handlers/handlers.js';
7
7
  import * as Types from '../types/types.js';
8
8
 
9
9
  /**
10
- * Use this helper whenever resolving an URL's source mapping is not an
11
- * option. For example when processing non-ui data. Otherwise use the
12
- * helper SourceMapsResolver::resolvedURLForEntry
10
+ * INSTEAD, you probably want `SourceMapsResolver.resolvedURLForEntry()`!
11
+ * If an URL will be displayed in the UI, it's likely you should NOT use `getNonResolved`.
13
12
  *
14
- * If an URL will be displayed in the UI, it's likely you should not use
15
- * this helper and prefer the other option instead.
13
+ * Use `getNonResolved` method whenever resolving an URL's source mapping is not an
14
+ * option. For example when processing non-ui data.
15
+ *
16
+ * TODO: migrate existing uses of this over to resolvedURLForEntry.
16
17
  */
17
18
 
18
19
  export function getNonResolved(
@@ -2,6 +2,7 @@
2
2
  // Use of this source code is governed by a BSD-style license that can be
3
3
  // found in the LICENSE file.
4
4
 
5
+ import * as Platform from '../../../core/platform/platform.js';
5
6
  import * as Types from '../types/types.js';
6
7
 
7
8
  /**
@@ -37,11 +38,14 @@ const paintImageByLazyPixelRef: Map<number, Types.Events.PaintImage> = new Map()
37
38
  // have a relationship to a individual PaintImage event.
38
39
  const eventToPaintImage: Map<Types.Events.Event, Types.Events.PaintImage> = new Map();
39
40
 
41
+ const urlToPaintImage: Map<string, Types.Events.PaintImage[]> = new Map();
42
+
40
43
  export function reset(): void {
41
44
  paintImageEvents.clear();
42
45
  decodeLazyPixelRefEvents.clear();
43
46
  paintImageByLazyPixelRef.clear();
44
47
  eventToPaintImage.clear();
48
+ urlToPaintImage.clear();
45
49
  }
46
50
 
47
51
  export function handleEvent(event: Types.Events.Event): void {
@@ -51,6 +55,12 @@ export function handleEvent(event: Types.Events.Event): void {
51
55
  forThread.push(event);
52
56
  forProcess.set(event.tid, forThread);
53
57
  paintImageEvents.set(event.pid, forProcess);
58
+
59
+ if (event.args.data.url) {
60
+ const paintsForUrl = Platform.MapUtilities.getWithDefault(urlToPaintImage, event.args.data.url, () => []);
61
+ paintsForUrl.push(event);
62
+ }
63
+
54
64
  return;
55
65
  }
56
66
 
@@ -118,11 +128,13 @@ export async function finalize(): Promise<void> {
118
128
  export interface ImagePaintData {
119
129
  paintImageByDrawLazyPixelRef: Map<number, Types.Events.PaintImage>;
120
130
  paintImageForEvent: Map<Types.Events.Event, Types.Events.PaintImage>;
131
+ paintImageEventForUrl: Map<string, Types.Events.PaintImage[]>;
121
132
  }
122
133
 
123
134
  export function data(): ImagePaintData {
124
135
  return {
125
136
  paintImageByDrawLazyPixelRef: paintImageByLazyPixelRef,
126
137
  paintImageForEvent: eventToPaintImage,
138
+ paintImageEventForUrl: urlToPaintImage,
127
139
  };
128
140
  }
@@ -147,6 +147,14 @@ export function traceWindowFromMicroSeconds(
147
147
  return traceWindow;
148
148
  }
149
149
 
150
+ export function traceWindowFromEvent(event: Types.Events.Event): Types.Timing.TraceWindowMicroSeconds {
151
+ return {
152
+ min: event.ts,
153
+ max: Types.Timing.MicroSeconds(event.ts + (event.dur ?? 0)),
154
+ range: event.dur ?? Types.Timing.MicroSeconds(0),
155
+ };
156
+ }
157
+
150
158
  export interface BoundsIncludeTimeRange {
151
159
  timeRange: Types.Timing.TraceWindowMicroSeconds;
152
160
  bounds: Types.Timing.TraceWindowMicroSeconds;
@@ -8,7 +8,7 @@ import type * as Protocol from '../../../generated/protocol.js';
8
8
  import * as Helpers from '../helpers/helpers.js';
9
9
  import * as Types from '../types/types.js';
10
10
 
11
- import type {InsightModel, InsightSetContext, RequiredData} from './types.js';
11
+ import {InsightCategory, type InsightModel, type InsightSetContext, type RequiredData} from './types.js';
12
12
 
13
13
  const UIStrings = {
14
14
  /** Title of an insight that provides details about why elements shift/move on the page. The causes for these shifts are referred to as culprits ("reasons"). */
@@ -420,8 +420,16 @@ function getFontRootCauses(
420
420
  return rootCausesByShift;
421
421
  }
422
422
 
423
- function finalize(partialModel: Omit<CLSCulpritsInsightModel, 'title'|'description'>): CLSCulpritsInsightModel {
424
- return {title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel};
423
+ function finalize(partialModel: Omit<CLSCulpritsInsightModel, 'title'|'description'|'category'|'shouldShow'>):
424
+ CLSCulpritsInsightModel {
425
+ return {
426
+ title: i18nString(UIStrings.title),
427
+ description: i18nString(UIStrings.description),
428
+ category: InsightCategory.CLS,
429
+ // TODO: getTopCulprits in component needs to move to model so this can be set here.
430
+ shouldShow: true,
431
+ ...partialModel,
432
+ };
425
433
  }
426
434
 
427
435
  export function generateInsight(
@@ -6,7 +6,7 @@ import * as i18n from '../../../core/i18n/i18n.js';
6
6
  import * as Helpers from '../helpers/helpers.js';
7
7
  import * as Types from '../types/types.js';
8
8
 
9
- import type {InsightModel, InsightSetContext, RequiredData} from './types.js';
9
+ import {InsightCategory, type InsightModel, type InsightSetContext, type RequiredData} from './types.js';
10
10
 
11
11
  const UIStrings = {
12
12
  /**
@@ -119,8 +119,21 @@ function getCompressionSavings(request: Types.Events.SyntheticNetworkRequest): n
119
119
  return estimatedSavings < IGNORE_THRESHOLD_IN_BYTES ? 0 : estimatedSavings;
120
120
  }
121
121
 
122
- function finalize(partialModel: Omit<DocumentLatencyInsightModel, 'title'|'description'>): DocumentLatencyInsightModel {
123
- return {title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel};
122
+ function finalize(partialModel: Omit<DocumentLatencyInsightModel, 'title'|'description'|'category'|'shouldShow'>):
123
+ DocumentLatencyInsightModel {
124
+ let hasFailure = false;
125
+ if (partialModel.data) {
126
+ hasFailure = partialModel.data.redirectDuration > 0 || partialModel.data.serverResponseTooSlow ||
127
+ partialModel.data.uncompressedResponseBytes > 0;
128
+ }
129
+
130
+ return {
131
+ title: i18nString(UIStrings.title),
132
+ description: i18nString(UIStrings.description),
133
+ category: InsightCategory.ALL,
134
+ shouldShow: hasFailure,
135
+ ...partialModel,
136
+ };
124
137
  }
125
138
 
126
139
  export function generateInsight(
@@ -7,7 +7,7 @@ import * as Platform from '../../../core/platform/platform.js';
7
7
  import * as Helpers from '../helpers/helpers.js';
8
8
  import * as Types from '../types/types.js';
9
9
 
10
- import type {InsightModel, InsightSetContext, RequiredData} from './types.js';
10
+ import {InsightCategory, type InsightModel, type InsightSetContext, type RequiredData} from './types.js';
11
11
 
12
12
  const UIStrings = {
13
13
  /** Title of an insight that provides details about the fonts used on the page, and the value of their `font-display` properties. */
@@ -34,8 +34,15 @@ export type FontDisplayInsightModel = InsightModel<{
34
34
  }>,
35
35
  }>;
36
36
 
37
- function finalize(partialModel: Omit<FontDisplayInsightModel, 'title'|'description'>): FontDisplayInsightModel {
38
- return {title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel};
37
+ function finalize(partialModel: Omit<FontDisplayInsightModel, 'title'|'description'|'category'|'shouldShow'>):
38
+ FontDisplayInsightModel {
39
+ return {
40
+ title: i18nString(UIStrings.title),
41
+ description: i18nString(UIStrings.description),
42
+ category: InsightCategory.INP,
43
+ shouldShow: Boolean(partialModel.fonts.find(font => font.wastedTime > 0)),
44
+ ...partialModel,
45
+ };
39
46
  }
40
47
 
41
48
  export function generateInsight(
@@ -0,0 +1,98 @@
1
+ // Copyright 2024 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import {describeWithEnvironment} from '../../../testing/EnvironmentHelpers.js';
6
+ import {getFirstOrError, getInsightOrError} from '../../../testing/InsightHelpers.js';
7
+ import {TraceLoader} from '../../../testing/TraceLoader.js';
8
+
9
+ export async function processTrace(testContext: Mocha.Suite|Mocha.Context|null, traceFile: string) {
10
+ const {parsedTrace, insights} = await TraceLoader.traceEngine(testContext, traceFile);
11
+ if (!insights) {
12
+ throw new Error('No insights');
13
+ }
14
+
15
+ return {data: parsedTrace, insights};
16
+ }
17
+
18
+ describeWithEnvironment('ImageDelivery', function() {
19
+ it('finds requests for remote fonts', async () => {
20
+ // See the following for a description of each test case:
21
+ // https://gist.github.com/adamraine/397e2bd08665f9e45f6072e446715115
22
+ const {data, insights} = await processTrace(this, 'image-delivery.json.gz');
23
+
24
+ const imageRequests = data.NetworkRequests.byTime.filter(r => r.args.data.resourceType === 'Image');
25
+ assert.deepStrictEqual(imageRequests.map(r => r.args.data.url), [
26
+ 'https://images.ctfassets.net/u275ja1nivmq/6T6z40ay5GFCUtwV7DONgh/0e23606ed1692d9721ab0f39a8d8a99e/yeti_cover.jpg',
27
+ 'https://raw.githubusercontent.com/GoogleChrome/lighthouse/refs/heads/main/cli/test/fixtures/dobetterweb/lighthouse-rotating.gif',
28
+ 'https://images-wixmp-ed30a86b8c4ca887773594c2.wixmp.com/f/5d52a2ab-7be3-4931-9e82-8728d1f55620/d51jfzi-b0efc925-7704-44bb-a3b8-8d98545af693.gif?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1cm46YXBwOjdlMGQxODg5ODIyNjQzNzNhNWYwZDQxNWVhMGQyNmUwIiwiaXNzIjoidXJuOmFwcDo3ZTBkMTg4OTgyMjY0MzczYTVmMGQ0MTVlYTBkMjZlMCIsIm9iaiI6W1t7InBhdGgiOiJcL2ZcLzVkNTJhMmFiLTdiZTMtNDkzMS05ZTgyLTg3MjhkMWY1NTYyMFwvZDUxamZ6aS1iMGVmYzkyNS03NzA0LTQ0YmItYTNiOC04ZDk4NTQ1YWY2OTMuZ2lmIn1dXSwiYXVkIjpbInVybjpzZXJ2aWNlOmZpbGUuZG93bmxvYWQiXX0.T898HUlAbGFPboxRE43H5JujnDGl0zd_T128PnGLlpg',
29
+ 'https://images.ctfassets.net/u275ja1nivmq/6T6z40ay5GFCUtwV7DONgh/0e23606ed1692d9721ab0f39a8d8a99e/yeti_cover.jpg?fm=webp',
30
+ 'https://images.ctfassets.net/u275ja1nivmq/6T6z40ay5GFCUtwV7DONgh/0e23606ed1692d9721ab0f39a8d8a99e/yeti_cover.jpg?fm=avif',
31
+ 'https://raw.githubusercontent.com/GoogleChrome/lighthouse/refs/heads/main/cli/test/fixtures/byte-efficiency/lighthouse-2048x1356.webp',
32
+ 'https://raw.githubusercontent.com/GoogleChrome/lighthouse/refs/heads/main/cli/test/fixtures/byte-efficiency/lighthouse-480x320.webp',
33
+ 'https://onlinepngtools.com/images/examples-onlinepngtools/elephant-hd-quality.png',
34
+ 'https://raw.githubusercontent.com/GoogleChrome/lighthouse/refs/heads/main/cli/test/fixtures/dobetterweb/lighthouse-480x318.jpg',
35
+ ]);
36
+
37
+ const insight =
38
+ getInsightOrError('ImageDelivery', insights, getFirstOrError(data.Meta.navigationsByNavigationId.values()));
39
+ assert.deepStrictEqual(
40
+ insight.optimizableImages.map(o => ({url: o.request.args.data.url, optimizations: o.optimizations})),
41
+ [
42
+ {
43
+ optimizations: [
44
+ {
45
+ byteSavings: 1057876,
46
+ type: 'modern-format-or-compression',
47
+ },
48
+ ],
49
+ url:
50
+ 'https://images.ctfassets.net/u275ja1nivmq/6T6z40ay5GFCUtwV7DONgh/0e23606ed1692d9721ab0f39a8d8a99e/yeti_cover.jpg',
51
+ },
52
+ {
53
+ optimizations: [
54
+ {
55
+ byteSavings: 682028,
56
+ type: 'video-format',
57
+ },
58
+ ],
59
+ url:
60
+ 'https://raw.githubusercontent.com/GoogleChrome/lighthouse/refs/heads/main/cli/test/fixtures/dobetterweb/lighthouse-rotating.gif',
61
+ },
62
+ {
63
+ optimizations: [
64
+ {
65
+ byteSavings: 49760,
66
+ type: 'compression',
67
+ },
68
+ ],
69
+ url:
70
+ 'https://images.ctfassets.net/u275ja1nivmq/6T6z40ay5GFCUtwV7DONgh/0e23606ed1692d9721ab0f39a8d8a99e/yeti_cover.jpg?fm=webp',
71
+ },
72
+ {
73
+ optimizations: [
74
+ {
75
+ byteSavings: 41421,
76
+ type: 'responsive-size',
77
+ },
78
+ ],
79
+ url:
80
+ 'https://raw.githubusercontent.com/GoogleChrome/lighthouse/refs/heads/main/cli/test/fixtures/byte-efficiency/lighthouse-2048x1356.webp',
81
+ },
82
+ {
83
+ optimizations: [
84
+ {
85
+ byteSavings: 134075,
86
+ type: 'modern-format-or-compression',
87
+ },
88
+ {
89
+ byteSavings: 162947,
90
+ type: 'responsive-size',
91
+ },
92
+ ],
93
+ url: 'https://onlinepngtools.com/images/examples-onlinepngtools/elephant-hd-quality.png',
94
+ },
95
+ ],
96
+ );
97
+ });
98
+ });
@@ -0,0 +1,183 @@
1
+ // Copyright 2024 The Chromium Authors. All rights reserved.
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import * as i18n from '../../../core/i18n/i18n.js';
6
+ import * as Helpers from '../helpers/helpers.js';
7
+ import type * as Types from '../types/types.js';
8
+
9
+ import {InsightCategory, type InsightModel, type InsightSetContext, type RequiredData} from './types.js';
10
+
11
+ const UIStrings = {
12
+ /**
13
+ * @description Title of an insight that recommends ways to reduce the size of images downloaded and used on the page.
14
+ */
15
+ title: 'Improve image delivery',
16
+ /**
17
+ * @description Description of an insight that recommends ways to reduce the size of images downloaded and used on the page.
18
+ */
19
+ description:
20
+ 'Reducing the download time of images can improve the perceived load time of the page and LCP. [Learn more about optimizing image size](https://developer.chrome.com/docs/lighthouse/performance/uses-optimized-images/)',
21
+ };
22
+
23
+ const str_ = i18n.i18n.registerUIStrings('models/trace/insights/ImageDelivery.ts', UIStrings);
24
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
25
+
26
+ /**
27
+ * Even JPEGs with lots of detail can usually be compressed down to <1 byte per pixel
28
+ * Using 4:2:2 subsampling already gets an uncompressed bitmap to 2 bytes per pixel.
29
+ * The compression ratio for JPEG is usually somewhere around 10:1 depending on content, so
30
+ * 8:1 is a reasonable expectation for web content which is 1.5MB for a 6MP image.
31
+ *
32
+ * WebP usually gives ~20% additional savings on top of that, so we will assume 10:1 for WebP.
33
+ * This is quite pessimistic as their study shows a photographic compression ratio of ~29:1.
34
+ * https://developers.google.com/speed/webp/docs/webp_lossless_alpha_study#results
35
+ *
36
+ * AVIF usually gives ~20% additional savings on top of WebP, so we will use 12:1 for AVIF.
37
+ * This is quite pessimistic as Netflix study shows a photographic compression ratio of ~40:1
38
+ * (0.4 *bits* per pixel at SSIM 0.97).
39
+ * https://netflixtechblog.com/avif-for-next-generation-image-coding-b1d75675fe4
40
+ */
41
+ const TARGET_BYTES_PER_PIXEL_AVIF = 2 * 1 / 12;
42
+
43
+ /**
44
+ * If GIFs are above this size, we'll flag them
45
+ * See https://github.com/GoogleChrome/lighthouse/pull/4885#discussion_r178406623 and https://github.com/GoogleChrome/lighthouse/issues/4696#issuecomment-370979920
46
+ */
47
+ const GIF_SIZE_THRESHOLD = 100 * 1024;
48
+
49
+ const BYTE_SAVINGS_THRESHOLD = 4096;
50
+
51
+ export function deps(): ['NetworkRequests', 'Meta', 'ImagePainting'] {
52
+ return ['NetworkRequests', 'Meta', 'ImagePainting'];
53
+ }
54
+
55
+ export type ImageOptimizationType = 'modern-format-or-compression'|'compression'|'video-format'|'responsive-size';
56
+
57
+ export interface ImageOptimization {
58
+ type: ImageOptimizationType;
59
+ byteSavings: number;
60
+ }
61
+
62
+ export interface OptimizableImage {
63
+ request: Types.Events.SyntheticNetworkRequest;
64
+ optimizations: ImageOptimization[];
65
+ /**
66
+ * If the an image resource has multiple `PaintImage`s, we compare its intrinsic size to the largest of the displayed sizes.
67
+ *
68
+ * It is theoretically possible for `PaintImage` events with the same URL to have different intrinsic sizes.
69
+ * However, this should be rare because it requires serving different images from the same URL.
70
+ */
71
+ largestImagePaint: Types.Events.PaintImage;
72
+ }
73
+
74
+ export type ImageDeliveryInsightModel = InsightModel<{
75
+ optimizableImages: OptimizableImage[],
76
+ }>;
77
+
78
+ function finalize(partialModel: Omit<ImageDeliveryInsightModel, 'title'|'description'|'category'|'shouldShow'>):
79
+ ImageDeliveryInsightModel {
80
+ return {
81
+ title: i18nString(UIStrings.title),
82
+ description: i18nString(UIStrings.description),
83
+ category: InsightCategory.LCP,
84
+ shouldShow: partialModel.optimizableImages.length > 0,
85
+ ...partialModel,
86
+ relatedEvents: partialModel.optimizableImages.map(image => image.request),
87
+ };
88
+ }
89
+
90
+ /**
91
+ * Calculate rough savings percentage based on 1000 real gifs transcoded to video
92
+ * https://github.com/GoogleChrome/lighthouse/issues/4696#issuecomment-380296510
93
+ */
94
+ function estimateGIFPercentSavings(request: Types.Events.SyntheticNetworkRequest): number {
95
+ return Math.round((29.1 * Math.log10(request.args.data.decodedBodyLength) - 100.7)) / 100;
96
+ }
97
+
98
+ function getPixelCounts(paintImage: Types.Events.PaintImage): {displayedPixels: number, filePixels: number} {
99
+ return {
100
+ filePixels: paintImage.args.data.srcWidth * paintImage.args.data.srcHeight,
101
+ displayedPixels: paintImage.args.data.width * paintImage.args.data.height,
102
+ };
103
+ }
104
+
105
+ export function generateInsight(
106
+ parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): ImageDeliveryInsightModel {
107
+ const isWithinContext = (event: Types.Events.Event): boolean => Helpers.Timing.eventIsInBounds(event, context.bounds);
108
+
109
+ const contextRequests = parsedTrace.NetworkRequests.byTime.filter(isWithinContext);
110
+
111
+ const optimizableImages: OptimizableImage[] = [];
112
+ for (const request of contextRequests) {
113
+ if (request.args.data.resourceType !== 'Image') {
114
+ continue;
115
+ }
116
+
117
+ const imagePaints =
118
+ parsedTrace.ImagePainting.paintImageEventForUrl.get(request.args.data.url)?.filter(isWithinContext);
119
+
120
+ // This will filter out things like preloaded image requests where an image file is downloaded
121
+ // but never rendered on the page.
122
+ if (!imagePaints?.length) {
123
+ continue;
124
+ }
125
+
126
+ const largestImagePaint = imagePaints.reduce((prev, curr) => {
127
+ const prevPixels = getPixelCounts(prev).displayedPixels;
128
+ const currPixels = getPixelCounts(curr).displayedPixels;
129
+ return prevPixels > currPixels ? prev : curr;
130
+ });
131
+
132
+ const {
133
+ filePixels: imageFilePixels,
134
+ displayedPixels: largestImageDisplayPixels,
135
+ } = getPixelCounts(largestImagePaint);
136
+
137
+ // Decoded body length is almost always the right one to be using because of the below:
138
+ // `encodedDataLength = decodedBodyLength + headers`.
139
+ // HOWEVER, there are some cases where an image is compressed again over the network and transfer size
140
+ // is smaller (see https://github.com/GoogleChrome/lighthouse/pull/4968).
141
+ // Use the min of the two numbers to be safe.
142
+ const imageBytes = Math.min(request.args.data.decodedBodyLength, request.args.data.encodedDataLength);
143
+
144
+ const bytesPerPixel = imageBytes / imageFilePixels;
145
+
146
+ let optimizations: ImageOptimization[] = [];
147
+ if (request.args.data.mimeType === 'image/gif') {
148
+ if (imageBytes > GIF_SIZE_THRESHOLD) {
149
+ const percentSavings = estimateGIFPercentSavings(request);
150
+ const byteSavings = Math.round(imageBytes * percentSavings);
151
+ optimizations.push({type: 'video-format', byteSavings});
152
+ }
153
+ } else if (bytesPerPixel > TARGET_BYTES_PER_PIXEL_AVIF) {
154
+ const idealAvifImageSize = Math.round(TARGET_BYTES_PER_PIXEL_AVIF * imageFilePixels);
155
+ const byteSavings = imageBytes - idealAvifImageSize;
156
+ if (request.args.data.mimeType !== 'image/webp' && request.args.data.mimeType !== 'image/avif') {
157
+ optimizations.push({type: 'modern-format-or-compression', byteSavings});
158
+ } else {
159
+ optimizations.push({type: 'compression', byteSavings});
160
+ }
161
+ }
162
+
163
+ const wastedPixelRatio = 1 - (largestImageDisplayPixels / imageFilePixels);
164
+ if (wastedPixelRatio > 0) {
165
+ const byteSavings = Math.round(wastedPixelRatio * imageBytes);
166
+ optimizations.push({type: 'responsive-size', byteSavings});
167
+ }
168
+
169
+ optimizations = optimizations.filter(optimization => optimization.byteSavings > BYTE_SAVINGS_THRESHOLD);
170
+
171
+ if (optimizations.length > 0) {
172
+ optimizableImages.push({
173
+ request,
174
+ largestImagePaint,
175
+ optimizations,
176
+ });
177
+ }
178
+ }
179
+
180
+ return finalize({
181
+ optimizableImages,
182
+ });
183
+ }
@@ -6,7 +6,7 @@ import * as i18n from '../../../core/i18n/i18n.js';
6
6
  import * as Helpers from '../helpers/helpers.js';
7
7
  import type {SyntheticInteractionPair} from '../types/TraceEvents.js';
8
8
 
9
- import type {InsightModel, InsightSetContext, RequiredData} from './types.js';
9
+ import {InsightCategory, type InsightModel, type InsightSetContext, type RequiredData} from './types.js';
10
10
 
11
11
  const UIStrings = {
12
12
  /**
@@ -32,8 +32,14 @@ export type INPInsightModel = InsightModel<{
32
32
  highPercentileInteractionEvent?: SyntheticInteractionPair,
33
33
  }>;
34
34
 
35
- function finalize(partialModel: Omit<INPInsightModel, 'title'|'description'>): INPInsightModel {
36
- return {title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel};
35
+ function finalize(partialModel: Omit<INPInsightModel, 'title'|'description'|'category'|'shouldShow'>): INPInsightModel {
36
+ return {
37
+ title: i18nString(UIStrings.title),
38
+ description: i18nString(UIStrings.description),
39
+ category: InsightCategory.INP,
40
+ shouldShow: Boolean(partialModel.longestInteractionEvent),
41
+ ...partialModel,
42
+ };
37
43
  }
38
44
 
39
45
  export function generateInsight(parsedTrace: RequiredData<typeof deps>, context: InsightSetContext): INPInsightModel {
@@ -7,7 +7,13 @@ import * as Handlers from '../handlers/handlers.js';
7
7
  import * as Helpers from '../helpers/helpers.js';
8
8
  import * as Types from '../types/types.js';
9
9
 
10
- import {type InsightModel, type InsightSetContext, InsightWarning, type RequiredData} from './types.js';
10
+ import {
11
+ InsightCategory,
12
+ type InsightModel,
13
+ type InsightSetContext,
14
+ InsightWarning,
15
+ type RequiredData,
16
+ } from './types.js';
11
17
 
12
18
  const UIStrings = {
13
19
  /**
@@ -38,8 +44,23 @@ export type LCPDiscoveryInsightModel = InsightModel<{
38
44
  earliestDiscoveryTimeTs?: Types.Timing.MicroSeconds,
39
45
  }>;
40
46
 
41
- function finalize(partialModel: Omit<LCPDiscoveryInsightModel, 'title'|'description'>): LCPDiscoveryInsightModel {
42
- return {title: i18nString(UIStrings.title), description: i18nString(UIStrings.description), ...partialModel};
47
+ function finalize(partialModel: Omit<LCPDiscoveryInsightModel, 'title'|'description'|'category'|'shouldShow'>):
48
+ LCPDiscoveryInsightModel {
49
+ const relatedEvents = partialModel.lcpEvent && partialModel.lcpRequest ?
50
+ // TODO: add entire request initiator chain?
51
+ [partialModel.lcpEvent, partialModel.lcpRequest] :
52
+ [];
53
+ return {
54
+ title: i18nString(UIStrings.title),
55
+ description: i18nString(UIStrings.description),
56
+ category: InsightCategory.LCP,
57
+ shouldShow: Boolean(
58
+ partialModel.lcpRequest &&
59
+ (partialModel.shouldIncreasePriorityHint || partialModel.shouldPreloadImage ||
60
+ partialModel.shouldRemoveLazyLoading)),
61
+ ...partialModel,
62
+ relatedEvents,
63
+ };
43
64
  }
44
65
 
45
66
  export function generateInsight(