chrome-devtools-frontend 1.0.1664496 → 1.0.1665921

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 (407) hide show
  1. package/.agents/skills/devtools-testing-guidance/SKILL.md +48 -0
  2. package/.agents/skills/devtools-ux-writing-refactor/SKILL.md +3 -3
  3. package/.agents/skills/repro-flaky-tests/SKILL.md +2 -2
  4. package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +7 -1
  5. package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +2 -0
  6. package/.agents/skills/version-control/SKILL.md +4 -3
  7. package/docs/ui_engineering.md +89 -0
  8. package/eslint.config.mjs +9 -2
  9. package/front_end/Images/rollup.config.mjs +1 -1
  10. package/front_end/Tests.js +15 -16
  11. package/front_end/core/common/Gzip.ts +2 -2
  12. package/front_end/core/common/Settings.ts +4 -20
  13. package/front_end/core/common/Srcset.ts +1 -1
  14. package/front_end/core/common/VersionController.ts +1 -1
  15. package/front_end/core/host/AidaClient.ts +19 -4
  16. package/front_end/core/host/AidaGcaTranslation.ts +2 -2
  17. package/front_end/core/host/GcaClient.ts +2 -2
  18. package/front_end/core/host/GdpClient.ts +3 -3
  19. package/front_end/core/host/InspectorFrontendHostStub.ts +1 -1
  20. package/front_end/core/host/ResourceLoader.ts +15 -15
  21. package/front_end/core/protocol_client/DevToolsCDPConnection.ts +2 -2
  22. package/front_end/core/protocol_client/InspectorBackend.ts +1 -1
  23. package/front_end/core/root/Runtime.ts +0 -1
  24. package/front_end/core/sdk/CSSMatchedStyles.ts +78 -3
  25. package/front_end/core/sdk/CSSMetadata.ts +17 -12
  26. package/front_end/core/sdk/CSSProperty.ts +1 -1
  27. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +2 -2
  28. package/front_end/core/sdk/CSSRule.ts +3 -3
  29. package/front_end/core/sdk/CSSStyleSheetHeader.ts +3 -3
  30. package/front_end/core/sdk/CompilerSourceMappingContentProvider.ts +1 -1
  31. package/front_end/core/sdk/Connections.ts +1 -1
  32. package/front_end/core/sdk/DebuggerModel.ts +13 -13
  33. package/front_end/core/sdk/NetworkManager.ts +19 -19
  34. package/front_end/core/sdk/NetworkRequest.ts +57 -57
  35. package/front_end/core/sdk/OverlayModel.ts +1 -1
  36. package/front_end/core/sdk/PageResourceLoader.ts +2 -2
  37. package/front_end/core/sdk/RehydratingConnection.ts +5 -5
  38. package/front_end/core/sdk/ScreenCaptureModel.ts +1 -1
  39. package/front_end/core/sdk/Script.ts +2 -2
  40. package/front_end/core/sdk/ServerTiming.ts +7 -7
  41. package/front_end/core/sdk/ServiceWorkerCacheModel.ts +1 -1
  42. package/front_end/core/sdk/ServiceWorkerManager.ts +11 -11
  43. package/front_end/core/sdk/SourceMapScopeChainEntry.ts +2 -2
  44. package/front_end/core/sdk/SourceMapScopesInfo.ts +1 -1
  45. package/front_end/core/sdk/StorageKeyManager.ts +1 -1
  46. package/front_end/core/sdk/sdk-meta.ts +98 -98
  47. package/front_end/devtools_compatibility.js +15 -13
  48. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +4 -8
  49. package/front_end/entrypoints/main/MainImpl.ts +2 -3
  50. package/front_end/entrypoints/main/main-meta.ts +1 -16
  51. package/front_end/entrypoints/shell/shell.ts +1 -0
  52. package/front_end/entrypoints/trace_app/trace_app.ts +1 -0
  53. package/front_end/foundation/README.md +1 -1
  54. package/front_end/foundation/Universe.test.api.ts +73 -0
  55. package/front_end/foundation/Universe.ts +22 -0
  56. package/front_end/generated/InspectorBackendCommands.ts +2 -2
  57. package/front_end/generated/SupportedCSSProperties.js +1 -1
  58. package/front_end/generated/protocol.ts +19 -0
  59. package/front_end/models/ai_assistance/AiAgent2.ts +1 -1
  60. package/front_end/models/ai_assistance/AiConversation.ts +1 -1
  61. package/front_end/models/ai_assistance/BuiltInAi.ts +1 -1
  62. package/front_end/models/ai_assistance/ChangeManager.ts +0 -70
  63. package/front_end/models/ai_assistance/ExtensionScope.ts +2 -36
  64. package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +9 -9
  65. package/front_end/models/ai_assistance/agents/AiAgent.ts +10 -2
  66. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +4 -4
  67. package/front_end/models/ai_assistance/agents/ExecuteJavascript.ts +1 -1
  68. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +21 -21
  69. package/front_end/models/ai_assistance/agents/StorageAgent.ts +4 -4
  70. package/front_end/models/ai_assistance/agents/StylingAgent.ts +1 -1
  71. package/front_end/models/ai_assistance/ai_assistance.ts +0 -5
  72. package/front_end/models/ai_assistance/data_formatters/FileFormatter.ts +11 -4
  73. package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +8 -2
  74. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +14 -11
  75. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +2 -2
  76. package/front_end/models/ai_assistance/performance/AICallTree.ts +2 -2
  77. package/front_end/models/ai_assistance/tools/ExecuteJavaScript.ts +1 -1
  78. package/front_end/models/ai_assistance/tools/GetNetworkRequestDetails.ts +9 -2
  79. package/front_end/models/ai_assistance/tools/GetStyles.ts +4 -4
  80. package/front_end/models/ai_assistance/tools/ListNetworkRequests.ts +2 -5
  81. package/front_end/models/ai_code_completion/AiCodeCompletion.ts +2 -2
  82. package/front_end/models/ai_code_generation/AiCodeGeneration.ts +2 -2
  83. package/front_end/models/badges/badges-meta.ts +27 -0
  84. package/front_end/models/bindings/CSSWorkspaceBinding.ts +4 -3
  85. package/front_end/models/bindings/ContentProviderBasedProject.ts +1 -1
  86. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +6 -7
  87. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +5 -4
  88. package/front_end/models/bindings/PresentationConsoleMessageHelper.ts +72 -29
  89. package/front_end/models/bindings/ResourceMapping.ts +38 -32
  90. package/front_end/models/bindings/ResourceScriptMapping.ts +5 -7
  91. package/front_end/models/breakpoints/BreakpointManager.ts +2 -1
  92. package/front_end/models/har/Writer.ts +2 -2
  93. package/front_end/models/issues_manager/ElementAccessibilityIssue.ts +1 -1
  94. package/front_end/models/issues_manager/GenericIssue.ts +1 -1
  95. package/front_end/models/issues_manager/IssuesManager.ts +14 -5
  96. package/front_end/models/issues_manager/PartitioningBlobURLIssue.ts +1 -1
  97. package/front_end/models/issues_manager/SRIMessageSignatureIssue.ts +2 -2
  98. package/front_end/models/issues_manager/SourceFrameIssuesManager.ts +13 -2
  99. package/front_end/models/issues_manager/issues_manager.ts +0 -2
  100. package/front_end/models/live-metrics/LiveMetrics.ts +22 -5
  101. package/front_end/models/live-metrics/web-vitals-injected/rollup.config.mjs +1 -1
  102. package/front_end/models/live-metrics/web-vitals-injected/spec/spec.ts +10 -4
  103. package/front_end/models/logs/logs-meta.ts +23 -16
  104. package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +2 -2
  105. package/front_end/models/persistence/IsolatedFileSystem.ts +1 -1
  106. package/front_end/models/persistence/IsolatedFileSystemManager.ts +1 -1
  107. package/front_end/models/source_map_scopes/NamesResolver.ts +104 -86
  108. package/front_end/models/source_map_scopes/ScopeChainModel.ts +6 -2
  109. package/front_end/models/stack_trace/StackTraceModel.ts +1 -1
  110. package/front_end/models/trace/handlers/ExtensionTraceDataHandler.ts +1 -1
  111. package/front_end/models/trace/handlers/UserTimingsHandler.ts +17 -6
  112. package/front_end/models/trace/helpers/SamplesIntegrator.ts +1 -1
  113. package/front_end/models/trace/helpers/Timing.ts +1 -1
  114. package/front_end/models/trace/insights/Common.ts +1 -1
  115. package/front_end/models/trace/insights/DocumentLatency.ts +3 -3
  116. package/front_end/models/trace/insights/LCPDiscovery.ts +1 -1
  117. package/front_end/models/trace/insights/ModernHTTP.ts +1 -1
  118. package/front_end/models/trace_source_maps_resolver/SourceMapsResolver.ts +2 -2
  119. package/front_end/models/workspace_diff/WorkspaceDiff.ts +14 -9
  120. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +2 -15
  121. package/front_end/panels/ai_assistance/ai_assistance.ts +1 -2
  122. package/front_end/panels/ai_assistance/components/ChatInput.ts +23 -19
  123. package/front_end/panels/ai_assistance/components/ChatMessage.ts +9 -18
  124. package/front_end/panels/ai_assistance/components/ChatView.ts +2 -35
  125. package/front_end/panels/ai_assistance/components/DisabledWidget.ts +1 -1
  126. package/front_end/panels/ai_assistance/components/ExploreWidget.ts +4 -4
  127. package/front_end/panels/ai_assistance/components/ImageResize.ts +74 -0
  128. package/front_end/panels/ai_assistance/components/WalkthroughView.ts +2 -2
  129. package/front_end/panels/animation/AnimationGroupPreviewUI.ts +28 -29
  130. package/front_end/panels/animation/AnimationTimeline.ts +3 -3
  131. package/front_end/panels/animation/animationTimeline.css +0 -2
  132. package/front_end/panels/application/AppManifestView.ts +1 -1
  133. package/front_end/panels/application/ApplicationPanelSidebar.ts +1 -1
  134. package/front_end/panels/application/CookieItemsView.ts +1 -1
  135. package/front_end/panels/application/CrashReportContextView.ts +3 -3
  136. package/front_end/panels/application/DeviceBoundSessionsModel.ts +1 -1
  137. package/front_end/panels/application/DeviceBoundSessionsTreeElement.ts +1 -1
  138. package/front_end/panels/application/DeviceBoundSessionsView.ts +1 -1
  139. package/front_end/panels/application/IndexedDBViews.ts +1 -1
  140. package/front_end/panels/application/KeyValueStorageItemsView.ts +1 -1
  141. package/front_end/panels/application/OriginTrialTreeView.ts +1 -1
  142. package/front_end/panels/application/ServiceWorkersView.ts +6 -6
  143. package/front_end/panels/application/StorageBucketsTreeElement.ts +1 -1
  144. package/front_end/panels/application/StorageItemsToolbar.ts +3 -3
  145. package/front_end/panels/application/WebMCPView.ts +7 -5
  146. package/front_end/panels/application/components/AdsView.ts +21 -6
  147. package/front_end/panels/application/components/BackForwardCacheView.ts +2 -2
  148. package/front_end/panels/application/components/ProtocolHandlersView.ts +1 -1
  149. package/front_end/panels/application/components/StorageMetadataView.ts +1 -1
  150. package/front_end/panels/application/preloading/components/MismatchedPreloadingGrid.ts +2 -2
  151. package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +2 -1
  152. package/front_end/panels/application/preloading/components/PreloadingString.ts +3 -3
  153. package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +2 -1
  154. package/front_end/panels/autofill/AutofillView.ts +1 -1
  155. package/front_end/panels/browser_debugger/DOMBreakpointsSidebarPane.ts +1 -1
  156. package/front_end/panels/browser_debugger/XHRBreakpointsSidebarPane.ts +2 -2
  157. package/front_end/panels/changes/ChangesSidebar.ts +2 -2
  158. package/front_end/panels/changes/ChangesView.ts +4 -5
  159. package/front_end/panels/changes/CombinedDiffView.ts +3 -3
  160. package/front_end/panels/changes/changes-meta.ts +2 -2
  161. package/front_end/panels/common/AiCodeCompletionTeaser.ts +1 -1
  162. package/front_end/panels/common/AiCodeGenerationTeaser.ts +3 -3
  163. package/front_end/panels/common/BadgeNotification.ts +8 -8
  164. package/front_end/panels/common/DOMLinkifier.ts +1 -1
  165. package/front_end/panels/common/GdpSignUpDialog.ts +2 -2
  166. package/front_end/panels/common/GeminiRebrandPromoDialog.ts +1 -1
  167. package/front_end/panels/common/aiCodeCompletionDisclaimer.css +0 -1
  168. package/front_end/panels/console/ConsoleInsightTeaser.ts +1 -1
  169. package/front_end/panels/console/ConsolePinPane.ts +3 -3
  170. package/front_end/panels/console/ConsolePrompt.ts +6 -4
  171. package/front_end/panels/console/ConsoleSidebar.ts +8 -10
  172. package/front_end/panels/console_counters/WarningErrorCounter.ts +10 -11
  173. package/front_end/panels/coverage/CoverageView.ts +2 -2
  174. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +3 -3
  175. package/front_end/panels/css_overview/CSSOverviewSidebarPanel.ts +1 -1
  176. package/front_end/panels/developer_resources/DeveloperResourcesView.ts +1 -1
  177. package/front_end/panels/elements/CSSRuleValidator.ts +1 -1
  178. package/front_end/panels/elements/ComputedStyleWidget.ts +3 -2
  179. package/front_end/panels/elements/ElementsTreeElement.ts +3 -3
  180. package/front_end/panels/elements/EventListenersWidget.ts +1 -3
  181. package/front_end/panels/elements/LayoutPane.ts +23 -13
  182. package/front_end/panels/elements/StandaloneStylesContainer.ts +7 -7
  183. package/front_end/panels/elements/StylePropertiesSection.ts +33 -5
  184. package/front_end/panels/elements/StylePropertyTreeElement.ts +5 -5
  185. package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +6 -6
  186. package/front_end/panels/elements/StylesSidebarPane.ts +4 -3
  187. package/front_end/panels/elements/elements-meta.ts +18 -2
  188. package/front_end/panels/emulation/DeviceModeToolbar.ts +100 -40
  189. package/front_end/panels/emulation/DeviceModeView.ts +5 -4
  190. package/front_end/panels/emulation/MediaQueryInspector.ts +35 -19
  191. package/front_end/panels/event_listeners/EventListenersView.ts +4 -4
  192. package/front_end/panels/explain/components/ConsoleInsight.ts +8 -9
  193. package/front_end/panels/explain/explain-meta.ts +3 -3
  194. package/front_end/panels/layer_viewer/LayerTreeOutline.ts +135 -167
  195. package/front_end/panels/layer_viewer/Layers3DView.ts +10 -23
  196. package/front_end/panels/layer_viewer/layer_viewer-meta.ts +27 -0
  197. package/front_end/panels/lighthouse/LighthouseController.ts +44 -55
  198. package/front_end/panels/lighthouse/LighthousePanel.ts +9 -9
  199. package/front_end/panels/lighthouse/LighthouseReportSelector.ts +2 -2
  200. package/front_end/panels/lighthouse/LighthouseStartView.ts +9 -12
  201. package/front_end/panels/lighthouse/LighthouseStatusView.ts +33 -33
  202. package/front_end/panels/lighthouse/RadioSetting.ts +1 -1
  203. package/front_end/panels/lighthouse/lighthouse-meta.ts +131 -1
  204. package/front_end/panels/media/EventDisplayTable.ts +67 -94
  205. package/front_end/panels/media/PlayerListView.ts +1 -1
  206. package/front_end/panels/media/eventDisplayTable.css +9 -4
  207. package/front_end/panels/mobile_throttling/NetworkThrottlingSelector.ts +5 -5
  208. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +1 -1
  209. package/front_end/panels/network/EventSourceMessagesView.ts +98 -107
  210. package/front_end/panels/network/NetworkLogViewColumns.ts +1 -1
  211. package/front_end/panels/network/NetworkWaterfallColumn.ts +1 -1
  212. package/front_end/panels/network/RequestConditionsDrawer.ts +2 -2
  213. package/front_end/panels/network/RequestCookiesView.ts +2 -2
  214. package/front_end/panels/network/RequestHeadersView.ts +5 -5
  215. package/front_end/panels/network/RequestPayloadView.ts +4 -4
  216. package/front_end/panels/network/RequestTimingView.ts +2 -2
  217. package/front_end/panels/network/components/DirectSocketConnectionView.ts +1 -1
  218. package/front_end/panels/network/eventSourceMessagesView.css +12 -3
  219. package/front_end/panels/network/networkTimingTable.css +2 -2
  220. package/front_end/panels/performance_monitor/PerformanceMonitor.ts +1 -1
  221. package/front_end/panels/profiler/BottomUpProfileDataGrid.ts +25 -29
  222. package/front_end/panels/profiler/HeapProfileView.ts +308 -247
  223. package/front_end/panels/profiler/HeapSnapshotDataGrids.ts +13 -3
  224. package/front_end/panels/profiler/HeapSnapshotView.ts +30 -10
  225. package/front_end/panels/profiler/HeapTimelineOverview.ts +5 -2
  226. package/front_end/panels/profiler/ProfileDataGrid.ts +128 -157
  227. package/front_end/panels/profiler/ProfileFlameChartDataProvider.ts +17 -5
  228. package/front_end/panels/profiler/ProfilesPanel.ts +2 -2
  229. package/front_end/panels/profiler/TopDownProfileDataGrid.ts +17 -21
  230. package/front_end/panels/profiler/profilesPanel.css +9 -13
  231. package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +2 -2
  232. package/front_end/panels/recorder/CreateRecordingView.ts +4 -4
  233. package/front_end/panels/recorder/RecorderPanel.ts +6 -6
  234. package/front_end/panels/recorder/RecordingView.ts +1 -1
  235. package/front_end/panels/recorder/ReplaySection.ts +1 -1
  236. package/front_end/panels/recorder/StepView.ts +1 -1
  237. package/front_end/panels/recorder/injected/rollup.config.mjs +1 -1
  238. package/front_end/panels/search/SearchView.ts +1 -1
  239. package/front_end/panels/security/SecurityPanel.ts +54 -41
  240. package/front_end/panels/sensors/LocationsSettingsTab.ts +246 -233
  241. package/front_end/panels/sensors/SensorsView.ts +1 -1
  242. package/front_end/panels/settings/AISettingsTab.ts +11 -10
  243. package/front_end/panels/settings/SettingsScreen.ts +29 -24
  244. package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +2 -2
  245. package/front_end/panels/sources/AiCodeCompletionPlugin.ts +5 -5
  246. package/front_end/panels/sources/BreakpointEditDialog.ts +2 -2
  247. package/front_end/panels/sources/BreakpointsView.ts +1 -1
  248. package/front_end/panels/sources/CallStackSidebarPane.ts +2 -2
  249. package/front_end/panels/sources/DebuggerPausedMessage.ts +2 -2
  250. package/front_end/panels/sources/DebuggerPlugin.ts +25 -22
  251. package/front_end/panels/sources/ScopeChainSidebarPane.ts +3 -1
  252. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +7 -5
  253. package/front_end/panels/sources/sources-meta.ts +1 -1
  254. package/front_end/panels/timeline/CountersGraph.ts +1 -2
  255. package/front_end/panels/timeline/ExtensionTrackAppender.ts +1 -1
  256. package/front_end/panels/timeline/TimelineDetailsView.ts +2 -2
  257. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +2 -2
  258. package/front_end/panels/timeline/TimelineFlameChartView.ts +4 -4
  259. package/front_end/panels/timeline/TimelinePaintProfilerView.ts +1 -1
  260. package/front_end/panels/timeline/TimelinePanel.ts +53 -81
  261. package/front_end/panels/timeline/TimelineSelectorStatsView.ts +10 -3
  262. package/front_end/panels/timeline/TimelineUIUtils.ts +18 -4
  263. package/front_end/panels/timeline/TrackConfigBanner.ts +1 -1
  264. package/front_end/panels/timeline/components/ExportTraceOptions.ts +1 -1
  265. package/front_end/panels/timeline/components/LayoutShiftDetails.ts +8 -9
  266. package/front_end/panels/timeline/components/NetworkRequestTooltip.ts +1 -1
  267. package/front_end/panels/timeline/components/TimelineRangeSummaryView.ts +1 -1
  268. package/front_end/panels/timeline/components/insights/DuplicatedJavaScript.ts +2 -2
  269. package/front_end/panels/timeline/components/insights/LCPBreakdown.ts +1 -1
  270. package/front_end/panels/timeline/components/insights/LegacyJavaScript.ts +1 -1
  271. package/front_end/panels/timeline/components/insights/SlowCSSSelector.ts +2 -2
  272. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +5 -0
  273. package/front_end/panels/timeline/overlays/components/TimespanBreakdownOverlay.ts +13 -8
  274. package/front_end/panels/timeline/overlays/components/timespanBreakdownOverlay.css +1 -0
  275. package/front_end/panels/timeline/timeline-meta.ts +169 -0
  276. package/front_end/panels/timeline/timelineFlameChartView.css +5 -0
  277. package/front_end/panels/webauthn/WebauthnPane.ts +1 -1
  278. package/front_end/panels/whats_new/ReleaseNoteText.ts +9 -9
  279. package/front_end/panels/whats_new/resources/WNDT.md +7 -8
  280. package/front_end/third_party/chromium/README.chromium +1 -1
  281. package/front_end/third_party/web-vitals/README.chromium +2 -2
  282. package/front_end/third_party/web-vitals/package/README.md +120 -19
  283. package/front_end/third_party/web-vitals/package/attribution.d.ts +16 -0
  284. package/front_end/third_party/web-vitals/package/attribution.js +18 -0
  285. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onCLS.d.ts +1 -1
  286. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onFCP.d.ts +1 -7
  287. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onFCP.js +53 -32
  288. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onINP.d.ts +2 -2
  289. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onINP.js +43 -12
  290. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onLCP.d.ts +1 -1
  291. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onLCP.js +21 -3
  292. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onTTFB.d.ts +1 -1
  293. package/front_end/third_party/web-vitals/package/dist/modules/attribution/onTTFB.js +30 -24
  294. package/front_end/third_party/web-vitals/package/dist/modules/lib/FCPEntryManager.d.ts +3 -0
  295. package/front_end/third_party/web-vitals/package/dist/modules/lib/FCPEntryManager.js +18 -0
  296. package/front_end/third_party/web-vitals/package/dist/modules/lib/InteractionManager.d.ts +2 -1
  297. package/front_end/third_party/web-vitals/package/dist/modules/lib/InteractionManager.js +18 -2
  298. package/front_end/third_party/web-vitals/package/dist/modules/lib/LCPEntryManager.d.ts +1 -0
  299. package/front_end/third_party/web-vitals/package/dist/modules/lib/LCPEntryManager.js +1 -0
  300. package/front_end/third_party/web-vitals/package/dist/modules/lib/bindReporter.d.ts +1 -1
  301. package/front_end/third_party/web-vitals/package/dist/modules/lib/generateUniqueID.js +1 -1
  302. package/front_end/third_party/web-vitals/package/dist/modules/lib/getLoadState.d.ts +1 -1
  303. package/front_end/third_party/web-vitals/package/dist/modules/lib/getLoadState.js +7 -7
  304. package/front_end/third_party/web-vitals/package/dist/modules/lib/getSelector.js +1 -1
  305. package/front_end/third_party/web-vitals/package/dist/modules/lib/getVisibilityWatcher.d.ts +1 -1
  306. package/front_end/third_party/web-vitals/package/dist/modules/lib/getVisibilityWatcher.js +4 -1
  307. package/front_end/third_party/web-vitals/package/dist/modules/lib/initMetric.d.ts +7 -3
  308. package/front_end/third_party/web-vitals/package/dist/modules/lib/initMetric.js +20 -11
  309. package/front_end/third_party/web-vitals/package/dist/modules/lib/initUnique.js +8 -3
  310. package/front_end/third_party/web-vitals/package/dist/modules/lib/observe.d.ts +3 -1
  311. package/front_end/third_party/web-vitals/package/dist/modules/lib/observe.js +19 -4
  312. package/front_end/third_party/web-vitals/package/dist/modules/lib/polyfills/interactionCountPolyfill.js +1 -1
  313. package/front_end/third_party/web-vitals/package/dist/modules/lib/softNavs.d.ts +3 -0
  314. package/front_end/third_party/web-vitals/package/dist/modules/lib/softNavs.js +38 -0
  315. package/front_end/third_party/web-vitals/package/dist/modules/lib/whenIdleOrHidden.js +5 -1
  316. package/front_end/third_party/web-vitals/package/dist/modules/onCLS.d.ts +1 -1
  317. package/front_end/third_party/web-vitals/package/dist/modules/onCLS.js +30 -11
  318. package/front_end/third_party/web-vitals/package/dist/modules/onFCP.d.ts +1 -1
  319. package/front_end/third_party/web-vitals/package/dist/modules/onFCP.js +36 -4
  320. package/front_end/third_party/web-vitals/package/dist/modules/onINP.d.ts +1 -1
  321. package/front_end/third_party/web-vitals/package/dist/modules/onINP.js +42 -22
  322. package/front_end/third_party/web-vitals/package/dist/modules/onLCP.d.ts +1 -1
  323. package/front_end/third_party/web-vitals/package/dist/modules/onLCP.js +109 -30
  324. package/front_end/third_party/web-vitals/package/dist/modules/onTTFB.d.ts +1 -1
  325. package/front_end/third_party/web-vitals/package/dist/modules/onTTFB.js +25 -7
  326. package/front_end/third_party/web-vitals/package/dist/modules/types/base.d.ts +24 -1
  327. package/front_end/third_party/web-vitals/package/dist/modules/types/fcp.d.ts +1 -1
  328. package/front_end/third_party/web-vitals/package/dist/modules/types/inp.d.ts +14 -6
  329. package/front_end/third_party/web-vitals/package/dist/modules/types/lcp.d.ts +1 -1
  330. package/front_end/third_party/web-vitals/package/dist/modules/types/ttfb.d.ts +2 -2
  331. package/front_end/third_party/web-vitals/package/dist/modules/types.d.ts +26 -4
  332. package/front_end/third_party/web-vitals/package/package.json +21 -22
  333. package/front_end/third_party/web-vitals/package/src/attribution/onCLS.ts +1 -1
  334. package/front_end/third_party/web-vitals/package/src/attribution/onFCP.ts +62 -39
  335. package/front_end/third_party/web-vitals/package/src/attribution/onINP.ts +52 -15
  336. package/front_end/third_party/web-vitals/package/src/attribution/onLCP.ts +25 -7
  337. package/front_end/third_party/web-vitals/package/src/attribution/onTTFB.ts +43 -37
  338. package/front_end/third_party/web-vitals/package/src/lib/{polyfills/getFirstHiddenTimePolyfill.ts → FCPEntryManager.ts} +4 -14
  339. package/front_end/third_party/web-vitals/package/src/lib/InteractionManager.ts +22 -2
  340. package/front_end/third_party/web-vitals/package/src/lib/LCPEntryManager.ts +1 -0
  341. package/front_end/third_party/web-vitals/package/src/lib/bindReporter.ts +1 -1
  342. package/front_end/third_party/web-vitals/package/src/lib/generateUniqueID.ts +1 -1
  343. package/front_end/third_party/web-vitals/package/src/lib/getLoadState.ts +11 -12
  344. package/front_end/third_party/web-vitals/package/src/lib/getSelector.ts +1 -1
  345. package/front_end/third_party/web-vitals/package/src/lib/getVisibilityWatcher.ts +4 -1
  346. package/front_end/third_party/web-vitals/package/src/lib/initMetric.ts +24 -11
  347. package/front_end/third_party/web-vitals/package/src/lib/initUnique.ts +12 -4
  348. package/front_end/third_party/web-vitals/package/src/lib/observe.ts +26 -5
  349. package/front_end/third_party/web-vitals/package/src/lib/polyfills/interactionCountPolyfill.ts +1 -1
  350. package/front_end/third_party/web-vitals/package/src/lib/softNavs.ts +48 -0
  351. package/front_end/third_party/web-vitals/package/src/lib/whenIdleOrHidden.ts +12 -4
  352. package/front_end/third_party/web-vitals/package/src/onCLS.ts +75 -18
  353. package/front_end/third_party/web-vitals/package/src/onFCP.ts +66 -7
  354. package/front_end/third_party/web-vitals/package/src/onINP.ts +100 -39
  355. package/front_end/third_party/web-vitals/package/src/onLCP.ts +169 -34
  356. package/front_end/third_party/web-vitals/package/src/onTTFB.ts +50 -13
  357. package/front_end/third_party/web-vitals/package/src/types/base.ts +31 -10
  358. package/front_end/third_party/web-vitals/package/src/types/fcp.ts +1 -1
  359. package/front_end/third_party/web-vitals/package/src/types/inp.ts +14 -6
  360. package/front_end/third_party/web-vitals/package/src/types/lcp.ts +1 -1
  361. package/front_end/third_party/web-vitals/package/src/types/ttfb.ts +2 -2
  362. package/front_end/third_party/web-vitals/package/src/types.ts +32 -9
  363. package/front_end/third_party/web-vitals/patches/0001-Add-onEachInteraction-to-onINP-options.patch +11 -11
  364. package/front_end/third_party/web-vitals/rebuild.sh +2 -2
  365. package/front_end/third_party/web-vitals/web-vitals-tsconfig.json +2 -0
  366. package/front_end/ui/components/buttons/Button.ts +16 -0
  367. package/front_end/ui/components/dialogs/Dialog.ts +1 -1
  368. package/front_end/ui/components/highlighting/HighlightManager.ts +6 -1
  369. package/front_end/ui/components/highlighting/highlighting.ts +1 -1
  370. package/front_end/ui/components/icon_button/FileSourceIcon.ts +1 -1
  371. package/front_end/ui/components/linkifier/LinkifierImpl.ts +1 -1
  372. package/front_end/ui/components/markdown_view/MarkdownLinksMap.ts +2 -2
  373. package/front_end/ui/components/settings/SettingCheckbox.ts +12 -7
  374. package/front_end/ui/components/text_editor/AiCodeCompletionProvider.ts +2 -2
  375. package/front_end/ui/components/text_editor/AiCodeGenerationProvider.ts +6 -6
  376. package/front_end/ui/components/text_editor/javascript.ts +3 -1
  377. package/front_end/ui/components/tooltips/Tooltip.ts +1 -1
  378. package/front_end/ui/legacy/ContextMenu.ts +12 -2
  379. package/front_end/ui/legacy/ListControl.ts +1 -1
  380. package/front_end/ui/legacy/SelectMenu.docs.ts +17 -19
  381. package/front_end/ui/legacy/Toolbar.ts +4 -1
  382. package/front_end/ui/legacy/Treeoutline.ts +1 -1
  383. package/front_end/ui/legacy/components/color_picker/spectrum.css +1 -2
  384. package/front_end/ui/legacy/components/data_grid/DataGrid.ts +1 -1
  385. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +50 -4
  386. package/front_end/ui/legacy/components/object_ui/JavaScriptREPL.ts +3 -1
  387. package/front_end/ui/legacy/components/perf_ui/ChartViewport.ts +4 -4
  388. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +8 -7
  389. package/front_end/ui/legacy/components/quick_open/CommandMenu.ts +14 -11
  390. package/front_end/ui/legacy/components/quick_open/QuickOpen.ts +1 -1
  391. package/front_end/ui/legacy/components/settings_ui/SettingsUI.ts +15 -5
  392. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +4 -4
  393. package/front_end/ui/legacy/components/utils/Linkifier.ts +5 -1
  394. package/front_end/ui/lit/render.ts +1 -1
  395. package/front_end/ui/settings/SettingUIRegistration.ts +8 -3
  396. package/front_end/ui/visual_logging/KnownContextValues.ts +8 -0
  397. package/front_end/ui/visual_logging/LoggingEvents.ts +1 -1
  398. package/inspector_overlay/main.ts +1 -1
  399. package/mcp/mcp.ts +5 -4
  400. package/package.json +13 -13
  401. package/front_end/models/ai_assistance/AgentProject.ts +0 -261
  402. package/front_end/models/ai_assistance/agents/PatchAgent.ts +0 -306
  403. package/front_end/models/issues_manager/CheckFormsIssuesTrigger.ts +0 -45
  404. package/front_end/models/text_utils/text_utils.ts +0 -5
  405. package/front_end/panels/ai_assistance/PatchWidget.ts +0 -867
  406. package/front_end/panels/ai_assistance/SelectWorkspaceDialog.ts +0 -368
  407. package/front_end/panels/ai_assistance/selectWorkspaceDialog.css +0 -92
