chrome-devtools-frontend 1.0.1526630 → 1.0.1528866

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 (319) hide show
  1. package/docs/ui_engineering.md +159 -0
  2. package/eslint.config.mjs +6 -1
  3. package/front_end/core/i18n/i18nImpl.ts +6 -1
  4. package/front_end/core/protocol_client/protocol_client.ts +1 -1
  5. package/front_end/core/root/Runtime.ts +28 -4
  6. package/front_end/core/sdk/CSSMatchedStyles.ts +50 -7
  7. package/front_end/core/sdk/CSSRule.ts +35 -6
  8. package/front_end/core/sdk/Connections.ts +2 -1
  9. package/front_end/core/sdk/DOMModel.ts +4 -0
  10. package/front_end/core/sdk/DebuggerModel.ts +5 -1
  11. package/front_end/core/sdk/NetworkManager.ts +214 -31
  12. package/front_end/core/sdk/PreloadingModel.ts +82 -17
  13. package/front_end/core/sdk/RehydratingConnection.snapshot.txt +1 -1
  14. package/front_end/core/sdk/RehydratingConnection.ts +29 -4
  15. package/front_end/core/sdk/ScopeTreeCache.ts +8 -3
  16. package/front_end/core/sdk/SourceMap.ts +37 -11
  17. package/front_end/core/sdk/SourceMapManager.ts +13 -2
  18. package/front_end/core/sdk/SourceMapScopesInfo.ts +17 -0
  19. package/front_end/core/sdk/TargetManager.ts +0 -22
  20. package/front_end/core/sdk/TraceObject.ts +8 -7
  21. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +81 -0
  22. package/front_end/entrypoints/inspector_main/InspectorMain.ts +3 -1
  23. package/front_end/entrypoints/main/GlobalAiButton.ts +1 -0
  24. package/front_end/entrypoints/main/MainImpl.ts +20 -25
  25. package/front_end/generated/InspectorBackendCommands.js +3 -2
  26. package/front_end/generated/protocol.ts +17 -3
  27. package/front_end/models/ai_assistance/BuiltInAi.ts +111 -0
  28. package/front_end/models/ai_assistance/ai_assistance.ts +53 -24
  29. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +105 -0
  30. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +6 -1
  31. package/front_end/models/extensions/ExtensionView.ts +3 -0
  32. package/front_end/models/javascript_metadata/NativeFunctions.js +23 -27
  33. package/front_end/models/live-metrics/web-vitals-injected/web-vitals-injected.ts +31 -29
  34. package/front_end/models/persistence/EditFileSystemView.ts +1 -0
  35. package/front_end/models/source_map_scopes/NamesResolver.ts +5 -11
  36. package/front_end/models/stack_trace/Trie.ts +9 -0
  37. package/front_end/models/trace/lantern/types/Lantern.ts +1 -1
  38. package/front_end/panels/accessibility/AXBreadcrumbsPane.ts +1 -0
  39. package/front_end/panels/accessibility/AccessibilitySidebarView.ts +1 -0
  40. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +120 -113
  41. package/front_end/panels/ai_assistance/PatchWidget.ts +9 -8
  42. package/front_end/panels/ai_assistance/SelectWorkspaceDialog.ts +2 -0
  43. package/front_end/panels/ai_assistance/components/ChatView.ts +29 -29
  44. package/front_end/panels/ai_assistance/components/UserActionRow.ts +1 -0
  45. package/front_end/panels/animation/AnimationTimeline.ts +1 -0
  46. package/front_end/panels/application/CookieItemsView.ts +1 -0
  47. package/front_end/panels/application/KeyValueStorageItemsView.ts +1 -0
  48. package/front_end/panels/application/ServiceWorkerCacheViews.ts +2 -0
  49. package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +11 -5
  50. package/front_end/panels/application/preloading/components/PreloadingMismatchedHeadersGrid.ts +2 -2
  51. package/front_end/panels/application/preloading/components/PreloadingString.ts +7 -5
  52. package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +22 -10
  53. package/front_end/panels/changes/CombinedDiffView.ts +1 -0
  54. package/front_end/panels/console/ConsoleInsightTeaser.ts +106 -0
  55. package/front_end/panels/console/ConsolePanel.ts +2 -0
  56. package/front_end/panels/console/ConsolePrompt.ts +12 -2
  57. package/front_end/panels/console/ConsoleSidebar.ts +1 -1
  58. package/front_end/panels/console/ConsoleView.ts +12 -0
  59. package/front_end/panels/console/ConsoleViewMessage.ts +27 -0
  60. package/front_end/panels/{explain → console}/PromptBuilder.ts +12 -7
  61. package/front_end/panels/console/console.ts +6 -0
  62. package/front_end/panels/console/consoleInsightTeaser.css +55 -0
  63. package/front_end/panels/coverage/CoverageListView.ts +29 -11
  64. package/front_end/panels/coverage/CoverageView.ts +292 -284
  65. package/front_end/panels/coverage/coverageView.css +17 -0
  66. package/front_end/panels/elements/ComputedStyleWidget.ts +1 -0
  67. package/front_end/panels/elements/LayoutPane.ts +1 -0
  68. package/front_end/panels/elements/NodeStackTraceWidget.ts +1 -0
  69. package/front_end/panels/elements/StylePropertyTreeElement.ts +5 -1
  70. package/front_end/panels/elements/stylePropertiesTreeOutline.css +17 -0
  71. package/front_end/panels/emulation/DeviceModeView.ts +2 -0
  72. package/front_end/panels/explain/ActionDelegate.ts +1 -2
  73. package/front_end/panels/explain/components/ConsoleInsight.ts +14 -12
  74. package/front_end/panels/explain/explain.ts +0 -1
  75. package/front_end/panels/js_timeline/js_timeline-meta.ts +1 -1
  76. package/front_end/panels/layer_viewer/Layers3DView.ts +2 -0
  77. package/front_end/panels/lighthouse/LighthouseReportSelector.ts +1 -0
  78. package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorPane.ts +1 -0
  79. package/front_end/panels/media/MainView.ts +1 -0
  80. package/front_end/panels/media/TickingFlameChart.ts +2 -0
  81. package/front_end/panels/network/BlockedURLsPane.ts +111 -85
  82. package/front_end/panels/network/EventSourceMessagesView.ts +1 -0
  83. package/front_end/panels/network/NetworkItemView.ts +1 -0
  84. package/front_end/panels/network/NetworkLogView.ts +9 -7
  85. package/front_end/panels/network/NetworkOverview.ts +1 -0
  86. package/front_end/panels/network/RequestCookiesView.ts +1 -0
  87. package/front_end/panels/network/RequestHTMLView.ts +1 -0
  88. package/front_end/panels/network/RequestInitiatorView.ts +1 -0
  89. package/front_end/panels/network/RequestPayloadView.ts +1 -0
  90. package/front_end/panels/network/RequestPreviewView.ts +1 -0
  91. package/front_end/panels/network/RequestResponseView.ts +1 -0
  92. package/front_end/panels/network/RequestTimingView.ts +2 -0
  93. package/front_end/panels/network/ResourceDirectSocketChunkView.ts +1 -0
  94. package/front_end/panels/network/ResourceWebSocketFrameView.ts +1 -0
  95. package/front_end/panels/network/components/RequestHeadersView.ts +2 -0
  96. package/front_end/panels/network/components/RequestTrustTokensView.ts +2 -0
  97. package/front_end/panels/performance_monitor/PerformanceMonitor.ts +2 -0
  98. package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +2 -0
  99. package/front_end/panels/profiler/HeapSnapshotView.ts +7 -0
  100. package/front_end/panels/profiler/IsolateSelector.ts +1 -0
  101. package/front_end/panels/profiler/LiveHeapProfileView.ts +1 -0
  102. package/front_end/panels/profiler/ProfileView.ts +1 -0
  103. package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +1 -0
  104. package/front_end/panels/recorder/RecorderPanel.ts +2 -0
  105. package/front_end/panels/screencast/ScreencastView.ts +1 -0
  106. package/front_end/panels/search/SearchView.ts +1 -0
  107. package/front_end/panels/settings/AISettingsTab.ts +3 -3
  108. package/front_end/panels/settings/WorkspaceSettingsTab.ts +2 -0
  109. package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +2 -2
  110. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +12 -0
  111. package/front_end/panels/sources/BreakpointsView.ts +1 -0
  112. package/front_end/panels/sources/DebuggerPlugin.ts +1 -0
  113. package/front_end/panels/sources/UISourceCodeFrame.ts +17 -2
  114. package/front_end/panels/timeline/README.md +2 -2
  115. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +1 -1
  116. package/front_end/panels/timeline/TimelineFlameChartView.ts +4 -3
  117. package/front_end/panels/timeline/TimelineLayersView.ts +1 -0
  118. package/front_end/panels/timeline/TimelinePaintProfilerView.ts +114 -37
  119. package/front_end/panels/timeline/TimelinePanel.ts +43 -62
  120. package/front_end/panels/timeline/TimelineTreeView.ts +1 -0
  121. package/front_end/panels/timeline/components/LiveMetricsView.ts +4 -8
  122. package/front_end/panels/timeline/components/Sidebar.ts +2 -0
  123. package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +1 -1
  124. package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +7 -7
  125. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +1 -1
  126. package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +4 -4
  127. package/front_end/panels/web_audio/WebAudioView.ts +1 -0
  128. package/front_end/third_party/chromium/README.chromium +1 -1
  129. package/front_end/third_party/lighthouse/README.chromium +2 -2
  130. package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1530 -2426
  131. package/front_end/third_party/lighthouse/locales/ar-XB.json +107 -455
  132. package/front_end/third_party/lighthouse/locales/ar.json +107 -455
  133. package/front_end/third_party/lighthouse/locales/bg.json +96 -444
  134. package/front_end/third_party/lighthouse/locales/ca.json +96 -444
  135. package/front_end/third_party/lighthouse/locales/cs.json +96 -444
  136. package/front_end/third_party/lighthouse/locales/da.json +96 -444
  137. package/front_end/third_party/lighthouse/locales/de.json +96 -444
  138. package/front_end/third_party/lighthouse/locales/el.json +96 -444
  139. package/front_end/third_party/lighthouse/locales/en-GB.json +96 -444
  140. package/front_end/third_party/lighthouse/locales/en-US.json +116 -467
  141. package/front_end/third_party/lighthouse/locales/en-XA.json +93 -441
  142. package/front_end/third_party/lighthouse/locales/en-XL.json +116 -467
  143. package/front_end/third_party/lighthouse/locales/es-419.json +96 -444
  144. package/front_end/third_party/lighthouse/locales/es.json +96 -444
  145. package/front_end/third_party/lighthouse/locales/fi.json +96 -444
  146. package/front_end/third_party/lighthouse/locales/fil.json +96 -444
  147. package/front_end/third_party/lighthouse/locales/fr.json +96 -444
  148. package/front_end/third_party/lighthouse/locales/he.json +118 -466
  149. package/front_end/third_party/lighthouse/locales/hi.json +96 -444
  150. package/front_end/third_party/lighthouse/locales/hr.json +100 -448
  151. package/front_end/third_party/lighthouse/locales/hu.json +96 -444
  152. package/front_end/third_party/lighthouse/locales/id.json +96 -444
  153. package/front_end/third_party/lighthouse/locales/it.json +96 -444
  154. package/front_end/third_party/lighthouse/locales/ja.json +96 -444
  155. package/front_end/third_party/lighthouse/locales/ko.json +97 -445
  156. package/front_end/third_party/lighthouse/locales/lt.json +96 -444
  157. package/front_end/third_party/lighthouse/locales/lv.json +97 -445
  158. package/front_end/third_party/lighthouse/locales/nl.json +96 -444
  159. package/front_end/third_party/lighthouse/locales/no.json +96 -444
  160. package/front_end/third_party/lighthouse/locales/pl.json +96 -444
  161. package/front_end/third_party/lighthouse/locales/pt-PT.json +96 -444
  162. package/front_end/third_party/lighthouse/locales/pt.json +97 -445
  163. package/front_end/third_party/lighthouse/locales/ro.json +97 -445
  164. package/front_end/third_party/lighthouse/locales/ru.json +96 -444
  165. package/front_end/third_party/lighthouse/locales/sk.json +96 -444
  166. package/front_end/third_party/lighthouse/locales/sl.json +96 -444
  167. package/front_end/third_party/lighthouse/locales/sr-Latn.json +96 -444
  168. package/front_end/third_party/lighthouse/locales/sr.json +96 -444
  169. package/front_end/third_party/lighthouse/locales/sv.json +96 -444
  170. package/front_end/third_party/lighthouse/locales/ta.json +96 -444
  171. package/front_end/third_party/lighthouse/locales/te.json +97 -445
  172. package/front_end/third_party/lighthouse/locales/th.json +96 -444
  173. package/front_end/third_party/lighthouse/locales/tr.json +96 -444
  174. package/front_end/third_party/lighthouse/locales/uk.json +96 -444
  175. package/front_end/third_party/lighthouse/locales/vi.json +96 -444
  176. package/front_end/third_party/lighthouse/locales/zh-HK.json +96 -444
  177. package/front_end/third_party/lighthouse/locales/zh-TW.json +97 -445
  178. package/front_end/third_party/lighthouse/locales/zh.json +96 -444
  179. package/front_end/third_party/lighthouse/report/bundle.d.ts +8 -14
  180. package/front_end/third_party/lighthouse/report/bundle.js +10 -49
  181. package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +1 -1
  182. package/front_end/third_party/web-vitals/README.chromium +5 -8
  183. package/front_end/third_party/web-vitals/package/README.md +191 -152
  184. package/front_end/third_party/web-vitals/package/dist/modules/attribution/index.d.ts +0 -1
  185. package/front_end/third_party/web-vitals/package/dist/modules/attribution/index.js +0 -1
  186. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onCLS.d.ts +2 -2
  187. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onCLS.js +45 -26
  188. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onFCP.d.ts +2 -2
  189. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onFCP.js +3 -3
  190. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onINP.d.ts +10 -10
  191. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onINP.js +307 -206
  192. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onLCP.d.ts +2 -2
  193. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onLCP.js +69 -49
  194. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onTTFB.d.ts +2 -2
  195. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onTTFB.js +2 -2
  196. package/front_end/third_party/web-vitals/package/dist/modules/index.d.ts +0 -1
  197. package/front_end/third_party/web-vitals/package/dist/modules/index.js +0 -1
  198. package/front_end/third_party/web-vitals/package/dist/modules/lib/InteractionManager.d.ts +33 -0
  199. package/front_end/third_party/web-vitals/package/dist/modules/lib/InteractionManager.js +111 -0
  200. package/front_end/third_party/web-vitals/package/dist/modules/lib/LCPEntryManager.d.ts +4 -0
  201. package/front_end/third_party/web-vitals/package/dist/modules/{attribution/deprecated.js → lib/LCPEntryManager.js} +6 -7
  202. package/front_end/third_party/web-vitals/package/dist/modules/lib/LayoutShiftManager.d.ts +6 -0
  203. package/front_end/third_party/web-vitals/package/dist/modules/lib/LayoutShiftManager.js +44 -0
  204. package/front_end/third_party/web-vitals/package/dist/modules/lib/bindReporter.js +1 -1
  205. package/front_end/third_party/web-vitals/package/dist/modules/lib/generateUniqueID.js +1 -1
  206. package/front_end/third_party/web-vitals/package/dist/modules/lib/getActivationStart.js +1 -1
  207. package/front_end/third_party/web-vitals/package/dist/modules/lib/getNavigationEntry.js +5 -7
  208. package/front_end/third_party/web-vitals/package/dist/modules/lib/getSelector.d.ts +1 -1
  209. package/front_end/third_party/web-vitals/package/dist/modules/lib/getSelector.js +9 -12
  210. package/front_end/third_party/web-vitals/package/dist/modules/lib/getVisibilityWatcher.d.ts +1 -0
  211. package/front_end/third_party/web-vitals/package/dist/modules/lib/getVisibilityWatcher.js +52 -33
  212. package/front_end/third_party/web-vitals/package/dist/modules/lib/initMetric.d.ts +0 -2
  213. package/front_end/third_party/web-vitals/package/dist/modules/lib/initMetric.js +2 -2
  214. package/front_end/third_party/web-vitals/package/dist/modules/lib/initUnique.d.ts +6 -0
  215. package/front_end/third_party/web-vitals/package/dist/modules/{deprecated.js → lib/initUnique.js} +11 -4
  216. package/front_end/third_party/web-vitals/package/dist/modules/lib/observe.js +3 -6
  217. package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/interactionCountPolyfill.js +6 -6
  218. package/front_end/third_party/web-vitals/package/dist/modules/lib/{whenIdle.d.ts → whenIdleOrHidden.d.ts} +1 -1
  219. package/front_end/third_party/web-vitals/package/dist/modules/lib/{whenIdle.js → whenIdleOrHidden.js} +10 -8
  220. package/front_end/third_party/web-vitals/package/dist/modules/onCLS.js +17 -35
  221. package/front_end/third_party/web-vitals/package/dist/modules/onFCP.js +3 -5
  222. package/front_end/third_party/web-vitals/package/dist/modules/onINP.d.ts +9 -7
  223. package/front_end/third_party/web-vitals/package/dist/modules/onINP.js +27 -19
  224. package/front_end/third_party/web-vitals/package/dist/modules/onLCP.js +33 -26
  225. package/front_end/third_party/web-vitals/package/dist/modules/onTTFB.js +2 -4
  226. package/front_end/third_party/web-vitals/package/dist/modules/types/base.d.ts +6 -5
  227. package/front_end/third_party/web-vitals/package/dist/modules/types/cls.d.ts +5 -3
  228. package/front_end/third_party/web-vitals/package/dist/modules/types/inp.d.ts +80 -33
  229. package/front_end/third_party/web-vitals/package/dist/modules/types/lcp.d.ts +6 -2
  230. package/front_end/third_party/web-vitals/package/dist/modules/types.d.ts +28 -4
  231. package/front_end/third_party/web-vitals/package/dist/modules/types.js +0 -1
  232. package/front_end/third_party/web-vitals/package/package.json +4 -10
  233. package/front_end/third_party/web-vitals/package/src/attribution/index.ts +0 -1
  234. package/front_end/third_party/web-vitals/package/src/attribution/onCLS.ts +58 -33
  235. package/front_end/third_party/web-vitals/package/src/attribution/onFCP.ts +4 -4
  236. package/front_end/third_party/web-vitals/package/src/attribution/onINP.ts +382 -258
  237. package/front_end/third_party/web-vitals/package/src/attribution/onLCP.ts +96 -69
  238. package/front_end/third_party/web-vitals/package/src/attribution/onTTFB.ts +3 -3
  239. package/front_end/third_party/web-vitals/package/src/index.ts +0 -1
  240. package/front_end/third_party/web-vitals/package/src/lib/InteractionManager.ts +146 -0
  241. package/front_end/third_party/web-vitals/package/src/{attribution/deprecated.ts → lib/LCPEntryManager.ts} +6 -9
  242. package/front_end/third_party/web-vitals/package/src/lib/LayoutShiftManager.ts +50 -0
  243. package/front_end/third_party/web-vitals/package/src/lib/bindReporter.ts +1 -1
  244. package/front_end/third_party/web-vitals/package/src/lib/generateUniqueID.ts +1 -1
  245. package/front_end/third_party/web-vitals/package/src/lib/getActivationStart.ts +1 -1
  246. package/front_end/third_party/web-vitals/package/src/lib/getNavigationEntry.ts +5 -8
  247. package/front_end/third_party/web-vitals/package/src/lib/getSelector.ts +12 -12
  248. package/front_end/third_party/web-vitals/package/src/lib/getVisibilityWatcher.ts +57 -35
  249. package/front_end/third_party/web-vitals/package/src/lib/initMetric.ts +2 -2
  250. package/front_end/third_party/web-vitals/package/src/{deprecated.ts → lib/initUnique.ts} +14 -8
  251. package/front_end/third_party/web-vitals/package/src/lib/observe.ts +3 -11
  252. package/front_end/third_party/web-vitals/package/src/lib/polyfills/interactionCountPolyfill.ts +12 -6
  253. package/front_end/third_party/web-vitals/package/src/lib/{whenIdle.ts → whenIdleOrHidden.ts} +10 -8
  254. package/front_end/third_party/web-vitals/package/src/onCLS.ts +17 -38
  255. package/front_end/third_party/web-vitals/package/src/onFCP.ts +3 -6
  256. package/front_end/third_party/web-vitals/package/src/onINP.ts +33 -28
  257. package/front_end/third_party/web-vitals/package/src/onLCP.ts +36 -29
  258. package/front_end/third_party/web-vitals/package/src/onTTFB.ts +2 -5
  259. package/front_end/third_party/web-vitals/package/src/types/base.ts +5 -5
  260. package/front_end/third_party/web-vitals/package/src/types/cls.ts +5 -3
  261. package/front_end/third_party/web-vitals/package/src/types/inp.ts +88 -33
  262. package/front_end/third_party/web-vitals/package/src/types/lcp.ts +6 -2
  263. package/front_end/third_party/web-vitals/package/src/types.ts +47 -4
  264. package/front_end/third_party/web-vitals/patches/0001-Add-onEachInteraction-to-onINP-options.patch +75 -0
  265. package/front_end/third_party/web-vitals/rebuild.sh +32 -18
  266. package/front_end/third_party/web-vitals/web-vitals-tsconfig.json +5 -10
  267. package/front_end/third_party/web-vitals/web-vitals.ts +0 -2
  268. package/front_end/ui/components/docs/console_insight/basic.ts +3 -2
  269. package/front_end/ui/components/legacy_wrapper/LegacyWrapper.ts +2 -0
  270. package/front_end/ui/components/text_editor/TextEditor.ts +0 -2
  271. package/front_end/ui/legacy/InspectorView.ts +2 -0
  272. package/front_end/ui/legacy/SplitWidget.ts +2 -0
  273. package/front_end/ui/legacy/TabbedPane.ts +1 -0
  274. package/front_end/ui/legacy/TargetCrashedScreen.ts +1 -0
  275. package/front_end/ui/legacy/UIUtils.ts +8 -19
  276. package/front_end/ui/legacy/ViewManager.ts +1 -0
  277. package/front_end/ui/legacy/components/color_picker/FormatPickerContextMenu.ts +7 -20
  278. package/front_end/ui/legacy/components/color_picker/Spectrum.ts +2 -0
  279. package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +1 -0
  280. package/front_end/ui/legacy/components/inline_editor/BezierEditor.ts +1 -0
  281. package/front_end/ui/legacy/components/perf_ui/ChartViewport.ts +1 -0
  282. package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +1 -0
  283. package/front_end/ui/legacy/components/source_frame/FontView.ts +1 -0
  284. package/front_end/ui/legacy/components/source_frame/ImageView.ts +1 -0
  285. package/front_end/ui/legacy/components/source_frame/JSONView.ts +1 -0
  286. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +1 -0
  287. package/front_end/ui/legacy/components/source_frame/StreamingContentHexView.ts +2 -0
  288. package/front_end/ui/visual_logging/KnownContextValues.ts +17 -0
  289. package/mcp/README.md +7 -0
  290. package/mcp/mcp.ts +8 -0
  291. package/package.json +1 -1
  292. package/front_end/models/live-metrics/web-vitals-injected/OnEachInteraction.ts +0 -34
  293. package/front_end/third_party/web-vitals/package/attribution.d.ts +0 -16
  294. package/front_end/third_party/web-vitals/package/attribution.js +0 -18
  295. package/front_end/third_party/web-vitals/package/dist/modules/attribution/deprecated.d.ts +0 -7
  296. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onFID.d.ts +0 -11
  297. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onFID.js +0 -46
  298. package/front_end/third_party/web-vitals/package/dist/modules/deprecated.d.ts +0 -5
  299. package/front_end/third_party/web-vitals/package/dist/modules/lib/interactions.d.ts +0 -31
  300. package/front_end/third_party/web-vitals/package/dist/modules/lib/interactions.js +0 -107
  301. package/front_end/third_party/web-vitals/package/dist/modules/lib/onHidden.d.ts +0 -1
  302. package/front_end/third_party/web-vitals/package/dist/modules/lib/onHidden.js +0 -22
  303. package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/firstInputPolyfill.d.ts +0 -7
  304. package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/firstInputPolyfill.js +0 -147
  305. package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/getFirstHiddenTimePolyfill.d.ts +0 -1
  306. package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/getFirstHiddenTimePolyfill.js +0 -25
  307. package/front_end/third_party/web-vitals/package/dist/modules/onFID.d.ts +0 -13
  308. package/front_end/third_party/web-vitals/package/dist/modules/onFID.js +0 -70
  309. package/front_end/third_party/web-vitals/package/dist/modules/types/fid.d.ts +0 -46
  310. package/front_end/third_party/web-vitals/package/dist/modules/types/fid.js +0 -16
  311. package/front_end/third_party/web-vitals/package/src/attribution/onFID.ts +0 -62
  312. package/front_end/third_party/web-vitals/package/src/lib/interactions.ts +0 -139
  313. package/front_end/third_party/web-vitals/package/src/lib/onHidden.ts +0 -23
  314. package/front_end/third_party/web-vitals/package/src/lib/polyfills/firstInputPolyfill.ts +0 -174
  315. package/front_end/third_party/web-vitals/package/src/onFID.ts +0 -105
  316. package/front_end/third_party/web-vitals/package/src/types/fid.ts +0 -65
  317. package/front_end/ui/components/text_editor/textEditor.css +0 -18
  318. package/front_end/ui/legacy/inlineButton.css +0 -22
  319. /package/front_end/entrypoints/{rehydrated_devtools_app/rehydrated_devtools_app.ts → trace_app/trace_app.ts} +0 -0
