chrome-devtools-frontend 1.0.1695017 → 1.0.1696961

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 (247) hide show
  1. package/eslint.config.mjs +4 -1
  2. package/front_end/core/common/Base64.ts +14 -4
  3. package/front_end/core/common/Gzip.ts +1 -1
  4. package/front_end/core/common/Object.ts +0 -1
  5. package/front_end/core/platform/Size.ts +43 -0
  6. package/front_end/core/platform/api/HostRuntime.ts +14 -0
  7. package/front_end/core/platform/browser/HostRuntime.ts +66 -0
  8. package/front_end/core/platform/node/HostRuntime.ts +12 -3
  9. package/front_end/core/platform/platform.ts +1 -0
  10. package/front_end/core/sdk/AccessibilityModel.ts +2 -2
  11. package/front_end/core/sdk/CSSMatchedStyles.ts +2 -0
  12. package/front_end/core/sdk/CSSPropertyParserMatchers.ts +29 -0
  13. package/front_end/core/sdk/CSSStyleSheetHeader.ts +2 -2
  14. package/front_end/core/sdk/ConsoleModel.ts +3 -3
  15. package/front_end/core/sdk/DOMModel.ts +10 -6
  16. package/front_end/core/sdk/DebuggerModel.ts +6 -0
  17. package/front_end/core/sdk/NetworkRequest.ts +19 -19
  18. package/front_end/core/sdk/RuntimeModel.ts +5 -0
  19. package/front_end/core/sdk/Script.ts +2 -2
  20. package/front_end/core/sdk/ServerTiming.ts +6 -6
  21. package/front_end/core/sdk/SourceMap.ts +112 -14
  22. package/front_end/core/sdk/SourceMapRangeMappings.ts +43 -0
  23. package/front_end/core/sdk/SourceMapScopeChainEntry.ts +15 -10
  24. package/front_end/core/sdk/SourceMapScopesInfo.ts +92 -10
  25. package/front_end/core/sdk/sdk.ts +2 -0
  26. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshot.ts +1 -1
  27. package/front_end/entrypoints/inspector_main/RenderingOptions.ts +6 -6
  28. package/front_end/entrypoints/main/MainImpl.ts +1 -1
  29. package/front_end/generated/InspectorBackendCommands.ts +6 -3
  30. package/front_end/generated/protocol-mapping.d.ts +7 -0
  31. package/front_end/generated/protocol-proxy-api.d.ts +5 -0
  32. package/front_end/generated/protocol.ts +36 -3
  33. package/front_end/models/ai_assistance/AiAgent2.ts +27 -27
  34. package/front_end/models/ai_assistance/agents/AiAgent.ts +4 -0
  35. package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +2 -2
  36. package/front_end/models/ai_assistance/contexts/AccessibilityContext.ts +1 -0
  37. package/front_end/models/ai_assistance/contexts/DOMNodeContext.ts +5 -4
  38. package/front_end/models/ai_assistance/contexts/FileContext.ts +1 -0
  39. package/front_end/models/ai_assistance/contexts/PerformanceTraceContext.ts +1 -0
  40. package/front_end/models/ai_assistance/contexts/RequestContext.ts +1 -0
  41. package/front_end/models/ai_assistance/contexts/StorageContext.ts +1 -0
  42. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +5 -5
  43. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +6 -6
  44. package/front_end/models/ai_assistance/tools/GetElementAccessibilityDetails.ts +5 -8
  45. package/front_end/models/ai_assistance/tools/GetNetworkRequestDetails.ts +4 -8
  46. package/front_end/models/ai_assistance/tools/GetSourceContent.ts +7 -5
  47. package/front_end/models/ai_assistance/tools/GetStyles.ts +10 -6
  48. package/front_end/models/ai_assistance/tools/ListSources.ts +26 -7
  49. package/front_end/models/ai_assistance/tools/ResolveDevtoolsNodePath.ts +5 -10
  50. package/front_end/models/ai_assistance/tools/Tool.ts +8 -1
  51. package/front_end/models/bindings/FileUtils.ts +18 -40
  52. package/front_end/models/bindings/TempFile.ts +5 -12
  53. package/front_end/models/comment_manager/CommentManager.ts +30 -6
  54. package/front_end/models/crux-manager/CrUXManager.ts +8 -5
  55. package/front_end/models/emulation/DeviceModeModel.ts +55 -105
  56. package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +1 -1
  57. package/front_end/models/issues_manager/CookieIssue.ts +1 -1
  58. package/front_end/models/issues_manager/DeprecationIssue.ts +2 -2
  59. package/front_end/models/javascript_metadata/NativeFunctions.ts +1 -5
  60. package/front_end/models/live-metrics/LiveMetrics.ts +1 -1
  61. package/front_end/models/persistence/IsolatedFileSystem.ts +16 -23
  62. package/front_end/models/trace/insights/DuplicatedJavaScript.ts +1 -1
  63. package/front_end/models/trace/insights/INPBreakdown.ts +1 -1
  64. package/front_end/models/trace/insights/ImageDelivery.ts +3 -3
  65. package/front_end/models/trace/insights/LCPDiscovery.ts +2 -2
  66. package/front_end/models/trace/insights/NetworkDependencyTree.ts +3 -3
  67. package/front_end/models/trace/insights/Viewport.ts +1 -1
  68. package/front_end/models/trace/types/Overlays.ts +2 -2
  69. package/front_end/panels/accessibility/AccessibilityNodeView.ts +2 -2
  70. package/front_end/panels/accessibility/AccessibilitySubPane.ts +0 -1
  71. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +74 -18
  72. package/front_end/panels/ai_assistance/components/AIv2MarkdownRenderer.ts +14 -3
  73. package/front_end/panels/ai_assistance/components/ChatInput.ts +1 -1
  74. package/front_end/panels/ai_assistance/components/ChatMessage.ts +1 -1
  75. package/front_end/panels/animation/AnimationUI.ts +1 -1
  76. package/front_end/panels/application/AppManifestView.ts +9 -11
  77. package/front_end/panels/application/ApplicationPanelSidebar.ts +9 -9
  78. package/front_end/panels/application/BackgroundServiceView.ts +1 -1
  79. package/front_end/panels/application/CookieItemsView.ts +1 -1
  80. package/front_end/panels/application/DOMStorageItemsView.ts +1 -1
  81. package/front_end/panels/application/DeviceBoundSessionsView.ts +2 -2
  82. package/front_end/panels/application/FrameDetailsView.ts +5 -5
  83. package/front_end/panels/application/IndexedDBViews.ts +2 -2
  84. package/front_end/panels/application/KeyValueStorageItemsView.ts +1 -2
  85. package/front_end/panels/application/ReportingApiView.ts +1 -1
  86. package/front_end/panels/application/ServiceWorkerCacheTreeElement.ts +1 -1
  87. package/front_end/panels/application/ServiceWorkersView.ts +1 -1
  88. package/front_end/panels/application/StorageBucketsTreeElement.ts +1 -1
  89. package/front_end/panels/application/WebMCPView.ts +1 -1
  90. package/front_end/panels/application/components/AdsView.ts +136 -7
  91. package/front_end/panels/application/components/BackForwardCacheStrings.ts +116 -117
  92. package/front_end/panels/application/components/BackForwardCacheView.ts +7 -7
  93. package/front_end/panels/application/components/BounceTrackingMitigationsView.ts +2 -2
  94. package/front_end/panels/application/components/PermissionsPolicySection.ts +2 -2
  95. package/front_end/panels/application/components/ProtocolHandlersView.ts +1 -1
  96. package/front_end/panels/application/components/ReportsGrid.ts +1 -1
  97. package/front_end/panels/application/components/StorageMetadataView.ts +1 -1
  98. package/front_end/panels/application/components/TrustTokensView.ts +3 -3
  99. package/front_end/panels/application/components/adScriptsTable.css +22 -0
  100. package/front_end/panels/application/preloading/PreloadingView.ts +20 -22
  101. package/front_end/panels/application/preloading/components/MismatchedPreloadingGrid.ts +9 -9
  102. package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +31 -33
  103. package/front_end/panels/application/preloading/components/PreloadingDisabledInfobar.ts +23 -23
  104. package/front_end/panels/application/preloading/components/PreloadingGrid.ts +4 -4
  105. package/front_end/panels/application/preloading/components/PreloadingString.ts +161 -161
  106. package/front_end/panels/application/preloading/components/RuleSetDetailsView.ts +2 -6
  107. package/front_end/panels/application/preloading/components/RuleSetGrid.ts +8 -8
  108. package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +32 -32
  109. package/front_end/panels/application/resourcesPanel.css +17 -17
  110. package/front_end/panels/browser_debugger/DOMBreakpointsSidebarPane.ts +1 -1
  111. package/front_end/panels/changes/ChangesView.ts +1 -1
  112. package/front_end/panels/common/AiCodeCompletionSummaryToolbar.ts +1 -1
  113. package/front_end/panels/common/CPUThrottlingOption.ts +0 -1
  114. package/front_end/panels/common/GdpSignUpDialog.ts +3 -4
  115. package/front_end/panels/common/GeminiRebrandPromoDialog.ts +1 -1
  116. package/front_end/panels/console/ConsoleInsightTeaser.ts +1 -1
  117. package/front_end/panels/console/ConsolePinPane.ts +0 -1
  118. package/front_end/panels/console/ConsoleView.ts +2 -3
  119. package/front_end/panels/console/ConsoleViewMessage.ts +2 -3
  120. package/front_end/panels/coverage/CoverageListView.ts +6 -6
  121. package/front_end/panels/coverage/CoverageView.ts +7 -7
  122. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +1 -1
  123. package/front_end/panels/elements/CSSRuleValidator.ts +10 -10
  124. package/front_end/panels/elements/ElementsPanel.ts +3 -3
  125. package/front_end/panels/elements/ElementsTreeElement.ts +1 -1
  126. package/front_end/panels/elements/ElementsTreeOutline.ts +1 -1
  127. package/front_end/panels/elements/LayoutPane.ts +1 -1
  128. package/front_end/panels/elements/StylePropertyTreeElement.ts +85 -2
  129. package/front_end/panels/elements/StylesSidebarPane.ts +3 -3
  130. package/front_end/panels/elements/stylePropertiesTreeOutline.css +2 -1
  131. package/front_end/panels/emulation/DeviceModeView.ts +1 -1
  132. package/front_end/panels/event_listeners/EventListenersView.ts +57 -89
  133. package/front_end/panels/explain/components/ConsoleInsight.ts +4 -4
  134. package/front_end/panels/issues/AffectedPartitioningBlobURLView.ts +3 -3
  135. package/front_end/panels/issues/IssuesPane.ts +1 -1
  136. package/front_end/panels/layer_viewer/Layers3DView.ts +4 -4
  137. package/front_end/panels/layers/LayerTreeModel.ts +1 -1
  138. package/front_end/panels/lighthouse/LighthouseController.ts +4 -4
  139. package/front_end/panels/lighthouse/LighthouseStatusView.ts +10 -10
  140. package/front_end/panels/lighthouse/LighthouseTimespanView.ts +2 -2
  141. package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorController.ts +1 -1
  142. package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorPane.ts +1 -1
  143. package/front_end/panels/media/MainView.ts +2 -2
  144. package/front_end/panels/mobile_throttling/CalibrationController.ts +4 -1
  145. package/front_end/panels/mobile_throttling/NetworkPanelIndicator.ts +1 -1
  146. package/front_end/panels/mobile_throttling/ThrottlingManager.ts +10 -0
  147. package/front_end/panels/mobile_throttling/ThrottlingSettingsTab.ts +3 -3
  148. package/front_end/panels/network/NetworkConfigView.ts +26 -16
  149. package/front_end/panels/network/NetworkItemView.ts +1 -1
  150. package/front_end/panels/network/NetworkLogView.ts +4 -5
  151. package/front_end/panels/network/NetworkPanel.ts +1 -1
  152. package/front_end/panels/network/RequestConditionsDrawer.ts +3 -3
  153. package/front_end/panels/network/RequestCookiesView.ts +2 -2
  154. package/front_end/panels/network/RequestPayloadView.ts +0 -2
  155. package/front_end/panels/network/RequestTimingView.ts +1 -1
  156. package/front_end/panels/network/ResourceChunkView.ts +1 -1
  157. package/front_end/panels/network/components/HeaderSectionRow.ts +2 -2
  158. package/front_end/panels/network/components/RequestHeaderSection.ts +1 -1
  159. package/front_end/panels/network/components/RequestTrustTokensView.ts +7 -7
  160. package/front_end/panels/network/components/ResponseHeaderSection.ts +3 -4
  161. package/front_end/panels/network/network-meta.ts +1 -1
  162. package/front_end/panels/profiler/HeapDetachedElementsView.ts +1 -1
  163. package/front_end/panels/profiler/HeapSnapshotGridNodes.ts +10 -10
  164. package/front_end/panels/profiler/HeapSnapshotView.ts +1 -1
  165. package/front_end/panels/profiler/IsolateSelector.ts +4 -4
  166. package/front_end/panels/profiler/ModuleUIStrings.ts +1 -1
  167. package/front_end/panels/profiler/ProfilesPanel.ts +2 -3
  168. package/front_end/panels/recorder/RecorderPanel.ts +1 -1
  169. package/front_end/panels/search/SearchView.ts +6 -6
  170. package/front_end/panels/security/SecurityModel.ts +4 -4
  171. package/front_end/panels/security/SecurityPanel.ts +83 -54
  172. package/front_end/panels/security/SecurityPanelSidebar.ts +41 -5
  173. package/front_end/panels/security/sidebar.css +9 -10
  174. package/front_end/panels/sensors/SensorsView.ts +1 -1
  175. package/front_end/panels/settings/AISettingsTab.ts +9 -9
  176. package/front_end/panels/settings/FrameworkIgnoreListSettingsTab.ts +1 -1
  177. package/front_end/panels/settings/KeybindsSettingsTab.ts +2 -2
  178. package/front_end/panels/settings/SettingsScreen.ts +156 -109
  179. package/front_end/panels/settings/WorkspaceSettingsTab.ts +1 -1
  180. package/front_end/panels/settings/components/SyncSection.ts +3 -3
  181. package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +13 -13
  182. package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +2 -2
  183. package/front_end/panels/snippets/SnippetsQuickOpen.ts +1 -1
  184. package/front_end/panels/sources/CSSPlugin.ts +3 -3
  185. package/front_end/panels/sources/DebuggerPlugin.ts +4 -4
  186. package/front_end/panels/sources/NavigatorView.ts +3 -3
  187. package/front_end/panels/sources/OutlineQuickOpen.ts +1 -1
  188. package/front_end/panels/sources/PersistenceActions.ts +2 -2
  189. package/front_end/panels/sources/SourcesNavigator.ts +5 -5
  190. package/front_end/panels/sources/TabbedEditorContainer.ts +1 -1
  191. package/front_end/panels/sources/WatchExpressionsSidebarPane.ts +0 -1
  192. package/front_end/panels/sources/components/HeadersView.ts +1 -1
  193. package/front_end/panels/timeline/LayoutShiftsTrackAppender.ts +1 -1
  194. package/front_end/panels/timeline/TimelinePaintProfilerView.ts +1 -1
  195. package/front_end/panels/timeline/TimelineUIUtils.ts +0 -1
  196. package/front_end/panels/timeline/components/ExportTraceOptions.ts +2 -2
  197. package/front_end/panels/timeline/components/FieldSettingsDialog.ts +4 -4
  198. package/front_end/panels/timeline/components/IgnoreListSetting.ts +1 -1
  199. package/front_end/panels/timeline/components/LiveMetricsView.ts +7 -7
  200. package/front_end/panels/timeline/components/MetricCard.ts +3 -3
  201. package/front_end/panels/timeline/components/MetricCompareStrings.ts +12 -14
  202. package/front_end/panels/timeline/components/OriginMap.ts +3 -3
  203. package/front_end/panels/timeline/components/SidebarAnnotationsTab.ts +4 -4
  204. package/front_end/panels/timeline/overlays/OverlaysImpl.ts +6 -0
  205. package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +1 -1
  206. package/front_end/panels/timeline/overlays/components/TimespanBreakdownOverlay.ts +3 -1
  207. package/front_end/panels/timeline/timelineMiniMap.css +9 -9
  208. package/front_end/panels/timeline/timelineStatusDialog.css +9 -9
  209. package/front_end/panels/web_audio/WebAudioView.ts +1 -1
  210. package/front_end/panels/webauthn/WebauthnPane.ts +1 -1
  211. package/front_end/third_party/chromium/README.chromium +1 -1
  212. package/front_end/ui/comments/CommentAnchorResolver.ts +114 -3
  213. package/front_end/ui/comments/CommentOverlayManager.ts +95 -16
  214. package/front_end/ui/components/dialogs/TypeToAllowDialog.ts +1 -1
  215. package/front_end/ui/components/markdown_view/codeBlock.css +3 -8
  216. package/front_end/ui/components/markdown_view/markdownView.css +2 -7
  217. package/front_end/ui/components/panel_feedback/PanelFeedback.ts +2 -2
  218. package/front_end/ui/components/panel_feedback/PreviewToggle.ts +1 -1
  219. package/front_end/ui/components/request_link_icon/RequestLinkIcon.ts +1 -1
  220. package/front_end/ui/components/text_editor/AiCodeCompletionTeaser.ts +4 -4
  221. package/front_end/ui/components/text_editor/AiCodeGenerationTeaser.ts +3 -3
  222. package/front_end/{models → ui}/geometry/GeometryImpl.ts +4 -40
  223. package/front_end/ui/legacy/GlassPane.ts +1 -1
  224. package/front_end/ui/legacy/RemoteDebuggingTerminatedScreen.ts +2 -2
  225. package/front_end/ui/legacy/SoftDropDown.ts +1 -1
  226. package/front_end/ui/legacy/SplitWidget.ts +1 -1
  227. package/front_end/ui/legacy/SuggestBox.ts +1 -1
  228. package/front_end/ui/legacy/TabbedPane.ts +1 -1
  229. package/front_end/ui/legacy/TargetCrashedScreen.ts +2 -2
  230. package/front_end/ui/legacy/Treeoutline.ts +5 -1
  231. package/front_end/ui/legacy/UIUtils.ts +1 -1
  232. package/front_end/ui/legacy/Widget.ts +1 -1
  233. package/front_end/ui/legacy/components/data_grid/DataGrid.ts +1 -1
  234. package/front_end/ui/legacy/components/inline_editor/AnimationTimingModel.ts +1 -1
  235. package/front_end/ui/legacy/components/inline_editor/AnimationTimingUI.ts +1 -1
  236. package/front_end/ui/legacy/components/inline_editor/BezierUI.ts +1 -1
  237. package/front_end/ui/legacy/components/inline_editor/CSSAngleUtils.ts +1 -1
  238. package/front_end/ui/legacy/components/inline_editor/CSSShadowEditor.ts +1 -1
  239. package/front_end/ui/legacy/components/inline_editor/PositionAreaEditor.ts +204 -17
  240. package/front_end/ui/legacy/components/inline_editor/positionAreaEditor.css +6 -0
  241. package/front_end/ui/legacy/components/object_ui/ObjectPopoverHelper.ts +1 -1
  242. package/front_end/ui/legacy/components/perf_ui/FilmStripView.ts +1 -1
  243. package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +7 -9
  244. package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +1 -1
  245. package/front_end/ui/visual_logging/KnownContextValues.ts +12 -0
  246. package/package.json +7 -4
  247. /package/front_end/{models → ui}/geometry/geometry.ts +0 -0