@@ -18,8 +18,9 @@ import {getNavigationEntry} from '../lib/getNavigationEntry.js';
18
18
  import {getSelector} from '../lib/getSelector.js';
19
19
  import {initUnique} from '../lib/initUnique.js';
20
20
  import {LCPEntryManager} from '../lib/LCPEntryManager.js';
21
+ import {checkSoftNavsEnabled} from '../lib/softNavs.js';
21
22
  import {onLCP as unattributedOnLCP} from '../onLCP.js';
22
- import {
23
+ import type {
23
24
  LCPAttribution,
24
25
  LCPMetric,
25
26
  LCPMetricWithAttribution,
@@ -50,6 +51,10 @@ export const onLCP = (
50
51
  const lcpEntryManager = initUnique(opts, LCPEntryManager);
51
52
  const lcpTargetMap: WeakMap<LargestContentfulPaint, string> = new WeakMap();
52
53
 
54
+ if (checkSoftNavsEnabled(opts)) {
55
+ lcpEntryManager._softNavigationEntryMap = new Map();
56
+ }
57
+
53
58
  lcpEntryManager._onBeforeProcessingEntry = (
54
59
  entry: LargestContentfulPaint,
55
60
  ) => {
@@ -94,14 +99,27 @@ export const onLCP = (
94
99
 
95
100
  // Get subparts from navigation entry. Do this last as occasionally
96
101
  // Safari seems to fail to find a navigation entry.
97
- const navigationEntry = getNavigationEntry();
98
- if (navigationEntry) {
99
- const activationStart = navigationEntry.activationStart || 0;
102
+ let navigationEntry;
103
+ let activationStart = 0;
104
+ let responseStart = 0;
100
105
 
101
- const ttfb = Math.max(
102
- 0,
103
- navigationEntry.responseStart - activationStart,
106
+ if (metric.navigationType !== 'soft-navigation') {
107
+ navigationEntry = getNavigationEntry();
108
+ activationStart = navigationEntry?.activationStart ?? 0;
109
+ responseStart = navigationEntry?.responseStart ?? 0;
110
+ } else {
111
+ // Set activationStart to the navigation start time
112
+ activationStart = metric.navigationStartTime || 0;
113
+ // Lookup the soft navigation entry. Do not use getEntriesByType since
114
+ // that is limited to the first 50 navigation entries due to buffer
115
+ // size.
116
+ navigationEntry = lcpEntryManager._softNavigationEntryMap?.get(
117
+ metric.navigationId,
104
118
  );
119
+ }
120
+
121
+ if (navigationEntry) {
122
+ const ttfb = Math.max(0, responseStart - activationStart);
105
123
 
106
124
  const lcpRequestStart = Math.max(
107
125
  ttfb,
@@ -15,7 +15,7 @@
15
15
  */
16
16
 
17
17
  import {onTTFB as unattributedOnTTFB} from '../onTTFB.js';
18
- import {
18
+ import type {
19
19
  TTFBMetric,
20
20
  TTFBMetricWithAttribution,
21
21
  AttributionReportOpts,
@@ -23,6 +23,7 @@ import {
23
23
  } from '../types.js';
24
24
 
25
25
  const attributeTTFB = (metric: TTFBMetric): TTFBMetricWithAttribution => {
26
+ const navigationEntry = metric.entries[0];
26
27
  // Use a default object if no other attribution has been set.
27
28
  let attribution: TTFBAttribution = {
28
29
  waitingDuration: 0,
@@ -30,47 +31,52 @@ const attributeTTFB = (metric: TTFBMetric): TTFBMetricWithAttribution => {
30
31
  dnsDuration: 0,
31
32
  connectionDuration: 0,
32
33
  requestDuration: 0,
34
+ // There should only be one instance per TTFB metric
35
+ navigationEntry: navigationEntry,
33
36
  };
34
37
 
35
38
  if (metric.entries.length) {
36
- const navigationEntry = metric.entries[0];
37
- const activationStart = navigationEntry.activationStart || 0;
39
+ // If it's the hard nav, then can give attribution.
40
+ // Otherwise it's 0 so the defaults are fine.
41
+ if (navigationEntry instanceof PerformanceNavigationTiming) {
42
+ const activationStart = navigationEntry.activationStart || 0;
38
43
 
39
- // Measure from workerStart or fetchStart so any service worker startup
40
- // time is included in cacheDuration (which also includes other sw time
41
- // anyway, that cannot be accurately split out cross-browser).
42
- const waitEnd = Math.max(
43
- (navigationEntry.workerStart || navigationEntry.fetchStart) -
44
- activationStart,
45
- 0,
46
- );
47
- const dnsStart = Math.max(
48
- navigationEntry.domainLookupStart - activationStart,
49
- 0,
50
- );
51
- const connectStart = Math.max(
52
- navigationEntry.connectStart - activationStart,
53
- 0,
54
- );
55
- const connectEnd = Math.max(
56
- navigationEntry.connectEnd - activationStart,
57
- 0,
58
- );
44
+ // Measure from workerStart or fetchStart so any service worker startup
45
+ // time is included in cacheDuration (which also includes other sw time
46
+ // anyway, that cannot be accurately split out cross-browser).
47
+ const waitEnd = Math.max(
48
+ (navigationEntry.workerStart || navigationEntry.fetchStart || 0) -
49
+ activationStart,
50
+ 0,
51
+ );
52
+ const dnsStart = Math.max(
53
+ navigationEntry.domainLookupStart - activationStart,
54
+ 0,
55
+ );
56
+ const connectStart = Math.max(
57
+ navigationEntry.connectStart - activationStart,
58
+ 0,
59
+ );
60
+ const connectEnd = Math.max(
61
+ navigationEntry.connectEnd - activationStart,
62
+ 0,
63
+ );
59
64
 
60
- attribution = {
61
- waitingDuration: waitEnd,
62
- cacheDuration: dnsStart - waitEnd,
63
- // dnsEnd usually equals connectStart but use connectStart over dnsEnd
64
- // for dnsDuration in case there ever is a gap.
65
- dnsDuration: connectStart - dnsStart,
66
- connectionDuration: connectEnd - connectStart,
67
- // There is often a gap between connectEnd and requestStart. Attribute
68
- // that to requestDuration so connectionDuration remains 0 for
69
- // service worker controlled requests were connectStart and connectEnd
70
- // are the same.
71
- requestDuration: metric.value - connectEnd,
72
- navigationEntry: navigationEntry,
73
- };
65
+ attribution = {
66
+ waitingDuration: waitEnd,
67
+ cacheDuration: dnsStart - waitEnd,
68
+ // dnsEnd usually equals connectStart but use connectStart over dnsEnd
69
+ // for dnsDuration in case there ever is a gap.
70
+ dnsDuration: connectStart - dnsStart,
71
+ connectionDuration: connectEnd - connectStart,
72
+ // There is often a gap between connectEnd and requestStart. Attribute
73
+ // that to requestDuration so connectionDuration remains 0 for
74
+ // service worker controlled requests were connectStart and connectEnd
75
+ // are the same.
76
+ requestDuration: metric.value - connectEnd,
77
+ navigationEntry: navigationEntry,
78
+ };
79
+ }
74
80
  }
75
81
 
76
82
  // Use `Object.assign()` to ensure the original metric object is returned.
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2020 Google LLC
2
+ * Copyright 2026 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.
@@ -14,16 +14,6 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- let firstHiddenTime = document.visibilityState === 'hidden' ? 0 : Infinity;
18
-
19
- const onVisibilityChange = (event: Event) => {
20
- if (document.visibilityState === 'hidden') {
21
- firstHiddenTime = event.timeStamp;
22
- removeEventListener('visibilitychange', onVisibilityChange, true);
23
- }
24
- };
25
-
26
- // Note: do not add event listeners unconditionally (outside of polyfills).
27
- addEventListener('visibilitychange', onVisibilityChange, true);
28
-
29
- export const getFirstHiddenTime = () => firstHiddenTime;
17
+ export class FCPEntryManager {
18
+ _softNavigationEntryMap?: Map<number, PerformanceSoftNavigation>;
19
+ }
@@ -15,6 +15,7 @@
15
15
  */
16
16
 
17
17
  import {getInteractionCount} from './polyfills/interactionCountPolyfill.js';
18
+ import type {Metric} from '../types.js';
18
19
 
19
20
  export interface Interaction {
20
21
  _latency: number;
@@ -70,12 +71,31 @@ export class InteractionManager {
70
71
  * Returns the estimated p98 longest interaction based on the stored
71
72
  * interaction candidates and the interaction count for the current page.
72
73
  */
73
- _estimateP98LongestInteraction() {
74
+ _estimateP98LongestInteraction(navigationType: Metric['navigationType']) {
75
+ const interactionCountForNavigation = getInteractionCountForNavigation();
74
76
  const candidateInteractionIndex = Math.min(
75
77
  this._longestInteractionList.length - 1,
76
- Math.floor(getInteractionCountForNavigation() / 50),
78
+ Math.floor(interactionCountForNavigation / 50),
77
79
  );
78
80
 
81
+ // If we have a non-zero interactionCountForNavigation but no
82
+ // candidateInteractionIndex, then it's below the 16ms limit
83
+ // so report a dummy 8ms interaction. This is only needed for
84
+ // soft-navs and bfcache restores as `first-input` handles the
85
+ // rest.
86
+ if (
87
+ interactionCountForNavigation &&
88
+ candidateInteractionIndex === -1 &&
89
+ (navigationType === 'soft-navigation' ||
90
+ navigationType === 'back-forward-cache')
91
+ ) {
92
+ return {
93
+ _latency: 8,
94
+ id: -1,
95
+ entries: [],
96
+ };
97
+ }
98
+
79
99
  return this._longestInteractionList[candidateInteractionIndex];
80
100
  }
81
101
 
@@ -16,6 +16,7 @@
16
16
 
17
17
  export class LCPEntryManager {
18
18
  _onBeforeProcessingEntry?: (entry: LargestContentfulPaint) => void;
19
+ _softNavigationEntryMap?: Map<number, PerformanceSoftNavigation>;
19
20
 
20
21
  _processEntry(entry: LargestContentfulPaint) {
21
22
  this._onBeforeProcessingEntry?.(entry);
@@ -14,7 +14,7 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- import {MetricType, MetricRatingThresholds} from '../types.js';
17
+ import type {MetricType, MetricRatingThresholds} from '../types.js';
18
18
 
19
19
  const getRating = (
20
20
  value: number,
@@ -20,5 +20,5 @@
20
20
  * @return {string}
21
21
  */
22
22
  export const generateUniqueID = () => {
23
- return `v5-${Date.now()}-${Math.floor(Math.random() * (9e12 - 1)) + 1e12}`;
23
+ return `v6-${Date.now()}-${Math.floor(Math.random() * (9e12 - 1)) + 1e12}`;
24
24
  };
@@ -15,7 +15,7 @@
15
15
  */
16
16
 
17
17
  import {getNavigationEntry} from './getNavigationEntry.js';
18
- import {LoadState} from '../types.js';
18
+ import type {LoadState} from '../types.js';
19
19
 
20
20
  export const getLoadState = (timestamp: number): LoadState => {
21
21
  if (document.readyState === 'loading') {
@@ -23,22 +23,21 @@ export const getLoadState = (timestamp: number): LoadState => {
23
23
  // since the timestamp has to be the current time or earlier.
24
24
  return 'loading';
25
25
  }
26
- const navigationEntry = getNavigationEntry();
27
- if (navigationEntry) {
28
- if (timestamp < navigationEntry.domInteractive) {
26
+
27
+ const hardNavEntry = getNavigationEntry();
28
+ if (hardNavEntry) {
29
+ if (timestamp < hardNavEntry.domInteractive) {
29
30
  return 'loading';
30
- }
31
- if (
32
- navigationEntry.domContentLoadedEventStart === 0 ||
33
- timestamp < navigationEntry.domContentLoadedEventStart
31
+ } else if (
32
+ hardNavEntry.domContentLoadedEventStart === 0 ||
33
+ timestamp < hardNavEntry.domContentLoadedEventStart
34
34
  ) {
35
35
  // If the `domContentLoadedEventStart` timestamp has not yet been
36
36
  // set, or if the given timestamp is less than that value.
37
37
  return 'dom-interactive';
38
- }
39
- if (
40
- navigationEntry.domComplete === 0 ||
41
- timestamp < navigationEntry.domComplete
38
+ } else if (
39
+ hardNavEntry.domComplete === 0 ||
40
+ timestamp < hardNavEntry.domComplete
42
41
  ) {
43
42
  // If the `domComplete` timestamp has not yet been
44
43
  // set, or if the given timestamp is less than that value.
@@ -31,7 +31,7 @@ export const getSelector = (node: Node | null) => {
31
31
  const el: Element = node as Element;
32
32
  const part = el.id
33
33
  ? '#' + el.id
34
- : [getName(el), ...Array.from(el.classList).sort()].join('.');
34
+ : [getName(el), ...Array.from(el.classList ?? []).sort()].join('.');
35
35
  if (sel.length + part.length > MAX_LEN - 1) {
36
36
  return sel || part;
37
37
  }
@@ -60,7 +60,10 @@ const onVisibilityUpdate = (event: Event) => {
60
60
  }
61
61
  };
62
62
 
63
- export const getVisibilityWatcher = () => {
63
+ export const getVisibilityWatcher = (reset = false) => {
64
+ if (reset) {
65
+ firstHiddenTime = Infinity;
66
+ }
64
67
  if (firstHiddenTime < 0) {
65
68
  // Check if we have a previous hidden `visibility-state` performance entry.
66
69
  const activationStart = getActivationStart();
@@ -18,24 +18,33 @@ import {getBFCacheRestoreTime} from './bfcache.js';
18
18
  import {generateUniqueID} from './generateUniqueID.js';
19
19
  import {getActivationStart} from './getActivationStart.js';
20
20
  import {getNavigationEntry} from './getNavigationEntry.js';
21
- import {MetricType} from '../types.js';
21
+ import type {MetricType} from '../types.js';
22
22
 
23
23
  export const initMetric = <MetricName extends MetricType['name']>(
24
24
  name: MetricName,
25
25
  value: number = -1,
26
+ navigationType?: MetricType['navigationType'],
27
+ navigationId: number = 0,
28
+ navigationInteractionId?: number,
29
+ navigationURL?: string,
30
+ navigationStartTime?: number,
26
31
  ) => {
27
- const navEntry = getNavigationEntry();
28
- let navigationType: MetricType['navigationType'] = 'navigate';
32
+ const hardNavEntry = getNavigationEntry();
33
+ const hardNavId = hardNavEntry?.navigationId || 0;
34
+ let _navigationType: MetricType['navigationType'] = 'navigate';
29
35
 
30
- if (getBFCacheRestoreTime() >= 0) {
31
- navigationType = 'back-forward-cache';
32
- } else if (navEntry) {
36
+ if (navigationType) {
37
+ // If it was passed in, then use that
38
+ _navigationType = navigationType;
39
+ } else if (getBFCacheRestoreTime() >= 0) {
40
+ _navigationType = 'back-forward-cache';
41
+ } else if (hardNavEntry) {
33
42
  if (document.prerendering || getActivationStart() > 0) {
34
- navigationType = 'prerender';
43
+ _navigationType = 'prerender';
35
44
  } else if (document.wasDiscarded) {
36
- navigationType = 'restore';
37
- } else if (navEntry.type) {
38
- navigationType = navEntry.type.replace(
45
+ _navigationType = 'restore';
46
+ } else if (hardNavEntry.type) {
47
+ _navigationType = hardNavEntry.type.replace(
39
48
  /_/g,
40
49
  '-',
41
50
  ) as MetricType['navigationType'];
@@ -52,6 +61,10 @@ export const initMetric = <MetricName extends MetricType['name']>(
52
61
  delta: 0,
53
62
  entries,
54
63
  id: generateUniqueID(),
55
- navigationType,
64
+ navigationType: _navigationType,
65
+ navigationId: navigationId || hardNavId,
66
+ navigationInteractionId: navigationInteractionId,
67
+ navigationURL: navigationURL || hardNavEntry?.name,
68
+ navigationStartTime: navigationStartTime || 0,
56
69
  };
57
70
  };
@@ -14,7 +14,10 @@
14
14
  * limitations under the License.
15
15
  */
16
16
 
17
- const instanceMap: WeakMap<object, unknown> = new WeakMap();
17
+ const instanceMap: WeakMap<
18
+ new () => unknown,
19
+ WeakMap<object, unknown>
20
+ > = new WeakMap();
18
21
 
19
22
  /**
20
23
  * A function that accepts and identity object and a class object and returns
@@ -22,8 +25,13 @@ const instanceMap: WeakMap<object, unknown> = new WeakMap();
22
25
  * identity object was previously used.
23
26
  */
24
27
  export function initUnique<T>(identityObj: object, ClassObj: new () => T): T {
25
- if (!instanceMap.get(identityObj)) {
26
- instanceMap.set(identityObj, new ClassObj());
28
+ let classInstances = instanceMap.get(ClassObj);
29
+ if (!classInstances) {
30
+ classInstances = new WeakMap();
31
+ instanceMap.set(ClassObj, classInstances);
27
32
  }
28
- return instanceMap.get(identityObj)! as T;
33
+ if (!classInstances.get(identityObj)) {
34
+ classInstances.set(identityObj, new ClassObj());
35
+ }
36
+ return classInstances.get(identityObj)! as T;
29
37
  }
@@ -17,12 +17,14 @@
17
17
  interface PerformanceEntryMap {
18
18
  'event': PerformanceEventTiming[];
19
19
  'first-input': PerformanceEventTiming[];
20
+ 'interaction-contentful-paint': InteractionContentfulPaint[];
20
21
  'layout-shift': LayoutShift[];
21
22
  'largest-contentful-paint': LargestContentfulPaint[];
22
23
  'long-animation-frame': PerformanceLongAnimationFrameTiming[];
23
24
  'paint': PerformancePaintTiming[];
24
25
  'navigation': PerformanceNavigationTiming[];
25
26
  'resource': PerformanceResourceTiming[];
27
+ 'soft-navigation': PerformanceSoftNavigation[];
26
28
  }
27
29
 
28
30
  /**
@@ -34,21 +36,40 @@ interface PerformanceEntryMap {
34
36
  * try/catch to avoid errors in unsupporting browsers.
35
37
  */
36
38
  export const observe = <K extends keyof PerformanceEntryMap>(
37
- type: K,
38
- callback: (entries: PerformanceEntryMap[K]) => void,
39
+ types: K[],
40
+ callback: (entries: Array<PerformanceEntryMap[K][number]>) => void,
39
41
  opts: PerformanceObserverInit = {},
40
42
  ): PerformanceObserver | undefined => {
41
43
  try {
42
- if (PerformanceObserver.supportedEntryTypes.includes(type)) {
44
+ const supportedTypes = types.filter((t) =>
45
+ PerformanceObserver.supportedEntryTypes.includes(t),
46
+ );
47
+ if (supportedTypes.length > 0) {
43
48
  const po = new PerformanceObserver((list) => {
44
49
  // Delay by a microtask to workaround a bug in Safari where the
45
50
  // callback is invoked immediately, rather than in a separate task.
46
51
  // See: https://github.com/GoogleChrome/web-vitals/issues/277
47
52
  queueMicrotask(() => {
48
- callback(list.getEntries() as PerformanceEntryMap[K]);
53
+ const entries = list.getEntries();
54
+ // When observing more than one entry type, entries from different
55
+ // types can be delivered out of order, so sort by end time
56
+ // (startTime + duration) to ensure they're in the right order.
57
+ // See: https://github.com/w3c/performance-timeline/issues/224
58
+ if (supportedTypes.length > 1) {
59
+ entries.sort((a, b) => {
60
+ const scoreA = a.startTime + a.duration;
61
+ const scoreB = b.startTime + b.duration;
62
+
63
+ return scoreA - scoreB;
64
+ });
65
+ }
66
+ callback(entries as Array<PerformanceEntryMap[K][number]>);
49
67
  });
50
68
  });
51
- po.observe({type, buffered: true, ...opts});
69
+
70
+ for (const t of supportedTypes) {
71
+ po.observe({type: t, buffered: true, ...opts});
72
+ }
52
73
  return po;
53
74
  }
54
75
  } catch {
@@ -61,7 +61,7 @@ export const getInteractionCount = () => {
61
61
  export const initInteractionCountPolyfill = () => {
62
62
  if ('interactionCount' in performance || po) return;
63
63
 
64
- po = observe('event', updateEstimate, {
64
+ po = observe(['event'], updateEstimate, {
65
65
  durationThreshold: 0,
66
66
  } as PerformanceObserverInit);
67
67
  };
@@ -0,0 +1,48 @@
1
+ /*
2
+ * Copyright 2023 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
+
17
+ import type {ReportOpts} from '../types.js';
18
+
19
+ export const checkSoftNavsEnabled = (opts?: ReportOpts) => {
20
+ return (
21
+ PerformanceObserver.supportedEntryTypes.includes('soft-navigation') &&
22
+ // Older implementations expose the value as an attribute rather than the
23
+ // method. We only support the newer method as that was what was launched
24
+ // to stable unflagged.
25
+ typeof globalThis.PerformanceSoftNavigation?.prototype
26
+ ?.getLargestInteractionContentfulPaint === 'function' &&
27
+ opts &&
28
+ opts.reportSoftNavs
29
+ );
30
+ };
31
+
32
+ // Stores a soft navigation entry keyed by its navigationId, keeping only
33
+ // the 2 most recent entries so the map cannot grow unbounded.
34
+ export const storeSoftNavEntry = (
35
+ map: Map<number, PerformanceSoftNavigation>,
36
+ entry: PerformanceSoftNavigation,
37
+ ) => {
38
+ map.set(entry.navigationId!, entry);
39
+
40
+ // Clean up older entries to prevent memory leaks, keeping only
41
+ // the 2 most recent entries.
42
+ if (map.size > 2) {
43
+ const firstKey = map.keys().next().value;
44
+ if (firstKey !== undefined) {
45
+ map.delete(firstKey);
46
+ }
47
+ }
48
+ };
@@ -21,6 +21,11 @@ import {runOnce} from './runOnce.js';
21
21
  * if the browser's visibility state is (or becomes) hidden.
22
22
  */
23
23
  export const whenIdleOrHidden = (cb: () => void) => {
24
+ // Cap the requestIdleCallback to 1 sec for very busy apps
25
+ // https://github.com/GoogleChrome/web-vitals/issues/754
26
+ // If not using rIC, then the setTimeout timeout should be 0
27
+ const timeout = 'requestIdleCallback' in globalThis ? 1000 : 0;
28
+
24
29
  const rIC = globalThis.requestIdleCallback || setTimeout;
25
30
  const cIC = globalThis.cancelIdleCallback || clearTimeout;
26
31
 
@@ -38,9 +43,12 @@ export const whenIdleOrHidden = (cb: () => void) => {
38
43
  };
39
44
 
40
45
  addEventListener('visibilitychange', onHidden, {once: true, capture: true});
41
- idleHandle = rIC(() => {
42
- removeEventListener('visibilitychange', onHidden, {capture: true});
43
- wrappedCb();
44
- });
46
+ idleHandle = rIC(
47
+ () => {
48
+ removeEventListener('visibilitychange', onHidden, {capture: true});
49
+ wrappedCb();
50
+ },
51
+ {timeout: timeout},
52
+ );
45
53
  }
46
54
  };