chrome-devtools-frontend 1.0.1662965 → 1.0.1664496

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 (273) hide show
  1. package/.agents/skills/{creating-a-model → devtools-model-management}/SKILL.md +0 -1
  2. package/.agents/skills/devtools-ux-writing-refactor/SKILL.md +2 -1
  3. package/.agents/skills/fixing-skipped-tests/SKILL.md +3 -3
  4. package/.agents/skills/merging-devtools-module/SKILL.md +1 -1
  5. package/.agents/skills/migrate-chromium-test/SKILL.md +3 -2
  6. package/.agents/skills/repro-flaky-tests/SKILL.md +71 -31
  7. package/.agents/skills/ui-eng-vision-widget-promoter/SKILL.md +1 -0
  8. package/docs/ui_engineering.md +2 -0
  9. package/eslint.config.mjs +1 -0
  10. package/front_end/core/common/Settings.ts +75 -0
  11. package/front_end/core/protocol_client/PuppeteerDevToolsConnection.ts +112 -0
  12. package/front_end/core/sdk/CPUProfilerModel.ts +21 -13
  13. package/front_end/core/sdk/CSSContainerQuery.ts +1 -1
  14. package/front_end/core/sdk/CSSLayer.ts +1 -1
  15. package/front_end/core/sdk/CSSMedia.ts +1 -1
  16. package/front_end/core/sdk/CSSModel.ts +1 -1
  17. package/front_end/core/sdk/CSSNavigation.ts +1 -1
  18. package/front_end/core/sdk/CSSProperty.ts +1 -1
  19. package/front_end/core/sdk/CSSQuery.ts +1 -1
  20. package/front_end/core/sdk/CSSRule.ts +1 -1
  21. package/front_end/core/sdk/CSSScope.ts +1 -1
  22. package/front_end/core/sdk/CSSStartingStyle.ts +1 -1
  23. package/front_end/core/sdk/CSSStyleDeclaration.ts +1 -1
  24. package/front_end/core/sdk/CSSStyleSheetHeader.ts +1 -1
  25. package/front_end/core/sdk/CSSSupports.ts +1 -1
  26. package/front_end/core/sdk/CompilerSourceMappingContentProvider.ts +1 -1
  27. package/front_end/core/sdk/NetworkManager.ts +1 -1
  28. package/front_end/core/sdk/NetworkRequest.ts +7 -7
  29. package/front_end/core/sdk/Resource.ts +1 -1
  30. package/front_end/core/sdk/ScopeTreeCache.ts +1 -1
  31. package/front_end/core/sdk/Script.ts +1 -1
  32. package/front_end/core/sdk/ServerSentEvents.ts +1 -1
  33. package/front_end/core/sdk/SourceMap.ts +1 -1
  34. package/front_end/core/sdk/SourceMapScopesInfo.ts +1 -1
  35. package/front_end/core/sdk/sdk-meta.ts +3 -3
  36. package/front_end/{models → core}/text_utils/ContentProvider.ts +4 -6
  37. package/front_end/{models → core}/text_utils/StaticContentProvider.ts +4 -6
  38. package/front_end/{models → core}/text_utils/StreamingContentData.ts +1 -2
  39. package/front_end/{models → core}/text_utils/TextRange.ts +6 -3
  40. package/front_end/{models → core}/text_utils/TextUtils.ts +7 -7
  41. package/front_end/{models → core}/text_utils/WasmDisassembly.ts +2 -2
  42. package/front_end/core/text_utils/text_utils.ts +27 -0
  43. package/front_end/entrypoints/formatter_worker/AcornTokenizer.ts +1 -1
  44. package/front_end/entrypoints/heap_snapshot_worker/HeapSnapshotLoader.ts +1 -1
  45. package/front_end/entrypoints/main/MainImpl.ts +14 -1
  46. package/front_end/foundation/Universe.ts +1 -1
  47. package/front_end/models/ai_assistance/AgentProject.ts +1 -1
  48. package/front_end/models/ai_assistance/agents/AccessibilityAgent.ts +3 -6
  49. package/front_end/models/ai_assistance/agents/AiAgent.ts +1 -1
  50. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +19 -11
  51. package/front_end/models/ai_assistance/agents/PerformanceAgent.snapshot.txt +2 -2
  52. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +23 -10
  53. package/front_end/models/ai_assistance/agents/StorageAgent.ts +19 -18
  54. package/front_end/models/ai_assistance/agents/StylingAgent.ts +2 -3
  55. package/front_end/models/ai_assistance/contexts/FileContext.ts +7 -3
  56. package/front_end/models/ai_assistance/contexts/PerformanceTraceContext.ts +39 -11
  57. package/front_end/models/ai_assistance/data_formatters/FileFormatter.ts +6 -3
  58. package/front_end/models/ai_assistance/data_formatters/NetworkRequestFormatter.ts +1 -1
  59. package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +4 -4
  60. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +8 -8
  61. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.ts +76 -3
  62. package/front_end/models/ai_assistance/tools/ListNetworkRequests.ts +11 -1
  63. package/front_end/models/badges/AiExplorerBadge.ts +8 -3
  64. package/front_end/models/badges/Badge.ts +1 -0
  65. package/front_end/models/badges/UserBadges.ts +11 -5
  66. package/front_end/models/bindings/CompilerScriptMapping.ts +1 -1
  67. package/front_end/models/bindings/ContentProviderBasedProject.ts +1 -1
  68. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +2 -2
  69. package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +1 -1
  70. package/front_end/models/bindings/DefaultScriptMapping.ts +1 -1
  71. package/front_end/models/bindings/FileUtils.ts +1 -1
  72. package/front_end/models/bindings/PresentationConsoleMessageHelper.ts +7 -10
  73. package/front_end/models/bindings/ResourceMapping.ts +1 -1
  74. package/front_end/models/bindings/ResourceScriptMapping.ts +1 -1
  75. package/front_end/models/bindings/SASSSourceMapping.ts +1 -1
  76. package/front_end/models/bindings/StylesSourceMapping.ts +1 -1
  77. package/front_end/models/breakpoints/BreakpointManager.ts +1 -1
  78. package/front_end/models/crux-manager/CrUXManager.ts +1 -1
  79. package/front_end/models/emulation/EmulatedDevices.ts +3 -2
  80. package/front_end/models/har/Importer.ts +1 -1
  81. package/front_end/models/har/Writer.ts +1 -1
  82. package/front_end/models/issues_manager/IssueAggregator.ts +9 -0
  83. package/front_end/models/issues_manager/IssuesManager.ts +5 -0
  84. package/front_end/models/issues_manager/LazyLoadImageIssue.ts +76 -0
  85. package/front_end/models/issues_manager/descriptions/lazyLoadImageZeroSize.md +7 -0
  86. package/front_end/models/issues_manager/issues_manager.ts +2 -0
  87. package/front_end/models/javascript_metadata/NativeFunctions.js +9 -10
  88. package/front_end/models/live-metrics/LiveMetrics.ts +2 -3
  89. package/front_end/models/logs/NetworkLog.ts +4 -3
  90. package/front_end/models/logs/logs-meta.ts +3 -3
  91. package/front_end/models/network_time_calculator/NetworkTimeCalculator.ts +4 -4
  92. package/front_end/models/persistence/Automapping.ts +1 -1
  93. package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +2 -2
  94. package/front_end/models/persistence/FileSystemWorkspaceBinding.ts +1 -1
  95. package/front_end/models/persistence/IsolatedFileSystem.ts +2 -2
  96. package/front_end/models/persistence/NetworkPersistenceManager.ts +1 -1
  97. package/front_end/models/persistence/PersistenceImpl.ts +1 -1
  98. package/front_end/models/persistence/PlatformFileSystem.ts +1 -1
  99. package/front_end/models/source_map_scopes/FunctionCodeResolver.ts +1 -1
  100. package/front_end/models/source_map_scopes/NamesResolver.ts +1 -1
  101. package/front_end/models/text_utils/text_utils.ts +2 -24
  102. package/front_end/models/trace/insights/ImageDelivery.ts +2 -2
  103. package/front_end/models/trace/insights/LegacyJavaScript.ts +1 -1
  104. package/front_end/models/trace/insights/RenderBlocking.ts +1 -1
  105. package/front_end/models/trace/insights/ThirdParties.ts +1 -1
  106. package/front_end/models/workspace/FileManager.ts +1 -1
  107. package/front_end/models/workspace/UISourceCode.ts +1 -1
  108. package/front_end/models/workspace/WorkspaceImpl.ts +1 -1
  109. package/front_end/models/workspace_diff/WorkspaceDiff.ts +1 -1
  110. package/front_end/panels/accessibility/AccessibilityNodeView.ts +1 -1
  111. package/front_end/panels/accessibility/AccessibilityStrings.ts +2 -2
  112. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +1 -1
  113. package/front_end/panels/ai_assistance/ExportConversation.ts +1 -1
  114. package/front_end/panels/ai_assistance/ai_assistance-meta.ts +1 -1
  115. package/front_end/panels/ai_assistance/components/ChatMessage.ts +1 -1
  116. package/front_end/panels/application/AppManifestView.ts +4 -4
  117. package/front_end/panels/application/ApplicationPanelSidebar.ts +1 -2
  118. package/front_end/panels/application/CrashReportContextView.ts +1 -1
  119. package/front_end/panels/application/DOMStorageItemsView.ts +1 -1
  120. package/front_end/panels/application/DeviceBoundSessionsView.ts +4 -4
  121. package/front_end/panels/application/ExtensionStorageItemsView.ts +1 -1
  122. package/front_end/panels/application/FrameDetailsView.ts +1 -1
  123. package/front_end/panels/application/ServiceWorkerCacheTreeElement.ts +12 -2
  124. package/front_end/panels/application/ServiceWorkerCacheViews.ts +1 -1
  125. package/front_end/panels/application/application.ts +2 -0
  126. package/front_end/panels/application/components/BackForwardCacheView.ts +21 -5
  127. package/front_end/panels/application/components/CrashReportContextGrid.ts +1 -1
  128. package/front_end/panels/application/components/TrustTokensView.ts +2 -2
  129. package/front_end/panels/application/preloading/PreloadingView.ts +1 -1
  130. package/front_end/panels/application/preloading/components/PreloadingDisabledInfobar.ts +2 -2
  131. package/front_end/panels/application/preloading/components/PreloadingString.ts +2 -2
  132. package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +4 -4
  133. package/front_end/panels/autofill/AutofillView.ts +1 -1
  134. package/front_end/panels/common/AiCodeCompletionTeaser.ts +1 -1
  135. package/front_end/panels/common/ExtensionServer.ts +1 -1
  136. package/front_end/panels/console/ConsoleFilter.ts +1 -1
  137. package/front_end/panels/console/ConsoleSidebar.ts +1 -1
  138. package/front_end/panels/console/ConsoleView.ts +1 -1
  139. package/front_end/panels/console/ConsoleViewMessage.ts +1 -1
  140. package/front_end/panels/console/PromptBuilder.ts +1 -1
  141. package/front_end/panels/coverage/CoverageDecorationManager.ts +9 -1
  142. package/front_end/panels/coverage/CoverageModel.ts +1 -1
  143. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +1 -1
  144. package/front_end/panels/developer_resources/DeveloperResourcesListView.ts +1 -1
  145. package/front_end/panels/developer_resources/DeveloperResourcesView.ts +1 -1
  146. package/front_end/panels/elements/AccessibilityTreeView.ts +38 -3
  147. package/front_end/panels/elements/AdoptedStyleSheetTreeElement.ts +1 -1
  148. package/front_end/panels/elements/ElementIssueUtils.ts +2 -2
  149. package/front_end/panels/elements/ElementsTreeElement.ts +10 -3
  150. package/front_end/panels/elements/StandaloneStylesContainer.ts +1 -1
  151. package/front_end/panels/elements/StylePropertiesSection.ts +1 -1
  152. package/front_end/panels/elements/StylePropertyTreeElement.ts +1 -1
  153. package/front_end/panels/elements/StylesAiCodeCompletionProvider.ts +1 -1
  154. package/front_end/panels/elements/StylesContainer.ts +1 -1
  155. package/front_end/panels/elements/StylesSidebarPane.ts +1 -1
  156. package/front_end/panels/elements/components/CSSPropertyDocsView.ts +1 -1
  157. package/front_end/panels/explain/components/ConsoleInsight.ts +2 -2
  158. package/front_end/panels/issues/AffectedLazyLoadImagesView.ts +76 -0
  159. package/front_end/panels/issues/AffectedResourcesView.ts +1 -1
  160. package/front_end/panels/issues/CorsIssueDetailsView.ts +1 -1
  161. package/front_end/panels/issues/IssueView.ts +2 -0
  162. package/front_end/panels/issues/issues.ts +2 -0
  163. package/front_end/panels/layer_viewer/Layers3DView.ts +1 -1
  164. package/front_end/panels/lighthouse/LighthouseController.ts +5 -0
  165. package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +1 -1
  166. package/front_end/panels/network/BinaryResourceView.ts +1 -1
  167. package/front_end/panels/network/NetworkDataGridNode.ts +29 -7
  168. package/front_end/panels/network/NetworkLogView.ts +1 -1
  169. package/front_end/panels/network/NetworkLogViewColumns.ts +6 -6
  170. package/front_end/panels/network/NetworkPanel.ts +4 -4
  171. package/front_end/panels/network/NetworkSearchScope.ts +1 -1
  172. package/front_end/panels/network/RequestConditionsDrawer.ts +1 -1
  173. package/front_end/panels/network/RequestHTMLView.ts +1 -1
  174. package/front_end/panels/network/RequestPayloadView.ts +1 -1
  175. package/front_end/panels/network/RequestPreviewView.ts +1 -1
  176. package/front_end/panels/network/RequestResponseView.ts +1 -1
  177. package/front_end/panels/network/ResourceChunkView.ts +1 -1
  178. package/front_end/panels/network/ResourceDirectSocketChunkView.ts +1 -1
  179. package/front_end/panels/network/ResourceWebSocketFrameView.ts +1 -1
  180. package/front_end/panels/network/components/ResponseHeaderSection.ts +1 -1
  181. package/front_end/panels/network/forward/UIRequestLocation.ts +1 -1
  182. package/front_end/panels/network/network-meta.ts +3 -3
  183. package/front_end/panels/profiler/HeapProfileView.ts +6 -6
  184. package/front_end/panels/profiler/HeapSnapshotView.ts +1 -1
  185. package/front_end/panels/profiler/ProfileDataGrid.ts +12 -8
  186. package/front_end/panels/protocol_monitor/ProtocolMonitor.ts +1 -1
  187. package/front_end/panels/recorder/RecorderPanel.ts +493 -381
  188. package/front_end/panels/recorder/RecordingListView.ts +8 -37
  189. package/front_end/panels/recorder/RecordingView.ts +54 -27
  190. package/front_end/panels/recorder/SelectorPicker.ts +0 -13
  191. package/front_end/panels/recorder/StepEditor.ts +6 -14
  192. package/front_end/panels/recorder/StepView.ts +36 -105
  193. package/front_end/panels/search/SearchResultsPane.ts +1 -1
  194. package/front_end/panels/security/SecurityPanel.ts +3 -3
  195. package/front_end/panels/settings/AISettingsTab.ts +4 -4
  196. package/front_end/panels/settings/components/SyncSection.ts +4 -4
  197. package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +3 -3
  198. package/front_end/panels/snippets/ScriptSnippetFileSystem.ts +1 -1
  199. package/front_end/panels/sources/BreakpointsView.ts +1 -1
  200. package/front_end/panels/sources/CoveragePlugin.ts +1 -1
  201. package/front_end/panels/sources/DebuggerPlugin.ts +4 -4
  202. package/front_end/panels/sources/FilteredUISourceCodeListProvider.ts +27 -3
  203. package/front_end/panels/sources/NavigatorView.ts +1 -1
  204. package/front_end/panels/sources/PersistenceActions.ts +1 -1
  205. package/front_end/panels/sources/SourcesNavigator.ts +1 -1
  206. package/front_end/panels/sources/SourcesSearchScope.ts +1 -1
  207. package/front_end/panels/sources/TabbedEditorContainer.ts +3 -3
  208. package/front_end/panels/sources/UISourceCodeFrame.ts +1 -1
  209. package/front_end/panels/sources/components/HeadersView.ts +1 -1
  210. package/front_end/panels/sources/filteredUISourceCodeListProvider.css +12 -1
  211. package/front_end/panels/sources/sources-meta.ts +1 -1
  212. package/front_end/panels/timeline/StatusDialog.ts +1 -1
  213. package/front_end/panels/timeline/TimelineController.ts +24 -3
  214. package/front_end/panels/timeline/TimelinePanel.ts +116 -25
  215. package/front_end/panels/timeline/TimelineSelectorStatsView.ts +2 -2
  216. package/front_end/panels/timeline/TimelineUIUtils.ts +1 -1
  217. package/front_end/panels/timeline/components/CWVMetrics.ts +1 -1
  218. package/front_end/panels/timeline/components/IgnoreListSetting.ts +1 -1
  219. package/front_end/panels/timeline/overlays/components/EntryLabelOverlay.ts +2 -2
  220. package/front_end/panels/timeline/timeline-meta.ts +13 -0
  221. package/front_end/services/tracing/TracingManager.ts +27 -2
  222. package/front_end/third_party/chromium/README.chromium +1 -1
  223. package/front_end/third_party/lighthouse/README.chromium +2 -2
  224. package/front_end/third_party/lighthouse/lighthouse-dt-bundle.js +1418 -1413
  225. package/front_end/third_party/lighthouse/locales/en-US.json +12 -6
  226. package/front_end/third_party/lighthouse/locales/en-XL.json +12 -6
  227. package/front_end/third_party/lighthouse/report-assets/report-generator.mjs +1 -1
  228. package/front_end/third_party/puppeteer/puppeteer.ts +20 -1
  229. package/front_end/ui/components/highlighting/HighlightElement.ts +4 -1
  230. package/front_end/ui/components/highlighting/HighlightManager.ts +1 -1
  231. package/front_end/ui/components/highlighting/MarkupHighlight.ts +1 -1
  232. package/front_end/ui/components/markdown_view/MarkdownView.ts +46 -2
  233. package/front_end/ui/components/markdown_view/markdownView.css +23 -0
  234. package/front_end/ui/components/text_editor/config.ts +1 -1
  235. package/front_end/ui/components/tree_outline/TreeOutline.ts +7 -1
  236. package/front_end/ui/legacy/Infobar.ts +1 -1
  237. package/front_end/ui/legacy/InspectorView.ts +12 -7
  238. package/front_end/ui/legacy/SuggestBox.ts +1 -1
  239. package/front_end/ui/legacy/TextPrompt.ts +1 -1
  240. package/front_end/ui/legacy/Toolbar.ts +5 -2
  241. package/front_end/ui/legacy/Treeoutline.ts +26 -7
  242. package/front_end/ui/legacy/components/color_picker/Spectrum.ts +1 -1
  243. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +1 -1
  244. package/front_end/ui/legacy/components/data_grid/ViewportDataGrid.ts +1 -1
  245. package/front_end/ui/legacy/components/data_grid/dataGrid.css +1 -1
  246. package/front_end/ui/legacy/components/inline_editor/AnimationTimingUI.ts +27 -13
  247. package/front_end/ui/legacy/components/inline_editor/BezierEditor.ts +5 -2
  248. package/front_end/ui/legacy/components/inline_editor/CSSLinearEasingModel.ts +23 -0
  249. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +161 -54
  250. package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +1 -1
  251. package/front_end/ui/legacy/components/source_frame/BinaryResourceViewFactory.ts +1 -1
  252. package/front_end/ui/legacy/components/source_frame/FontView.ts +1 -1
  253. package/front_end/ui/legacy/components/source_frame/ImageView.ts +1 -1
  254. package/front_end/ui/legacy/components/source_frame/JSONView.ts +105 -115
  255. package/front_end/ui/legacy/components/source_frame/PreviewFactory.ts +1 -1
  256. package/front_end/ui/legacy/components/source_frame/ResourceSourceFrame.ts +1 -1
  257. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +3 -3
  258. package/front_end/ui/legacy/components/source_frame/StreamingContentHexView.ts +1 -1
  259. package/front_end/ui/legacy/components/source_frame/XMLView.ts +5 -1
  260. package/front_end/ui/legacy/components/source_frame/jsonView.css +4 -0
  261. package/front_end/ui/legacy/components/utils/Linkifier.ts +1 -1
  262. package/front_end/ui/legacy/inspectorCommon.css +6 -2
  263. package/front_end/ui/settings/SettingUIRegistration.ts +105 -0
  264. package/front_end/ui/settings/settings.ts +9 -0
  265. package/front_end/ui/visual_logging/KnownContextValues.ts +13 -0
  266. package/mcp/mcp.ts +1 -0
  267. package/package.json +1 -1
  268. /package/.agents/skills/{verification → devtools-verification}/SKILL.md +0 -0
  269. /package/front_end/{models → core}/text_utils/CodeMirrorUtils.ts +0 -0
  270. /package/front_end/{models → core}/text_utils/ContentData.ts +0 -0
  271. /package/front_end/{models → core}/text_utils/Text.ts +0 -0
  272. /package/front_end/{models → core}/text_utils/TextCursor.ts +0 -0
  273. /package/front_end/{models → core}/text_utils/TextUtils.snapshot.txt +0 -0