@@ -15,55 +15,9 @@
15
15
  */
16
16
  import { getNavigationEntry } from '../lib/getNavigationEntry.js';
17
17
  import { getSelector } from '../lib/getSelector.js';
18
+ import { initUnique } from '../lib/initUnique.js';
19
+ import { LCPEntryManager } from '../lib/LCPEntryManager.js';
18
20
  import { onLCP as unattributedOnLCP } from '../onLCP.js';
19
- const attributeLCP = (metric) => {
20
- // Use a default object if no other attribution has been set.
21
- let attribution = {
22
- timeToFirstByte: 0,
23
- resourceLoadDelay: 0,
24
- resourceLoadDuration: 0,
25
- elementRenderDelay: metric.value,
26
- };
27
- if (metric.entries.length) {
28
- const navigationEntry = getNavigationEntry();
29
- if (navigationEntry) {
30
- const activationStart = navigationEntry.activationStart || 0;
31
- const lcpEntry = metric.entries[metric.entries.length - 1];
32
- const lcpResourceEntry = lcpEntry.url &&
33
- performance
34
- .getEntriesByType('resource')
35
- .filter((e) => e.name === lcpEntry.url)[0];
36
- const ttfb = Math.max(0, navigationEntry.responseStart - activationStart);
37
- const lcpRequestStart = Math.max(ttfb,
38
- // Prefer `requestStart` (if TOA is set), otherwise use `startTime`.
39
- lcpResourceEntry
40
- ? (lcpResourceEntry.requestStart || lcpResourceEntry.startTime) -
41
- activationStart
42
- : 0);
43
- const lcpResponseEnd = Math.max(lcpRequestStart, lcpResourceEntry ? lcpResourceEntry.responseEnd - activationStart : 0);
44
- const lcpRenderTime = Math.max(lcpResponseEnd, lcpEntry.startTime - activationStart);
45
- attribution = {
46
- element: getSelector(lcpEntry.element),
47
- timeToFirstByte: ttfb,
48
- resourceLoadDelay: lcpRequestStart - ttfb,
49
- resourceLoadDuration: lcpResponseEnd - lcpRequestStart,
50
- elementRenderDelay: lcpRenderTime - lcpResponseEnd,
51
- navigationEntry,
52
- lcpEntry,
53
- };
54
- // Only attribution the URL and resource entry if they exist.
55
- if (lcpEntry.url) {
56
- attribution.url = lcpEntry.url;
57
- }
58
- if (lcpResourceEntry) {
59
- attribution.lcpResourceEntry = lcpResourceEntry;
60
- }
61
- }
62
- }
63
- // Use Object.assign to set property to keep tsc happy.
64
- const metricWithAttribution = Object.assign(metric, { attribution });
65
- return metricWithAttribution;
66
- };
67
21
  /**
68
22
  * Calculates the [LCP](https://web.dev/articles/lcp) value for the current page and
69
23
  * calls the `callback` function once the value is ready (along with the
@@ -75,7 +29,73 @@ const attributeLCP = (metric) => {
75
29
  * performance entry is dispatched, or once the final value of the metric has
76
30
  * been determined.
77
31
  */
