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
@@ -16,40 +16,61 @@
16
16
  import { getBFCacheRestoreTime } from '../lib/bfcache.js';
17
17
  import { getLoadState } from '../lib/getLoadState.js';
18
18
  import { getNavigationEntry } from '../lib/getNavigationEntry.js';
19
+ import { initUnique } from '../lib/initUnique.js';
20
+ import { FCPEntryManager } from '../lib/FCPEntryManager.js';
21
+ import { checkSoftNavsEnabled } from '../lib/softNavs.js';
19
22
  import { onFCP as unattributedOnFCP } from '../onFCP.js';
20
- const attributeFCP = (metric) => {
21
- // Use a default object if no other attribution has been set.
22
- let attribution = {
23
- timeToFirstByte: 0,
24
- firstByteToFCP: metric.value,
25
- loadState: getLoadState(getBFCacheRestoreTime()),
26
- };
27
- if (metric.entries.length) {
28
- const navigationEntry = getNavigationEntry();
29
- const fcpEntry = metric.entries.at(-1);
30
- if (navigationEntry) {
31
- const activationStart = navigationEntry.activationStart || 0;
32
- const ttfb = Math.max(0, navigationEntry.responseStart - activationStart);
33
- attribution = {
34
- timeToFirstByte: ttfb,
35
- firstByteToFCP: metric.value - ttfb,
36
- loadState: getLoadState(metric.entries[0].startTime),
37
- navigationEntry,
38
- fcpEntry,
39
- };
40
- }
41
- }
42
- // Use `Object.assign()` to ensure the original metric object is returned.
43
- const metricWithAttribution = Object.assign(metric, { attribution });
44
- return metricWithAttribution;
45
- };
46
- /**
47
- * Calculates the [FCP](https://web.dev/articles/fcp) value for the current page and
48
- * calls the `callback` function once the value is ready, along with the
49
- * relevant `paint` performance entry used to determine the value. The reported
50
- * value is a `DOMHighResTimeStamp`.
51
- */
52
23
  export const onFCP = (onReport, opts = {}) => {
24
+ opts = Object.assign({}, opts);
25
+ // Init the fcpEntryManager (which will already be initialised in the
26
+ // unattributed onFCP method if soft navigation reporting is enabled
27
+ // and so will return that fcpEntryManager, rather than a new one)
28
+ const fcpEntryManager = initUnique(opts, FCPEntryManager);
29
+ if (checkSoftNavsEnabled(opts)) {
30
+ fcpEntryManager._softNavigationEntryMap = new Map();
31
+ }
32
+ const attributeFCP = (metric) => {
33
+ // Use a default object if no other attribution has been set.
34
+ let attribution = {
35
+ timeToFirstByte: 0,
36
+ firstByteToFCP: metric.value,
37
+ loadState: getLoadState(getBFCacheRestoreTime()),
38
+ };
39
+ if (metric.navigationType !== 'soft-navigation') {
40
+ if (metric.entries.length) {
41
+ const navigationEntry = getNavigationEntry();
42
+ const fcpEntry = metric.entries.at(-1);
43
+ if (navigationEntry) {
44
+ const responseStart = navigationEntry.responseStart;
45
+ const activationStart = navigationEntry.activationStart || 0;
46
+ const ttfb = Math.max(0, responseStart - activationStart);
47
+ attribution = {
48
+ timeToFirstByte: ttfb,
49
+ firstByteToFCP: metric.value - ttfb,
50
+ loadState: getLoadState(metric.entries[0].startTime),
51
+ navigationEntry,
52
+ fcpEntry,
53
+ };
54
+ }
55
+ }
56
+ }
57
+ else {
58
+ // Lookup the soft navigation entry. Do not use getEntriesByType since
59
+ // that is limited to the first 50 navigation entries due to buffer size.
60
+ const navigationEntry = fcpEntryManager._softNavigationEntryMap?.get(metric.navigationId);
61
+ if (navigationEntry) {
62
+ attribution = {
63
+ timeToFirstByte: 0,
64
+ firstByteToFCP: metric.value,
65
+ loadState: 'complete',
66
+ navigationEntry,
67
+ };
68
+ }
69
+ }
70
+ // Use `Object.assign()` to ensure the original metric object is returned.
71
+ const metricWithAttribution = Object.assign(metric, { attribution });
72
+ return metricWithAttribution;
73
+ };
53
74
  unattributedOnFCP((metric) => {
54
75
  onReport(attributeFCP(metric));
55
76
  }, opts);
@@ -1,4 +1,4 @@
1
- import { INPAttributionReportOpts, INPMetricWithAttribution } from '../types.js';
1
+ import type { INPAttributionReportOpts, INPMetricWithAttribution } from '../types.js';
2
2
  /**
3
3
  * Calculates the [INP](https://web.dev/articles/inp) value for the current
4
4
  * page and calls the `callback` function once the value is ready, along with
@@ -16,7 +16,7 @@ import { INPAttributionReportOpts, INPMetricWithAttribution } from '../types.js'
16
16
  *
17
17
  * A custom `includeProcessedEventEntries` configuration option can optionally
18
18
  * be passed to control whether the `processedEventEntries` array in the
19
- * attribution object is populated. The default value is `true`.
19
+ * attribution object is populated. The default value is `false`.
20
20
  *
21
21
  * If the `reportAllChanges` configuration option is set to `true`, the
22
22
  * `callback` function will be called as soon as the value is initially
@@ -16,7 +16,7 @@
16
16
  import { getLoadState } from '../lib/getLoadState.js';
17
17
  import { getSelector } from '../lib/getSelector.js';
18
18
  import { initUnique } from '../lib/initUnique.js';
19
- import { InteractionManager } from '../lib/InteractionManager.js';
19
+ import { InteractionManager, } from '../lib/InteractionManager.js';
20
20
  import { observe } from '../lib/observe.js';
21
21
  import { whenIdleOrHidden } from '../lib/whenIdleOrHidden.js';
22
22
  import { onINP as unattributedOnINP } from '../onINP.js';
@@ -45,7 +45,7 @@ const MAX_PENDING_FRAMES = 10;
45
45
  *
46
46
  * A custom `includeProcessedEventEntries` configuration option can optionally
47
47
  * be passed to control whether the `processedEventEntries` array in the
48
- * attribution object is populated. The default value is `true`.
48
+ * attribution object is populated. The default value is `false`.
49
49
  *
50
50
  * If the `reportAllChanges` configuration option is set to `true`, the
51
51
  * `callback` function will be called as soon as the value is initially
@@ -95,11 +95,19 @@ export const onINP = (onReport, opts = {}) => {
95
95
  };
96
96
  const saveInteractionTarget = (interaction) => {
97
97
  if (!interactionTargetMap.get(interaction)) {
98
- const node = interaction.entries[0].target;
98
+ // Use find to get first selector
99
+ const node = interaction.entries.find((e) => e.target)?.target;
99
100
  if (node) {
100
101
  const customTarget = opts.generateTarget?.(node) ?? getSelector(node);
101
102
  interactionTargetMap.set(interaction, customTarget);
102
103
  }
104
+ else {
105
+ // Fall back to targetSelector
106
+ const selector = interaction.entries.find((e) => e.targetSelector)?.targetSelector;
107
+ if (selector) {
108
+ interactionTargetMap.set(interaction, selector);
109
+ }
110
+ }
103
111
  }
104
112
  };
105
113
  /**
@@ -129,7 +137,7 @@ export const onINP = (onReport, opts = {}) => {
129
137
  group.processingEnd = Math.max(entry.processingEnd, group.processingEnd);
130
138
  // processedEventEntries can be quite large, so only include them if
131
139
  // the user explicitly requests them (default is to include).
132
- if (opts.includeProcessedEventEntries !== false) {
140
+ if (opts.includeProcessedEventEntries) {
133
141
  group.entries.push(entry);
134
142
  }
135
143
  break;
@@ -144,7 +152,7 @@ export const onINP = (onReport, opts = {}) => {
144
152
  renderTime,
145
153
  // processedEventEntries can be quite large, so only include them if
146
154
  // the user explicitly requests them (default is to include).
147
- entries: opts.includeProcessedEventEntries !== false ? [entry] : [],
155
+ entries: opts.includeProcessedEventEntries ? [entry] : [],
148
156
  };
149
157
  pendingEntriesGroups.push(group);
150
158
  }
@@ -216,6 +224,7 @@ export const onINP = (onReport, opts = {}) => {
216
224
  rating: 'good',
217
225
  value: entry.duration,
218
226
  delta: entry.duration,
227
+ navigationId: entry.navigationId,
219
228
  navigationType: 'navigate',
220
229
  id: 'N/A',
221
230
  });
@@ -242,11 +251,15 @@ export const onINP = (onReport, opts = {}) => {
242
251
  return intersectingLoAFs;
243
252
  };
244
253
  const attributeLoAFDetails = (attribution) => {
245
- // If there is no LoAF data then nothing further to attribute
246
- if (!attribution.longAnimationFrameEntries?.length) {
254
+ const interactionTime = attribution.interactionTime;
255
+ const nextPaintTime = attribution.nextPaintTime;
256
+ // If there is no LoAF data, interactionTime or paintTime
257
+ // then nothing further to attribute here.
258
+ if (!attribution.longAnimationFrameEntries?.length ||
259
+ !interactionTime ||
260
+ !nextPaintTime) {
247
261
  return;
248
262
  }
249
- const interactionTime = attribution.interactionTime;
250
263
  const inputDelay = attribution.inputDelay;
251
264
  const processingDuration = attribution.processingDuration;
252
265
  // Stats across all LoAF entries and scripts.
@@ -302,7 +315,7 @@ export const onINP = (onReport, opts = {}) => {
302
315
  ? lastLoAF.startTime + lastLoAF.duration
303
316
  : 0;
304
317
  if (lastLoAFEndTime >= interactionTime + inputDelay + processingDuration) {
305
- totalPaintDuration = attribution.nextPaintTime - lastLoAFEndTime;
318
+ totalPaintDuration = nextPaintTime - lastLoAFEndTime;
306
319
  }
307
320
  if (longestScriptEntry && longestScriptSubpart) {
308
321
  attribution.longestScript = {
@@ -315,16 +328,34 @@ export const onINP = (onReport, opts = {}) => {
315
328
  attribution.totalStyleAndLayoutDuration = totalStyleAndLayoutDuration;
316
329
  attribution.totalPaintDuration = totalPaintDuration;
317
330
  attribution.totalUnattributedDuration =
318
- attribution.nextPaintTime -
331
+ nextPaintTime -
319
332
  interactionTime -
320
333
  totalScriptDuration -
321
334
  totalStyleAndLayoutDuration -
322
335
  totalPaintDuration;
323
336
  };
324
337
  const attributeINP = (metric) => {
338
+ // Soft navs and bfcache can have a dummy INP as no first-input entry to
339
+ // fall back on so we report dummy values when the interactionCount has
340
+ // gone up, even if no entry was emitted.
341
+ // See https://github.com/GoogleChrome/web-vitals/issues/724
342
+ // All other INPs should have at least one entry, but we'll do same dummy
343
+ // processing if they don't for some reason.
344
+ if (metric.entries.length === 0) {
345
+ const navStartTime = metric.navigationStartTime || 0;
346
+ const attribution = {
347
+ processedEventEntries: [],
348
+ longAnimationFrameEntries: [],
349
+ inputDelay: 0,
350
+ processingDuration: 0,
351
+ presentationDelay: metric.value,
352
+ loadState: getLoadState(navStartTime),
353
+ };
354
+ return Object.assign(metric, { attribution });
355
+ }
325
356
  const firstEntry = metric.entries[0];
326
357
  const group = entryToEntriesGroupMap.get(firstEntry);
327
- const processingStart = firstEntry.processingStart;
358
+ const processingStart = group.processingStart;
328
359
  // Due to the fact that durations can be rounded down to the nearest 8ms,
329
360
  // we have to clamp `nextPaintTime` so it doesn't appear to occur before
330
361
  // processing starts. Note: we can't use `processingEnd` since processing
@@ -368,7 +399,7 @@ export const onINP = (onReport, opts = {}) => {
368
399
  return Object.assign(metric, { attribution });
369
400
  };
370
401
  // Start observing LoAF entries for attribution.
371
- observe('long-animation-frame', handleLoAFEntries);
402
+ observe(['long-animation-frame'], handleLoAFEntries, opts);
372
403
  unattributedOnINP((metric) => {
373
404
  onReport(attributeINP(metric));
374
405
  }, opts);
@@ -1,4 +1,4 @@
1
- import { LCPMetricWithAttribution, AttributionReportOpts } from '../types.js';
1
+ import type { LCPMetricWithAttribution, AttributionReportOpts } from '../types.js';
2
2
  /**
3
3
  * Calculates the [LCP](https://web.dev/articles/lcp) value for the current page and
4
4
  * calls the `callback` function once the value is ready (along with the
@@ -17,6 +17,7 @@ import { getNavigationEntry } from '../lib/getNavigationEntry.js';
17
17
  import { getSelector } from '../lib/getSelector.js';
18
18
  import { initUnique } from '../lib/initUnique.js';
19
19
  import { LCPEntryManager } from '../lib/LCPEntryManager.js';
20
+ import { checkSoftNavsEnabled } from '../lib/softNavs.js';
20
21
  import { onLCP as unattributedOnLCP } from '../onLCP.js';
21
22
  /**
22
23
  * Calculates the [LCP](https://web.dev/articles/lcp) value for the current page and
@@ -37,6 +38,9 @@ export const onLCP = (onReport, opts = {}) => {
37
38
  opts = Object.assign({}, opts);
38
39
  const lcpEntryManager = initUnique(opts, LCPEntryManager);
39
40
  const lcpTargetMap = new WeakMap();
41
+ if (checkSoftNavsEnabled(opts)) {
42
+ lcpEntryManager._softNavigationEntryMap = new Map();
43
+ }
40
44
  lcpEntryManager._onBeforeProcessingEntry = (entry) => {
41
45
  const node = entry.element;
42
46
  if (node) {
@@ -75,10 +79,24 @@ export const onLCP = (onReport, opts = {}) => {
75
79
  }
76
80
  // Get subparts from navigation entry. Do this last as occasionally
77
81
  // Safari seems to fail to find a navigation entry.
78
- const navigationEntry = getNavigationEntry();
82
+ let navigationEntry;
83
+ let activationStart = 0;
84
+ let responseStart = 0;
85
+ if (metric.navigationType !== 'soft-navigation') {
86
+ navigationEntry = getNavigationEntry();
87
+ activationStart = navigationEntry?.activationStart ?? 0;
88
+ responseStart = navigationEntry?.responseStart ?? 0;
89
+ }
90
+ else {
91
+ // Set activationStart to the navigation start time
92
+ activationStart = metric.navigationStartTime || 0;
93
+ // Lookup the soft navigation entry. Do not use getEntriesByType since
94
+ // that is limited to the first 50 navigation entries due to buffer
95
+ // size.
96
+ navigationEntry = lcpEntryManager._softNavigationEntryMap?.get(metric.navigationId);
97
+ }
79
98
  if (navigationEntry) {
80
- const activationStart = navigationEntry.activationStart || 0;
81
- const ttfb = Math.max(0, navigationEntry.responseStart - activationStart);
99
+ const ttfb = Math.max(0, responseStart - activationStart);
82
100
  const lcpRequestStart = Math.max(ttfb,
83
101
  // Prefer `requestStart` (if TOA is set), otherwise use `startTime`.
84
102
  lcpResourceEntry
@@ -1,4 +1,4 @@
1
- import { TTFBMetricWithAttribution, AttributionReportOpts } from '../types.js';
1
+ import type { TTFBMetricWithAttribution, AttributionReportOpts } from '../types.js';
2
2
  /**
3
3
  * Calculates the [TTFB](https://web.dev/articles/ttfb) value for the
4
4
  * current page and calls the `callback` function once the page has loaded,
@@ -15,6 +15,7 @@
15
15
  */
16
16
  import { onTTFB as unattributedOnTTFB } from '../onTTFB.js';
17
17
  const attributeTTFB = (metric) => {
18
+ const navigationEntry = metric.entries[0];
18
19
  // Use a default object if no other attribution has been set.
19
20
  let attribution = {
20
21
  waitingDuration: 0,
@@ -22,32 +23,37 @@ const attributeTTFB = (metric) => {
22
23
  dnsDuration: 0,
23
24
  connectionDuration: 0,
24
25
  requestDuration: 0,
26
+ // There should only be one instance per TTFB metric
27
+ navigationEntry: navigationEntry,
25
28
  };
26
29
  if (metric.entries.length) {
27
- const navigationEntry = metric.entries[0];
28
- const activationStart = navigationEntry.activationStart || 0;
29
- // Measure from workerStart or fetchStart so any service worker startup
30
- // time is included in cacheDuration (which also includes other sw time
31
- // anyway, that cannot be accurately split out cross-browser).
32
- const waitEnd = Math.max((navigationEntry.workerStart || navigationEntry.fetchStart) -
33
- activationStart, 0);
34
- const dnsStart = Math.max(navigationEntry.domainLookupStart - activationStart, 0);
35
- const connectStart = Math.max(navigationEntry.connectStart - activationStart, 0);
36
- const connectEnd = Math.max(navigationEntry.connectEnd - activationStart, 0);
37
- attribution = {
38
- waitingDuration: waitEnd,
39
- cacheDuration: dnsStart - waitEnd,
40
- // dnsEnd usually equals connectStart but use connectStart over dnsEnd
41
- // for dnsDuration in case there ever is a gap.
42
- dnsDuration: connectStart - dnsStart,
43
- connectionDuration: connectEnd - connectStart,
44
- // There is often a gap between connectEnd and requestStart. Attribute
45
- // that to requestDuration so connectionDuration remains 0 for
46
- // service worker controlled requests were connectStart and connectEnd
47
- // are the same.
48
- requestDuration: metric.value - connectEnd,
49
- navigationEntry: navigationEntry,
50
- };
30
+ // If it's the hard nav, then can give attribution.
31
+ // Otherwise it's 0 so the defaults are fine.
32
+ if (navigationEntry instanceof PerformanceNavigationTiming) {
33
+ const activationStart = navigationEntry.activationStart || 0;
34
+ // Measure from workerStart or fetchStart so any service worker startup
35
+ // time is included in cacheDuration (which also includes other sw time
36
+ // anyway, that cannot be accurately split out cross-browser).
37
+ const waitEnd = Math.max((navigationEntry.workerStart || navigationEntry.fetchStart || 0) -
38
+ activationStart, 0);
39
+ const dnsStart = Math.max(navigationEntry.domainLookupStart - activationStart, 0);
40
+ const connectStart = Math.max(navigationEntry.connectStart - activationStart, 0);
41
+ const connectEnd = Math.max(navigationEntry.connectEnd - activationStart, 0);
42
+ attribution = {
43
+ waitingDuration: waitEnd,
44
+ cacheDuration: dnsStart - waitEnd,
45
+ // dnsEnd usually equals connectStart but use connectStart over dnsEnd
46
+ // for dnsDuration in case there ever is a gap.
47
+ dnsDuration: connectStart - dnsStart,
48
+ connectionDuration: connectEnd - connectStart,
49
+ // There is often a gap between connectEnd and requestStart. Attribute
50
+ // that to requestDuration so connectionDuration remains 0 for
51
+ // service worker controlled requests were connectStart and connectEnd
52
+ // are the same.
53
+ requestDuration: metric.value - connectEnd,
54
+ navigationEntry: navigationEntry,
55
+ };
56
+ }
51
57
  }
52
58
  // Use `Object.assign()` to ensure the original metric object is returned.
53
59
  const metricWithAttribution = Object.assign(metric, { attribution });
@@ -0,0 +1,3 @@
1
+ export declare class FCPEntryManager {
2
+ _softNavigationEntryMap?: Map<number, PerformanceSoftNavigation>;
3
+ }
@@ -0,0 +1,18 @@
1
+ /*
2
+ * Copyright 2026 Google LLC
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * https://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ export class FCPEntryManager {
17
+ _softNavigationEntryMap;
18
+ }
@@ -1,3 +1,4 @@
1
+ import type { Metric } from '../types.js';
1
2
  export interface Interaction {
2
3
  _latency: number;
3
4
  id: number;
@@ -22,7 +23,7 @@ export declare class InteractionManager {
22
23
  * Returns the estimated p98 longest interaction based on the stored
23
24
  * interaction candidates and the interaction count for the current page.
24
25
  */
25
- _estimateP98LongestInteraction(): Interaction;
26
+ _estimateP98LongestInteraction(navigationType: Metric['navigationType']): Interaction;
26
27
  /**
27
28
  * Takes a performance entry and adds it to the list of worst interactions
28
29
  * if its duration is long enough to make it among the worst. If the
@@ -50,8 +50,24 @@ export class InteractionManager {
50
50
  * Returns the estimated p98 longest interaction based on the stored
51
51
  * interaction candidates and the interaction count for the current page.
52
52
  */
53
- _estimateP98LongestInteraction() {
54
- const candidateInteractionIndex = Math.min(this._longestInteractionList.length - 1, Math.floor(getInteractionCountForNavigation() / 50));
53
+ _estimateP98LongestInteraction(navigationType) {
54
+ const interactionCountForNavigation = getInteractionCountForNavigation();
55
+ const candidateInteractionIndex = Math.min(this._longestInteractionList.length - 1, Math.floor(interactionCountForNavigation / 50));
56
+ // If we have a non-zero interactionCountForNavigation but no
57
+ // candidateInteractionIndex, then it's below the 16ms limit
58
+ // so report a dummy 8ms interaction. This is only needed for
59
+ // soft-navs and bfcache restores as `first-input` handles the
60
+ // rest.
61
+ if (interactionCountForNavigation &&
62
+ candidateInteractionIndex === -1 &&
63
+ (navigationType === 'soft-navigation' ||
64
+ navigationType === 'back-forward-cache')) {
65
+ return {
66
+ _latency: 8,
67
+ id: -1,
68
+ entries: [],
69
+ };
70
+ }
55
71
  return this._longestInteractionList[candidateInteractionIndex];
56
72
  }
57
73
  /**
@@ -1,4 +1,5 @@
1
1
  export declare class LCPEntryManager {
2
2
  _onBeforeProcessingEntry?: (entry: LargestContentfulPaint) => void;
3
+ _softNavigationEntryMap?: Map<number, PerformanceSoftNavigation>;
3
4
  _processEntry(entry: LargestContentfulPaint): void;
4
5
  }
@@ -15,6 +15,7 @@
15
15
  */
16
16
  export class LCPEntryManager {
17
17
  _onBeforeProcessingEntry;
18
+ _softNavigationEntryMap;
18
19
  _processEntry(entry) {
19
20
  this._onBeforeProcessingEntry?.(entry);
20
21
  }
@@ -1,4 +1,4 @@
1
- import { MetricType, MetricRatingThresholds } from '../types.js';
1
+ import type { MetricType, MetricRatingThresholds } from '../types.js';
2
2
  export declare const bindReporter: <MetricName extends MetricType["name"]>(callback: (metric: Extract<MetricType, {
3
3
  name: MetricName;
4
4
  }>) => void, metric: Extract<MetricType, {
@@ -19,5 +19,5 @@
19
19
  * @return {string}
20
20
  */
21
21
  export const generateUniqueID = () => {
22
- return `v5-${Date.now()}-${Math.floor(Math.random() * (9e12 - 1)) + 1e12}`;
22
+ return `v6-${Date.now()}-${Math.floor(Math.random() * (9e12 - 1)) + 1e12}`;
23
23
  };
@@ -1,2 +1,2 @@
1
- import { LoadState } from '../types.js';
1
+ import type { LoadState } from '../types.js';
2
2
  export declare const getLoadState: (timestamp: number) => LoadState;
@@ -20,19 +20,19 @@ export const getLoadState = (timestamp) => {
20
20
  // since the timestamp has to be the current time or earlier.
21
21
  return 'loading';
22
22
  }
23
- const navigationEntry = getNavigationEntry();
24
- if (navigationEntry) {
25
- if (timestamp < navigationEntry.domInteractive) {
23
+ const hardNavEntry = getNavigationEntry();
24
+ if (hardNavEntry) {
25
+ if (timestamp < hardNavEntry.domInteractive) {
26
26
  return 'loading';
27
27
  }
28
- if (navigationEntry.domContentLoadedEventStart === 0 ||
29
- timestamp < navigationEntry.domContentLoadedEventStart) {
28
+ else if (hardNavEntry.domContentLoadedEventStart === 0 ||
29
+ timestamp < hardNavEntry.domContentLoadedEventStart) {
30
30
  // If the `domContentLoadedEventStart` timestamp has not yet been
31
31
  // set, or if the given timestamp is less than that value.
32
32
  return 'dom-interactive';
33
33
  }
34
- if (navigationEntry.domComplete === 0 ||
35
- timestamp < navigationEntry.domComplete) {
34
+ else if (hardNavEntry.domComplete === 0 ||
35
+ timestamp < hardNavEntry.domComplete) {
36
36
  // If the `domComplete` timestamp has not yet been
37
37
  // set, or if the given timestamp is less than that value.
38
38
  return 'dom-content-loaded';
@@ -27,7 +27,7 @@ export const getSelector = (node) => {
27
27
  const el = node;
28
28
  const part = el.id
29
29
  ? '#' + el.id
30
- : [getName(el), ...Array.from(el.classList).sort()].join('.');
30
+ : [getName(el), ...Array.from(el.classList ?? []).sort()].join('.');
31
31
  if (sel.length + part.length > MAX_LEN - 1) {
32
32
  return sel || part;
33
33
  }
@@ -1,4 +1,4 @@
1
- export declare const getVisibilityWatcher: () => {
1
+ export declare const getVisibilityWatcher: (reset?: boolean) => {
2
2
  readonly firstHiddenTime: number;
3
3
  onHidden(cb: () => void): void;
4
4
  };
@@ -53,7 +53,10 @@ const onVisibilityUpdate = (event) => {
53
53
  }
54
54
  }
55
55
  };
56
- export const getVisibilityWatcher = () => {
56
+ export const getVisibilityWatcher = (reset = false) => {
57
+ if (reset) {
58
+ firstHiddenTime = Infinity;
59
+ }
57
60
  if (firstHiddenTime < 0) {
58
61
  // Check if we have a previous hidden `visibility-state` performance entry.
59
62
  const activationStart = getActivationStart();
@@ -1,5 +1,5 @@
1
- import { MetricType } from '../types.js';
2
- export declare const initMetric: <MetricName extends MetricType["name"]>(name: MetricName, value?: number) => {
1
+ import type { MetricType } from '../types.js';
2
+ export declare const initMetric: <MetricName extends MetricType["name"]>(name: MetricName, value?: number, navigationType?: MetricType["navigationType"], navigationId?: number, navigationInteractionId?: number, navigationURL?: string, navigationStartTime?: number) => {
3
3
  name: MetricName;
4
4
  value: number;
5
5
  rating: "good";
@@ -16,5 +16,9 @@ export declare const initMetric: <MetricName extends MetricType["name"]>(name: M
16
16
  name: MetricName;
17
17
  }>)["entries"];
18
18
  id: string;
19
- navigationType: "reload" | "navigate" | "back-forward" | "back-forward-cache" | "prerender" | "restore";
19
+ navigationType: "reload" | "navigate" | "soft-navigation" | "back-forward" | "back-forward-cache" | "prerender" | "restore";
20
+ navigationId: number;
21
+ navigationInteractionId: number | undefined;
22
+ navigationURL: string | undefined;
23
+ navigationStartTime: number;
20
24
  };
@@ -17,21 +17,26 @@ import { getBFCacheRestoreTime } from './bfcache.js';
17
17
  import { generateUniqueID } from './generateUniqueID.js';
18
18
  import { getActivationStart } from './getActivationStart.js';
19
19
  import { getNavigationEntry } from './getNavigationEntry.js';
20
- export const initMetric = (name, value = -1) => {
21
- const navEntry = getNavigationEntry();
22
- let navigationType = 'navigate';
23
- if (getBFCacheRestoreTime() >= 0) {
24
- navigationType = 'back-forward-cache';
20
+ export const initMetric = (name, value = -1, navigationType, navigationId = 0, navigationInteractionId, navigationURL, navigationStartTime) => {
21
+ const hardNavEntry = getNavigationEntry();
22
+ const hardNavId = hardNavEntry?.navigationId || 0;
23
+ let _navigationType = 'navigate';
24
+ if (navigationType) {
25
+ // If it was passed in, then use that
26
+ _navigationType = navigationType;
25
27
  }
26
- else if (navEntry) {
28
+ else if (getBFCacheRestoreTime() >= 0) {
29
+ _navigationType = 'back-forward-cache';
30
+ }
31
+ else if (hardNavEntry) {
27
32
  if (document.prerendering || getActivationStart() > 0) {
28
- navigationType = 'prerender';
33
+ _navigationType = 'prerender';
29
34
  }
30
35
  else if (document.wasDiscarded) {
31
- navigationType = 'restore';
36
+ _navigationType = 'restore';
32
37
  }
33
- else if (navEntry.type) {
34
- navigationType = navEntry.type.replace(/_/g, '-');
38
+ else if (hardNavEntry.type) {
39
+ _navigationType = hardNavEntry.type.replace(/_/g, '-');
35
40
  }
36
41
  }
37
42
  // Use `entries` type specific for the metric.
@@ -43,6 +48,10 @@ export const initMetric = (name, value = -1) => {
43
48
  delta: 0,
44
49
  entries,
45
50
  id: generateUniqueID(),
46
- navigationType,
51
+ navigationType: _navigationType,
52
+ navigationId: navigationId || hardNavId,
53
+ navigationInteractionId: navigationInteractionId,
54
+ navigationURL: navigationURL || hardNavEntry?.name,
55
+ navigationStartTime: navigationStartTime || 0,
47
56
  };
48
57
  };
@@ -20,8 +20,13 @@ const instanceMap = new WeakMap();
20
20
  * identity object was previously used.
21
21
  */
22
22
  export function initUnique(identityObj, ClassObj) {
23
- if (!instanceMap.get(identityObj)) {
24
- instanceMap.set(identityObj, new ClassObj());
23
+ let classInstances = instanceMap.get(ClassObj);
24
+ if (!classInstances) {
25
+ classInstances = new WeakMap();
26
+ instanceMap.set(ClassObj, classInstances);
25
27
  }
26
- return instanceMap.get(identityObj);
28
+ if (!classInstances.get(identityObj)) {
29
+ classInstances.set(identityObj, new ClassObj());
30
+ }
31
+ return classInstances.get(identityObj);
27
32
  }