@@ -942,23 +942,23 @@ The following images could be optimized:
942
942
  ### https://images.ctfassets.net/u275ja1nivmq/6T6z40ay5GFCUtwV7DONgh/0e23606ed1692d9721ab0f39a8d8a99e/yeti_cover.jpg (eventKey: s-1212, ts: 59728701403)
943
943
  - Potential savings: 1.1 MB
944
944
  - Optimizations:
945
- Using a modern image format (WebP, AVIF) or increasing the image compression could improve this image’s download size. (Est 1.1 MB)
945
+ Using a modern image format (WebP, AVIF) or increasing the image compression could improve this image’s download size (Est 1.1 MB)
946
946
 
947
947
  ### https://raw.githubusercontent.com/GoogleChrome/lighthouse/refs/heads/main/cli/test/fixtures/dobetterweb/lighthouse-rotating.gif (eventKey: s-1216, ts: 59728702014)
948
948
  - Potential savings: 682 kB
949
949
  - Optimizations:
950
- Using video formats instead of GIFs can improve the download size of animated content. (Est 682 kB)
950
+ Using video formats instead of GIFs can improve the download size of animated content (Est 682 kB)
951
951
 
952
952
  ### https://onlinepngtools.com/images/examples-onlinepngtools/elephant-hd-quality.png (eventKey: s-1228, ts: 59728702737)
