chrome-devtools-frontend 1.0.1657855 → 1.0.1660788

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 (274) hide show
  1. package/.agents/skills/migrate-chromium-test/SKILL.md +15 -70
  2. package/.agents/skills/ui-eng-vision-orchestrator/SKILL.md +37 -18
  3. package/.agents/skills/version-control/SKILL.md +8 -1
  4. package/AUTHORS +1 -0
  5. package/SECURITY.md +3 -0
  6. package/docs/get_the_code.md +6 -0
  7. package/front_end/Tests.js +6 -6
  8. package/front_end/core/common/Gzip.ts +12 -5
  9. package/front_end/core/host/AidaClient.ts +35 -9
  10. package/front_end/core/host/GdpClient.ts +10 -7
  11. package/front_end/core/platform/StringUtilities.ts +35 -0
  12. package/front_end/core/sdk/AccessibilityModel.snapshot.txt +17 -0
  13. package/front_end/core/sdk/AccessibilityModel.ts +132 -2
  14. package/front_end/core/sdk/CPUThrottlingManager.ts +8 -5
  15. package/front_end/core/sdk/CompilerSourceMappingContentProvider.ts +2 -5
  16. package/front_end/core/sdk/ConsoleModel.ts +5 -5
  17. package/front_end/core/sdk/DOMDebuggerModel.ts +5 -1
  18. package/front_end/core/sdk/DOMModel.ts +32 -18
  19. package/front_end/core/sdk/NetworkManager.ts +57 -11
  20. package/front_end/core/sdk/NetworkRequest.ts +37 -1
  21. package/front_end/core/sdk/OverlayModel.ts +45 -6
  22. package/front_end/core/sdk/ResourceTreeModel.ts +6 -7
  23. package/front_end/core/sdk/ScreenCaptureModel.ts +2 -2
  24. package/front_end/core/sdk/ServerTiming.ts +17 -13
  25. package/front_end/core/sdk/ServiceWorkerCacheModel.ts +4 -2
  26. package/front_end/core/sdk/ServiceWorkerManager.ts +19 -5
  27. package/front_end/core/sdk/TargetManager.ts +10 -1
  28. package/front_end/core/sdk/TraceObject.ts +4 -2
  29. package/front_end/core/sdk/sdk-meta.ts +170 -0
  30. package/front_end/design_system_tokens.css +0 -5
  31. package/front_end/entrypoints/formatter_worker/FormattedContentBuilder.ts +5 -2
  32. package/front_end/entrypoints/formatter_worker/HTMLFormatter.ts +26 -4
  33. package/front_end/entrypoints/formatter_worker/JavaScriptFormatter.ts +8 -3
  34. package/front_end/entrypoints/inspector_main/InspectorMain.ts +4 -4
  35. package/front_end/entrypoints/inspector_main/OutermostTargetSelector.ts +2 -2
  36. package/front_end/entrypoints/inspector_main/RenderingOptions.ts +36 -37
  37. package/front_end/entrypoints/inspector_main/inspector_main-meta.ts +15 -33
  38. package/front_end/entrypoints/js_app/js_app.ts +6 -5
  39. package/front_end/entrypoints/main/GlobalAiButton.ts +4 -4
  40. package/front_end/entrypoints/main/MainImpl.ts +18 -21
  41. package/front_end/entrypoints/main/main-meta.ts +42 -42
  42. package/front_end/entrypoints/node_app/node_app.ts +3 -2
  43. package/front_end/entrypoints/worker_app/WorkerMain.ts +1 -1
  44. package/front_end/foundation/Universe.ts +44 -1
  45. package/front_end/generated/InspectorBackendCommands.ts +2 -2
  46. package/front_end/generated/SupportedCSSProperties.js +19 -12
  47. package/front_end/generated/protocol.ts +3 -1
  48. package/front_end/models/ai_assistance/AiConversation.ts +19 -17
  49. package/front_end/models/ai_assistance/AiHistoryStorage.ts +37 -14
  50. package/front_end/models/ai_assistance/AiUtils.ts +38 -42
  51. package/front_end/models/ai_assistance/agents/AiAgent.ts +5 -1
  52. package/front_end/models/ai_assistance/agents/ContextSelectionAgent.ts +3 -2
  53. package/front_end/models/ai_assistance/agents/PerformanceAgent.ts +2 -1
  54. package/front_end/models/ai_assistance/agents/StorageAgent.ts +7 -5
  55. package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +270 -286
  56. package/front_end/models/ai_assistance/data_formatters/UnitFormatters.ts +20 -0
  57. package/front_end/models/ai_assistance/performance/AICallTree.ts +3 -1
  58. package/front_end/models/ai_assistance/tools/ListNetworkRequests.ts +3 -2
  59. package/front_end/models/autofill_manager/AutofillManager.ts +3 -1
  60. package/front_end/models/bindings/CompilerScriptMapping.ts +2 -1
  61. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +2 -1
  62. package/front_end/models/bindings/NetworkProject.ts +4 -0
  63. package/front_end/models/bindings/PresentationConsoleMessageHelper.ts +2 -1
  64. package/front_end/models/bindings/ResourceUtils.ts +1 -1
  65. package/front_end/models/bindings/SASSSourceMapping.ts +8 -5
  66. package/front_end/models/emulation/EmulatedDevices.ts +389 -8
  67. package/front_end/models/extensions/ExtensionAPI.ts +6 -6
  68. package/front_end/models/extensions/LanguageExtensionEndpoint.ts +13 -12
  69. package/front_end/models/issues_manager/BounceTrackingIssue.ts +1 -1
  70. package/front_end/models/issues_manager/ClientHintIssue.ts +1 -1
  71. package/front_end/models/issues_manager/ConnectionAllowlistIssue.ts +1 -1
  72. package/front_end/models/issues_manager/ContentSecurityPolicyIssue.ts +7 -7
  73. package/front_end/models/issues_manager/CookieDeprecationMetadataIssue.ts +2 -2
  74. package/front_end/models/issues_manager/CookieIssue.ts +6 -7
  75. package/front_end/models/issues_manager/CorsIssue.ts +3 -3
  76. package/front_end/models/issues_manager/CrossOriginEmbedderPolicyIssue.ts +2 -2
  77. package/front_end/models/issues_manager/DeprecationIssue.ts +3 -3
  78. package/front_end/models/issues_manager/EmailVerificationRequestIssue.ts +1 -1
  79. package/front_end/models/issues_manager/FederatedAuthRequestIssue.ts +1 -1
  80. package/front_end/models/issues_manager/FederatedAuthUserInfoRequestIssue.ts +1 -1
  81. package/front_end/models/issues_manager/GenericIssue.ts +7 -7
  82. package/front_end/models/issues_manager/HeavyAdIssue.ts +3 -3
  83. package/front_end/models/issues_manager/Issue.ts +8 -8
  84. package/front_end/models/issues_manager/MixedContentIssue.ts +1 -1
  85. package/front_end/models/issues_manager/PartitioningBlobURLIssue.ts +3 -3
  86. package/front_end/models/issues_manager/QuirksModeIssue.ts +1 -1
  87. package/front_end/models/issues_manager/SRIMessageSignatureIssue.ts +2 -2
  88. package/front_end/models/issues_manager/SelectivePermissionsInterventionIssue.ts +2 -2
  89. package/front_end/models/issues_manager/SharedArrayBufferIssue.ts +2 -2
  90. package/front_end/models/issues_manager/SharedDictionaryIssue.ts +1 -1
  91. package/front_end/models/issues_manager/UnencodedDigestIssue.ts +3 -3
  92. package/front_end/models/javascript_metadata/NativeFunctions.js +5 -1
  93. package/front_end/models/stack_trace/StackTraceModel.ts +3 -3
  94. package/front_end/models/text_utils/ContentData.ts +27 -0
  95. package/front_end/models/trace/helpers/SamplesIntegrator.ts +21 -5
  96. package/front_end/models/trace_source_maps_resolver/SourceMapsResolver.ts +29 -14
  97. package/front_end/models/web_mcp/WebMCPModel.ts +24 -6
  98. package/front_end/models/workspace/IgnoreListManager.ts +6 -6
  99. package/front_end/models/workspace/UISourceCode.ts +3 -3
  100. package/front_end/panels/ai_assistance/AiAssistancePanel.ts +25 -22
  101. package/front_end/panels/ai_assistance/ExportConversation.ts +3 -4
  102. package/front_end/panels/ai_assistance/ai_assistance-meta.ts +3 -3
  103. package/front_end/panels/ai_assistance/components/ChatInput.ts +2 -2
  104. package/front_end/panels/ai_assistance/components/ChatMessage.ts +7 -0
  105. package/front_end/panels/ai_assistance/components/DisabledWidget.ts +2 -2
  106. package/front_end/panels/animation/AnimationTimeline.ts +17 -19
  107. package/front_end/panels/animation/AnimationUI.ts +5 -5
  108. package/front_end/panels/animation/animation-meta.ts +2 -2
  109. package/front_end/panels/application/ApplicationPanelSidebar.ts +4 -3
  110. package/front_end/panels/application/DeviceBoundSessionsView.ts +2 -6
  111. package/front_end/panels/application/IndexedDBViews.ts +220 -266
  112. package/front_end/panels/application/OpenedWindowDetailsView.ts +1 -1
  113. package/front_end/panels/application/ResourcesPanel.ts +9 -2
  114. package/front_end/panels/application/ServiceWorkersView.ts +252 -211
  115. package/front_end/panels/application/StorageView.ts +97 -33
  116. package/front_end/panels/application/WebMCPView.ts +15 -1
  117. package/front_end/panels/application/indexedDBViews.css +38 -9
  118. package/front_end/panels/application/preloading/helper/PreloadingForward.ts +2 -1
  119. package/front_end/panels/application/storageView.css +26 -9
  120. package/front_end/panels/browser_debugger/XHRBreakpointsSidebarPane.ts +5 -1
  121. package/front_end/panels/browser_debugger/browser_debugger-meta.ts +8 -6
  122. package/front_end/panels/common/DOMLinkifier.ts +1 -1
  123. package/front_end/panels/common/ExtensionServer.ts +119 -14
  124. package/front_end/panels/console/ConsoleContextSelector.ts +1 -1
  125. package/front_end/panels/console/ConsolePinPane.ts +2 -2
  126. package/front_end/panels/console/ConsolePrompt.ts +2 -2
  127. package/front_end/panels/console/ConsoleView.ts +1 -1
  128. package/front_end/panels/console/SymbolizedErrorWidget.ts +2 -1
  129. package/front_end/panels/console_counters/WarningErrorCounter.ts +2 -2
  130. package/front_end/panels/coverage/CoverageListView.ts +28 -28
  131. package/front_end/panels/coverage/CoverageModel.ts +2 -1
  132. package/front_end/panels/coverage/CoverageView.ts +22 -22
  133. package/front_end/panels/coverage/coverage-meta.ts +5 -5
  134. package/front_end/panels/css_overview/CSSOverviewCompletedView.ts +36 -36
  135. package/front_end/panels/css_overview/CSSOverviewProcessingView.ts +1 -1
  136. package/front_end/panels/css_overview/CSSOverviewSidebarPanel.ts +2 -2
  137. package/front_end/panels/css_overview/CSSOverviewStartView.ts +6 -6
  138. package/front_end/panels/css_overview/CSSOverviewUnusedDeclarations.ts +6 -6
  139. package/front_end/panels/css_overview/css_overview-meta.ts +2 -2
  140. package/front_end/panels/developer_resources/DeveloperResourcesListView.ts +1 -1
  141. package/front_end/panels/elements/AccessibilityTreeUtils.ts +8 -102
  142. package/front_end/panels/elements/AccessibilityTreeView.ts +163 -70
  143. package/front_end/panels/elements/ElementsPanel.ts +17 -11
  144. package/front_end/panels/elements/ElementsTreeElement.ts +4 -1
  145. package/front_end/panels/elements/ElementsTreeOutline.ts +4 -4
  146. package/front_end/panels/elements/LayoutPane.ts +1 -1
  147. package/front_end/panels/elements/MetricsSidebarPane.ts +100 -34
  148. package/front_end/panels/elements/StylePropertiesSection.ts +2 -2
  149. package/front_end/panels/elements/StylePropertyTreeElement.ts +8 -2
  150. package/front_end/panels/elements/StylesSidebarPane.ts +1 -1
  151. package/front_end/panels/elements/components/AccessibilityTreeNode.ts +7 -18
  152. package/front_end/panels/elements/components/ElementsBreadcrumbs.ts +2 -2
  153. package/front_end/panels/elements/components/QueryContainer.ts +1 -1
  154. package/front_end/panels/issues/AffectedDirectivesView.ts +1 -1
  155. package/front_end/panels/issues/AffectedResourcesView.ts +2 -1
  156. package/front_end/panels/layer_viewer/LayerViewHost.ts +1 -1
  157. package/front_end/panels/network/NetworkDataGridNode.ts +124 -36
  158. package/front_end/panels/network/NetworkLogView.ts +9 -1
  159. package/front_end/panels/network/NetworkLogViewColumns.ts +18 -0
  160. package/front_end/panels/network/NetworkPanel.ts +2 -1
  161. package/front_end/panels/network/RequestPayloadView.ts +53 -7
  162. package/front_end/panels/network/RequestPreviewView.ts +7 -1
  163. package/front_end/panels/network/components/ResponseHeaderSection.ts +1 -1
  164. package/front_end/panels/network/forward/UIFilter.ts +1 -0
  165. package/front_end/panels/network/requestPayloadView.css +10 -0
  166. package/front_end/panels/performance_monitor/PerformanceMonitor.ts +12 -12
  167. package/front_end/panels/performance_monitor/performance_monitor-meta.ts +7 -7
  168. package/front_end/panels/profiler/HeapDetachedElementsView.ts +2 -2
  169. package/front_end/panels/profiler/HeapProfileView.ts +563 -51
  170. package/front_end/panels/profiler/HeapSnapshotView.ts +13 -8
  171. package/front_end/panels/profiler/ProfilesPanel.ts +13 -7
  172. package/front_end/panels/profiler/WritableProfileHeader.ts +152 -0
  173. package/front_end/panels/profiler/profiler.ts +2 -2
  174. package/front_end/panels/recorder/RecorderController.ts +14 -15
  175. package/front_end/panels/recorder/components/CreateRecordingView.ts +11 -11
  176. package/front_end/panels/recorder/components/ExtensionView.ts +74 -83
  177. package/front_end/panels/recorder/components/RecordingListView.ts +3 -3
  178. package/front_end/panels/recorder/components/RecordingView.ts +13 -10
  179. package/front_end/panels/recorder/components/ReplaySection.ts +9 -9
  180. package/front_end/panels/recorder/components/StepEditor.ts +352 -321
  181. package/front_end/panels/recorder/components/StepView.ts +36 -37
  182. package/front_end/panels/recorder/components/recordingView.css +1 -1
  183. package/front_end/panels/recorder/models/RecorderSettings.ts +2 -2
  184. package/front_end/panels/recorder/recorder-meta.ts +7 -7
  185. package/front_end/panels/screencast/ScreencastApp.ts +1 -1
  186. package/front_end/panels/screencast/ScreencastView.ts +12 -12
  187. package/front_end/panels/search/SearchResultsPane.ts +4 -4
  188. package/front_end/panels/search/SearchView.ts +20 -20
  189. package/front_end/panels/security/SecurityModel.ts +7 -7
  190. package/front_end/panels/security/SecurityPanel.ts +99 -107
  191. package/front_end/panels/security/SecurityPanelSidebar.ts +7 -7
  192. package/front_end/panels/security/security-meta.ts +2 -2
  193. package/front_end/panels/sensors/LocationsSettingsTab.ts +19 -19
  194. package/front_end/panels/sensors/SensorsView.ts +27 -27
  195. package/front_end/panels/sensors/sensors-meta.ts +13 -167
  196. package/front_end/panels/settings/AISettingsTab.ts +98 -56
  197. package/front_end/panels/settings/EditFileSystemView.ts +2 -2
  198. package/front_end/panels/settings/FrameworkIgnoreListSettingsTab.ts +20 -20
  199. package/front_end/panels/settings/KeybindsSettingsTab.ts +20 -21
  200. package/front_end/panels/settings/SettingsScreen.ts +11 -11
  201. package/front_end/panels/settings/WorkspaceSettingsTab.ts +5 -5
  202. package/front_end/panels/settings/components/SyncSection.ts +12 -12
  203. package/front_end/panels/settings/emulation/DevicesSettingsTab.ts +13 -13
  204. package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +31 -31
  205. package/front_end/panels/settings/emulation/emulation-meta.ts +1 -1
  206. package/front_end/panels/settings/settings-meta.ts +14 -14
  207. package/front_end/panels/sources/NavigatorView.ts +7 -6
  208. package/front_end/panels/sources/ScopeChainSidebarPane.ts +83 -37
  209. package/front_end/panels/sources/SourcesNavigator.ts +20 -18
  210. package/front_end/panels/sources/SourcesView.ts +10 -1
  211. package/front_end/panels/sources/scopeChainSidebarPane.css +12 -4
  212. package/front_end/panels/sources/sources-meta.ts +4 -4
  213. package/front_end/panels/timeline/CompatibilityTracksAppender.ts +5 -2
  214. package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +2 -1
  215. package/front_end/panels/timeline/TimelineFlameChartNetworkDataProvider.ts +2 -1
  216. package/front_end/panels/timeline/TimelineFlameChartView.ts +1 -1
  217. package/front_end/panels/timeline/TimelinePanel.ts +2 -1
  218. package/front_end/panels/timeline/TimelineUIUtils.ts +5 -2
  219. package/front_end/panels/timeline/components/NetworkRequestDetails.ts +4 -2
  220. package/front_end/panels/timeline/components/NetworkRequestTooltip.ts +4 -2
  221. package/front_end/panels/timeline/components/insights/ImageRef.ts +2 -1
  222. package/front_end/panels/utils/utils.ts +7 -3
  223. package/front_end/panels/web_audio/WebAudioView.ts +17 -18
  224. package/front_end/panels/web_audio/web_audio-meta.ts +3 -3
  225. package/front_end/panels/whats_new/ReleaseNoteView.ts +1 -1
  226. package/front_end/panels/whats_new/whats_new-meta.ts +11 -11
  227. package/front_end/third_party/chromium/README.chromium +1 -1
  228. package/front_end/third_party/lit/lib/async-directive.d.ts +2 -1
  229. package/front_end/third_party/lit/lib/async-directive.js +1 -1
  230. package/front_end/third_party/lit/lib/async-directive.js.map +1 -1
  231. package/front_end/third_party/lit/lib/decorators.d.ts +2 -1
  232. package/front_end/third_party/lit/lib/decorators.js.map +1 -1
  233. package/front_end/third_party/lit/lib/directive.d.ts +2 -1
  234. package/front_end/third_party/lit/lib/directive.js.map +1 -1
  235. package/front_end/third_party/lit/lib/directives.d.ts +2 -1
  236. package/front_end/third_party/lit/lib/directives.js +8 -8
  237. package/front_end/third_party/lit/lib/directives.js.map +1 -1
  238. package/front_end/third_party/lit/lib/lit.d.ts +2 -1
  239. package/front_end/third_party/lit/lib/lit.js +1 -1
  240. package/front_end/third_party/lit/lib/lit.js.map +1 -1
  241. package/front_end/third_party/lit/lib/static-html.d.ts +2 -1
  242. package/front_end/third_party/lit/lib/static-html.js +1 -1
  243. package/front_end/third_party/lit/lib/static-html.js.map +1 -1
  244. package/front_end/third_party/lit/package.json +2 -2
  245. package/front_end/third_party/lit/rebuild.sh +1 -1
  246. package/front_end/third_party/lit/src/async-directive.ts +5 -0
  247. package/front_end/ui/components/dialogs/Dialog.ts +1 -1
  248. package/front_end/ui/components/dialogs/ShortcutDialog.ts +1 -1
  249. package/front_end/ui/components/diff_view/DiffView.ts +2 -2
  250. package/front_end/ui/components/issue_counter/IssueCounter.ts +3 -3
  251. package/front_end/ui/components/issue_counter/IssueLinkIcon.ts +5 -5
  252. package/front_end/ui/components/lists/List.ts +2 -2
  253. package/front_end/ui/components/panel_feedback/PreviewToggle.ts +1 -1
  254. package/front_end/ui/components/request_link_icon/RequestLinkIcon.ts +5 -5
  255. package/front_end/ui/components/settings/SettingCheckbox.ts +1 -1
  256. package/front_end/ui/components/snackbars/Snackbar.ts +1 -1
  257. package/front_end/ui/components/survey_link/SurveyLink.ts +3 -3
  258. package/front_end/ui/components/text_editor/config.ts +2 -2
  259. package/front_end/ui/components/tree_outline/TreeOutline.ts +34 -1
  260. package/front_end/ui/legacy/ReportView.ts +5 -0
  261. package/front_end/ui/legacy/Treeoutline.ts +3 -0
  262. package/front_end/ui/legacy/View.ts +1 -1
  263. package/front_end/ui/legacy/components/data_grid/DataGrid.ts +2 -0
  264. package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +8 -3
  265. package/front_end/ui/legacy/components/data_grid/data_grid.ts +1 -0
  266. package/front_end/ui/legacy/components/object_ui/ObjectPopoverHelper.ts +1 -1
  267. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +100 -36
  268. package/front_end/ui/legacy/components/source_frame/ResourceSourceFrame.ts +7 -1
  269. package/front_end/ui/legacy/components/utils/ImagePreview.ts +4 -2
  270. package/front_end/ui/legacy/inspectorCommon.css +5 -0
  271. package/front_end/ui/visual_logging/KnownContextValues.ts +3 -0
  272. package/mcp/mcp.ts +2 -0
  273. package/package.json +4 -4
  274. package/front_end/panels/profiler/ProfileView.ts +0 -611
