chrome-devtools-frontend 1.0.1526630 → 1.0.1529186

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 (339) hide show
  1. package/docs/ui_engineering.md +159 -0
  2. package/eslint.config.mjs +6 -1
  3. package/front_end/core/host/UserMetrics.ts +2 -1
  4. package/front_end/core/i18n/i18nImpl.ts +6 -1
  5. package/front_end/core/protocol_client/protocol_client.ts +1 -1
  6. package/front_end/core/root/Runtime.ts +38 -4
  7. package/front_end/core/sdk/CSSMatchedStyles.ts +50 -7
  8. package/front_end/core/sdk/CSSRule.ts +35 -6
  9. package/front_end/core/sdk/Connections.ts +2 -1
  10. package/front_end/core/sdk/DOMModel.ts +4 -0
  11. package/front_end/core/sdk/DebuggerModel.ts +5 -1
  12. package/front_end/core/sdk/NetworkManager.ts +267 -34
  13. package/front_end/core/sdk/PreloadingModel.ts +82 -17
  14. package/front_end/core/sdk/RehydratingConnection.snapshot.txt +1 -1
  15. package/front_end/core/sdk/RehydratingConnection.ts +29 -4
  16. package/front_end/core/sdk/ScopeTreeCache.ts +8 -3
  17. package/front_end/core/sdk/SourceMap.ts +41 -11
  18. package/front_end/core/sdk/SourceMapManager.ts +13 -2
  19. package/front_end/core/sdk/SourceMapScopesInfo.ts +49 -2
  20. package/front_end/core/sdk/TargetManager.ts +0 -22
  21. package/front_end/core/sdk/TraceObject.ts +8 -7
  22. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +81 -0
  23. package/front_end/entrypoints/inspector_main/InspectorMain.ts +3 -1
  24. package/front_end/entrypoints/main/GlobalAiButton.ts +1 -0
  25. package/front_end/entrypoints/main/MainImpl.ts +42 -28
  26. package/front_end/generated/InspectorBackendCommands.js +3 -2
  27. package/front_end/generated/SupportedCSSProperties.js +2 -0
  28. package/front_end/generated/protocol.ts +17 -3
  29. package/front_end/models/ai_assistance/BuiltInAi.ts +111 -0
  30. package/front_end/models/ai_assistance/ConversationHandler.ts +15 -14
  31. package/front_end/models/ai_assistance/ai_assistance.ts +53 -24
  32. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +105 -0
  33. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +6 -1
  34. package/front_end/models/extensions/ExtensionView.ts +3 -0
  35. package/front_end/models/javascript_metadata/NativeFunctions.js +31 -27
  36. package/front_end/models/live-metrics/web-vitals-injected/web-vitals-injected.ts +31 -29
  37. package/front_end/models/persistence/NetworkPersistenceManager.ts +3 -5
  38. package/front_end/models/persistence/PersistenceImpl.ts +0 -5
  39. package/front_end/models/persistence/persistence-meta.ts +0 -31
  40. package/front_end/models/persistence/persistence.ts +0 -6
  41. package/front_end/models/source_map_scopes/NamesResolver.ts +5 -11
  42. package/front_end/models/stack_trace/Trie.ts +9 -0
  43. package/front_end/models/trace/lantern/types/Lantern.ts +1 -1
  44. package/front_end/panels/accessibility/AXBreadcrumbsPane.ts +1 -0
  45. package/front_end/panels/accessibility/AccessibilitySidebarView.ts +1 -0
  46. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +120 -113
  47. package/front_end/panels/ai_assistance/PatchWidget.ts +9 -8
  48. package/front_end/panels/ai_assistance/SelectWorkspaceDialog.ts +2 -0
  49. package/front_end/panels/ai_assistance/components/ChatView.ts +29 -29
  50. package/front_end/panels/ai_assistance/components/UserActionRow.ts +1 -0
  51. package/front_end/panels/animation/AnimationTimeline.ts +1 -0
  52. package/front_end/panels/application/CookieItemsView.ts +1 -0
  53. package/front_end/panels/application/KeyValueStorageItemsView.ts +1 -0
  54. package/front_end/panels/application/ServiceWorkerCacheViews.ts +2 -0
  55. package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +11 -5
  56. package/front_end/panels/application/preloading/components/PreloadingMismatchedHeadersGrid.ts +2 -2
  57. package/front_end/panels/application/preloading/components/PreloadingString.ts +7 -5
  58. package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +22 -10
  59. package/front_end/panels/changes/CombinedDiffView.ts +1 -0
  60. package/front_end/{models/persistence → panels/common}/PersistenceUtils.ts +15 -17
  61. package/front_end/panels/common/common.ts +1 -0
  62. package/front_end/panels/console/ConsoleInsightTeaser.ts +369 -0
  63. package/front_end/panels/console/ConsolePanel.ts +2 -0
  64. package/front_end/panels/console/ConsolePrompt.ts +12 -2
  65. package/front_end/panels/console/ConsoleSidebar.ts +1 -1
  66. package/front_end/panels/console/ConsoleView.ts +12 -0
  67. package/front_end/panels/console/ConsoleViewMessage.ts +44 -0
  68. package/front_end/panels/{explain → console}/PromptBuilder.ts +12 -7
  69. package/front_end/panels/console/console-meta.ts +14 -0
  70. package/front_end/panels/console/console.ts +6 -0
  71. package/front_end/panels/console/consoleInsightTeaser.css +83 -0
  72. package/front_end/panels/coverage/CoverageListView.ts +29 -11
  73. package/front_end/panels/coverage/CoverageView.ts +292 -284
  74. package/front_end/panels/coverage/coverageView.css +17 -0
  75. package/front_end/panels/elements/ComputedStyleWidget.ts +1 -0
  76. package/front_end/panels/elements/LayoutPane.ts +1 -0
  77. package/front_end/panels/elements/NodeStackTraceWidget.ts +1 -0
  78. package/front_end/panels/elements/StylePropertyTreeElement.ts +5 -1
  79. package/front_end/panels/elements/stylePropertiesTreeOutline.css +17 -0
  80. package/front_end/panels/emulation/DeviceModeView.ts +2 -0
  81. package/front_end/panels/explain/ActionDelegate.ts +4 -2
  82. package/front_end/panels/explain/components/ConsoleInsight.ts +14 -12
  83. package/front_end/panels/explain/explain-meta.ts +7 -0
  84. package/front_end/panels/explain/explain.ts +0 -1
  85. package/front_end/panels/js_timeline/js_timeline-meta.ts +1 -1
  86. package/front_end/panels/layer_viewer/Layers3DView.ts +2 -0
  87. package/front_end/panels/lighthouse/LighthouseReportSelector.ts +1 -0
  88. package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorPane.ts +1 -0
  89. package/front_end/panels/media/MainView.ts +1 -0
  90. package/front_end/panels/media/TickingFlameChart.ts +2 -0
  91. package/front_end/panels/network/BlockedURLsPane.ts +237 -108
  92. package/front_end/panels/network/EventSourceMessagesView.ts +1 -0
  93. package/front_end/panels/network/NetworkItemView.ts +1 -0
  94. package/front_end/panels/network/NetworkLogView.ts +9 -7
  95. package/front_end/panels/network/NetworkOverview.ts +1 -0
  96. package/front_end/panels/network/RequestCookiesView.ts +1 -0
  97. package/front_end/panels/network/RequestHTMLView.ts +1 -0
  98. package/front_end/panels/network/RequestInitiatorView.ts +1 -0
  99. package/front_end/panels/network/RequestPayloadView.ts +1 -0
  100. package/front_end/panels/network/RequestPreviewView.ts +1 -0
  101. package/front_end/panels/network/RequestResponseView.ts +1 -0
  102. package/front_end/panels/network/RequestTimingView.ts +2 -0
  103. package/front_end/panels/network/ResourceDirectSocketChunkView.ts +1 -0
  104. package/front_end/panels/network/ResourceWebSocketFrameView.ts +1 -0
  105. package/front_end/panels/network/components/RequestHeadersView.ts +2 -0
  106. package/front_end/panels/network/components/RequestTrustTokensView.ts +2 -0
  107. package/front_end/panels/performance_monitor/PerformanceMonitor.ts +2 -0
  108. package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +2 -0
  109. package/front_end/panels/profiler/HeapSnapshotView.ts +7 -0
  110. package/front_end/panels/profiler/IsolateSelector.ts +1 -0
  111. package/front_end/panels/profiler/LiveHeapProfileView.ts +1 -0
  112. package/front_end/panels/profiler/ProfileView.ts +1 -0
  113. package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +1 -0
  114. package/front_end/panels/recorder/RecorderPanel.ts +2 -0
  115. package/front_end/panels/screencast/ScreencastView.ts +1 -0
  116. package/front_end/panels/search/SearchView.ts +1 -0
  117. package/front_end/panels/settings/AISettingsTab.ts +3 -3
  118. package/front_end/{models/persistence → panels/settings}/EditFileSystemView.ts +3 -6
  119. package/front_end/panels/settings/WorkspaceSettingsTab.ts +4 -1
  120. package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +2 -2
  121. package/front_end/panels/settings/settings.ts +2 -0
  122. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +12 -0
  123. package/front_end/panels/sources/BreakpointsView.ts +1 -0
  124. package/front_end/panels/sources/DebuggerPlugin.ts +1 -0
  125. package/front_end/{models/persistence → panels/sources}/PersistenceActions.ts +8 -12
  126. package/front_end/panels/sources/TabbedEditorContainer.ts +2 -1
  127. package/front_end/panels/sources/UISourceCodeFrame.ts +17 -2
  128. package/front_end/panels/sources/sources-meta.ts +15 -0
  129. package/front_end/panels/sources/sources.ts +2 -0
  130. package/front_end/panels/timeline/README.md +2 -2
  131. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +1 -1
  132. package/front_end/panels/timeline/TimelineFlameChartView.ts +4 -3
  133. package/front_end/panels/timeline/TimelineLayersView.ts +1 -0
  134. package/front_end/panels/timeline/TimelinePaintProfilerView.ts +114 -37
  135. package/front_end/panels/timeline/TimelinePanel.ts +43 -62
  136. package/front_end/panels/timeline/TimelineTreeView.ts +1 -0
  137. package/front_end/panels/timeline/components/LiveMetricsView.ts +4 -8
  138. package/front_end/panels/timeline/components/Sidebar.ts +2 -0
  139. package/front_end/panels/timeline/components/SidebarSingleInsightSet.ts +1 -1
  140. package/front_end/panels/timeline/components/insights/BaseInsightComponent.ts +7 -7
  141. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +1 -1
  142. package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +4 -4
  143. package/front_end/panels/utils/utils.ts +2 -1
  144. package/front_end/panels/web_audio/WebAudioView.ts +1 -0
  145. package/front_end/third_party/chromium/README.chromium +1 -1
  146. package/front_end/third_party/diff/diff_match_patch.js +1 -1
  147. package/front_end/third_party/lighthouse/README.chromium +2 -2
  148. package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1530 -2426
  149. package/front_end/third_party/lighthouse/locales/ar-XB.json +107 -455
  150. package/front_end/third_party/lighthouse/locales/ar.json +107 -455
  151. package/front_end/third_party/lighthouse/locales/bg.json +96 -444
  152. package/front_end/third_party/lighthouse/locales/ca.json +96 -444
  153. package/front_end/third_party/lighthouse/locales/cs.json +96 -444
  154. package/front_end/third_party/lighthouse/locales/da.json +96 -444
  155. package/front_end/third_party/lighthouse/locales/de.json +96 -444
  156. package/front_end/third_party/lighthouse/locales/el.json +96 -444
  157. package/front_end/third_party/lighthouse/locales/en-GB.json +96 -444
  158. package/front_end/third_party/lighthouse/locales/en-US.json +116 -467
  159. package/front_end/third_party/lighthouse/locales/en-XA.json +93 -441
  160. package/front_end/third_party/lighthouse/locales/en-XL.json +116 -467
  161. package/front_end/third_party/lighthouse/locales/es-419.json +96 -444
  162. package/front_end/third_party/lighthouse/locales/es.json +96 -444
  163. package/front_end/third_party/lighthouse/locales/fi.json +96 -444
  164. package/front_end/third_party/lighthouse/locales/fil.json +96 -444
  165. package/front_end/third_party/lighthouse/locales/fr.json +96 -444
  166. package/front_end/third_party/lighthouse/locales/he.json +118 -466
  167. package/front_end/third_party/lighthouse/locales/hi.json +96 -444
  168. package/front_end/third_party/lighthouse/locales/hr.json +100 -448
  169. package/front_end/third_party/lighthouse/locales/hu.json +96 -444
  170. package/front_end/third_party/lighthouse/locales/id.json +96 -444
  171. package/front_end/third_party/lighthouse/locales/it.json +96 -444
  172. package/front_end/third_party/lighthouse/locales/ja.json +96 -444
  173. package/front_end/third_party/lighthouse/locales/ko.json +97 -445
  174. package/front_end/third_party/lighthouse/locales/lt.json +96 -444
  175. package/front_end/third_party/lighthouse/locales/lv.json +97 -445
  176. package/front_end/third_party/lighthouse/locales/nl.json +96 -444
  177. package/front_end/third_party/lighthouse/locales/no.json +96 -444
  178. package/front_end/third_party/lighthouse/locales/pl.json +96 -444
  179. package/front_end/third_party/lighthouse/locales/pt-PT.json +96 -444
  180. package/front_end/third_party/lighthouse/locales/pt.json +97 -445
  181. package/front_end/third_party/lighthouse/locales/ro.json +97 -445
  182. package/front_end/third_party/lighthouse/locales/ru.json +96 -444
  183. package/front_end/third_party/lighthouse/locales/sk.json +96 -444
  184. package/front_end/third_party/lighthouse/locales/sl.json +96 -444
  185. package/front_end/third_party/lighthouse/locales/sr-Latn.json +96 -444
  186. package/front_end/third_party/lighthouse/locales/sr.json +96 -444
  187. package/front_end/third_party/lighthouse/locales/sv.json +96 -444
  188. package/front_end/third_party/lighthouse/locales/ta.json +96 -444
  189. package/front_end/third_party/lighthouse/locales/te.json +97 -445
  190. package/front_end/third_party/lighthouse/locales/th.json +96 -444
  191. package/front_end/third_party/lighthouse/locales/tr.json +96 -444
  192. package/front_end/third_party/lighthouse/locales/uk.json +96 -444
  193. package/front_end/third_party/lighthouse/locales/vi.json +96 -444
  194. package/front_end/third_party/lighthouse/locales/zh-HK.json +96 -444
  195. package/front_end/third_party/lighthouse/locales/zh-TW.json +97 -445
  196. package/front_end/third_party/lighthouse/locales/zh.json +96 -444
  197. package/front_end/third_party/lighthouse/report/bundle.d.ts +8 -14
  198. package/front_end/third_party/lighthouse/report/bundle.js +10 -49
  199. package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +1 -1
  200. package/front_end/third_party/web-vitals/README.chromium +5 -8
  201. package/front_end/third_party/web-vitals/package/README.md +191 -152
  202. package/front_end/third_party/web-vitals/package/dist/modules/attribution/index.d.ts +0 -1
  203. package/front_end/third_party/web-vitals/package/dist/modules/attribution/index.js +0 -1
  204. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onCLS.d.ts +2 -2
  205. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onCLS.js +45 -26
  206. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onFCP.d.ts +2 -2
  207. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onFCP.js +3 -3
  208. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onINP.d.ts +10 -10
  209. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onINP.js +307 -206
  210. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onLCP.d.ts +2 -2
  211. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onLCP.js +69 -49
  212. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onTTFB.d.ts +2 -2
  213. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onTTFB.js +2 -2
  214. package/front_end/third_party/web-vitals/package/dist/modules/index.d.ts +0 -1
  215. package/front_end/third_party/web-vitals/package/dist/modules/index.js +0 -1
  216. package/front_end/third_party/web-vitals/package/dist/modules/lib/InteractionManager.d.ts +33 -0
  217. package/front_end/third_party/web-vitals/package/dist/modules/lib/InteractionManager.js +111 -0
  218. package/front_end/third_party/web-vitals/package/dist/modules/lib/LCPEntryManager.d.ts +4 -0
  219. package/front_end/third_party/web-vitals/package/dist/modules/{attribution/deprecated.js → lib/LCPEntryManager.js} +6 -7
  220. package/front_end/third_party/web-vitals/package/dist/modules/lib/LayoutShiftManager.d.ts +6 -0
  221. package/front_end/third_party/web-vitals/package/dist/modules/lib/LayoutShiftManager.js +44 -0
  222. package/front_end/third_party/web-vitals/package/dist/modules/lib/bindReporter.js +1 -1
  223. package/front_end/third_party/web-vitals/package/dist/modules/lib/generateUniqueID.js +1 -1
  224. package/front_end/third_party/web-vitals/package/dist/modules/lib/getActivationStart.js +1 -1
  225. package/front_end/third_party/web-vitals/package/dist/modules/lib/getNavigationEntry.js +5 -7
  226. package/front_end/third_party/web-vitals/package/dist/modules/lib/getSelector.d.ts +1 -1
  227. package/front_end/third_party/web-vitals/package/dist/modules/lib/getSelector.js +9 -12
  228. package/front_end/third_party/web-vitals/package/dist/modules/lib/getVisibilityWatcher.d.ts +1 -0
  229. package/front_end/third_party/web-vitals/package/dist/modules/lib/getVisibilityWatcher.js +52 -33
  230. package/front_end/third_party/web-vitals/package/dist/modules/lib/initMetric.d.ts +0 -2
  231. package/front_end/third_party/web-vitals/package/dist/modules/lib/initMetric.js +2 -2
  232. package/front_end/third_party/web-vitals/package/dist/modules/lib/initUnique.d.ts +6 -0
  233. package/front_end/third_party/web-vitals/package/dist/modules/{deprecated.js → lib/initUnique.js} +11 -4
  234. package/front_end/third_party/web-vitals/package/dist/modules/lib/observe.js +3 -6
  235. package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/interactionCountPolyfill.js +6 -6
  236. package/front_end/third_party/web-vitals/package/dist/modules/lib/{whenIdle.d.ts → whenIdleOrHidden.d.ts} +1 -1
  237. package/front_end/third_party/web-vitals/package/dist/modules/lib/{whenIdle.js → whenIdleOrHidden.js} +10 -8
  238. package/front_end/third_party/web-vitals/package/dist/modules/onCLS.js +17 -35
  239. package/front_end/third_party/web-vitals/package/dist/modules/onFCP.js +3 -5
  240. package/front_end/third_party/web-vitals/package/dist/modules/onINP.d.ts +9 -7
  241. package/front_end/third_party/web-vitals/package/dist/modules/onINP.js +27 -19
  242. package/front_end/third_party/web-vitals/package/dist/modules/onLCP.js +33 -26
  243. package/front_end/third_party/web-vitals/package/dist/modules/onTTFB.js +2 -4
  244. package/front_end/third_party/web-vitals/package/dist/modules/types/base.d.ts +6 -5
  245. package/front_end/third_party/web-vitals/package/dist/modules/types/cls.d.ts +5 -3
  246. package/front_end/third_party/web-vitals/package/dist/modules/types/inp.d.ts +80 -33
  247. package/front_end/third_party/web-vitals/package/dist/modules/types/lcp.d.ts +6 -2
  248. package/front_end/third_party/web-vitals/package/dist/modules/types.d.ts +28 -4
  249. package/front_end/third_party/web-vitals/package/dist/modules/types.js +0 -1
  250. package/front_end/third_party/web-vitals/package/package.json +4 -10
  251. package/front_end/third_party/web-vitals/package/src/attribution/index.ts +0 -1
  252. package/front_end/third_party/web-vitals/package/src/attribution/onCLS.ts +58 -33
  253. package/front_end/third_party/web-vitals/package/src/attribution/onFCP.ts +4 -4
  254. package/front_end/third_party/web-vitals/package/src/attribution/onINP.ts +382 -258
  255. package/front_end/third_party/web-vitals/package/src/attribution/onLCP.ts +96 -69
  256. package/front_end/third_party/web-vitals/package/src/attribution/onTTFB.ts +3 -3
  257. package/front_end/third_party/web-vitals/package/src/index.ts +0 -1
  258. package/front_end/third_party/web-vitals/package/src/lib/InteractionManager.ts +146 -0
  259. package/front_end/third_party/web-vitals/package/src/{attribution/deprecated.ts → lib/LCPEntryManager.ts} +6 -9
  260. package/front_end/third_party/web-vitals/package/src/lib/LayoutShiftManager.ts +50 -0
  261. package/front_end/third_party/web-vitals/package/src/lib/bindReporter.ts +1 -1
  262. package/front_end/third_party/web-vitals/package/src/lib/generateUniqueID.ts +1 -1
  263. package/front_end/third_party/web-vitals/package/src/lib/getActivationStart.ts +1 -1
  264. package/front_end/third_party/web-vitals/package/src/lib/getNavigationEntry.ts +5 -8
  265. package/front_end/third_party/web-vitals/package/src/lib/getSelector.ts +12 -12
  266. package/front_end/third_party/web-vitals/package/src/lib/getVisibilityWatcher.ts +57 -35
  267. package/front_end/third_party/web-vitals/package/src/lib/initMetric.ts +2 -2
  268. package/front_end/third_party/web-vitals/package/src/{deprecated.ts → lib/initUnique.ts} +14 -8
  269. package/front_end/third_party/web-vitals/package/src/lib/observe.ts +3 -11
  270. package/front_end/third_party/web-vitals/package/src/lib/polyfills/interactionCountPolyfill.ts +12 -6
  271. package/front_end/third_party/web-vitals/package/src/lib/{whenIdle.ts → whenIdleOrHidden.ts} +10 -8
  272. package/front_end/third_party/web-vitals/package/src/onCLS.ts +17 -38
  273. package/front_end/third_party/web-vitals/package/src/onFCP.ts +3 -6
  274. package/front_end/third_party/web-vitals/package/src/onINP.ts +33 -28
  275. package/front_end/third_party/web-vitals/package/src/onLCP.ts +36 -29
  276. package/front_end/third_party/web-vitals/package/src/onTTFB.ts +2 -5
  277. package/front_end/third_party/web-vitals/package/src/types/base.ts +5 -5
  278. package/front_end/third_party/web-vitals/package/src/types/cls.ts +5 -3
  279. package/front_end/third_party/web-vitals/package/src/types/inp.ts +88 -33
  280. package/front_end/third_party/web-vitals/package/src/types/lcp.ts +6 -2
  281. package/front_end/third_party/web-vitals/package/src/types.ts +47 -4
  282. package/front_end/third_party/web-vitals/patches/0001-Add-onEachInteraction-to-onINP-options.patch +75 -0
  283. package/front_end/third_party/web-vitals/rebuild.sh +32 -18
  284. package/front_end/third_party/web-vitals/web-vitals-tsconfig.json +5 -10
  285. package/front_end/third_party/web-vitals/web-vitals.ts +0 -2
  286. package/front_end/ui/components/docs/console_insight/basic.ts +3 -2
  287. package/front_end/ui/components/legacy_wrapper/LegacyWrapper.ts +2 -0
  288. package/front_end/ui/components/text_editor/TextEditor.ts +0 -2
  289. package/front_end/ui/legacy/InspectorView.ts +2 -0
  290. package/front_end/ui/legacy/ListWidget.ts +2 -2
  291. package/front_end/ui/legacy/SplitWidget.ts +2 -0
  292. package/front_end/ui/legacy/TabbedPane.ts +1 -0
  293. package/front_end/ui/legacy/TargetCrashedScreen.ts +1 -0
  294. package/front_end/ui/legacy/UIUtils.ts +8 -19
  295. package/front_end/ui/legacy/ViewManager.ts +1 -0
  296. package/front_end/ui/legacy/components/color_picker/FormatPickerContextMenu.ts +7 -20
  297. package/front_end/ui/legacy/components/color_picker/Spectrum.ts +2 -0
  298. package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +1 -0
  299. package/front_end/ui/legacy/components/inline_editor/BezierEditor.ts +1 -0
  300. package/front_end/ui/legacy/components/perf_ui/ChartViewport.ts +1 -0
  301. package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +1 -0
  302. package/front_end/ui/legacy/components/source_frame/FontView.ts +1 -0
  303. package/front_end/ui/legacy/components/source_frame/ImageView.ts +1 -0
  304. package/front_end/ui/legacy/components/source_frame/JSONView.ts +1 -0
  305. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +1 -0
  306. package/front_end/ui/legacy/components/source_frame/StreamingContentHexView.ts +2 -0
  307. package/front_end/ui/visual_logging/KnownContextValues.ts +25 -0
  308. package/mcp/README.md +7 -0
  309. package/mcp/mcp.ts +8 -0
  310. package/package.json +1 -1
  311. package/front_end/models/live-metrics/web-vitals-injected/OnEachInteraction.ts +0 -34
  312. package/front_end/third_party/web-vitals/package/attribution.d.ts +0 -16
  313. package/front_end/third_party/web-vitals/package/attribution.js +0 -18
  314. package/front_end/third_party/web-vitals/package/dist/modules/attribution/deprecated.d.ts +0 -7
  315. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onFID.d.ts +0 -11
  316. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onFID.js +0 -46
  317. package/front_end/third_party/web-vitals/package/dist/modules/deprecated.d.ts +0 -5
  318. package/front_end/third_party/web-vitals/package/dist/modules/lib/interactions.d.ts +0 -31
  319. package/front_end/third_party/web-vitals/package/dist/modules/lib/interactions.js +0 -107
  320. package/front_end/third_party/web-vitals/package/dist/modules/lib/onHidden.d.ts +0 -1
  321. package/front_end/third_party/web-vitals/package/dist/modules/lib/onHidden.js +0 -22
  322. package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/firstInputPolyfill.d.ts +0 -7
  323. package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/firstInputPolyfill.js +0 -147
  324. package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/getFirstHiddenTimePolyfill.d.ts +0 -1
  325. package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/getFirstHiddenTimePolyfill.js +0 -25
  326. package/front_end/third_party/web-vitals/package/dist/modules/onFID.d.ts +0 -13
  327. package/front_end/third_party/web-vitals/package/dist/modules/onFID.js +0 -70
  328. package/front_end/third_party/web-vitals/package/dist/modules/types/fid.d.ts +0 -46
  329. package/front_end/third_party/web-vitals/package/dist/modules/types/fid.js +0 -16
  330. package/front_end/third_party/web-vitals/package/src/attribution/onFID.ts +0 -62
  331. package/front_end/third_party/web-vitals/package/src/lib/interactions.ts +0 -139
  332. package/front_end/third_party/web-vitals/package/src/lib/onHidden.ts +0 -23
  333. package/front_end/third_party/web-vitals/package/src/lib/polyfills/firstInputPolyfill.ts +0 -174
  334. package/front_end/third_party/web-vitals/package/src/onFID.ts +0 -105
  335. package/front_end/third_party/web-vitals/package/src/types/fid.ts +0 -65
  336. package/front_end/ui/components/text_editor/textEditor.css +0 -18
  337. package/front_end/ui/legacy/inlineButton.css +0 -22
  338. /package/front_end/entrypoints/{rehydrated_devtools_app/rehydrated_devtools_app.ts → trace_app/trace_app.ts} +0 -0
  339. /package/front_end/{models/persistence → panels/settings}/editFileSystemView.css +0 -0