953
953
  - Potential savings: 176 kB
954
954
  - Optimizations:
955
- Using a modern image format (WebP, AVIF) or increasing the image compression could improve this image’s download size. (Est 134.1 kB)
955
+ Using a modern image format (WebP, AVIF) or increasing the image compression could improve this image’s download size (Est 134.1 kB)
956
956
  This image file is larger than it needs to be (640x436) for its displayed dimensions (200x136). Use responsive images to reduce the image download size. (Est 162.9 kB)
957
957
 
958
958
  ### https://images.ctfassets.net/u275ja1nivmq/6T6z40ay5GFCUtwV7DONgh/0e23606ed1692d9721ab0f39a8d8a99e/yeti_cover.jpg?fm=webp (eventKey: s-1224, ts: 59728702313)
959
959
  - Potential savings: 49.8 kB
960
960
  - Optimizations:
961
- Increasing the image compression factor could improve this image’s download size. (Est 49.8 kB)
961
+ Increasing the image compression factor could improve this image’s download size (Est 49.8 kB)
962
962
 
963
963
  ### https://raw.githubusercontent.com/GoogleChrome/lighthouse/refs/heads/main/cli/test/fixtures/byte-efficiency/lighthouse-2048x1356.webp (eventKey: s-1226, ts: 59728702539)