@@ -1,22 +1,18 @@
1
1
  ---
2
2
  name: devtools-migrate-chromium-test
3
- description: Use when migrating chromium `third_party/blink/web_tests/http/tests/devtools/` tests to modern unit tests in `third_party/devtools-frontend/src/front_end/`.
3
+ description: Use when migrating Chromium layout tests to DevTools unit tests
4
4
  ---
5
5
 
6
- # Migrating Legacy DevTools Tests
7
-
8
- The skill should be used from within a Chromium check out. The agent should make a devtools CL for the changes in `third_party/devtools-frontend`.
9
-
10
6
  ## Workflow
11
7
 
12
8
  1. **Identify the Test to Move**:
13
9
 
14
- - Locate the legacy test file (usually `.js`) and its expectation file (`-expected.txt`) in `third_party/blink/web_tests/http/tests/devtools/`.
15
- - Example: `unit/datagrid-editable-longtext.js`
10
+ - You should have already received the issue ID, the test title, and the exact local paths of the downloaded legacy test file (`.js`) and its expectation file (`-expected.txt`) in your initial prompt.
11
+ - Refer to these local copies as you write the new modern test.
16
12
 
17
13
  2. **Identify the Target Location**:
18
14
 
19
- - Find the file being tested in `third_party/devtools-frontend/src/front_end/`.
15
+ - Find the file being tested in `front_end/`.
20
16
  - Place the new test file next to the file being tested, following the naming convention `[FileName].test.ts`.