@@ -0,0 +1,6 @@
1
+ /**
2
+ * A function that accepts and identity object and a class object and returns
3
+ * either a new instance of that class or an existing instance, if the
4
+ * identity object was previously used.
5
+ */
6
+ export declare function initUnique<T>(identityObj: object, ClassObj: new () => T): T;
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2022 Google LLC
2
+ * Copyright 2024 Google LLC
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -13,8 +13,15 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- export {
16
+ const instanceMap = new WeakMap();
17
17
  /**
18
- * @deprecated Use `onINP()` instead.
18
+ * A function that accepts and identity object and a class object and returns
19
+ * either a new instance of that class or an existing instance, if the
20
+ * identity object was previously used.
19
21
  */
20
- onFID, FIDThresholds, } from './onFID.js';
22
+ export function initUnique(identityObj, ClassObj) {
23
+ if (!instanceMap.get(identityObj)) {
24
+ instanceMap.set(identityObj, new ClassObj());
25
+ }
26
+ return instanceMap.get(identityObj);
27
+ }
@@ -21,7 +21,7 @@
21
21
  * This function also feature-detects entry support and wraps the logic in a
22
22
  * try/catch to avoid errors in unsupporting browsers.
23
23
  */
24
- export const observe = (type, callback, opts) => {
24
+ export const observe = (type, callback, opts = {}) => {
25
25
  try {
26
26
  if (PerformanceObserver.supportedEntryTypes.includes(type)) {
27
27
  const po = new PerformanceObserver((list) => {
@@ -32,14 +32,11 @@ export const observe = (type, callback, opts) => {
32
32
  callback(list.getEntries());
33
33
  });
34
34
  });
35
- po.observe(Object.assign({
36
- type,
37
- buffered: true,
38
- }, opts || {}));
35
+ po.observe({ type, buffered: true, ...opts });
39
36
  return po;
40
37
  }
41
38
  }
42
- catch (e) {
39
+ catch {
43
40
  // Do nothing.
44
41
  }
45
42
  return;
@@ -18,15 +18,15 @@ let interactionCountEstimate = 0;
18
18
  let minKnownInteractionId = Infinity;
19
19
  let maxKnownInteractionId = 0;
20
20
  const updateEstimate = (entries) => {
21
- entries.forEach((e) => {
22
- if (e.interactionId) {
23
- minKnownInteractionId = Math.min(minKnownInteractionId, e.interactionId);
24
- maxKnownInteractionId = Math.max(maxKnownInteractionId, e.interactionId);
21
+ for (const entry of entries) {
22
+ if (entry.interactionId) {
23
+ minKnownInteractionId = Math.min(minKnownInteractionId, entry.interactionId);
24
+ maxKnownInteractionId = Math.max(maxKnownInteractionId, entry.interactionId);
25
25
  interactionCountEstimate = maxKnownInteractionId
26
26
  ? (maxKnownInteractionId - minKnownInteractionId) / 7 + 1
27
27
  : 0;
28
28
  }
29
- });
29
+ }
30
30
  };
31
31
  let po;
32
32
  /**
@@ -34,7 +34,7 @@ let po;
34
34
  * or the polyfill estimate in this module.
35
35
  */
36
36
  export const getInteractionCount = () => {
37
- return po ? interactionCountEstimate : performance.interactionCount || 0;
37
+ return po ? interactionCountEstimate : performance.interactionCount ?? 0;
38
38
  };
39
39
  /**
40
40
  * Feature detects native support or initializes the polyfill if needed.
@@ -2,4 +2,4 @@
2
2
  * Runs the passed callback during the next idle period, or immediately
3
3
  * if the browser's visibility state is (or becomes) hidden.
4
4
  */
5
- export declare const whenIdle: (cb: () => void) => number;
5
+ export declare const whenIdleOrHidden: (cb: () => void) => void;
@@ -13,24 +13,26 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { onHidden } from './onHidden.js';
17
16
  import { runOnce } from './runOnce.js';
18
17
  /**
19
18
  * Runs the passed callback during the next idle period, or immediately
20
19
  * if the browser's visibility state is (or becomes) hidden.
21
20
  */
22
- export const whenIdle = (cb) => {
23
- const rIC = self.requestIdleCallback || self.setTimeout;
24
- let handle = -1;
25
- cb = runOnce(cb);
21
+ export const whenIdleOrHidden = (cb) => {
22
+ const rIC = globalThis.requestIdleCallback || setTimeout;
26
23
  // If the document is hidden, run the callback immediately, otherwise
27
24
  // race an idle callback with the next `visibilitychange` event.
28
25
  if (document.visibilityState === 'hidden') {
29
26
  cb();
30
27
  }
31
28
  else {
32
- handle = rIC(cb);
33
- onHidden(cb);
29
+ cb = runOnce(cb);
30
+ addEventListener('visibilitychange', cb, { once: true, capture: true });
31
+ rIC(() => {
32
+ cb();
33
+ // Remove the above event listener since no longer required.
34
+ // See: https://github.com/GoogleChrome/web-vitals/issues/622
35
+ removeEventListener('visibilitychange', cb, { capture: true });
36
+ });
34
37
  }
35
- return handle;
36
38
  };
@@ -14,13 +14,15 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { onBFCacheRestore } from './lib/bfcache.js';
17
- import { initMetric } from './lib/initMetric.js';
18
- import { observe } from './lib/observe.js';
19
17
  import { bindReporter } from './lib/bindReporter.js';
20
18
  import { doubleRAF } from './lib/doubleRAF.js';
21
- import { onHidden } from './lib/onHidden.js';
19
+ import { initMetric } from './lib/initMetric.js';
20
+ import { initUnique } from './lib/initUnique.js';
21
+ import { LayoutShiftManager } from './lib/LayoutShiftManager.js';
22
+ import { observe } from './lib/observe.js';
22
23
  import { runOnce } from './lib/runOnce.js';
23
24
  import { onFCP } from './onFCP.js';
25
+ import { getVisibilityWatcher } from './lib/getVisibilityWatcher.js';
24
26
  /** Thresholds for CLS. See https://web.dev/articles/cls#what_is_a_good_cls_score */
25
27
  export const CLSThresholds = [0.1, 0.25];
26
28
  /**
@@ -44,57 +46,37 @@ export const CLSThresholds = [0.1, 0.25];
44
46
  * hidden. As a result, the `callback` function might be called multiple times
45
47
  * during the same page load._
46
48
  */
47
- export const onCLS = (onReport, opts) => {
48
- // Set defaults
49
- opts = opts || {};
49
+ export const onCLS = (onReport, opts = {}) => {
50
+ const visibilityWatcher = getVisibilityWatcher();
50
51
  // Start monitoring FCP so we can only report CLS if FCP is also reported.
51
52
  // Note: this is done to match the current behavior of CrUX.
52
53
  onFCP(runOnce(() => {
53
54
  let metric = initMetric('CLS', 0);
54
55
  let report;
55
- let sessionValue = 0;
56
- let sessionEntries = [];
56
+ const layoutShiftManager = initUnique(opts, LayoutShiftManager);
57
57
  const handleEntries = (entries) => {
58
- entries.forEach((entry) => {
59
- // Only count layout shifts without recent user input.
60
- if (!entry.hadRecentInput) {
61
- const firstSessionEntry = sessionEntries[0];
62
- const lastSessionEntry = sessionEntries[sessionEntries.length - 1];
63
- // If the entry occurred less than 1 second after the previous entry
64
- // and less than 5 seconds after the first entry in the session,
65
- // include the entry in the current session. Otherwise, start a new
66
- // session.
67
- if (sessionValue &&
68
- entry.startTime - lastSessionEntry.startTime < 1000 &&
69
- entry.startTime - firstSessionEntry.startTime < 5000) {
70
- sessionValue += entry.value;
71
- sessionEntries.push(entry);
72
- }
73
- else {
74
- sessionValue = entry.value;
75
- sessionEntries = [entry];
76
- }
77
- }
78
- });
58
+ for (const entry of entries) {
59
+ layoutShiftManager._processEntry(entry);
60
+ }
79
61
  // If the current session value is larger than the current CLS value,
80
62
  // update CLS and the entries contributing to it.
81
- if (sessionValue > metric.value) {
82
- metric.value = sessionValue;
83
- metric.entries = sessionEntries;
63
+ if (layoutShiftManager._sessionValue > metric.value) {
64
+ metric.value = layoutShiftManager._sessionValue;
65
+ metric.entries = layoutShiftManager._sessionEntries;
84
66
  report();
85
67
  }
86
68
  };
87
69
  const po = observe('layout-shift', handleEntries);
88
70
  if (po) {
89
71
  report = bindReporter(onReport, metric, CLSThresholds, opts.reportAllChanges);
90
- onHidden(() => {
72
+ visibilityWatcher.onHidden(() => {
91
73
  handleEntries(po.takeRecords());
92
74
  report(true);
93
75
  });
94
76
  // Only report after a bfcache restore if the `PerformanceObserver`
95
77
  // successfully registered.
96
78
  onBFCacheRestore(() => {
97
- sessionValue = 0;
79
+ layoutShiftManager._sessionValue = 0;
98
80
  metric = initMetric('CLS', 0);
99
81
  report = bindReporter(onReport, metric, CLSThresholds, opts.reportAllChanges);
100
82
  doubleRAF(() => report());
@@ -102,7 +84,7 @@ export const onCLS = (onReport, opts) => {
102
84
  // Queue a task to report (if nothing else triggers a report first).
103
85
  // This allows CLS to be reported as soon as FCP fires when
104
86
  // `reportAllChanges` is true.
105
- setTimeout(report, 0);
87
+ setTimeout(report);
106
88
  }
107
89
  }));
108
90
  };
@@ -29,15 +29,13 @@ export const FCPThresholds = [1800, 3000];
29
29
  * relevant `paint` performance entry used to determine the value. The reported
30
30
  * value is a `DOMHighResTimeStamp`.
31
31
  */
32
- export const onFCP = (onReport, opts) => {
33
- // Set defaults
34
- opts = opts || {};
32
+ export const onFCP = (onReport, opts = {}) => {
35
33
  whenActivated(() => {
36
34
  const visibilityWatcher = getVisibilityWatcher();
37
35
  let metric = initMetric('FCP');
38
36
  let report;
39
37
  const handleEntries = (entries) => {
40
- entries.forEach((entry) => {
38
+ for (const entry of entries) {
41
39
  if (entry.name === 'first-contentful-paint') {
42
40
  po.disconnect();
43
41
  // Only report if the page wasn't hidden prior to the first paint.
@@ -51,7 +49,7 @@ export const onFCP = (onReport, opts) => {
51
49
  report(true);
52
50
  }
53
51
  }
54
- });
52
+ }
55
53
  };
56
54
  const po = observe('paint', handleEntries);
57
55
  if (po) {
@@ -1,4 +1,4 @@
1
- import { INPMetric, MetricRatingThresholds, ReportOpts } from './types.js';
1
+ import { INPMetric, MetricRatingThresholds, INPReportOpts } from './types.js';
2
2
  /** Thresholds for INP. See https://web.dev/articles/inp#what_is_a_good_inp_score */
3
3
  export declare const INPThresholds: MetricRatingThresholds;
4
4
  /**
@@ -7,11 +7,13 @@ export declare const INPThresholds: MetricRatingThresholds;
7
7
  * the `event` performance entries reported for that interaction. The reported
8
8
  * value is a `DOMHighResTimeStamp`.
9
9
  *
10
- * A custom `durationThreshold` configuration option can optionally be passed to
11
- * control what `event-timing` entries are considered for INP reporting. The
12
- * default threshold is `40`, which means INP scores of less than 40 are
13
- * reported as 0. Note that this will not affect your 75th percentile INP value
14
- * unless that value is also less than 40 (well below the recommended
10
+ * A custom `durationThreshold` configuration option can optionally be passed
11
+ * to control what `event-timing` entries are considered for INP reporting. The
12
+ * default threshold is `40`, which means INP scores of less than 40 will not
13
+ * be reported. To avoid reporting no interactions in these cases, the library
14
+ * will fall back to the input delay of the first interaction. Note that this
15
+ * will not affect your 75th percentile INP value unless that value is also
16
+ * less than 40 (well below the recommended
15
17
  * [good](https://web.dev/articles/inp#what_is_a_good_inp_score) threshold).
16
18
  *
17
19
  * If the `reportAllChanges` configuration option is set to `true`, the
@@ -28,4 +30,4 @@ export declare const INPThresholds: MetricRatingThresholds;
28
30
  * hidden. As a result, the `callback` function might be called multiple times
29
31
  * during the same page load._
30
32
  */
31
- export declare const onINP: (onReport: (metric: INPMetric) => void, opts?: ReportOpts) => void;
33
+ export declare const onINP: (onReport: (metric: INPMetric) => void, opts?: INPReportOpts) => void;
@@ -16,25 +16,31 @@
16
16
  import { onBFCacheRestore } from './lib/bfcache.js';
17
17
  import { bindReporter } from './lib/bindReporter.js';
18
18
  import { initMetric } from './lib/initMetric.js';
19
- import { DEFAULT_DURATION_THRESHOLD, processInteractionEntry, estimateP98LongestInteraction, resetInteractions, } from './lib/interactions.js';
19
+ import { initUnique } from './lib/initUnique.js';
20
+ import { InteractionManager } from './lib/InteractionManager.js';
20
21
  import { observe } from './lib/observe.js';
21
- import { onHidden } from './lib/onHidden.js';
22
22
  import { initInteractionCountPolyfill } from './lib/polyfills/interactionCountPolyfill.js';
23
23
  import { whenActivated } from './lib/whenActivated.js';
24
- import { whenIdle } from './lib/whenIdle.js';
24
+ import { getVisibilityWatcher } from './lib/getVisibilityWatcher.js';
25
+ import { whenIdleOrHidden } from './lib/whenIdleOrHidden.js';
25
26
  /** Thresholds for INP. See https://web.dev/articles/inp#what_is_a_good_inp_score */
26
27
  export const INPThresholds = [200, 500];
28
+ // The default `durationThreshold` used across this library for observing
29
+ // `event` entries via PerformanceObserver.
30
+ const DEFAULT_DURATION_THRESHOLD = 40;
27
31
  /**
28
32
  * Calculates the [INP](https://web.dev/articles/inp) value for the current
29
33
  * page and calls the `callback` function once the value is ready, along with
30
34
  * the `event` performance entries reported for that interaction. The reported
31
35
  * value is a `DOMHighResTimeStamp`.
32
36
  *
33
- * A custom `durationThreshold` configuration option can optionally be passed to
34
- * control what `event-timing` entries are considered for INP reporting. The
35
- * default threshold is `40`, which means INP scores of less than 40 are
36
- * reported as 0. Note that this will not affect your 75th percentile INP value
37
- * unless that value is also less than 40 (well below the recommended
37
+ * A custom `durationThreshold` configuration option can optionally be passed
38
+ * to control what `event-timing` entries are considered for INP reporting. The
39
+ * default threshold is `40`, which means INP scores of less than 40 will not
40
+ * be reported. To avoid reporting no interactions in these cases, the library
41
+ * will fall back to the input delay of the first interaction. Note that this
42
+ * will not affect your 75th percentile INP value unless that value is also
43
+ * less than 40 (well below the recommended
38
44
  * [good](https://web.dev/articles/inp#what_is_a_good_inp_score) threshold).
39
45
  *
40
46
  * If the `reportAllChanges` configuration option is set to `true`, the
@@ -51,19 +57,19 @@ export const INPThresholds = [200, 500];
51
57
  * hidden. As a result, the `callback` function might be called multiple times
52
58
  * during the same page load._
53
59
  */
54
- export const onINP = (onReport, opts) => {
60
+ export const onINP = (onReport, opts = {}) => {
55
61
  // Return if the browser doesn't support all APIs needed to measure INP.
56
- if (!('PerformanceEventTiming' in self &&
62
+ if (!(globalThis.PerformanceEventTiming &&
57
63
  'interactionId' in PerformanceEventTiming.prototype)) {
58
64
  return;
59
65
  }
60
- // Set defaults
61
- opts = opts || {};
66
+ const visibilityWatcher = getVisibilityWatcher();
62
67
  whenActivated(() => {
63
68
  // TODO(philipwalton): remove once the polyfill is no longer needed.
64
69
  initInteractionCountPolyfill();
65
70
  let metric = initMetric('INP');
66
71
  let report;
72
+ const interactionManager = initUnique(opts, InteractionManager);
67
73
  const handleEntries = (entries) => {
68
74
  // Queue the `handleEntries()` callback in the next idle task.
69
75
  // This is needed to increase the chances that all event entries that
@@ -71,11 +77,13 @@ export const onINP = (onReport, opts) => {
71
77
  // have been dispatched. Note: there is currently an experiment
72
78
  // running in Chrome (EventTimingKeypressAndCompositionInteractionId)
73
79
  // 123+ that if rolled out fully may make this no longer necessary.
74
- whenIdle(() => {
75
- entries.forEach(processInteractionEntry);
76
- const inp = estimateP98LongestInteraction();
77
- if (inp && inp.latency !== metric.value) {
78
- metric.value = inp.latency;
80
+ whenIdleOrHidden(() => {
81
+ for (const entry of entries) {
82
+ interactionManager._processEntry(entry);
83
+ }
84
+ const inp = interactionManager._estimateP98LongestInteraction();
85
+ if (inp && inp._latency !== metric.value) {
86
+ metric.value = inp._latency;
79
87
  metric.entries = inp.entries;
80
88
  report();
81
89
  }
@@ -95,14 +103,14 @@ export const onINP = (onReport, opts) => {
95
103
  // Also observe entries of type `first-input`. This is useful in cases
96
104
  // where the first interaction is less than the `durationThreshold`.
97
105
  po.observe({ type: 'first-input', buffered: true });
98
- onHidden(() => {
106
+ visibilityWatcher.onHidden(() => {
99
107
  handleEntries(po.takeRecords());
100
108
  report(true);
101
109
  });
102
110
  // Only report after a bfcache restore if the `PerformanceObserver`
103
111
  // successfully registered.
104
112
  onBFCacheRestore(() => {
105
- resetInteractions();
113
+ interactionManager._resetInteractions();
106
114
  metric = initMetric('INP');
107
115
  report = bindReporter(onReport, metric, INPThresholds, opts.reportAllChanges);
108
116
  });
@@ -13,20 +13,20 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
+ import { LCPEntryManager } from './lib/LCPEntryManager.js';
16
17
  import { onBFCacheRestore } from './lib/bfcache.js';
17
18
  import { bindReporter } from './lib/bindReporter.js';
18
19
  import { doubleRAF } from './lib/doubleRAF.js';
19
20
  import { getActivationStart } from './lib/getActivationStart.js';
20
21
  import { getVisibilityWatcher } from './lib/getVisibilityWatcher.js';
21
22
  import { initMetric } from './lib/initMetric.js';
23
+ import { initUnique } from './lib/initUnique.js';
22
24
  import { observe } from './lib/observe.js';
23
- import { onHidden } from './lib/onHidden.js';
24
25
  import { runOnce } from './lib/runOnce.js';
25
26
  import { whenActivated } from './lib/whenActivated.js';
26
- import { whenIdle } from './lib/whenIdle.js';
27
+ import { whenIdleOrHidden } from './lib/whenIdleOrHidden.js';
27
28
  /** Thresholds for LCP. See https://web.dev/articles/lcp#what_is_a_good_lcp_score */
28
29
  export const LCPThresholds = [2500, 4000];
29
- const reportedMetricIDs = {};
30
30
  /**
31
31
  * Calculates the [LCP](https://web.dev/articles/lcp) value for the current page and
32
32
  * calls the `callback` function once the value is ready (along with the
@@ -38,20 +38,20 @@ const reportedMetricIDs = {};
38
38
  * performance entry is dispatched, or once the final value of the metric has
39
39
  * been determined.
40
40
  */
41
- export const onLCP = (onReport, opts) => {
42
- // Set defaults
43
- opts = opts || {};
41
+ export const onLCP = (onReport, opts = {}) => {
44
42
  whenActivated(() => {
45
43
  const visibilityWatcher = getVisibilityWatcher();
46
44
  let metric = initMetric('LCP');
47
45
  let report;
46
+ const lcpEntryManager = initUnique(opts, LCPEntryManager);
48
47
  const handleEntries = (entries) => {
49
48
  // If reportAllChanges is set then call this function for each entry,
50
49
  // otherwise only consider the last one.
51
50
  if (!opts.reportAllChanges) {
52
51
  entries = entries.slice(-1);
53
52
  }
54
- entries.forEach((entry) => {
53
+ for (const entry of entries) {
54
+ lcpEntryManager._processEntry(entry);
55
55
  // Only report if the page wasn't hidden prior to LCP.
56
56
  if (entry.startTime < visibilityWatcher.firstHiddenTime) {
57
57
  // The startTime attribute returns the value of the renderTime if it is
@@ -64,32 +64,40 @@ export const onLCP = (onReport, opts) => {
64
64
  metric.entries = [entry];
65
65
  report();
66
66
  }
67
- });
67
+ }
68
68
  };
69
69
  const po = observe('largest-contentful-paint', handleEntries);
70
70
  if (po) {
71
71
  report = bindReporter(onReport, metric, LCPThresholds, opts.reportAllChanges);
72
+ // Ensure this logic only runs once, since it can be triggered from
73
+ // any of three different event listeners below.
72
74
  const stopListening = runOnce(() => {
73
- if (!reportedMetricIDs[metric.id]) {
74
- handleEntries(po.takeRecords());
75
- po.disconnect();
76
- reportedMetricIDs[metric.id] = true;
77
- report(true);
78
- }
75
+ handleEntries(po.takeRecords());
76
+ po.disconnect();
77
+ report(true);
79
78
  });
80
- // Stop listening after input. Note: while scrolling is an input that
81
- // stops LCP observation, it's unreliable since it can be programmatically
82
- // generated. See: https://github.com/GoogleChrome/web-vitals/issues/75
83
- ['keydown', 'click'].forEach((type) => {
84
- // Wrap in a setTimeout so the callback is run in a separate task
85
- // to avoid extending the keyboard/click handler to reduce INP impact
86
- // https://github.com/GoogleChrome/web-vitals/issues/383
87
- addEventListener(type, () => whenIdle(stopListening), {
88
- once: true,
79
+ // Need a separate wrapper to ensure the `runOnce` function above is
80
+ // common for all three functions
81
+ const stopListeningWrapper = (event) => {
82
+ if (event.isTrusted) {
83
+ // Wrap the listener in an idle callback so it's run in a separate
84
+ // task to reduce potential INP impact.
85
+ // https://github.com/GoogleChrome/web-vitals/issues/383
86
+ whenIdleOrHidden(stopListening);
87
+ removeEventListener(event.type, stopListeningWrapper, {
88
+ capture: true,
89
+ });
90
+ }
91
+ };
92
+ // Stop listening after input or visibilitychange.
93
+ // Note: while scrolling is an input that stops LCP observation, it's
94
+ // unreliable since it can be programmatically generated.
95
+ // See: https://github.com/GoogleChrome/web-vitals/issues/75
96
+ for (const type of ['keydown', 'click', 'visibilitychange']) {
97
+ addEventListener(type, stopListeningWrapper, {
89
98
  capture: true,
90
99
  });
91
- });
92
- onHidden(stopListening);
100
+ }
93
101
  // Only report after a bfcache restore if the `PerformanceObserver`
94
102
  // successfully registered.
95
103
  onBFCacheRestore((event) => {
@@ -97,7 +105,6 @@ export const onLCP = (onReport, opts) => {
97
105
  report = bindReporter(onReport, metric, LCPThresholds, opts.reportAllChanges);
98
106
  doubleRAF(() => {
99
107
  metric.value = performance.now() - event.timeStamp;
100
- reportedMetricIDs[metric.id] = true;
101
108
  report(true);
102
109
  });
103
110
  });
@@ -34,7 +34,7 @@ const whenReady = (callback) => {
34
34
  }
35
35
  else {
36
36
  // Queue a task so the callback runs after `loadEventEnd`.
37
- setTimeout(callback, 0);
37
+ setTimeout(callback);
38
38
  }
39
39
  };
40
40
  /**
@@ -52,9 +52,7 @@ const whenReady = (callback) => {
52
52
  * includes time spent on DNS lookup, connection negotiation, network latency,
53
53
  * and server processing time.
54
54
  */
55
- export const onTTFB = (onReport, opts) => {
56
- // Set defaults
57
- opts = opts || {};
55
+ export const onTTFB = (onReport, opts = {}) => {
58
56
  let metric = initMetric('TTFB');
59
57
  let report = bindReporter(onReport, metric, TTFBThresholds, opts.reportAllChanges);
60
58
  whenReady(() => {
@@ -1,6 +1,5 @@
1
1
  import type { CLSMetric, CLSMetricWithAttribution } from './cls.js';
2
2
  import type { FCPMetric, FCPMetricWithAttribution } from './fcp.js';
3
- import type { FIDMetric, FIDMetricWithAttribution } from './fid.js';
4
3
  import type { INPMetric, INPMetricWithAttribution } from './inp.js';
5
4
  import type { LCPMetric, LCPMetricWithAttribution } from './lcp.js';
6
5
  import type { TTFBMetric, TTFBMetricWithAttribution } from './ttfb.js';
@@ -8,7 +7,7 @@ export interface Metric {
8
7
  /**
9
8
  * The name of the metric (in acronym form).
10
9
  */
11
- name: 'CLS' | 'FCP' | 'FID' | 'INP' | 'LCP' | 'TTFB';
10
+ name: 'CLS' | 'FCP' | 'INP' | 'LCP' | 'TTFB';
12
11
  /**
13
12
  * The current value of the metric.
14
13
  */
@@ -54,9 +53,9 @@ export interface Metric {
54
53
  navigationType: 'navigate' | 'reload' | 'back-forward' | 'back-forward-cache' | 'prerender' | 'restore';
55
54
  }
56
55
  /** The union of supported metric types. */
57
- export type MetricType = CLSMetric | FCPMetric | FIDMetric | INPMetric | LCPMetric | TTFBMetric;
56
+ export type MetricType = CLSMetric | FCPMetric | INPMetric | LCPMetric | TTFBMetric;
58
57
  /** The union of supported metric attribution types. */
59
- export type MetricWithAttribution = CLSMetricWithAttribution | FCPMetricWithAttribution | FIDMetricWithAttribution | INPMetricWithAttribution | LCPMetricWithAttribution | TTFBMetricWithAttribution;
58
+ export type MetricWithAttribution = CLSMetricWithAttribution | FCPMetricWithAttribution | INPMetricWithAttribution | LCPMetricWithAttribution | TTFBMetricWithAttribution;
60
59
  /**
61
60
  * The thresholds of metric's "good", "needs improvement", and "poor" ratings.
62
61
  *
@@ -81,7 +80,9 @@ export interface ReportCallback {
81
80
  }
82
81
  export interface ReportOpts {
83
82
  reportAllChanges?: boolean;
84
- durationThreshold?: number;
83
+ }
84
+ export interface AttributionReportOpts extends ReportOpts {
85
+ generateTarget?: (el: Node | null) => string | undefined;
85
86
  }
86
87
  /**
87
88
  * The loading state of the document. Note: this value is similar to
@@ -13,9 +13,11 @@ export interface CLSMetric extends Metric {
13
13
  */
14
14
  export interface CLSAttribution {
15
15
  /**
16
- * A selector identifying the first element (in document order) that
17
- * shifted when the single largest layout shift contributing to the page's
18
- * CLS score occurred.
16
+ * By default, a selector identifying the first element (in document order)
17
+ * that shifted when the single largest layout shift that contributed to the
18
+ * page's CLS score occurred. If the `generateTarget` configuration option
19
+ * was passed, then this will instead be the return value of that function,
20
+ * falling back to the default if that returns null or undefined.
19
21
  */
20
22
  largestShiftTarget?: string;
21
23
  /**