964
964
  - Potential savings: 41.4 kB
@@ -1258,7 +1258,7 @@ The webpage is not optimized for mobile viewing.
1258
1258
 
1259
1259
  The viewport meta tag is missing.
1260
1260
 
1261
- Tap interactions may be [delayed by up to 300 ms](https://developer.chrome.com/docs/performance/insights/viewport) if the viewport isn’t optimized for mobile.
1261
+ Tap interactions may be [delayed by up to 300 ms](https://developer.chrome.com/docs/performance/insights/viewport) if the viewport isn’t optimized for mobile
1262
1262
 
1263
1263
  ## Estimated savings: none
1264
1264
 
@@ -351,7 +351,7 @@ Available insights:
351
351
  example question: Help me optimize my CLS score
352
352
  example question: How can I prevent layout shifts on this page?
353
353
  - insight name: NetworkDependencyTree
354
- description: [Avoid chaining critical requests](https://developer.chrome.com/docs/performance/insights/network-dependency-tree) by reducing the length of chains, reducing the download size of resources, or deferring the download of unnecessary resources to improve page load.
354
+ description: [Avoid chaining critical requests](https://developer.chrome.com/docs/performance/insights/network-dependency-tree) by reducing the length of chains, reducing the download size of resources, or deferring the download of unnecessary resources to improve page load
355
355
  relevant trace bounds: {min: 157423489126µs, max: 157426527569µs}
356
356
  example question: How do I optimize my network dependency tree?
357
357
  - insight name: ImageDelivery
@@ -498,7 +498,7 @@ Available insights:
498
498
  example question: Which LCP subpart was most problematic?
499
499
  example question: What can I do to reduce the LCP time for this page load?
500
500
  - insight name: LCPDiscovery
501
- description: [Optimize LCP](https://developer.chrome.com/docs/performance/insights/lcp-discovery) by making the LCP image discoverable from the HTML immediately, and avoiding lazy-loading.
501
+ description: [Optimize LCP](https://developer.chrome.com/docs/performance/insights/lcp-discovery) by making the LCP image discoverable from the HTML immediately, and avoiding lazy-loading
502
502
  relevant trace bounds: {min: 59728656735µs, max: 59729209036µs}
503
503
  example question: Suggest fixes to reduce my LCP
504
504
  example question: What can I do to reduce my LCP discovery time?
@@ -516,7 +516,7 @@ Available insights:
516
516
  example question: How do I decrease the initial loading time of my page?
517
517
  example question: Did anything slow down the request for this document?
518
518
  - insight name: Viewport
519
- description: Tap interactions may be [delayed by up to 300 ms](https://developer.chrome.com/docs/performance/insights/viewport) if the viewport isn’t optimized for mobile.
519
+ description: Tap interactions may be [delayed by up to 300 ms](https://developer.chrome.com/docs/performance/insights/viewport) if the viewport isn’t optimized for mobile
520
520
  relevant trace bounds: {min: 59728649746µs, max: 59734400108µs}
521
521
  estimated metric savings: INP 0 ms
522
522
  example question: How do I make sure my page is optimized for mobile viewing?
@@ -582,7 +582,7 @@ Available insights:
582
582
  example question: Which LCP subpart was most problematic?
583
583
  example question: What can I do to reduce the LCP time for this page load?
584
584
  - insight name: LCPDiscovery
585
- description: [Optimize LCP](https://developer.chrome.com/docs/performance/insights/lcp-discovery) by making the LCP image discoverable from the HTML immediately, and avoiding lazy-loading.
585
+ description: [Optimize LCP](https://developer.chrome.com/docs/performance/insights/lcp-discovery) by making the LCP image discoverable from the HTML immediately, and avoiding lazy-loading
586
586
  relevant trace bounds: {min: 59728656735µs, max: 59729209036µs}
587
587
  example question: Suggest fixes to reduce my LCP
588
588
  example question: What can I do to reduce my LCP discovery time?
@@ -600,7 +600,7 @@ Available insights:
600
600
  example question: How do I decrease the initial loading time of my page?
601
601
  example question: Did anything slow down the request for this document?
602
602
  - insight name: Viewport
603
- description: Tap interactions may be [delayed by up to 300 ms](https://developer.chrome.com/docs/performance/insights/viewport) if the viewport isn’t optimized for mobile.
603
+ description: Tap interactions may be [delayed by up to 300 ms](https://developer.chrome.com/docs/performance/insights/viewport) if the viewport isn’t optimized for mobile
604
604
  relevant trace bounds: {min: 59728649746µs, max: 59734400108µs}
605
605
  estimated metric savings: INP 0 ms
606
606
  example question: How do I make sure my page is optimized for mobile viewing?
@@ -635,7 +635,7 @@ Metrics (lab / observed):
635
635
  Metrics (field / real users): n/a – no data for this page in CrUX
636
636
  Available insights:
637
637
  - insight name: INPBreakdown
638
- description: Start investigating [how to improve INP](https://developer.chrome.com/docs/performance/insights/inp-breakdown) by looking at the longest subpart.
638
+ description: Start investigating [how to improve INP](https://developer.chrome.com/docs/performance/insights/inp-breakdown) by looking at the longest subpart
639
639
  relevant trace bounds: {min: 337944870984µs, max: 337945010222µs}
640
640
  example question: Suggest fixes for my longest interaction
641
641
  example question: Why is a large INP score problematic?
@@ -6,7 +6,6 @@ import * as Host from '../../../core/host/host.js';
6
6
  import * as i18n from '../../../core/i18n/i18n.js';
7
7
  import * as SDK from '../../../core/sdk/sdk.js';
8
8
  import type * as Protocol from '../../../generated/protocol.js';
9
- import {DOMNodeContext} from '../contexts/DOMNodeContext.js';
10
9
 
11
10
  import {
12
11
  type BaseToolCapability,
@@ -82,9 +81,6 @@ export class GetElementAccessibilityDetailsTool implements
82
81
  context: BaseToolCapability&TargetCapability&OriginLockCapability,
83
82
  ): Promise<DataHandlerResult<string>> {
84
83
  const establishedOrigin = context.getEstablishedOrigin();
85
- if (!establishedOrigin || establishedOrigin.isOpaque()) {
86
- return {error: 'Error: Origin lock is not established.'};
87
- }
88
84
 
89
85
  const target = context.getTarget();
90
86
  if (!target) {
@@ -100,13 +96,14 @@ export class GetElementAccessibilityDetailsTool implements
100
96
  return {error: 'Error: Could not resolve element by ID.'};
101
97
  }
102
98
 
103
- const nodeContext = new DOMNodeContext(resolved);
104
99
  // Security check: Ensure the element matches the active conversation's origin lock.
105
- if (!isOriginAllowedByLock(establishedOrigin, nodeContext.getOrigin())) {
106
- return {error: 'Error: Node does not belong to the locked origin.'};
100
+ // Because getTarget() returns the primary page target to support resolving elements
101
+ // across frames, origin validation must be enforced directly on the resolved node.
102
+ if (!isOriginAllowedByLock(establishedOrigin, resolved.securityOrigin())) {
103
+ return {error: 'Error: Node does not belong to the current origin.'};
107
104
  }
108
105
 
109
- const axModel = target.model(SDK.AccessibilityModel.AccessibilityModel);
106
+ const axModel = resolved.domModel().target().model(SDK.AccessibilityModel.AccessibilityModel);
110
107
  if (!axModel) {
111
108
  return {error: 'Error: Accessibility model not found.'};
112
109
  }
@@ -79,13 +79,6 @@ export class GetNetworkRequestDetailsTool implements
79
79
  // We only allow inspecting requests matching the conversation's established origin.
80
80
  const establishedOrigin = context.getEstablishedOrigin();
81
81
 
82
- // Opaque origins are never allowed to be used as context.
83
- if (!establishedOrigin || establishedOrigin.isOpaque()) {
84
- return {
85
- error: 'Opaque origin not allowed',
86
- };
87
- }
88
-
89
82
  // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
90
83
  const networkLog = this.#networkLog ?? Logs.NetworkLog.NetworkLog.instance();
91
84
  const request = networkLog.requests().find(req => {
@@ -97,7 +90,10 @@ export class GetNetworkRequestDetailsTool implements
97
90
  return isOriginAllowedByLock(establishedOrigin, req.initiatorSecurityOrigin());
98
91
  });
99
92
 
100
- if (!request) {
93
+ // If establishedOrigin is undefined or opaque, isOriginAllowedByLock() fails closed,
94
+ // so find() will never return a request. We check establishedOrigin here as a defensive
95
+ // guard and to narrow the type for NetworkRequestFormatter below.
96
+ if (!establishedOrigin || !request) {
101
97
  return {
102
98
  error: 'No request found',
103
99
  };
@@ -5,7 +5,6 @@
5
5
  import * as Host from '../../../core/host/host.js';
6
6
  import * as i18n from '../../../core/i18n/i18n.js';
7
7
  import * as TextUtils from '../../../core/text_utils/text_utils.js';
8
- import {FileContext} from '../contexts/FileContext.js';
9
8
  import {FileFormatter} from '../data_formatters/FileFormatter.js';
10
9
 
11
10
  import {ListSourcesTool} from './ListSources.js';
@@ -13,7 +12,6 @@ import {
13
12
  type BaseToolCapability,
14
13
  type DataHandlerResult,
15
14
  type DataTool,
16
- isOriginAllowedByLock,
17
15
  type OriginLockCapability,
18
16
  type ToolArgs,
19
17
  ToolName,
@@ -67,9 +65,13 @@ export class GetSourceContentTool implements
67
65
  context: BaseToolCapability&OriginLockCapability,
68
66
  ): Promise<DataHandlerResult<{content: string}>> {
69
67
  const establishedOrigin = context.getEstablishedOrigin();
70
- const file = ListSourcesTool.getUISourceCodes()
71
- .filter(f => isOriginAllowedByLock(establishedOrigin, FileContext.originForUISourceCode(f)))
72
- .find(f => ListSourcesTool.uiSourceCodeId.get(f) === args.id);
68
+ if (!establishedOrigin) {
69
+ return {
70
+ error: 'Unable to find file.',
71
+ };
72
+ }
73
+
74
+ const file = ListSourcesTool.getSourceById(args.id, establishedOrigin);
73
75
 
74
76
  if (!file) {
75
77
  return {
@@ -6,7 +6,6 @@ import * as Host from '../../../core/host/host.js';
6
6
  import * as SDK from '../../../core/sdk/sdk.js';
7
7
  import type * as Protocol from '../../../generated/protocol.js';
8
8
  import type {ComputedStyleAiWidget, FunctionHandlerOptions} from '../agents/AiAgent.js';
9
- import {DOMNodeContext} from '../contexts/DOMNodeContext.js';
10
9
 
11
10
  import {
12
11
  type BaseToolCapability,
@@ -78,6 +77,12 @@ export class GetStylesTool implements
78
77
  };
79
78
  }
80
79
 
80
+ /**
81
+ * Handles the request to retrieve computed and authored CSS styles for specified elements.
82
+ *
83
+ * Resolves element backend node IDs using the primary page target and verifies that each
84
+ * element's security origin matches the established origin lock before querying CSS models.
85
+ */
81
86
  async handler(
82
87
  params: GetStylesArgs,
83
88
  context: BaseToolCapability&TargetCapability&OriginLockCapability,
@@ -93,9 +98,6 @@ export class GetStylesTool implements
93
98
  }
94
99
 
95
100
  const establishedOrigin = context.getEstablishedOrigin();
96
- if (!establishedOrigin || establishedOrigin.isOpaque()) {
97
- return {error: 'Error: Origin lock is not established.'};
98
- }
99
101
 
100
102
  for (const uid of params.elements) {
101
103
  result[uid] = {computed: {}, authored: {}};
@@ -104,8 +106,10 @@ export class GetStylesTool implements
104
106
  if (!resolved) {
105
107
  return {error: 'Error: Could not find the element with uid=' + uid};
106
108
  }
107
- const newContext = new DOMNodeContext(resolved);
108
- if (!isOriginAllowedByLock(establishedOrigin, newContext.getOrigin())) {
109
+ // Security check: Ensure the resolved element belongs to the locked origin.
110
+ // Because getTarget() returns the primary page target to support resolving elements
111
+ // across frames, origin validation must be enforced directly on the resolved node.
112
+ if (!isOriginAllowedByLock(establishedOrigin, resolved.securityOrigin())) {
109
113
  return {error: 'Error: Node does not belong to the current origin.'};
110
114
  }
111
115
  const styles = await resolved.domModel().cssModel().getComputedStyle(resolved.id);
@@ -4,6 +4,7 @@
4
4
 
5
5
  import * as Host from '../../../core/host/host.js';
6
6
  import * as i18n from '../../../core/i18n/i18n.js';
7
+ import type * as SDK from '../../../core/sdk/sdk.js';
7
8
  import * as Workspace from '../../workspace/workspace.js';
8
9
  import {FileContext} from '../contexts/FileContext.js';
9
10
 
@@ -46,9 +47,15 @@ export class ListSourcesTool implements
46
47
  ListSourcesTool.uiSourceCodeId = new WeakMap();
47
48
  }
48
49
 
49
- // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
50
- static getUISourceCodes(workspace: Workspace.Workspace.WorkspaceImpl = Workspace.Workspace.WorkspaceImpl.instance()):
51
- Workspace.UISourceCode.UISourceCode[] {
50
+ static getUISourceCodes(
51
+ establishedOrigin: SDK.SecurityOrigin.SecurityOrigin,
52
+ // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
53
+ workspace: Workspace.Workspace.WorkspaceImpl = Workspace.Workspace.WorkspaceImpl.instance(),
54
+ ): Workspace.UISourceCode.UISourceCode[] {
55
+ if (establishedOrigin.isOpaque()) {
56
+ return [];
57
+ }
58
+
52
59
  const projects =
53
60
  workspace.projects().filter(project => project.type() === Workspace.Workspace.projectTypes.Network);
54
61
  const uiSourceCodes = new Map<string, Workspace.UISourceCode.UISourceCode>();
@@ -68,7 +75,21 @@ export class ListSourcesTool implements
68
75
  }
69
76
  }
70
77
 
71
- return [...uiSourceCodes.values()];
78
+ return [...uiSourceCodes.values()].filter(
79
+ file => isOriginAllowedByLock(establishedOrigin, FileContext.originForUISourceCode(file)));
80
+ }
81
+
82
+ static getSourceById(
83
+ id: number,
84
+ establishedOrigin: SDK.SecurityOrigin.SecurityOrigin,
85
+ // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
86
+ workspace: Workspace.Workspace.WorkspaceImpl = Workspace.Workspace.WorkspaceImpl.instance(),
87
+ ): Workspace.UISourceCode.UISourceCode|undefined {
88
+ if (establishedOrigin.isOpaque()) {
89
+ return undefined;
90
+ }
91
+ return ListSourcesTool.getUISourceCodes(establishedOrigin, workspace)
92
+ .find(file => ListSourcesTool.uiSourceCodeId.get(file) === id);
72
93
  }
73
94
 
74
95
  readonly parameters: Host.AidaClient.FunctionObjectParam<never> = {
@@ -100,9 +121,7 @@ export class ListSourcesTool implements
100
121
  };
101
122
  }
102
123
 
103
- const files = ListSourcesTool.getUISourceCodes().filter(file => {
104
- return isOriginAllowedByLock(establishedOrigin, FileContext.originForUISourceCode(file));
105
- });
124
+ const files = ListSourcesTool.getUISourceCodes(establishedOrigin);
106
125
 
107
126
  return {
108
127
  result: {
@@ -4,7 +4,6 @@
4
4
 
5
5
  import * as Host from '../../../core/host/host.js';
6
6
  import * as SDK from '../../../core/sdk/sdk.js';
7
- import {DOMNodeContext} from '../contexts/DOMNodeContext.js';
8
7
 
9
8
  import {
10
9
  type BaseToolCapability,
@@ -85,11 +84,6 @@ export class ResolveDevtoolsNodePathTool implements DataTool<ResolveDevtoolsNode
85
84
  params: ResolveDevtoolsNodePathArgs,
86
85
  context: BaseToolCapability&TargetCapability&OriginLockCapability,
87
86
  ): Promise<DataHandlerResult<{backendNodeId: number}>> {
88
- const establishedOrigin = context.getEstablishedOrigin();
89
- if (!establishedOrigin || establishedOrigin.isOpaque()) {
90
- return {error: 'Error: Origin lock is not established.'};
91
- }
92
-
93
87
  const target = context.getTarget();
94
88
  const domModel = target?.model(SDK.DOMModel.DOMModel);
95
89
  if (!domModel) {
@@ -102,7 +96,8 @@ export class ResolveDevtoolsNodePathTool implements DataTool<ResolveDevtoolsNode
102
96
  // and ensures the node is loaded into the frontend DOM model, returning its ID.
103
97
  nodeId = await domModel.pushNodeByPathToFrontend(params.path);
104
98
  } catch {
105
- // pushNodeByPathToFrontend can fail or return undefined
99
+ // pushNodeByPathToFrontend throws when the path is invalid or the node cannot be found.
100
+ // Swallow the error here so execution falls through to the structured error response below.
106
101
  }
107
102
  if (!nodeId) {
108
103
  return {error: 'Error: Could not find node by path.'};
@@ -113,11 +108,11 @@ export class ResolveDevtoolsNodePathTool implements DataTool<ResolveDevtoolsNode
113
108
  return {error: 'Error: Could not retrieve resolved node.'};
114
109
  }
115
110
 
116
- const nodeContext = new DOMNodeContext(node);
111
+ const establishedOrigin = context.getEstablishedOrigin();
117
112
  // Security check: Ensure the resolved node belongs to the same origin
118
113
  // that this AI assistance session is locked to, preventing cross-origin access.
119
- if (!isOriginAllowedByLock(establishedOrigin, nodeContext.getOrigin())) {
120
- return {error: 'Error: Node does not belong to the locked origin.'};
114
+ if (!isOriginAllowedByLock(establishedOrigin, node.securityOrigin())) {
115
+ return {error: 'Error: Node does not belong to the current origin.'};
121
116
  }
122
117
 
123
118
  return {
@@ -106,7 +106,14 @@ export interface StyleMutationCapability {
106
106
  */
107
107
  export interface TargetCapability {
108
108
  /**
109
- * Returns the current SDK Target for the inspected page.
109
+ * Returns the primary SDK Target for the inspected page.
110
+ *
111
+ * WARNING: This method does not perform a security origin check. When a conversation
112
+ * is locked to an iframe or subframe origin, this still returns the primary page target
113
+ * so tools can resolve DOM nodes and frame hierarchies across frames.
114
+ *
115
+ * Tools that consume this target must independently validate the security origin of
116
+ * any resolved entities (e.g. via `node.securityOrigin()`) against `getEstablishedOrigin()`.
110
117
  */
111
118
  getTarget(): SDK.Target.Target|null;
112
119
  }
@@ -16,7 +16,7 @@ export interface ChunkedReader {
16
16
 
17
17
  cancel(): void;
18
18
 
19
- error(): DOMError|null;
19
+ error(): DOMException|Error|null;
20
20
  }
21
21
 
22
22
  export class ChunkedFileReader implements ChunkedReader {
@@ -26,12 +26,11 @@ export class ChunkedFileReader implements ChunkedReader {
26
26
  #streamReader: ReadableStreamDefaultReader<Uint8Array<ArrayBuffer>>|null;
27
27
  readonly #chunkSize: number;
28
28
  readonly #chunkTransferredCallback: ((arg0: ChunkedReader) => void)|undefined;
29
- readonly #decoder: TextDecoder;
29
+ readonly #decoder = new TextDecoder();
30
30
  #isCanceled: boolean;
31
31
  #error: DOMException|null;
32
32
  #transferFinished!: (arg0: boolean) => void;
33
33
  #output?: Common.StringOutputStream.OutputStream;
34
- #reader?: FileReader|null;
35
34
 
36
35
  constructor(file: File, chunkSize?: number, chunkTransferredCallback?: ((arg0: ChunkedReader) => void)) {
37
36
  this.#file = file;
@@ -39,7 +38,6 @@ export class ChunkedFileReader implements ChunkedReader {
39
38
  this.#loadedSize = 0;
40
39
  this.#chunkSize = (chunkSize) ? chunkSize : Number.MAX_VALUE;
41
40
  this.#chunkTransferredCallback = chunkTransferredCallback;
42
- this.#decoder = new TextDecoder();
43
41
  this.#isCanceled = false;
44
42
  this.#error = null;
45
43
  this.#streamReader = null;
@@ -54,10 +52,6 @@ export class ChunkedFileReader implements ChunkedReader {
54
52
  const fileStream = this.#file.stream();
55
53
  const stream = Common.Gzip.decompressStream(fileStream);
56
54
  this.#streamReader = stream.getReader();
57
- } else {
58
- this.#reader = new FileReader();
59
- this.#reader.onload = this.onChunkLoaded.bind(this);
60
- this.#reader.onerror = this.onError.bind(this);
61
55
  }
62
56
 
63
57
  this.#output = output;
@@ -91,26 +85,6 @@ export class ChunkedFileReader implements ChunkedReader {
91
85
  return this.#error;
92
86
  }
93
87
 
94
- private onChunkLoaded(event: Event): void {
95
- if (this.#isCanceled) {
96
- return;
97
- }
98
-
99
- const eventTarget = (event.target as FileReader);
100
- if (eventTarget.readyState !== FileReader.DONE) {
101
- return;
102
- }
103
-
104
- if (!this.#reader) {
105
- return;
106
- }
107
-
108
- const buffer = (this.#reader.result as ArrayBuffer);
109
- this.#loadedSize += buffer.byteLength;
110
- const endOfFile = this.#loadedSize === this.#fileSize;
111
- void this.decodeChunkBuffer(buffer, endOfFile);
112
- }
113
-
114
88
  private async decodeChunkBuffer(buffer: ArrayBuffer, endOfFile: boolean): Promise<void> {
115
89
  if (!this.#output) {
116
90
  return;
@@ -136,7 +110,6 @@ export class ChunkedFileReader implements ChunkedReader {
136
110
  return;
137
111
  }
138
112
  this.#file = null;
139
- this.#reader = null;
140
113
  await this.#output.close();
141
114
  this.#transferFinished(!this.#error);
142
115
  }
@@ -153,19 +126,24 @@ export class ChunkedFileReader implements ChunkedReader {
153
126
  return await this.finishRead();
154
127
  }
155
128
  void this.decodeChunkBuffer(value.buffer, false);
129
+ return;
156
130
  }
157
- if (this.#reader) {
158
- const chunkStart = this.#loadedSize;
159
- const chunkEnd = Math.min(this.#fileSize, chunkStart + this.#chunkSize);
160
- const nextPart = this.#file.slice(chunkStart, chunkEnd);
161
- this.#reader.readAsArrayBuffer(nextPart);
162
- }
163
- }
164
131
 
165
- private onError(event: Event): void {
166
- const eventTarget = (event.target as FileReader);
167
- this.#error = eventTarget.error;
168
- this.#transferFinished(false);
132
+ const chunkStart = this.#loadedSize;
133
+ const chunkEnd = Math.min(this.#fileSize, chunkStart + this.#chunkSize);
134
+ const nextPart = this.#file.slice(chunkStart, chunkEnd);
135
+ try {
136
+ const buffer = await nextPart.arrayBuffer();
137
+ if (this.#isCanceled) {
138
+ return;
139
+ }
140
+ this.#loadedSize += buffer.byteLength;
141
+ const endOfFile = this.#loadedSize === this.#fileSize;
142
+ void this.decodeChunkBuffer(buffer, endOfFile);
143
+ } catch (error) {
144
+ this.#error = error as DOMException;
145
+ this.#transferFinished(false);
146
+ }
169
147
  }
170
148
  }
171
149
 
@@ -38,23 +38,16 @@ export class TempFile {
38
38
  this.#lastBlob.slice((startOffset as number), (endOffset as number)) :
39
39
  this.#lastBlob;
40
40
 
41
- const reader = new FileReader();
42
41
  try {
43
- await new Promise((resolve, reject) => {
44
- reader.onloadend = resolve;
45
- reader.onerror = reject;
46
- reader.readAsText(blob);
47
- });
42
+ return await blob.text();
48
43
  } catch (error) {
49
- this.#console.error('Failed to read from temp file: ' + error.message);
44
+ this.#console.error('Failed to read from temp file: ' + (error as Error).message);
45
+ return null;
50
46
  }
51
-
52
- return reader.result as string | null;
53
47
  }
54
48
 
55
- async copyToOutputStream(
56
- outputStream: Common.StringOutputStream.OutputStream,
57
- progress?: ((arg0: ChunkedReader) => void)): Promise<DOMError|null> {
49
+ async copyToOutputStream(outputStream: Common.StringOutputStream.OutputStream,
50
+ progress?: ((arg0: ChunkedReader) => void)): Promise<DOMException|Error|null> {
58
51
  if (!this.#lastBlob) {
59
52
  void outputStream.close();
60
53
  return null;
@@ -18,6 +18,21 @@ export interface DOMNodeAnchorSignature {
18
18
  targetId: string;
19
19
  }
20
20
 
21
+ export interface TimelineAnchorSignature {
22
+ /** Identifier of the trace to scope comments to a specific recording */
23
+ traceId: string;
24
+ /** Serializable key from Trace.EventsSerializer (e.g. 'r-123', 'p-1-2-3-4', 's-5') */
25
+ traceEventKey: string;
26
+ /** Primary event title or category name */
27
+ entryName: string;
28
+ /** Event start timestamp in microseconds */
29
+ startTimeMicro: number;
30
+ /** Chart location */
31
+ chartLocation: 'main'|'network';
32
+ /** Event duration in microseconds (omitted for instant markers) */
33
+ durationMicro?: number;
34
+ }
35
+
21
36
  export interface CommentAnchorSignature {
22
37
  /** Visual logging tree path, e.g. "Panel: elements > Pane: styles > TreeOutline > TreeItem: color" */
23
38
  vePath: string;
@@ -33,6 +48,8 @@ export interface CommentAnchorSignature {
33
48
  node?: DOMNodeAnchorSignature;
34
49
  /** Optional editor anchor coordinates for CodeMirror text editors */
35
50
  editor?: EditorAnchorSignature;
51
+ /** Optional timeline flamechart anchor coordinates for Performance panel trace entries */
52
+ timeline?: TimelineAnchorSignature;
36
53
  }
37
54
 
38
55
  export interface Comment {
@@ -41,13 +58,19 @@ export interface Comment {
41
58
  timestamp: number;
42
59
  }
43
60
 
61
+ export interface ChangeRecord {
62
+ id: string;
63
+ description: string;
64
+ timestamp: number;
65
+ }
66
+
44
67
  export interface CommentThread {
45
68
  id: string;
46
69
  anchor: CommentAnchorSignature;
47
70
  comments: Comment[];
48
71
  status: 'ACTIVE'|'RESOLVED';
49
72
  transmitted?: boolean;
50
- changes?: Array<Record<string, unknown>>;
73
+ changes?: ChangeRecord[];
51
74
  index: number;
52
75
  }
53
76
 
@@ -83,21 +106,22 @@ export class CommentManager extends Common.ObjectWrapper.ObjectWrapper<EventType
83
106
 
84
107
  createCommentThread(
85
108
  anchor: CommentAnchorSignature,
86
- text: string,
109
+ text?: string,
87
110
  author: 'DEVELOPER'|'AGENT' = 'DEVELOPER',
88
- changes?: Array<Record<string, unknown>>,
111
+ changes?: ChangeRecord[],
89
112
  ): CommentThread {
90
113
  const index = this.#nextId++;
91
114
  const id = `comment-${index}`;
92
- const comment: Comment = {
115
+ const comments: Comment[] = text ? [{
93
116
  author,
94
117
  text,
95
118
  timestamp: Date.now(),
96
- };
119
+ }] :
120
+ [];
97
121
  const thread: CommentThread = {
98
122
  id,
99
123
  anchor,
100
- comments: [comment],
124
+ comments,
101
125
  status: 'ACTIVE',
102
126
  transmitted: false,
103
127
  changes,
@@ -12,7 +12,7 @@ const UIStrings = {
12
12
  /**
13
13
  * @description Warning message indicating that the user will see real user data for a URL which is different from the URL they are currently looking at.
14
14
  */
15
- fieldOverrideWarning: 'Field metrics are for a different URL than the current page.',
15
+ fieldOverrideWarning: 'Field metrics are for a different URL than the current page',
16
16
  } as const;
17
17
 
18
18
  const str_ = i18n.i18n.registerUIStrings('models/crux-manager/CrUXManager.ts', UIStrings);
@@ -366,18 +366,21 @@ export class CrUXManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
366
366
  if (response.status === 404) {
367
367
  // This is how CrUX tells us that there is not data available for the provided url/origin
368
368
  // Since it's a valid response, just return null instead of throwing an error.
369
- if (responseData?.error?.status === 'NOT_FOUND') {
370
- return null;
369
+ if (typeof responseData === 'object' && responseData && 'error' in responseData) {
370
+ const error = (responseData as {error?: {status?: string}}).error;
371
+ if (error?.status === 'NOT_FOUND') {
372
+ return null;
373
+ }
371
374
  }
372
375
 
373
376
  throw new Error(`Failed to fetch data from CrUX server (Status code: ${response.status})`);
374
377
  }
375
378
 
376
- if (!('record' in responseData)) {
379
+ if (typeof responseData !== 'object' || !responseData || !('record' in responseData)) {
377
380
  throw new Error(`Failed to find data in CrUX response: ${JSON.stringify(responseData)}`);
378
381
  }
379
382
 
380
- return responseData;
383
+ return responseData as CrUXResponse;
381
384
  }
382
385
 
383
386
  #getAutoDeviceScope(): DeviceScope {