21
17
  - Example: If testing `ui/legacy/components/data_grid/DataGrid.ts`, the test should be `ui/legacy/components/data_grid/DataGrid.test.ts`.
22
18
 
@@ -35,21 +31,23 @@ The skill should be used from within a Chromium check out. The agent should make
35
31
 
36
32
  5. **Verify the Changes**:
37
33
 
38
- - Build the unittests target: `autoninja -C out/Default <target_path>:unittests`
39
- - Run the test using the DevTools test runner: `npm run test -- <relative_path_to_test>`
34
+ - Use the `verification` skill to correctly build the project and run the new test.
40
35
  - Ensure the test passes.
41
36
 
42
- 6. **Clean Up**:
37
+ 6. **Evaluate Test Completeness and Utility**:
43
38
 
44
- - Delete the original legacy test file and its expectation file from `third_party/blink/web_tests/...`.
45
- - _(Optional)_ If instructed by the user, you may leave the files or handle them differently.
39
+ - Critically review the newly created test to ensure it provides meaningful coverage. Cross-reference it with the original Chromium layout test to verify that all original behaviors, edge cases, and assertions have been fully migrated and are actively being tested.
40
+ - If the newly added test does not test any logic from the component but just the getters from the mocked data explain to the user that this test does not add value and it's better to close it without adding the test. Provide a command without executing it to close the issue as "Fixed".
41
+ - If the newly added test uses too extensive mocks of CDP objects and methods explain to the user that the test should be foundation e2e test instead of unit test and we won't migrate it. Provide a command without executing it to close the issue as "Won't Fix (Infeasible)".
42
+
43
+ 7. Upload a CL with your changes using the `version-control` skill. Make sure the CL description has a `Fixed: <issue number>` trailer instead of `Bug: <issue number>`.
46
44
 