@@ -3,6 +3,7 @@
3
3
  // found in the LICENSE file.
4
4
  /* eslint-disable @devtools/no-imperative-dom-api */
5
5
 
6
+ import * as i18n from '../../../../core/i18n/i18n.js';
6
7
  import * as Platform from '../../../../core/platform/platform.js';
7
8
  import * as Geometry from '../../../../models/geometry/geometry.js';
8
9
  import * as VisualLogging from '../../../visual_logging/visual_logging.js';
@@ -12,6 +13,15 @@ import type {AnimationTimingModel} from './AnimationTimingModel.js';
12
13
  import {BezierUI} from './BezierUI.js';
13
14
  import {CSSLinearEasingModel, type Point} from './CSSLinearEasingModel.js';
14
15
 
16
+ const UIStrings = {
17
+ /**
18
+ * @description Tooltip text for control points in the linear easing editor.
19
+ */
20
+ doubleClickToDelete: 'Double-click to delete',
21
+ } as const;
22
+ const str_ = i18n.i18n.registerUIStrings('ui/legacy/components/inline_editor/AnimationTimingUI.ts', UIStrings);
23
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
24
+
15
25
  const DOUBLE_CLICK_DELAY = 500;
16
26
 
17
27
  interface Params {
@@ -130,6 +140,10 @@ class LinearEasingPresentation {
130
140
  circle.setAttribute('cx', String(controlX));
131
141
  circle.setAttribute('cy', String(controlY));
132
142
  circle.setAttribute('r', String(this.params.pointRadius));
143
+ // SVG sub-elements do not support tooltips via the 'title' attribute.
144
+ // Instead, a child <title> element must be appended to the shape.
145
+ const title = UI.UIUtils.createSVGChild(circle, 'title');
146
+ title.textContent = i18nString(UIStrings.doubleClickToDelete);
133
147
  }
134
148
 
135
149
  timingPointToPosition(point: Point): Position {
@@ -178,6 +192,10 @@ class LinearEasingUI {
178
192
  #doubleClickTimer?: number;
179
193
  #pointIndexForDoubleClick?: number;
180
194
  #mouseDownPosition?: {x: number, y: number};
195
+ /**
196
+ * The rendered SVG coordinate position of the dragged control point at the start of the drag gesture.
197
+ */
198
+ #dragStartPointPosition?: Position;
181
199
 
182
200
  #svg: Element;
183
201
 
@@ -214,6 +232,8 @@ class LinearEasingUI {
214
232
  #handleControlPointClick(event: MouseEvent, pointIndex: number): void {
215
233
  this.#selectedPointIndex = pointIndex;
216
234
  this.#mouseDownPosition = {x: event.x, y: event.y};
235
+ const controlPosition = this.#presentation.renderedPositions?.[pointIndex];
236
+ this.#dragStartPointPosition = controlPosition ? {...controlPosition} : undefined;
217
237
 
218
238
  // This is a workaround to understand whether the user double clicked
219
239
  // a point or not. The reason is, we also want to handle drag interactions
@@ -259,26 +279,20 @@ class LinearEasingUI {
259
279
  }
260
280
 
261
281
  #updatePointPosition(mouseX: number, mouseY: number): void {
262
- if (this.#selectedPointIndex === undefined || this.#mouseDownPosition === undefined) {
263
- return;
264
- }
265
-
266
- const controlPosition = this.#presentation.renderedPositions?.[this.#selectedPointIndex];
267
- if (!controlPosition) {
282
+ if (this.#selectedPointIndex === undefined || this.#mouseDownPosition === undefined ||
283
+ this.#dragStartPointPosition === undefined) {
268
284
  return;
269
285
  }
270
286
 
287
+ // By calculating the position relative to the initial drag start position (#dragStartPointPosition)
288
+ // and the total drag distance (deltaX/deltaY), we avoid incremental coordinate drift and rounding
289
+ // errors that would accumulate if we updated the mouse starting point relative to the previous frame's position.
271
290
  const deltaX = mouseX - this.#mouseDownPosition.x;
272
291
  const deltaY = mouseY - this.#mouseDownPosition.y;
273
292
 
274
- this.#mouseDownPosition = {
275
- x: mouseX,
276
- y: mouseY,
277
- };
278
-
279
293
  const newPoint = {
280
- x: controlPosition.x + deltaX,
281
- y: controlPosition.y + deltaY,
294
+ x: this.#dragStartPointPosition.x + deltaX,
295
+ y: this.#dragStartPointPosition.y + deltaY,
282
296
  };
283
297
 
284
298
  this.#model.setPoint(this.#selectedPointIndex, this.#presentation.positionToTimingPoint(newPoint));
@@ -4,6 +4,7 @@
4
4
  /* eslint-disable @devtools/no-imperative-dom-api */
5
5
 
6
6
  import * as Common from '../../../../core/common/common.js';
7
+ import * as Platform from '../../../../core/platform/platform.js';
7
8
  import * as VisualLogging from '../../../visual_logging/visual_logging.js';
8
9
  import * as UI from '../../legacy.js';
9
10
 
@@ -135,11 +136,13 @@ export class BezierEditor extends Common.ObjectWrapper.eventMixin<EventTypes, ty
135
136
  if (!pivot) {
136
137
  return null;
137
138
  }
139
+ const logContext = VisualLogging.bezierPresetCategory()
140
+ .track({click: true})
141
+ .context(Platform.StringUtilities.toKebabCase(presetGroup[0].name));
138
142
 
139
143
  const presetElement = document.createElement('div');
140
144
  presetElement.classList.add('bezier-preset-category');
141
- presetElement.setAttribute(
142
- 'jslog', `${VisualLogging.bezierPresetCategory().track({click: true}).context(presetGroup[0].name)}`);
145
+ presetElement.setAttribute('jslog', `${logContext}`);
143
146
  const iconElement = UI.UIUtils.createSVGChild(presetElement, 'svg', 'bezier-preset monospace');
144
147
  const category = {presets: presetGroup, presetIndex: 0, icon: presetElement};
145
148
  this.presetUI.draw(pivot, iconElement);
@@ -6,8 +6,17 @@ import * as CodeMirror from '../../../../third_party/codemirror.next/codemirror.
6
6
 
7
7
  const cssParser = CodeMirror.css.cssLanguage.parser;
8
8
 
9
+ /**
10
+ * Represents a point in a linear easing function graph.
11
+ */
9
12
  export interface Point {
13
+ /**
14
+ * The timeline percentage fraction (0 to 100).
15
+ */
10
16
  input: number;
17
+ /**
18
+ * The progress value (typically between 0 and 1, but can exceed bounds for bounce/elastic effects).
19
+ */
11
20
  output: number;
12
21
  }
13
22
 
@@ -105,6 +114,10 @@ const KeywordToValue: Record<string, string> = {
105
114
  linear: 'linear(0 0%, 1 100%)',
106
115
  };
107
116
 
117
+ /**
118
+ * Model representing a CSS `linear()` easing function, conforming to the CSS Easing Level 1 specification.
119
+ * It parses CSS linear easing text into a list of control points and manages point mutations.
120
+ */
108
121
  export class CSSLinearEasingModel {
109
122
  #points: Point[];
110
123
 
@@ -207,7 +220,17 @@ export class CSSLinearEasingModel {
207
220
  this.#points.splice(index, 1);
208
221
  }
209
222
 
223
+ /**
224
+ * Sets the timing point at the specified index, clamping its input value (percentage)
225
+ * to ensure it remains non-decreasing and within the bounds of neighboring points.
226
+ *
227
+ * @param index The index of the point to update.
228
+ * @param point The new timing point coordinates.
229
+ */
210
230
  setPoint(index: number, point: Point): void {
231
+ const minInput = index > 0 ? this.#points[index - 1].input : 0;
232
+ const maxInput = index < this.#points.length - 1 ? this.#points[index + 1].input : 100;
233
+ point.input = Math.max(minInput, Math.min(point.input, maxInput));
211
234
  this.#points[index] = point;
212
235
  }
213
236
 
@@ -34,12 +34,19 @@ import * as Host from '../../../../core/host/host.js';
34
34
  import * as i18n from '../../../../core/i18n/i18n.js';
35
35
  import * as Platform from '../../../../core/platform/platform.js';
36
36
  import * as SDK from '../../../../core/sdk/sdk.js';
37
+ import * as TextUtils from '../../../../core/text_utils/text_utils.js';
37
38
  import type * as Protocol from '../../../../generated/protocol.js';
38
- import * as TextUtils from '../../../../models/text_utils/text_utils.js';
39
39
  import * as uiI18n from '../../../../ui/i18n/i18n.js';
40
40
  import * as Highlighting from '../../../components/highlighting/highlighting.js';
41
41
  import * as TextEditor from '../../../components/text_editor/text_editor.js';
42
- import {Directives, html, type LitTemplate, nothing, render} from '../../../lit/lit.js';
42
+ import {
43
+ type DirectiveResult,
44
+ Directives,
45
+ html,
46
+ type LitTemplate,
47
+ nothing,
48
+ render,
49
+ } from '../../../lit/lit.js';
43
50
  import * as VisualLogging from '../../../visual_logging/visual_logging.js';
44
51
  import * as UI from '../../legacy.js';
45
52
  import type * as Components from '../utils/utils.js';
@@ -52,6 +59,10 @@ import {RemoteObjectPreviewFormatter, renderNodeTitle, renderTrustedType} from '
52
59
 
53
60
  export {objectPropertiesSectionStyles, objectValueStyles};
54
61
 
62
+ export interface ObjectPropertySearchResult extends UI.TreeOutline.TreeSearchResult<ObjectTreeNodeBase> {
63
+ matchType: 'name'|'value';
64
+ range: TextUtils.TextRange.SourceRange;
65
+ }
55
66
  const {widget} = UI.Widget;
56
67
  const {ref, repeat, ifDefined, classMap, until} = Directives;
57
68
  const UIStrings = {
@@ -169,15 +180,7 @@ export interface ObjectTreeOptions {
169
180
  readonly propertiesMode: ObjectPropertiesMode;
170
181
  readonly readOnly: boolean;
171
182
  readonly expansionTracker?: ObjectTreeExpansionTracker;
172
- }
173
-
174
- let cachedSortAlphabeticallySetting: Common.Settings.Setting<boolean>|undefined;
175
- export function sortPropertiesAlphabeticallySetting(): Common.Settings.Setting<boolean> {
176
- if (!cachedSortAlphabeticallySetting) {
177
- cachedSortAlphabeticallySetting =
178
- Common.Settings.Settings.instance().createSetting('object-properties-sort-alphabetically', true);
179
- }
180
- return cachedSortAlphabeticallySetting;
183
+ readonly search?: UI.TreeOutline.TreeSearch<ObjectTreeNodeBase>;
181
184
  }
182
185
 
183
186
  // WASM properties are index-based (e.g. locals[0], globals[1]); alphabetical
@@ -398,11 +401,15 @@ export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrap
398
401
  protected filter: {includeNullOrUndefinedValues: boolean, regex: RegExp|null}|null = null;
399
402
  protected extraProperties: ObjectTreeNode[] = [];
400
403
  #expanded = false;
404
+ #sortPropertiesAlphabeticallySetting: Common.Settings.Setting<boolean>;
401
405
 
402
406
  constructor(readonly parent: ObjectTreeNodeBase|undefined, options: ObjectTreeOptions) {
403
407
  super();
404
408
  this.filter = parent?.filter ?? null;
405
409
  this.options = {...options};
410
+ this.#sortPropertiesAlphabeticallySetting = parent ?
411
+ parent.#sortPropertiesAlphabeticallySetting :
412
+ Common.Settings.Settings.instance().createSetting('object-properties-sort-alphabetically', true);
406
413
  }
407
414
 
408
415
  get isWasm(): boolean {
@@ -432,6 +439,9 @@ export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrap
432
439
  return this.options.propertiesMode;
433
440
  }
434
441
 
442
+ get search(): UI.TreeOutline.TreeSearch<ObjectTreeNodeBase>|undefined {
443
+ return this.options.search;
444
+ }
435
445
  get includeNullOrUndefinedValues(): boolean {
436
446
  return this.filter?.includeNullOrUndefinedValues ?? true;
437
447
  }
@@ -448,37 +458,36 @@ export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrap
448
458
  if (this.isWasm) {
449
459
  return false;
450
460
  }
451
- return sortPropertiesAlphabeticallySetting().get();
461
+ return this.#sortPropertiesAlphabeticallySetting.get();
452
462
  }
453
463
 
454
464
  set sortPropertiesAlphabetically(value: boolean) {
455
- const setting = sortPropertiesAlphabeticallySetting();
456
- if (this.isWasm || setting.get() === value) {
465
+ if (this.isWasm || this.#sortPropertiesAlphabeticallySetting.get() === value) {
457
466
  return;
458
467
  }
459
- setting.set(value);
468
+ this.#sortPropertiesAlphabeticallySetting.set(value);
460
469
  this.removeChildren();
461
470
  }
471
+ * treeNodeChildren(): Generator<ObjectTreeNodeBase> {
472
+ if (this.#children) {
473
+ yield* this.#children.properties ?? [];
474
+ yield* this.#children.arrayRanges ?? [];
475
+ yield* this.#children.internalProperties ?? [];
476
+ }
477
+ }
462
478
  // Performs a pre-order tree traversal over the populated children. If any children need to be populated, callers must
463
479
  // do that while walking (pre-order visitation enables that).
464
480
  * #walk(maxDepth = -1, filter?: (node: ObjectTreeNodeBase) => boolean): Generator<ObjectTreeNodeBase> {
465
481
  if (filter && !filter(this)) {
466
482
  return;
467
483
  }
468
- function* walkChildren(children: ObjectTreeNodeBase[]|undefined): Generator<ObjectTreeNodeBase> {
469
- if (children) {
470
- for (const child of children) {
471
- yield* child.#walk(Math.max(-1, maxDepth - 1), filter);
472
- }
473
- }
474
- }
475
484
  yield this;
476
485
  if (maxDepth !== 0) {
477
- yield* walkChildren(this.#children?.properties);
478
- yield* walkChildren(this.#children?.arrayRanges);
479
- yield* walkChildren(this.#children?.internalProperties);
486
+ for (const child of this.treeNodeChildren()) {
487
+ yield* child.#walk(Math.max(-1, maxDepth - 1), filter);
488
+ }
489
+ }
480
490
  }
481
- }
482
491
 
483
492
  async expandRecursively(maxDepth: number): Promise<void> {
484
493
  for (const node of this.#walk(maxDepth, n => n.canExpandRecursively)) {
@@ -509,6 +518,9 @@ export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrap
509
518
  this.dispatchEventToListeners(ObjectTreeNodeBase.Events.CHILDREN_CHANGED);
510
519
  }
511
520
 
521
+ match(_regex: RegExp): ObjectPropertySearchResult[] {
522
+ return [];
523
+ }
512
524
  removeChild(child: ObjectTreeNodeBase): void {
513
525
  remove(this.#children?.arrayRanges, child);
514
526
  remove(this.#children?.internalProperties, child);
@@ -564,9 +576,7 @@ export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrap
564
576
  const ranges = await arrayRangeGroups(object, 0, this.arrayLength - 1);
565
577
  const arrayRanges = ranges?.ranges.map(([fromIndex, toIndex, count]) => new ArrayGroupTreeNode(
566
578
  object, {fromIndex, toIndex, count}, effectiveParent, {
567
- readOnly: this.readOnly,
568
- propertiesMode: this.propertiesMode,
569
- expansionTracker: this.options.expansionTracker,
579
+ ...this.options,
570
580
  }));
571
581
  if (!arrayRanges) {
572
582
  return {};
@@ -577,16 +587,14 @@ export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrap
577
587
  true /* nonIndexedPropertiesOnly */);
578
588
 
579
589
  const properties = objectProperties?.map(p => new ObjectTreeNode(p, effectiveParent, {
580
- readOnly: this.readOnly,
590
+ ...this.options,
581
591
  propertiesMode: ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
582
- expansionTracker: this.options.expansionTracker,
583
592
  }));
584
593
 
585
594
  const internalProperties =
586
595
  objectInternalProperties?.map(p => new ObjectTreeNode(p, effectiveParent, {
587
- readOnly: this.readOnly,
596
+ ...this.options,
588
597
  propertiesMode: ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
589
- expansionTracker: this.options.expansionTracker,
590
598
  }));
591
599
  return {arrayRanges, properties, internalProperties};
592
600
  }
@@ -605,9 +613,8 @@ export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrap
605
613
  }
606
614
 
607
615
  const properties = objectProperties?.map(p => new ObjectTreeNode(p, effectiveParent, {
608
- readOnly: this.readOnly,
616
+ ...this.options,
609
617
  propertiesMode: ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
610
- expansionTracker: this.options.expansionTracker,
611
618
  }));
612
619
  properties?.push(...this.extraProperties);
613
620
  properties?.sort((a, b) => ObjectPropertiesSection.compareProperties(a, b, this.sortPropertiesAlphabetically));
@@ -615,9 +622,8 @@ export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrap
615
622
 
616
623
  const internalProperties =
617
624
  objectInternalProperties?.map(p => new ObjectTreeNode(p, effectiveParent, {
618
- readOnly: this.readOnly,
625
+ ...this.options,
619
626
  propertiesMode: ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
620
- expansionTracker: this.options.expansionTracker,
621
627
  }));
622
628
  return {properties, internalProperties, accessors};
623
629
  }
@@ -637,9 +643,8 @@ export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrap
637
643
 
638
644
  addExtraProperties(...properties: SDK.RemoteObject.RemoteObjectProperty[]): void {
639
645
  this.extraProperties.push(...properties.map(p => new ObjectTreeNode(p, this, {
640
- readOnly: this.readOnly,
646
+ ...this.options,
641
647
  propertiesMode: ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
642
- expansionTracker: this.options.expansionTracker,
643
648
  })));
644
649
  }
645
650
 
@@ -651,18 +656,18 @@ export abstract class ObjectTreeNodeBase extends Common.ObjectWrapper.ObjectWrap
651
656
  const getterProperty = new SDK.RemoteObject.RemoteObjectProperty('get ' + property.property.name,
652
657
  property.property.getter, false);
653
658
  gettersAndSetters.push(new ObjectTreeNode(getterProperty, property.parent, {
659
+ ...options,
654
660
  propertiesMode: property.propertiesMode,
655
661
  readOnly: property.readOnly,
656
- expansionTracker: options.expansionTracker,
657
662
  }));
658
663
  }
659
664
  if (property.property.setter) {
660
665
  const setterProperty = new SDK.RemoteObject.RemoteObjectProperty('set ' + property.property.name,
661
666
  property.property.setter, false);
662
667
  gettersAndSetters.push(new ObjectTreeNode(setterProperty, property.parent, {
668
+ ...options,
663
669
  propertiesMode: property.propertiesMode,
664
670
  readOnly: property.readOnly,
665
- expansionTracker: options.expansionTracker,
666
671
  }));
667
672
  }
668
673
  }
@@ -739,9 +744,7 @@ export class ArrayGroupTreeNode extends ObjectTreeNodeBase {
739
744
  await arrayFragment.getAllProperties(false /* accessorPropertiesOnly */, true /* generatePreview */);
740
745
  arrayFragment.release();
741
746
  const properties = allProperties.properties?.map(p => new ObjectTreeNode(p, this, {
742
- propertiesMode: this.propertiesMode,
743
- readOnly: this.readOnly,
744
- expansionTracker: this.options.expansionTracker,
747
+ ...this.options,
745
748
  }));
746
749
  properties?.push(...this.extraProperties);
747
750
  properties?.sort((a, b) => ObjectPropertiesSection.compareProperties(a, b, this.sortPropertiesAlphabetically));
@@ -867,6 +870,59 @@ export class ObjectTreeNode extends ObjectTreeNodeBase {
867
870
  this.property.wasThrown = result.wasThrown || false;
868
871
  this.dispatchEventToListeners(ObjectTreeNodeBase.Events.VALUE_CHANGED);
869
872
  }
873
+ #getSearchableNameText(): string {
874
+ return /^\s|\s$|^$|\n/.test(this.property.name) ? `"${this.property.name.replace(/\n/g, '\u21B5')}"` :
875
+ this.property.name;
876
+ }
877
+
878
+ #getSearchableValueText(): string {
879
+ const value = this.property.value;
880
+ if (!value || (value.type !== 'string' && value.type !== 'number') || value.description === undefined) {
881
+ return '';
882
+ }
883
+ if (value.type === 'string' && typeof value.description === 'string') {
884
+ const text = Platform.StringUtilities.safeEscapeUnicode(JSON.stringify(value.description));
885
+ if (value.description.length > maxRenderableStringLength) {
886
+ return text.slice(0, ExpandableTextPropertyValue.EXPANDABLE_MAX_LENGTH);
887
+ }
888
+ return text;
889
+ }
890
+ return value.description;
891
+ }
892
+
893
+ override match(regex: RegExp): ObjectPropertySearchResult[] {
894
+ const results: ObjectPropertySearchResult[] = [];
895
+
896
+ // 1. Match name against search text model
897
+ const nameText = this.#getSearchableNameText();
898
+ const nameGlobalRegex = regex.global ? regex : new RegExp(regex.source, regex.flags + 'g');
899
+ for (const m of nameText.matchAll(nameGlobalRegex)) {
900
+ results.push({
901
+ node: this,
902
+ isPostOrderMatch: false,
903
+ matchIndexInNode: results.length,
904
+ matchType: 'name',
905
+ range: new TextUtils.TextRange.SourceRange(m.index ?? 0, m[0].length),
906
+ });
907
+ }
908
+
909
+ // 2. Match value against search text model
910
+ const valueText = this.#getSearchableValueText();
911
+ if (valueText) {
912
+ const valueGlobalRegex = regex.global ? regex : new RegExp(regex.source, regex.flags + 'g');
913
+ for (const m of valueText.matchAll(valueGlobalRegex)) {
914
+ results.push({
915
+ node: this,
916
+ isPostOrderMatch: false,
917
+ matchIndexInNode: results.length,
918
+ matchType: 'value',
919
+ range: new TextUtils.TextRange.SourceRange(m.index ?? 0, m[0].length),
920
+ });
921
+ }
922
+ }
923
+
924
+ return results;
925
+ }
870
926
  }
871
927
 
872
928
  export const getObjectPropertiesSectionFrom = (element: Element): ObjectPropertiesSection|undefined => {
@@ -880,11 +936,13 @@ export class ObjectPropertiesSection extends UI.TreeOutline.TreeOutlineInShadow
880
936
  skipProtoInternal?: boolean;
881
937
 
882
938
  constructor(object: SDK.RemoteObject.RemoteObject, title?: string|Element|null,
883
- linkifier?: Components.Linkifier.Linkifier, showOverflow?: boolean, editable = true) {
939
+ linkifier?: Components.Linkifier.Linkifier, showOverflow?: boolean, editable = true,
940
+ search?: UI.TreeOutline.TreeSearch<ObjectTreeNodeBase>) {
884
941
  super();
885
942
  this.root = new ObjectTree(object, {
886
943
  readOnly: !editable,
887
944
  propertiesMode: ObjectPropertiesMode.OWN_AND_INTERNAL_AND_INHERITED,
945
+ search,
888
946
  });
889
947
  if (!showOverflow) {
890
948
  this.setHideOverflow(true);
@@ -1341,15 +1399,16 @@ export function populateObjectTreeContextMenu(
1341
1399
  {checked: object.includeNullOrUndefinedValues, jslogContext: 'show-all'});
1342
1400
  }
1343
1401
 
1344
- export function renderObjectTree(
1402
+ function renderObjectTreeInternal(
1345
1403
  objectTree: ObjectTree,
1346
1404
  linkifier?: Components.Linkifier.Linkifier,
1347
1405
  emptyPlaceholder?: string|null,
1348
- ): unknown {
1406
+ classes: Record<string, boolean> = {},
1407
+ ): LitTemplate|DirectiveResult {
1349
1408
  const entry = topLevelNodesCache.get(objectTree);
1350
1409
  if (entry && entry.linkifier === linkifier) {
1351
1410
  return html`
1352
- <ul class="source-code object-properties-section" role="group">
1411
+ <ul class=${classMap(classes)} role="group">
1353
1412
  ${entry.nodes.map(node => html`<devtools-tree-wrapper .treeElement=${node}></devtools-tree-wrapper>`)}
1354
1413
  </ul>
1355
1414
  `;
@@ -1367,13 +1426,43 @@ export function renderObjectTree(
1367
1426
  objectTree.addEventListener(ObjectTreeNodeBase.Events.CHILDREN_CHANGED, listener);
1368
1427
 
1369
1428
  return html`
1370
- <ul class="source-code object-properties-section" role="group">
1429
+ <ul class=${classMap(classes)} role="group">
1371
1430
  ${nodes.map(node => html`<devtools-tree-wrapper .treeElement=${node}></devtools-tree-wrapper>`)}
1372
1431
  </ul>
1373
1432
  `;
1374
1433
  })();
1375
1434
 
1376
- return until(promise, html`<ul class="source-code object-properties-section" role="group"></ul>`);
1435
+ return until(promise, html`<ul class=${classMap(classes)} role="group"></ul>`);
1436
+ }
1437
+
1438
+ export function renderObjectTree(
1439
+ objectTree: ObjectTree,
1440
+ linkifier?: Components.Linkifier.Linkifier,
1441
+ emptyPlaceholder?: string|null,
1442
+ ): LitTemplate|DirectiveResult {
1443
+ return renderObjectTreeInternal(objectTree, linkifier, emptyPlaceholder, {
1444
+ 'source-code': true,
1445
+ 'object-properties-section': true,
1446
+ });
1447
+ }
1448
+
1449
+ export function renderObjectPropertiesSection(
1450
+ objectTree: ObjectTree,
1451
+ title: LitTemplate,
1452
+ linkifier?: Components.Linkifier.Linkifier,
1453
+ ): LitTemplate {
1454
+ const treeContent = renderObjectTreeInternal(objectTree, linkifier, undefined, {});
1455
+
1456
+ return html`<devtools-tree class="object-properties-section" show-selection-on-keyboard-focus .template=${html`
1457
+ <ul role="tree" class="source-code object-properties-section">
1458
+ <style>${objectValueStyles}</style>
1459
+ <style>${objectPropertiesSectionStyles}</style>
1460
+ <li role="treeitem" class="object-properties-section-root-element" ?open=${objectTree.expanded}>
1461
+ ${title}
1462
+ ${treeContent}
1463
+ </li>
1464
+ </ul>
1465
+ `}></devtools-tree>`;
1377
1466
  }
1378
1467
  class RootElement extends UI.TreeOutline.TreeElement {
1379
1468
  private readonly object: ObjectTree;
@@ -1461,6 +1550,7 @@ export interface ObjectPropertyViewInput {
1461
1550
  editingEnded(): unknown;
1462
1551
  editingCommitted(detail: string): unknown;
1463
1552
  node: ObjectTreeNode;
1553
+ search?: UI.TreeOutline.TreeSearch<ObjectTreeNodeBase>;
1464
1554
  }
1465
1555
  interface ObjectPropertyViewOutput {
1466
1556
  valueElement: Element|undefined;
@@ -1490,6 +1580,17 @@ export const OBJECT_PROPERTY_DEFAULT_VIEW: ObjectPropertyView = (input, output,
1490
1580
  !property.value.customPreview() && property.value.subtype !== 'node' && property.value.type !== 'function' &&
1491
1581
  (property.value.type !== 'object' || property.value.preview);
1492
1582
 
1583
+ const search = input.search;
1584
+ const entries = search?.getResults(input.node) as ObjectPropertySearchResult[] | undefined;
1585
+ const currentMatch = search?.currentMatch() as ObjectPropertySearchResult | undefined;
1586
+ const isCurrentNode = currentMatch?.node === input.node;
1587
+ const nameCurrent = (isCurrentNode && currentMatch?.matchType === 'name') ? currentMatch.range.cssValue() : '';
1588
+ const valueCurrent = (isCurrentNode && currentMatch?.matchType === 'value') ? currentMatch.range.cssValue() : '';
1589
+
1590
+ const nameRanges =
1591
+ (entries ?? []).filter(e => e !== currentMatch && e.matchType === 'name').map(e => e.range.cssValue()).join(' ');
1592
+ const valueRanges =
1593
+ (entries ?? []).filter(e => e !== currentMatch && e.matchType === 'value').map(e => e.range.cssValue()).join(' ');
1493
1594
  const value = (): LitTemplate|HTMLElement => {
1494
1595
  const valueRef = ref(e => {
1495
1596
  output.valueElement = e;
@@ -1538,9 +1639,9 @@ export const OBJECT_PROPERTY_DEFAULT_VIEW: ObjectPropertyView = (input, output,
1538
1639
  html`<span class=name-and-value><span
1539
1640
  ${ref(e => { output.nameElement = e; })}
1540
1641
  class=${nameClasses}
1541
- title=${input.node.path}>${property.private ?
1642
+ title=${input.node.path}><devtools-highlight ranges=${nameRanges} current-range=${nameCurrent}>${property.private ?
1542
1643
  html`<span class="private-property-hash">${property.name[0]}</span>${
1543
- property.name.substring(1)}</span>` : quotedName}</span>${
1644
+ property.name.substring(1)}` : quotedName}</devtools-highlight></span>${
1544
1645
  isInternalEntries ? nothing :
1545
1646
  html`<span class='separator'>: </span><devtools-prompt
1546
1647
  @commit=${(e: UI.TextPrompt.TextPromptElement.CommitEvent) => input.editingCommitted(e.detail)}
@@ -1551,7 +1652,8 @@ export const OBJECT_PROPERTY_DEFAULT_VIEW: ObjectPropertyView = (input, output,
1551
1652
  completions=${completionsId}
1552
1653
  placeholder=${i18nString(UIStrings.stringIsTooLargeToEdit)}
1553
1654
  ?editing=${input.editing}>
1554
- ${input.expanded && isExpandable && property.value ?
1655
+ <devtools-highlight ranges=${valueRanges} current-range=${valueCurrent}>${
1656
+ input.expanded && isExpandable && property.value ?
1555
1657
  html`<span
1556
1658
  class="value object-value-${property.value.subtype || property.value.type}"
1557
1659
  title=${ifDefined(property.value.description)}>${
@@ -1561,7 +1663,7 @@ export const OBJECT_PROPERTY_DEFAULT_VIEW: ObjectPropertyView = (input, output,
1561
1663
  property.synthetic ? nothing :
1562
1664
  ObjectPropertiesSection.getMemoryIcon(property.value)}</span>` :
1563
1665
  value()
1564
- }
1666
+ }</devtools-highlight>
1565
1667
  <datalist id=${completionsId}>${repeat(input.completions, c => html`<option>${c}</option>`)}</datalist>
1566
1668
  </devtools-prompt></span>`}</span>`,
1567
1669
  target);
@@ -1579,6 +1681,7 @@ export class ObjectPropertyWidget extends UI.Widget.Widget {
1579
1681
  #expanded = false;
1580
1682
  #linkifier: Components.Linkifier.Linkifier|undefined;
1581
1683
  #editable = false;
1684
+ #search?: UI.TreeOutline.TreeSearch<ObjectTreeNodeBase>;
1582
1685
 
1583
1686
  constructor(target?: HTMLElement, view = OBJECT_PROPERTY_DEFAULT_VIEW) {
1584
1687
  super(target);
@@ -1594,10 +1697,13 @@ export class ObjectPropertyWidget extends UI.Widget.Widget {
1594
1697
  this.#property.removeEventListener(ObjectTreeNodeBase.Events.CHILDREN_CHANGED, this.requestUpdate, this);
1595
1698
  this.#property.removeEventListener(ObjectTreeNodeBase.Events.FILTER_CHANGED, this.requestUpdate, this);
1596
1699
  }
1700
+ this.#search?.removeEventListener(UI.TreeOutline.TreeSearch.Events.SEARCH_CHANGED, this.requestUpdate, this);
1597
1701
  this.#property = property;
1598
1702
  this.#property.addEventListener(ObjectTreeNodeBase.Events.VALUE_CHANGED, this.requestUpdate, this);
1599
1703
  this.#property.addEventListener(ObjectTreeNodeBase.Events.CHILDREN_CHANGED, this.requestUpdate, this);
1600
1704
  this.#property.addEventListener(ObjectTreeNodeBase.Events.FILTER_CHANGED, this.requestUpdate, this);
1705
+ this.#search = property.search;
1706
+ this.#search?.addEventListener(UI.TreeOutline.TreeSearch.Events.SEARCH_CHANGED, this.requestUpdate, this);
1601
1707
  this.requestUpdate();
1602
1708
  }
1603
1709
 
@@ -1641,6 +1747,7 @@ export class ObjectPropertyWidget extends UI.Widget.Widget {
1641
1747
  onAutoComplete: this.#updateCompletions.bind(this),
1642
1748
  invokeGetter: this.#invokeGetter.bind(this),
1643
1749
  startEditing: this.startEditing.bind(this),
1750
+ search: this.#search,
1644
1751
  };
1645
1752
  const that = this;
1646
1753
  const output: ObjectPropertyViewOutput = {
@@ -6,8 +6,8 @@
6
6
  import * as Common from '../../../../core/common/common.js';
7
7
  import * as i18n from '../../../../core/i18n/i18n.js';
8
8
  import * as Platform from '../../../../core/platform/platform.js';
9
+ import * as TextUtils from '../../../../core/text_utils/text_utils.js';
9
10
  import * as Geometry from '../../../../models/geometry/geometry.js';
10
- import * as TextUtils from '../../../../models/text_utils/text_utils.js';
11
11
  import * as Diff from '../../../../third_party/diff/diff.js';
12
12
  import * as TextPrompt from '../../../../ui/components/text_prompt/text_prompt.js';
13
13
  import {type LitTemplate, nothing, render} from '../../../lit/lit.js';
@@ -4,7 +4,7 @@
4
4
 
5
5
  import type * as Common from '../../../../core/common/common.js';
6
6
  import type * as Platform from '../../../../core/platform/platform.js';
7
- import * as TextUtils from '../../../../models/text_utils/text_utils.js';
7
+ import * as TextUtils from '../../../../core/text_utils/text_utils.js';
8
8
 
9
9
  import {ResourceSourceFrame} from './ResourceSourceFrame.js';
10
10
  import {StreamingContentHexView} from './StreamingContentHexView.js';
@@ -32,7 +32,7 @@
32
32
 
33
33
  import * as i18n from '../../../../core/i18n/i18n.js';
34
34
  import type * as Platform from '../../../../core/platform/platform.js';
35
- import * as TextUtils from '../../../../models/text_utils/text_utils.js';
35
+ import * as TextUtils from '../../../../core/text_utils/text_utils.js';
36
36
  import {Directives, html, render} from '../../../lit/lit.js';
37
37
  import * as VisualLogging from '../../../visual_logging/visual_logging.js';
38
38
  import * as UI from '../../legacy.js';
@@ -35,7 +35,7 @@ import * as Common from '../../../../core/common/common.js';
35
35
  import * as Host from '../../../../core/host/host.js';
36
36
  import * as i18n from '../../../../core/i18n/i18n.js';
37
37
  import * as Platform from '../../../../core/platform/platform.js';
38
- import * as TextUtils from '../../../../models/text_utils/text_utils.js';
38
+ import * as TextUtils from '../../../../core/text_utils/text_utils.js';
39
39
  import * as Workspace from '../../../../models/workspace/workspace.js';
40
40
  import {createIcon} from '../../../kit/kit.js';
41
41
  import * as VisualLogging from '../../../visual_logging/visual_logging.js';