78
- export const onLCP = (onReport, opts) => {
32
+ export const onLCP = (onReport, opts = {}) => {
33
+ // Clone the opts object to ensure it's unique, so we can initialize a
34
+ // single instance of the `LCPEntryManager` class that's shared only with
35
+ // this function invocation and the `unattributedOnLCP()` invocation below
36
+ // (which is passed the same `opts` object).
37
+ opts = Object.assign({}, opts);
38
+ const lcpEntryManager = initUnique(opts, LCPEntryManager);
39
+ const lcpTargetMap = new WeakMap();
40
+ lcpEntryManager._onBeforeProcessingEntry = (entry) => {
41
+ const node = entry.element;
42
+ if (node) {
43
+ const customTarget = opts.generateTarget?.(node) ?? getSelector(node);
44
+ lcpTargetMap.set(entry, customTarget);
45
+ }
46
+ };
47
+ const attributeLCP = (metric) => {
48
+ // Use a default object if no other attribution has been set.
49
+ let attribution = {
50
+ timeToFirstByte: 0,
51
+ resourceLoadDelay: 0,
52
+ resourceLoadDuration: 0,
53
+ elementRenderDelay: metric.value,
54
+ };
55
+ if (metric.entries.length) {
56
+ const navigationEntry = getNavigationEntry();
57
+ if (navigationEntry) {
58
+ const activationStart = navigationEntry.activationStart || 0;
59
+ // The `metric.entries.length` check ensures there will be an entry.
60
+ const lcpEntry = metric.entries.at(-1);
61
+ const lcpResourceEntry = lcpEntry.url &&
62
+ performance
63
+ .getEntriesByType('resource')
64
+ .filter((e) => e.name === lcpEntry.url)[0];
65
+ const ttfb = Math.max(0, navigationEntry.responseStart - activationStart);
66
+ const lcpRequestStart = Math.max(ttfb,
67
+ // Prefer `requestStart` (if TOA is set), otherwise use `startTime`.
68
+ lcpResourceEntry
69
+ ? (lcpResourceEntry.requestStart || lcpResourceEntry.startTime) -
70
+ activationStart
71
+ : 0);
72
+ const lcpResponseEnd = Math.min(
73
+ // Cap at LCP time (videos continue downloading after LCP for example)
74
+ metric.value, Math.max(lcpRequestStart, lcpResourceEntry
75
+ ? lcpResourceEntry.responseEnd - activationStart
76
+ : 0));
77
+ attribution = {
78
+ target: lcpTargetMap.get(lcpEntry),
79
+ timeToFirstByte: ttfb,
80
+ resourceLoadDelay: lcpRequestStart - ttfb,
81
+ resourceLoadDuration: lcpResponseEnd - lcpRequestStart,
82
+ elementRenderDelay: metric.value - lcpResponseEnd,
83
+ navigationEntry,
84
+ lcpEntry,
85
+ };
86
+ // Only attribute the URL and resource entry if they exist.
87
+ if (lcpEntry.url) {
88
+ attribution.url = lcpEntry.url;
89
+ }
90
+ if (lcpResourceEntry) {
91
+ attribution.lcpResourceEntry = lcpResourceEntry;
92
+ }
93
+ }
94
+ }
95
+ // Use `Object.assign()` to ensure the original metric object is returned.
96
+ const metricWithAttribution = Object.assign(metric, { attribution });
97
+ return metricWithAttribution;
98
+ };
79
99
  unattributedOnLCP((metric) => {
80
100
  const metricWithAttribution = attributeLCP(metric);
81
101
  onReport(metricWithAttribution);
@@ -1,4 +1,4 @@
1
- import { TTFBMetricWithAttribution, ReportOpts } from '../types.js';
1
+ import { TTFBMetricWithAttribution, AttributionReportOpts } from '../types.js';
2
2
  /**
3
3
  * Calculates the [TTFB](https://web.dev/articles/ttfb) value for the
4
4
  * current page and calls the `callback` function once the page has loaded,
@@ -14,4 +14,4 @@ import { TTFBMetricWithAttribution, ReportOpts } from '../types.js';
14
14
  * includes time spent on DNS lookup, connection negotiation, network latency,
15
15
  * and server processing time.
16
16
  */
17
- export declare const onTTFB: (onReport: (metric: TTFBMetricWithAttribution) => void, opts?: ReportOpts) => void;
17
+ export declare const onTTFB: (onReport: (metric: TTFBMetricWithAttribution) => void, opts?: AttributionReportOpts) => void;
@@ -49,7 +49,7 @@ const attributeTTFB = (metric) => {
49
49
  navigationEntry: navigationEntry,
50
50
  };
51
51
  }
52
- // Use Object.assign to set property to keep tsc happy.
52
+ // Use `Object.assign()` to ensure the original metric object is returned.
53
53
  const metricWithAttribution = Object.assign(metric, { attribution });
54
54
  return metricWithAttribution;
55
55
  };
@@ -68,7 +68,7 @@ const attributeTTFB = (metric) => {
68
68
  * includes time spent on DNS lookup, connection negotiation, network latency,
69
69
  * and server processing time.
70
70
  */
71
- export const onTTFB = (onReport, opts) => {
71
+ export const onTTFB = (onReport, opts = {}) => {
72
72
  unattributedOnTTFB((metric) => {
73
73
  const metricWithAttribution = attributeTTFB(metric);
74
74
  onReport(metricWithAttribution);
@@ -3,5 +3,4 @@ export { onFCP, FCPThresholds } from './onFCP.js';
3
3
  export { onINP, INPThresholds } from './onINP.js';
4
4
  export { onLCP, LCPThresholds } from './onLCP.js';
5
5
  export { onTTFB, TTFBThresholds } from './onTTFB.js';
6
- export * from './deprecated.js';
7
6
  export * from './types.js';
@@ -18,5 +18,4 @@ export { onFCP, FCPThresholds } from './onFCP.js';
18
18
  export { onINP, INPThresholds } from './onINP.js';
19
19
  export { onLCP, LCPThresholds } from './onLCP.js';
20
20
  export { onTTFB, TTFBThresholds } from './onTTFB.js';
21
- export * from './deprecated.js';
22
21
  export * from './types.js';
@@ -0,0 +1,33 @@
1
+ export interface Interaction {
2
+ _latency: number;
3
+ id: number;
4
+ entries: PerformanceEventTiming[];
5
+ }
6
+ export declare class InteractionManager {
7
+ /**
8
+ * A list of longest interactions on the page (by latency) sorted so the
9
+ * longest one is first. The list is at most MAX_INTERACTIONS_TO_CONSIDER
10
+ * long.
11
+ */
12
+ _longestInteractionList: Interaction[];
13
+ /**
14
+ * A mapping of longest interactions by their interaction ID.
15
+ * This is used for faster lookup.
16
+ */
17
+ _longestInteractionMap: Map<number, Interaction>;
18
+ _onBeforeProcessingEntry?: (entry: PerformanceEventTiming) => void;
19
+ _onAfterProcessingINPCandidate?: (interaction: Interaction) => void;
20
+ _resetInteractions(): void;
21
+ /**
22
+ * Returns the estimated p98 longest interaction based on the stored
23
+ * interaction candidates and the interaction count for the current page.
24
+ */
25
+ _estimateP98LongestInteraction(): Interaction;
26
+ /**
27
+ * Takes a performance entry and adds it to the list of worst interactions
28
+ * if its duration is long enough to make it among the worst. If the
29
+ * entry is part of an existing interaction, it is merged and the latency
30
+ * and entries list is updated as needed.
31
+ */
32
+ _processEntry(entry: PerformanceEventTiming): void;
33
+ }
@@ -0,0 +1,111 @@
1
+ /*
2
+ * Copyright 2024 Google LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * https://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { getInteractionCount } from './polyfills/interactionCountPolyfill.js';
17
+ // To prevent unnecessary memory usage on pages with lots of interactions,
18
+ // store at most 10 of the longest interactions to consider as INP candidates.
19
+ const MAX_INTERACTIONS_TO_CONSIDER = 10;
20
+ // Used to store the interaction count after a bfcache restore, since p98
21
+ // interaction latencies should only consider the current navigation.
22
+ let prevInteractionCount = 0;
23
+ /**
24
+ * Returns the interaction count since the last bfcache restore (or for the
25
+ * full page lifecycle if there were no bfcache restores).
26
+ */
27
+ const getInteractionCountForNavigation = () => {
28
+ return getInteractionCount() - prevInteractionCount;
29
+ };
30
+ export class InteractionManager {
31
+ /**
32
+ * A list of longest interactions on the page (by latency) sorted so the
33
+ * longest one is first. The list is at most MAX_INTERACTIONS_TO_CONSIDER
34
+ * long.
35
+ */
36
+ _longestInteractionList = [];
37
+ /**
38
+ * A mapping of longest interactions by their interaction ID.
39
+ * This is used for faster lookup.
40
+ */
41
+ _longestInteractionMap = new Map();
42
+ _onBeforeProcessingEntry;
43
+ _onAfterProcessingINPCandidate;
44
+ _resetInteractions() {
45
+ prevInteractionCount = getInteractionCount();
46
+ this._longestInteractionList.length = 0;
47
+ this._longestInteractionMap.clear();
48
+ }
49
+ /**
50
+ * Returns the estimated p98 longest interaction based on the stored
51
+ * interaction candidates and the interaction count for the current page.
52
+ */
53
+ _estimateP98LongestInteraction() {
54
+ const candidateInteractionIndex = Math.min(this._longestInteractionList.length - 1, Math.floor(getInteractionCountForNavigation() / 50));
55
+ return this._longestInteractionList[candidateInteractionIndex];
56
+ }
57
+ /**
58
+ * Takes a performance entry and adds it to the list of worst interactions
59
+ * if its duration is long enough to make it among the worst. If the
60
+ * entry is part of an existing interaction, it is merged and the latency
61
+ * and entries list is updated as needed.
62
+ */
63
+ _processEntry(entry) {
64
+ this._onBeforeProcessingEntry?.(entry);
65
+ // Skip further processing for entries that cannot be INP candidates.
66
+ if (!(entry.interactionId || entry.entryType === 'first-input'))
67
+ return;
68
+ // The least-long of the 10 longest interactions.
69
+ const minLongestInteraction = this._longestInteractionList.at(-1);
70
+ let interaction = this._longestInteractionMap.get(entry.interactionId);
71
+ // Only process the entry if it's possibly one of the ten longest,
72
+ // or if it's part of an existing interaction.
73
+ if (interaction ||
74
+ this._longestInteractionList.length < MAX_INTERACTIONS_TO_CONSIDER ||
75
+ // If the above conditions are false, `minLongestInteraction` will be set.
76
+ entry.duration > minLongestInteraction._latency) {
77
+ // If the interaction already exists, update it. Otherwise create one.
78
+ if (interaction) {
79
+ // If the new entry has a longer duration, replace the old entries,
80
+ // otherwise add to the array.
81
+ if (entry.duration > interaction._latency) {
82
+ interaction.entries = [entry];
83
+ interaction._latency = entry.duration;
84
+ }
85
+ else if (entry.duration === interaction._latency &&
86
+ entry.startTime === interaction.entries[0].startTime) {
87
+ interaction.entries.push(entry);
88
+ }
89
+ }
90
+ else {
91
+ interaction = {
92
+ id: entry.interactionId,
93
+ entries: [entry],
94
+ _latency: entry.duration,
95
+ };
96
+ this._longestInteractionMap.set(interaction.id, interaction);
97
+ this._longestInteractionList.push(interaction);
98
+ }
99
+ // Sort the entries by latency (descending) and keep only the top ten.
100
+ this._longestInteractionList.sort((a, b) => b._latency - a._latency);
101
+ if (this._longestInteractionList.length > MAX_INTERACTIONS_TO_CONSIDER) {
102
+ const removedInteractions = this._longestInteractionList.splice(MAX_INTERACTIONS_TO_CONSIDER);
103
+ for (const interaction of removedInteractions) {
104
+ this._longestInteractionMap.delete(interaction.id);
105
+ }
106
+ }
107
+ // Call any post-processing on the interaction
108
+ this._onAfterProcessingINPCandidate?.(interaction);
109
+ }
110
+ }
111
+ }
@@ -0,0 +1,4 @@
1
+ export declare class LCPEntryManager {
2
+ _onBeforeProcessingEntry?: (entry: LargestContentfulPaint) => void;
3
+ _processEntry(entry: LargestContentfulPaint): void;
4
+ }
@@ -13,10 +13,9 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- export {
17
- /**
18
- * @deprecated Use `onINP()` instead.
19
- */
20
- onFID, } from './onFID.js';
21
- export { FIDThresholds } from '../onFID.js';
22
- export * from '../types.js';
16
+ export class LCPEntryManager {
17
+ _onBeforeProcessingEntry;
18
+ _processEntry(entry) {
19
+ this._onBeforeProcessingEntry?.(entry);
20
+ }
21
+ }
@@ -0,0 +1,6 @@
1
+ export declare class LayoutShiftManager {
2
+ _onAfterProcessingUnexpectedShift?: (entry: LayoutShift) => void;
3
+ _sessionValue: number;
4
+ _sessionEntries: LayoutShift[];
5
+ _processEntry(entry: LayoutShift): void;
6
+ }
@@ -0,0 +1,44 @@
1
+ /*
2
+ * Copyright 2024 Google LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * https://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ export class LayoutShiftManager {
17
+ _onAfterProcessingUnexpectedShift;
18
+ _sessionValue = 0;
19
+ _sessionEntries = [];
20
+ _processEntry(entry) {
21
+ // Only count layout shifts without recent user input.
22
+ if (entry.hadRecentInput)
23
+ return;
24
+ const firstSessionEntry = this._sessionEntries[0];
25
+ const lastSessionEntry = this._sessionEntries.at(-1);
26
+ // If the entry occurred less than 1 second after the previous entry
27
+ // and less than 5 seconds after the first entry in the session,
28
+ // include the entry in the current session. Otherwise, start a new
29
+ // session.
30
+ if (this._sessionValue &&
31
+ firstSessionEntry &&
32
+ lastSessionEntry &&
33
+ entry.startTime - lastSessionEntry.startTime < 1000 &&
34
+ entry.startTime - firstSessionEntry.startTime < 5000) {
35
+ this._sessionValue += entry.value;
36
+ this._sessionEntries.push(entry);
37
+ }
38
+ else {
39
+ this._sessionValue = entry.value;
40
+ this._sessionEntries = [entry];
41
+ }
42
+ this._onAfterProcessingUnexpectedShift?.(entry);
43
+ }
44
+ }
@@ -28,7 +28,7 @@ export const bindReporter = (callback, metric, thresholds, reportAllChanges) =>
28
28
  return (forceReport) => {
29
29
  if (metric.value >= 0) {
30
30
  if (forceReport || reportAllChanges) {
31
- delta = metric.value - (prevValue || 0);
31
+ delta = metric.value - (prevValue ?? 0);
32
32
  // Report the metric if there's a non-zero delta or if no previous
33
33
  // value exists (which can happen in the case of the document becoming
34
34
  // hidden when the metric value is 0).
@@ -19,5 +19,5 @@
19
19
  * @return {string}
20
20
  */
21
21
  export const generateUniqueID = () => {
22
- return `v4-${Date.now()}-${Math.floor(Math.random() * (9e12 - 1)) + 1e12}`;
22
+ return `v5-${Date.now()}-${Math.floor(Math.random() * (9e12 - 1)) + 1e12}`;
23
23
  };
@@ -16,5 +16,5 @@
16
16
  import { getNavigationEntry } from './getNavigationEntry.js';
17
17
  export const getActivationStart = () => {
18
18
  const navEntry = getNavigationEntry();
19
- return (navEntry && navEntry.activationStart) || 0;
19
+ return navEntry?.activationStart ?? 0;
20
20
  };
@@ -14,16 +14,14 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  export const getNavigationEntry = () => {
17
- const navigationEntry = self.performance &&
18
- performance.getEntriesByType &&
19
- performance.getEntriesByType('navigation')[0];
17
+ const navigationEntry = performance.getEntriesByType('navigation')[0];
20
18
  // Check to ensure the `responseStart` property is present and valid.
21
- // In some cases no value is reported by the browser (for
19
+ // In some cases a zero value is reported by the browser (for
22
20
  // privacy/security reasons), and in other cases (bugs) the value is
23
21
  // negative or is larger than the current page time. Ignore these cases:
24
- // https://github.com/GoogleChrome/web-vitals/issues/137
25
- // https://github.com/GoogleChrome/web-vitals/issues/162
26
- // https://github.com/GoogleChrome/web-vitals/issues/275
22
+ // - https://github.com/GoogleChrome/web-vitals/issues/137
23
+ // - https://github.com/GoogleChrome/web-vitals/issues/162
24
+ // - https://github.com/GoogleChrome/web-vitals/issues/275
27
25
  if (navigationEntry &&
28
26
  navigationEntry.responseStart > 0 &&
29
27
  navigationEntry.responseStart < performance.now()) {
@@ -1 +1 @@
1
- export declare const getSelector: (node: Node | null | undefined, maxLen?: number) => string;
1
+ export declare const getSelector: (node: Node | null) => string;
@@ -19,29 +19,26 @@ const getName = (node) => {
19
19
  ? name.toLowerCase()
20
20
  : name.toUpperCase().replace(/^#/, '');
21
21
  };
22
- export const getSelector = (node, maxLen) => {
22
+ const MAX_LEN = 100;
23
+ export const getSelector = (node) => {
23
24
  let sel = '';
24
25
  try {
25
- while (node && node.nodeType !== 9) {
26
+ while (node?.nodeType !== 9) {
26
27
  const el = node;
27
28
  const part = el.id
28
29
  ? '#' + el.id
29
- : getName(el) +
30
- (el.classList &&
31
- el.classList.value &&
32
- el.classList.value.trim() &&
33
- el.classList.value.trim().length
34
- ? '.' + el.classList.value.trim().replace(/\s+/g, '.')
35
- : '');
36
- if (sel.length + part.length > (maxLen || 100) - 1)
30
+ : [getName(el), ...Array.from(el.classList).sort()].join('.');
31
+ if (sel.length + part.length > MAX_LEN - 1) {
37
32
  return sel || part;
33
+ }
38
34
  sel = sel ? part + '>' + sel : part;
39
- if (el.id)
35
+ if (el.id) {
40
36
  break;
37
+ }
41
38
  node = el.parentNode;
42
39
  }
43
40
  }
44
- catch (err) {
41
+ catch {
45
42
  // Do nothing...
46
43
  }
47
44
  return sel;
@@ -1,3 +1,4 @@
1
1
  export declare const getVisibilityWatcher: () => {
2
2
  readonly firstHiddenTime: number;
3
+ onHidden(cb: () => void): void;
3
4
  };
@@ -14,7 +14,9 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { onBFCacheRestore } from './bfcache.js';
17
+ import { getActivationStart } from './getActivationStart.js';
17
18
  let firstHiddenTime = -1;
19
+ const onHiddenFunctions = new Set();
18
20
  const initHiddenTime = () => {
19
21
  // If the document is hidden when this code runs, assume it was always
20
22
  // hidden and the page was loaded in the background, with the one exception
@@ -26,41 +28,56 @@ const initHiddenTime = () => {
26
28
  : Infinity;
27
29
  };
28
30
  const onVisibilityUpdate = (event) => {
29
- // If the document is 'hidden' and no previous hidden timestamp has been
30
- // set, update it based on the current event data.
31
- if (document.visibilityState === 'hidden' && firstHiddenTime > -1) {
32
- // If the event is a 'visibilitychange' event, it means the page was
33
- // visible prior to this change, so the event timestamp is the first
34
- // hidden time.
35
- // However, if the event is not a 'visibilitychange' event, then it must
36
- // be a 'prerenderingchange' event, and the fact that the document is
37
- // still 'hidden' from the above check means the tab was activated
38
- // in a background state and so has always been hidden.
39
- firstHiddenTime = event.type === 'visibilitychange' ? event.timeStamp : 0;
40
- // Remove all listeners now that a `firstHiddenTime` value has been set.
41
- removeChangeListeners();
31
+ // Handle changes to hidden state
32
+ if (document.visibilityState === 'hidden') {
33
+ if (event.type === 'visibilitychange') {
34
+ for (const onHiddenFunction of onHiddenFunctions) {
35
+ onHiddenFunction();
36
+ }
37
+ }
38
+ // If the document is 'hidden' and no previous hidden timestamp has been
39
+ // set (so is infinity), update it based on the current event data.
40
+ if (!isFinite(firstHiddenTime)) {
41
+ // If the event is a 'visibilitychange' event, it means the page was
42
+ // visible prior to this change, so the event timestamp is the first
43
+ // hidden time.
44
+ // However, if the event is not a 'visibilitychange' event, then it must
45
+ // be a 'prerenderingchange' event, and the fact that the document is
46
+ // still 'hidden' from the above check means the tab was activated
47
+ // in a background state and so has always been hidden.
48
+ firstHiddenTime = event.type === 'visibilitychange' ? event.timeStamp : 0;
49
+ // We no longer need the `prerenderingchange` event listener now we've
50
+ // set an initial init time so remove that
51
+ // (we'll keep the visibilitychange one for onHiddenFunction above)
52
+ removeEventListener('prerenderingchange', onVisibilityUpdate, true);
53
+ }
42
54
  }
43
55
  };
44
- const addChangeListeners = () => {
45
- addEventListener('visibilitychange', onVisibilityUpdate, true);
46
- // IMPORTANT: when a page is prerendering, its `visibilityState` is
47
- // 'hidden', so in order to account for cases where this module checks for
48
- // visibility during prerendering, an additional check after prerendering
49
- // completes is also required.
50
- addEventListener('prerenderingchange', onVisibilityUpdate, true);
51
- };
52
- const removeChangeListeners = () => {
53
- removeEventListener('visibilitychange', onVisibilityUpdate, true);
54
- removeEventListener('prerenderingchange', onVisibilityUpdate, true);
55
- };
56
56
  export const getVisibilityWatcher = () => {
57
57
  if (firstHiddenTime < 0) {
58
- // If the document is hidden when this code runs, assume it was hidden
59
- // since navigation start. This isn't a perfect heuristic, but it's the
60
- // best we can do until an API is available to support querying past
61
- // visibilityState.
62
- firstHiddenTime = initHiddenTime();
63
- addChangeListeners();
58
+ // Check if we have a previous hidden `visibility-state` performance entry.
59
+ const activationStart = getActivationStart();
60
+ /* eslint-disable indent */
61
+ const firstVisibilityStateHiddenTime = !document.prerendering
62
+ ? globalThis.performance
63
+ .getEntriesByType('visibility-state')
64
+ .filter((e) => e.name === 'hidden' && e.startTime > activationStart)[0]?.startTime
65
+ : undefined;
66
+ /* eslint-enable indent */
67
+ // Prefer that, but if it's not available and the document is hidden when
68
+ // this code runs, assume it was hidden since navigation start. This isn't
69
+ // a perfect heuristic, but it's the best we can do until the
70
+ // `visibility-state` performance entry becomes available in all browsers.
71
+ firstHiddenTime = firstVisibilityStateHiddenTime ?? initHiddenTime();
72
+ // Listen for visibility changes so we can handle things like bfcache
73
+ // restores and/or prerender without having to examine individual
74
+ // timestamps in detail and also for onHidden function calls.
75
+ addEventListener('visibilitychange', onVisibilityUpdate, true);
76
+ // IMPORTANT: when a page is prerendering, its `visibilityState` is
77
+ // 'hidden', so in order to account for cases where this module checks for
78
+ // visibility during prerendering, an additional check after prerendering
79
+ // completes is also required.
80
+ addEventListener('prerenderingchange', onVisibilityUpdate, true);
64
81
  // Reset the time on bfcache restores.
65
82
  onBFCacheRestore(() => {
66
83
  // Schedule a task in order to track the `visibilityState` once it's
@@ -68,13 +85,15 @@ export const getVisibilityWatcher = () => {
68
85
  // https://bugs.chromium.org/p/chromium/issues/detail?id=1133363
69
86
  setTimeout(() => {
70
87
  firstHiddenTime = initHiddenTime();
71
- addChangeListeners();
72
- }, 0);
88
+ });
73
89
  });
74
90
  }
75
91
  return {
76
92
  get firstHiddenTime() {
77
93
  return firstHiddenTime;
78
94
  },
95
+ onHidden(cb) {
96
+ onHiddenFunctions.add(cb);
97
+ },
79
98
  };
80
99
  };
@@ -8,8 +8,6 @@ export declare const initMetric: <MetricName extends MetricType["name"]>(name: M
8
8
  name: MetricName;
9
9
  }> | Extract<import("../types.js").FCPMetric, {
10
10
  name: MetricName;
11
- }> | Extract<import("../types.js").FIDMetric, {
12
- name: MetricName;
13
11
  }> | Extract<import("../types.js").INPMetric, {
14
12
  name: MetricName;
15
13
  }> | Extract<import("../types.js").LCPMetric, {
@@ -17,7 +17,7 @@ import { getBFCacheRestoreTime } from './bfcache.js';
17
17
  import { generateUniqueID } from './generateUniqueID.js';
18
18
  import { getActivationStart } from './getActivationStart.js';
19
19
  import { getNavigationEntry } from './getNavigationEntry.js';
20
- export const initMetric = (name, value) => {
20
+ export const initMetric = (name, value = -1) => {
21
21
  const navEntry = getNavigationEntry();
22
22
  let navigationType = 'navigate';
23
23
  if (getBFCacheRestoreTime() >= 0) {
@@ -38,7 +38,7 @@ export const initMetric = (name, value) => {
38
38
  const entries = [];
39
39
  return {
40
40
  name,
41
- value: typeof value === 'undefined' ? -1 : value,
41
+ value,
42
42
  rating: 'good', // If needed, will be updated when reported. `const` to keep the type from widening to `string`.
43
43
  delta: 0,
44
44
  entries,