47
45
  ## Example Conversion
48
46
 
49
47
  ### Legacy Test (`datagrid-editable-longtext.js`)
50
48
 
51
49
  ```javascript
52
- import { TestRunner } from 'test_runner';
50
+ import {TestRunner} from 'test_runner';
53
51
  import * as DataGrid from 'devtools/ui/legacy/components/data_grid/data_grid.js';
54
52
 
55
53
  (async function () {
@@ -65,8 +63,8 @@ import * as DataGrid from 'devtools/ui/legacy/components/data_grid/data_grid.js'
65
63
 
66
64
  ```typescript
67
65
  import * as DataGrid from './data_grid.js';
68
- import { renderElementIntoDOM } from '../../../../testing/DOMHelpers.js';
69
- import { describeWithEnvironment } from '../../../../testing/EnvironmentHelpers.js';
66
+ import {renderElementIntoDOM} from '../../../../testing/DOMHelpers.js';
67
+ import {describeWithEnvironment} from '../../../../testing/EnvironmentHelpers.js';
70
68
 
71
69
  describeWithEnvironment('DataGrid', () => {
72
70
  it('tests long text in datagrid', () => {
@@ -86,59 +84,6 @@ describeWithEnvironment('DataGrid', () => {
86
84
  - **Ignoring Environment Failures**: In some environments, `npm run test` may exit with code 1 due to memory leaks (e.g., `WebFrame LEAKED`) or infrastructure issues (e.g., `gpkg` or `Corp Airlock` logs), even if the tests themselves passed. Always check the end of the test log for `TOTAL: X SUCCESS` to confirm if the test logic was successful.
87
85
  - **Rendering issue**: If you encounter an issue where checking values never gives correct information it may be due to async rendering. To resolve that you may trying using `raf()` from `front_end/testing/DOMHelpers.ts` to wait for the next rendering cycle.
88
86
 
89
- ## Creating a DevTools CL from a Chromium Checkout
90
-
91
- To create a DevTools Change List (CL) from a Chromium checkout, you'll be working within the devtools-frontend repository, which is located inside your Chromium source tree. The depot_tools package (which includes git cl) must be in your PATH.
92
-
93
- Here's the typical workflow:
94
-
95
- 1. **Navigate to the DevTools Frontend Directory**:
96
- The DevTools frontend code resides in `third_party/devtools-frontend/src/` within your Chromium checkout (`chromium/src`).
97
-
98
- ```bash
99
- cd path/to/chromium/src/third_party/devtools-frontend/src/
100
- ```
101
-
102
- 2. **Create a New Branch**:
103
- It's best practice to create a new branch for your changes:
104
-
105
- ```bash
106
- git new-branch my-devtools-feature
107
- ```
108
-
109
- (Or use `git checkout -b my-devtools-feature`)
110
-
111
- 3. **Make Your Code Changes**:
112
- Edit the files as needed for your feature or bug fix.
113
-
114
- 4. **Commit Changes Locally**:
115
- Stage and commit your changes using standard Git commands:
116
-
117
- ```bash
118
- git add .
119
- git commit -m "My DevTools feature description"
120
- ```
121
-
122
- _See the Chromium guide on commit messages for best practices on formatting descriptions, including the use of tags like Bug:. _
123
-
124
- 5. **Upload the CL for Review**:
125
- Use `git cl upload` to send your changes to the Chromium Gerrit code review system:
126
-
127
- ```bash
128
- git cl upload
129
- ```
130
-
131
- This command will create a CL on `https://chromium-review.googlesource.com`. Follow the prompts to add a description, reviewers, etc. You can also add reviewers and trigger builds through the Gerrit web UI.
132
-
133
- 6. **Code Review Process**:
134
- Your CL will be reviewed by DevTools owners. You may need to address feedback by amending your commit and uploading new patch sets using `git cl upload` again. Once approved, you can land the change via the Commit Queue (CQ).
135
-
136
- ### Working on Changes Across DevTools and Chromium Core
137
-
138
- - DevTools frontend (`third_party/devtools-frontend/src/`) and the main Chromium codebase (`chromium/src`) are distinct Git repositories.
139
- - If your work involves changes in both areas, you generally need to create separate CLs: one within the devtools-frontend repo and one within the main `chromium/src` repo.
140
- - The "Juggling the git submodules" section of the DevTools documentation provides guidance on managing these cross-repository changes.
141
-
142
87
  ## After finishing the migration
143
88
 
144
- Identify any helping tips that you discovered during the migration and add them to this skill.
89
+ If you encountered any novel issues, workarounds, or helpful tips during the migration that are not already documented, please report them to the user so they can be added to the skill documentation.
@@ -11,7 +11,8 @@ DevTools views into declarative `UI.Widget` components based on lit-html,
11
11
  managing a multi-pass sequential CL pipeline to ensure each code modification is
12
12
  small, testable, and highly reviewable.
13
13
 
14
- Refer to [ui_engineering.md](../../../docs/ui_engineering.md) for general principles.
14
+ Refer to [ui_engineering.md](../../../docs/ui_engineering.md) for general
15
+ principles.
15
16
 
16
17
  --------------------------------------------------------------------------------
17
18
 
@@ -28,9 +29,12 @@ Refer to [ui_engineering.md](../../../docs/ui_engineering.md) for general princi
28
29
  file matches older patterns or generic examples. Always perform a structure
29
30
  analysis of the active file first and adapt the plan to the actual, current
30
31
  code.
31
- 4. **Hybrid Files**: Files may contain multiple classes in different states of
32
- modernization (e.g., one partially migrated class and one fully legacy
33
- class). Propose modifications only for classes with actual violations.
32
+ 4. **Hybrid Files/Multiple Classes**: Files may contain multiple classes in
33
+ different states of modernization (e.g., one partially migrated class and
34
+ one fully legacy class). If the file being migrated contains several
35
+ classes, the migration needs to be done separately for each class, starting
36
+ with the leaves and going up the dependency chain. Propose modifications
37
+ only for classes with actual violations.
34
38
  5. **Coupling Analysis**: Always check the integration files (e.g., sidebar
35
39
  files, parent panel files) where the target class is instantiated to see if
36
40
  there are any direct `.element` or `.contentElement` couplings. If found,
@@ -43,12 +47,21 @@ Refer to [ui_engineering.md](../../../docs/ui_engineering.md) for general princi
43
47
  single responsibility per CL. Do not combine technology migrations (e.g.,
44
48
  converting imperative DOM to Lit-html) with base class refactoring in the
45
49
  same diff.
46
- 8. **Never Break Compilation**: Run a compiler build and execute the DevTools
47
- test suite between every pass.
50
+ 8. **Strict Intermediate Stability**: The code must compile and work correctly,
51
+ and all tests must pass after each step. We should not split the class API
52
+ update from its usage update.
48
53
  9. **Establish Comprehensive Guardrails First**: Ensure both **logic tests**
49
- (verifying presenter interactions and state updates) and **screenshot tests**
50
- (verifying layout/styling) exist before rewriting code. If coverage is
51
- missing, scaffold it first.
54
+ (verifying presenter interactions and state updates) and **screenshot
55
+ tests** (verifying layout/styling) exist before rewriting code. If coverage
56
+ is missing, scaffold it first.
57
+ 10. **Pre-flight Clarification**: Before starting, verify if the task is
58
+ underspecified or ambiguous. If so, point this out and ask for
59
+ clarifications before proceeding.
60
+ 11. **Step Sizing & Complexity Assessment**: Assess the complexity of each step
61
+ beforehand. Aim for intermediate steps that involve changing or adding
62
+ roughly 300 lines of code. If a step is predicted to be too complex, break
63
+ it down into smaller substeps. The agent must stop and report back after
64
+ each step or substep to allow verification.
52
65
 
53
66
  --------------------------------------------------------------------------------
54
67
 
@@ -57,17 +70,22 @@ Refer to [ui_engineering.md](../../../docs/ui_engineering.md) for general princi
57
70
  ### Plan Generation (Gated)
58
71
 
59
72
  * **Actions**:
60
- 1. Scan the target file to determine size, complexity, legacy elements
73
+ 1. Verify if the task is underspecified or ambiguous. If so, ask for
74
+ clarifications first.
75
+ 2. Scan the target file to determine size, complexity, legacy elements
61
76
  (e.g., `ReportView`, `ToolbarButton`, `DataGrid`, `TreeOutline`), and
62
77
  actual class inheritance. Deconstruct the file mentally (or in the plan)
63
78
  into **Business Logic** (state, event handlers) and **Rendering Logic**
64
79
  (DOM creation, CSS classes). Reference code elements by **Name** (not
65
80
  line numbers) to ensure the plan remains valid as the codebase evolves.
66
- Check if the class dependencies have been migrated to the ui eng vision or not.
67
- 2. Check the files depending on this file, to understand how the code in
81
+ Check if the class dependencies have been migrated to the ui eng vision
82
+ or not. If the file contains multiple classes, plan the migration
83
+ separately for each class, starting with the leaves and going up the
84
+ dependency chain.
85
+ 3. Check the files depending on this file, to understand how the code in
68
86
  this file is being used.
69
- 3. **Dynamic Ordering Decision**: Determine whether to run
70
- Logic Consolidation first or Local lit-html rendering first:
87
+ 4. **Dynamic Ordering Decision**: Determine whether to run Logic
88
+ Consolidation first or Local lit-html rendering first:
71
89
  * **Option A (Logic First)**: Choose this if the component has a
72
90
  complex, nested state model or highly coupled event-handlers.
73
91
  Consolidating the state variables and defining the `ViewInput`
@@ -78,9 +96,9 @@ Refer to [ui_engineering.md](../../../docs/ui_engineering.md) for general princi
78
96
  DOM construction. Converting the layout to declarative Lit templates
79
97
  first (using temporary inline or local state) makes it much easier
80
98
  to isolate and group the remaining state updates afterward.
81
- 4. Generate a `migration_plan.md` reflecting this ordering and outlining
99
+ 5. Generate a `migration_plan.md` reflecting this ordering and outlining
82
100
  the target steps.
83
- 5. Halt execution and print the formatted plan in Markdown to the chat.
101
+ 6. Halt execution and print the formatted plan in Markdown to the chat.
84
102
  Wait for user approval.
85
103
 
86
104
  ### Baseline & Safety Scaffolding
@@ -90,8 +108,9 @@ Refer to [ui_engineering.md](../../../docs/ui_engineering.md) for general princi
90
108
  * **Subskill to Import**: `ui-eng-vision-test-scaffolder`
91
109
  * **Actions**:
92
110
  1. Verify existing test coverage. Propose and add missing **logic tests**
93
- for interactions and **screenshot tests** for visual validation to avoid regressions.
94
- 2. Pay extra attention not to skip this step.
111
+ for interactions and **screenshot tests** for visual validation to avoid
112
+ regressions.
113
+ 2. Pay extra attention not to skip this step.
95
114
 
96
115
  ### Logic Consolidation
97
116
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: devtools-version-control
3
- description: Use when starting a new task, creating a branch, switching branches, managing branches, creating and uploading CLs, or handling stacked changes in the DevTools Gerrit-based workflow. ALWAYS use this instead of running standard git checkout/switch commands for branch creation.
3
+ description: Use when starting a new task, creating a branch, switching branches, managing branches, creating and uploading CLs, handling stacked changes, or checking release and roll status in the DevTools Gerrit-based workflow. ALWAYS use this instead of running standard git checkout/switch commands for branch creation.
4
4
  ---
5
5
 
6
6
  # DevTools Version Control
@@ -73,6 +73,12 @@ To upload an updated CL:
73
73
  git cl upload -d -t "<one sentence patch set description>"
74
74
  ```
75
75
 
76
+ ## Release and Roll Status
77
+
78
+ To check whether a DevTools commit (`devtools/devtools-frontend`) has rolled into `chromium/src` (`Roll status`) and what version or channel it is deployed to (`Release status`), look it up via the Chromium Dash API:
79
+
80
+ `https://chromiumdash.appspot.com/fetch_commit?commit=<sha>`
81
+
76
82
  ## Quick Reference
77
83
 
78
84
  | Action | Command |
@@ -83,6 +89,7 @@ git cl upload -d -t "<one sentence patch set description>"
83
89
  | Upload to Gerrit | `git cl upload` |
84
90
  | Change branch parent | `git reparent-branch <new-parent>` |
85
91
  | Sync all branches | `git rebase-update` |
92
+ | Check release & roll status | Query `https://chromiumdash.appspot.com/fetch_commit?commit=<sha>` |
86
93
 
87
94
  ## Common Mistakes
88
95
  - **Multiple commits on one branch:** Gerrit expects one commit per CL. Always `commit --amend`.
package/AUTHORS CHANGED
@@ -82,6 +82,7 @@ Nourhan Hasan <nourhan.m.hasan@gmail.com>
82
82
  Paras Awasthi <awasthiparas6@gmail.com>
83
83
  Paul Fisher <paul@pfish.zone>
84
84
  Peng Zhou <zhoupeng.1996@bytedance.com>
85
+ Percy Wang <a945970854@gmail.com>
85
86
  Per-Olov Jernberg <possan@possan.se>
86
87
  PhistucK <phistuck@gmail.com>
87
88
  Pradhuman Singh Baid <pradhumansinghbaid@gmail.com>
package/SECURITY.md CHANGED
@@ -54,3 +54,6 @@ Chrome DevTools is a privileged web app running in a sandboxed renderer process,
54
54
 
55
55
  ### Side-Effect Free Evaluation
56
56
  * Side-effect free JavaScript evaluation is a best-effort developer heuristic to prevent accidental state changes, not a security boundary. Bypassing it to cause side effects on the debugged page is not a vulnerability.
57
+
58
+ ### Self-XSS Paste Gate
59
+ * The self-XSS paste gate is not a security boundary. It is supposed to reduce the chance for abuse, not to fully prevent it. Issues around bypassing it are social engineering, and outside of our threat model.
@@ -499,3 +499,9 @@ ln -s src/third_party/devtools-frontend/src devtools-frontend
499
499
  If you did run `gclient sync` first, remove the devtools-frontend directory and start over.
500
500
 
501
501
  Run `gclient sync` after creating the link to fetch the dependencies for the standalone checkout.
502
+
503
+ ### Known issues
504
+
505
+ - GN/Siso wrappers in `depot_tools` don't assume the side-by-side solutions, and
506
+ always use the binaries in Chromium. Please make sure updating Chromium when
507
+ you get a build error.
@@ -496,8 +496,8 @@
496
496
 
497
497
  TestSuite.prototype.testConsoleOnNavigateBack = function() {
498
498
  function filteredMessages() {
499
- return SDK.ConsoleModel.ConsoleModel.allMessagesUnordered().filter(
500
- a => a.source !== Protocol.Log.LogEntrySource.Violation);
499
+ return SDK.ConsoleModel.ConsoleModel.allMessagesUnordered(SDK.TargetManager.TargetManager.instance())
500
+ .filter(a => a.source !== Protocol.Log.LogEntrySource.Violation);
501
501
  }
502
502
 
503
503
  if (filteredMessages().length === 1) {
@@ -710,7 +710,7 @@
710
710
  SDK.TargetManager.TargetManager.instance().addModelListener(
711
711
  SDK.ConsoleModel.ConsoleModel, SDK.ConsoleModel.Events.MessageAdded, onConsoleMessage, this);
712
712
 
713
- const messages = SDK.ConsoleModel.ConsoleModel.allMessagesUnordered();
713
+ const messages = SDK.ConsoleModel.ConsoleModel.allMessagesUnordered(SDK.TargetManager.TargetManager.instance());
714
714
  if (messages.length) {
715
715
  const text = messages[0].messageText;
716
716
  this.assertEquals('ready', text);
@@ -976,7 +976,7 @@
976
976
  TestSuite.prototype.testWindowInitializedOnNavigateBack = function() {
977
977
  const test = this;
978
978
  test.takeControl();
979
- const messages = SDK.ConsoleModel.ConsoleModel.allMessagesUnordered();
979
+ const messages = SDK.ConsoleModel.ConsoleModel.allMessagesUnordered(SDK.TargetManager.TargetManager.instance());
980
980
  if (messages.length === 1) {
981
981
  checkMessages();
982
982
  } else {
@@ -985,7 +985,7 @@
985
985
  }
986
986
 
987
987
  function checkMessages() {
988
- const messages = SDK.ConsoleModel.ConsoleModel.allMessagesUnordered();
988
+ const messages = SDK.ConsoleModel.ConsoleModel.allMessagesUnordered(SDK.TargetManager.TargetManager.instance());
989
989
  test.assertEquals(1, messages.length);
990
990
  test.assertTrue(messages[0].messageText.indexOf('Uncaught') === -1);
991
991
  test.releaseControl();
@@ -1062,7 +1062,7 @@
1062
1062
  };
1063
1063
 
1064
1064
  TestSuite.prototype.waitForTestResultsInConsole = function() {
1065
- const messages = SDK.ConsoleModel.ConsoleModel.allMessagesUnordered();
1065
+ const messages = SDK.ConsoleModel.ConsoleModel.allMessagesUnordered(SDK.TargetManager.TargetManager.instance());
1066
1066
  for (let i = 0; i < messages.length; ++i) {
1067
1067
  const text = messages[i].messageText;
1068
1068
  if (text === 'PASS') {
@@ -38,24 +38,31 @@ export async function fileToString(file: File): Promise<string> {
38
38
  * Consider using `arrayBufferToString` instead, which can handle both gzipped and plain text buffers.
39
39
  */
40
40
  export async function decompress(gzippedBuffer: ArrayBufferLike, charset = 'utf-8'): Promise<string> {
41
- const buffer = await gzipCodec(gzippedBuffer, new DecompressionStream('gzip'));
41
+ const buffer = await decompressToBuffer(gzippedBuffer);
42
42
  const str = new TextDecoder(charset).decode(buffer);
43
43
  return str;
44
44
  }
45
45
 
46
+ export async function decompressToBuffer(gzippedBuffer: ArrayBufferLike): Promise<ArrayBuffer> {
47
+ return await gzipCodec(gzippedBuffer, new DecompressionStream('gzip'));
48
+ }
49
+
46
50
  /**
47
51
  * Decompress a deflate-encoded ArrayBuffer to a string.
48
52
  * Tries 'deflate' (zlib wrapper) first, then falls back to 'deflate-raw'.
49
53
  */
50
54
  export async function decompressDeflate(buffer: ArrayBufferLike, charset = 'utf-8'): Promise<string> {
51
- let decompressedBuffer: ArrayBuffer;
55
+ const decompressedBuffer = await decompressDeflateToBuffer(buffer);
56
+ return new TextDecoder(charset).decode(decompressedBuffer);
57
+ }
58
+
59
+ export async function decompressDeflateToBuffer(buffer: ArrayBufferLike): Promise<ArrayBuffer> {
52
60
  try {
53
- decompressedBuffer = await gzipCodec(buffer, new DecompressionStream('deflate'));
61
+ return await gzipCodec(buffer, new DecompressionStream('deflate'));
54
62
  } catch {
55
63
  // Try deflate-raw format if zlib-wrapped deflate fails.
56
- decompressedBuffer = await gzipCodec(buffer, new DecompressionStream('deflate-raw'));
64
+ return await gzipCodec(buffer, new DecompressionStream('deflate-raw'));
57
65
  }
58
- return new TextDecoder(charset).decode(decompressedBuffer);
59
66
  }
60
67
  export async function compress(str: string): Promise<ArrayBuffer> {
61
68
  const encoded = new TextEncoder().encode(str);
@@ -63,6 +63,7 @@ const AidaLanguageToMarkdown: Record<AidaInferenceLanguage, string> = {
63
63
 
64
64
  export class AidaAbortError extends Error {}
65
65
  export class AidaBlockError extends Error {}
66
+ export class AidaQuotaError extends Error {}
66
67
 
67
68
  interface AiStream {
68
69
  write: (data: string) => Promise<void>;
@@ -185,12 +186,23 @@ export class AidaClient {
185
186
  debugLog('doConversation failed with error:', JSON.stringify(err));
186
187
  if (err instanceof DispatchHttpRequestClient.DispatchHttpRequestError && err.response) {
187
188
  const result = err.response;
189
+ if (result.statusCode === 429) {
190
+ stream.fail(new AidaQuotaError('Server responded: quota exceeded'));
191
+ return;
192
+ }
188
193
  if (result.statusCode === 403) {
189
194
  stream.fail(new Error('Server responded: permission denied'));
190
195
  return;
191
196
  }
192
197
  if ('error' in result && result.error) {
193
- stream.fail(new Error(`Cannot send request: ${result.error} ${result.detail || ''}`));
198
+ const errorStr = typeof result.error === 'string' ? result.error : '';
199
+ const detailStr = typeof result.detail === 'string' ? result.detail : '';
200
+ if (errorStr.toLowerCase().includes('quota') || detailStr.toLowerCase().includes('quota')) {
201
+ stream.fail(new AidaQuotaError(
202
+ `Cannot send request: ${result.error}${result.detail ? ` ${result.detail}` : ''}`));
203
+ return;
204
+ }
205
+ stream.fail(new Error(`Cannot send request: ${result.error}${result.detail ? ` ${result.detail}` : ''}`));
194
206
  return;
195
207
  }
196
208
  if ('netErrorName' in result && result.netErrorName === 'net::ERR_TIMED_OUT') {
@@ -249,6 +261,9 @@ export class AidaClient {
249
261
  thoughtSignature: result.functionCallChunk.functionCall.thoughtSignature,
250
262
  });
251
263
  } else if ('error' in result) {
264
+ if (typeof result.error === 'string' && result.error.toLowerCase().includes('quota')) {
265
+ throw new AidaQuotaError(`Server responded: ${JSON.stringify(result)}`);
266
+ }
252
267
  throw new Error(`Server responded: ${JSON.stringify(result)}`);
253
268
  } else {
254
269
  throw new Error(`Unknown chunk result ${JSON.stringify(result)}`);
@@ -435,21 +450,32 @@ export function getClientFeatureName(feature: ClientFeature): string {
435
450
  return name;
436
451
  }
437
452
 
438
- let hostConfigTrackerInstance: HostConfigTracker|undefined;
439
-
440
453
  export class HostConfigTracker extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
441
454
  #pollTimer?: ReturnType<typeof setTimeout>;
442
455
  #aidaAvailability?: AidaAccessPreconditions;
443
456
 
444
- private constructor() {
445
- super();
457
+ static instance({forceNew}: {
458
+ forceNew: boolean,
459
+ } = {forceNew: false}): HostConfigTracker {
460
+ if (!Root.DevToolsContext.globalInstance().has(HostConfigTracker) || forceNew) {
461
+ Root.DevToolsContext.globalInstance().set(
462
+ HostConfigTracker,
463
+ new HostConfigTracker(),
464
+ );
465
+ }
466
+ return Root.DevToolsContext.globalInstance().get(HostConfigTracker);
467
+ }
468
+
469
+ dispose(): void {
470
+ clearTimeout(this.#pollTimer);
471
+ this.listeners = undefined;
446
472
  }
447
473
 
448
- static instance(): HostConfigTracker {
449
- if (!hostConfigTrackerInstance) {
450
- hostConfigTrackerInstance = new HostConfigTracker();
474
+ static removeInstance(): void {
475
+ if (Root.DevToolsContext.globalInstance().has(HostConfigTracker)) {
476
+ Root.DevToolsContext.globalInstance().get(HostConfigTracker).dispose();
477
+ Root.DevToolsContext.globalInstance().delete(HostConfigTracker);
451
478
  }
452
- return hostConfigTrackerInstance;
453
479
  }
454
480
 
455
481
  override addEventListener(eventType: Events, listener: Common.EventTarget.EventListener<EventTypes, Events>):
@@ -98,21 +98,24 @@ async function makeHttpRequest<R>(request: DispatchHttpRequestRequest): Promise<
98
98
  }
99
99
 
100
100
  const SERVICE_NAME = 'gdpService';
101
- let gdpClientInstance: GdpClient|null = null;
102
101
  export class GdpClient {
103
102
  #cachedProfilePromise?: Promise<Profile>;
104
103
  #cachedEligibilityPromise?: Promise<CheckElibigilityResponse>;
105
104
 
106
- private constructor() {
107
- }
108
-
109
105
  static instance({forceNew}: {
110
106
  forceNew: boolean,
111
107
  } = {forceNew: false}): GdpClient {
112
- if (!gdpClientInstance || forceNew) {
113
- gdpClientInstance = new GdpClient();
108
+ if (!Root.DevToolsContext.globalInstance().has(GdpClient) || forceNew) {
109
+ Root.DevToolsContext.globalInstance().set(
110
+ GdpClient,
111
+ new GdpClient(),
112
+ );
114
113
  }
115
- return gdpClientInstance;
114
+ return Root.DevToolsContext.globalInstance().get(GdpClient);
115
+ }
116
+
117
+ static removeInstance(): void {
118
+ Root.DevToolsContext.globalInstance().delete(GdpClient);
116
119
  }
117
120
 
118
121
  /**
@@ -4,6 +4,8 @@
4
4
 
5
5
  import type {Brand} from './Brand.js';
6
6
 
7
+ let graphemeSegmenter: Intl.Segmenter|null = null;
8
+
7
9
  export const escapeCharacters = (inputString: string, charsToEscape: string): string => {
8
10
  let foundChar = false;
9
11
  for (let i = 0; i < charsToEscape.length; ++i) {
@@ -447,6 +449,39 @@ export const trimEndWithMaxLength = (str: string, maxLength: number): string =>
447
449
  return str.slice(0, lastSegmentIndex) + ellipsis;
448
450
  };
449
451
 
452
+ /**
453
+ * Truncates a string to not exceed a maximum number of UTF-16 code units (as measured by JS `string.length`).
454
+ *
455
+ * Unlike simple character limiters, this helper is grapheme-aware and uses `Intl.Segmenter` to prevent
456
+ * slicing inside surrogate pairs (e.g. Plane 1+ characters or emojis like 'š œŽ' / '🄳') or combining characters
457
+ * (e.g. 'é' represented in NFD as 'e' + combining acute accent). If the limit falls in the middle of a
458
+ * grapheme cluster, the function backs off to drop the entire cluster, ensuring the result is always a valid
459
+ * Unicode string.
460
+ *
461
+ * @param str The string to truncate.
462
+ * @param maxCodeUnits The maximum allowed code unit length (must be >= 0).
463
+ * @returns The truncated string, guaranteed to be <= maxCodeUnits in length and grapheme-safe.
464
+ */
465
+ export const truncateToCodeUnitLength = (str: string, maxCodeUnits: number): string => {
466
+ if (isNaN(maxCodeUnits) || maxCodeUnits <= 0) {
467
+ return '';
468
+ }
469
+ if (str.length <= maxCodeUnits) {
470
+ return str;
471
+ }
472
+ if (!graphemeSegmenter) {
473
+ graphemeSegmenter = new Intl.Segmenter(undefined, {granularity: 'grapheme'});
474
+ }
475
+ let lastSafeIndex = 0;
476
+ for (const {index, segment} of graphemeSegmenter.segment(str)) {
477
+ if (index + segment.length > maxCodeUnits) {
478
+ break;
479
+ }
480
+ lastSafeIndex = index + segment.length;
481
+ }
482
+ return str.slice(0, lastSafeIndex);
483
+ };
484
+
450
485
  export const escapeForRegExp = (str: string): string => {
451
486
  return escapeCharacters(str, SPECIAL_REGEX_CHARACTERS);
452
487
  };
@@ -0,0 +1,17 @@
1
+ Title: AccessibilityModel axNodeToText correctly formats an accessibility node tree to text
2
+ Content:
3
+ dialog "Confirmation"
4
+ button "Submit" focusable: true
5
+ === end content
6
+
7
+ Title: AccessibilityModel axNodeToText correctly formats when the root node is ignored
8
+ Content:
9
+ Ignored
10
+ button "Submit" focusable: true
11
+ === end content
12
+
13
+ Title: AccessibilityModel axNodeToText correctly formats when a nested node is ignored
14
+ Content:
15
+ dialog "Confirmation"
16
+ button "Submit" focusable: true
17
+ === end content