chrome-devtools-frontend 1.0.1660788 → 1.0.1662289

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 (177) hide show
  1. package/.agents/skills/evaluate-ai-css-completion/SKILL.md +143 -0
  2. package/.agents/skills/evaluate-ai-css-completion/scripts/evaluate.js +104 -0
  3. package/.agents/skills/migrate-chromium-test/SKILL.md +7 -2
  4. package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +7 -1
  5. package/docs/ui_engineering.md +75 -42
  6. package/eslint.config.mjs +7 -0
  7. package/extension-api/ExtensionAPI.d.ts +88 -0
  8. package/front_end/core/common/SettingRegistration.ts +0 -5
  9. package/front_end/core/host/InspectorFrontendHost.ts +1 -0
  10. package/front_end/core/host/InspectorFrontendHostStub.ts +2 -0
  11. package/front_end/core/platform/ArrayUtilities.ts +10 -0
  12. package/front_end/core/platform/StringUtilities.ts +20 -4
  13. package/front_end/core/sdk/CPUThrottlingManager.ts +2 -0
  14. package/front_end/core/sdk/DOMDebuggerModel.ts +2 -0
  15. package/front_end/core/sdk/DOMModel.ts +1 -0
  16. package/front_end/core/sdk/DebuggerModel.ts +4 -4
  17. package/front_end/core/sdk/EventBreakpointsModel.ts +2 -0
  18. package/front_end/core/sdk/FrameManager.ts +1 -0
  19. package/front_end/core/sdk/IsolateManager.ts +1 -0
  20. package/front_end/core/sdk/NetworkManager.ts +2 -0
  21. package/front_end/core/sdk/NetworkRequest.ts +1 -0
  22. package/front_end/core/sdk/PageResourceLoader.ts +2 -0
  23. package/front_end/core/sdk/SourceMap.ts +5 -5
  24. package/front_end/core/sdk/SourceMapManager.ts +3 -2
  25. package/front_end/core/sdk/TargetManager.ts +4 -0
  26. package/front_end/entrypoints/main/MainImpl.ts +2 -1
  27. package/front_end/foundation/README.md +86 -0
  28. package/front_end/generated/InspectorBackendCommands.ts +4 -5
  29. package/front_end/generated/protocol.ts +20 -38
  30. package/front_end/models/bindings/CompilerScriptMapping.ts +5 -5
  31. package/front_end/models/bindings/ContentProviderBasedProject.ts +2 -3
  32. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +3 -3
  33. package/front_end/models/bindings/DefaultScriptMapping.ts +3 -3
  34. package/front_end/models/bindings/ResourceMapping.ts +3 -3
  35. package/front_end/models/bindings/ResourceScriptMapping.ts +2 -2
  36. package/front_end/models/bindings/SASSSourceMapping.ts +3 -3
  37. package/front_end/models/bindings/TempFile.ts +8 -3
  38. package/front_end/models/extensions/ExtensionAPI.ts +110 -46
  39. package/front_end/models/extensions/RecorderExtensionEndpoint.ts +7 -5
  40. package/front_end/models/formatter/ScriptFormatter.ts +8 -11
  41. package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +14 -5
  42. package/front_end/models/issues_manager/CheckFormsIssuesTrigger.ts +8 -9
  43. package/front_end/models/issues_manager/CookieIssue.ts +21 -9
  44. package/front_end/models/issues_manager/Issue.ts +3 -4
  45. package/front_end/models/issues_manager/IssueAggregator.ts +0 -9
  46. package/front_end/models/issues_manager/IssueResolver.ts +2 -2
  47. package/front_end/models/issues_manager/IssuesManager.ts +136 -137
  48. package/front_end/models/issues_manager/RelatedIssue.ts +10 -8
  49. package/front_end/models/issues_manager/issues_manager.ts +0 -2
  50. package/front_end/models/javascript_metadata/NativeFunctions.js +1 -1
  51. package/front_end/models/logs/RequestResolver.ts +2 -2
  52. package/front_end/models/source_map_scopes/FunctionCodeResolver.ts +12 -9
  53. package/front_end/models/trace/handlers/FramesHandler.ts +4 -7
  54. package/front_end/models/trace/handlers/ModelHandlers.ts +0 -1
  55. package/front_end/models/trace/handlers/RendererHandler.ts +2 -15
  56. package/front_end/models/trace/handlers/Threads.ts +4 -11
  57. package/front_end/models/trace/insights/DOMSize.ts +1 -1
  58. package/front_end/models/workspace_diff/WorkspaceDiff.ts +10 -4
  59. package/front_end/panels/ai_assistance/components/ChatMessage.ts +2 -1
  60. package/front_end/panels/application/ApplicationPanelSidebar.ts +0 -44
  61. package/front_end/panels/application/CookieItemsView.ts +1 -1
  62. package/front_end/panels/application/ServiceWorkersView.ts +494 -411
  63. package/front_end/panels/application/WebMCPView.ts +38 -43
  64. package/front_end/panels/application/application.ts +0 -6
  65. package/front_end/panels/application/components/AdsView.ts +201 -30
  66. package/front_end/panels/application/components/adsView.css +25 -0
  67. package/front_end/panels/application/components/components.ts +0 -2
  68. package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +1 -1
  69. package/front_end/panels/application/preloading/components/RuleSetDetailsView.ts +2 -2
  70. package/front_end/panels/application/serviceWorkersView.css +40 -4
  71. package/front_end/panels/browser_debugger/XHRBreakpointsSidebarPane.ts +147 -123
  72. package/front_end/panels/common/ExtensionServer.ts +3 -3
  73. package/front_end/panels/console/ConsoleView.ts +3 -2
  74. package/front_end/panels/console/PromptBuilder.ts +2 -1
  75. package/front_end/panels/emulation/DeviceModeView.ts +164 -113
  76. package/front_end/panels/issues/AffectedResourcesView.ts +1 -1
  77. package/front_end/panels/issues/IssueView.ts +0 -2
  78. package/front_end/panels/issues/IssuesPane.ts +1 -8
  79. package/front_end/panels/js_timeline/js_timeline-meta.ts +3 -2
  80. package/front_end/panels/lighthouse/LighthouseProtocolService.ts +53 -12
  81. package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorController.ts +3 -3
  82. package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorPane.ts +5 -5
  83. package/front_end/panels/linear_memory_inspector/components/LinearMemoryHighlightChipList.ts +4 -4
  84. package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +2 -2
  85. package/front_end/panels/linear_memory_inspector/components/LinearMemoryNavigator.ts +6 -6
  86. package/front_end/panels/linear_memory_inspector/components/LinearMemoryValueInterpreter.ts +3 -3
  87. package/front_end/panels/linear_memory_inspector/components/ValueInterpreterDisplay.ts +8 -9
  88. package/front_end/panels/linear_memory_inspector/components/ValueInterpreterDisplayUtils.ts +2 -2
  89. package/front_end/panels/linear_memory_inspector/components/ValueInterpreterSettings.ts +1 -1
  90. package/front_end/panels/linear_memory_inspector/linear_memory_inspector-meta.ts +2 -2
  91. package/front_end/panels/network/RequestPayloadView.ts +92 -52
  92. package/front_end/panels/network/RequestTimingView.ts +95 -127
  93. package/front_end/panels/network/components/ResponseHeaderSection.ts +5 -3
  94. package/front_end/panels/profiler/HeapSnapshotView.ts +3 -3
  95. package/front_end/panels/profiler/WritableProfileHeader.ts +2 -2
  96. package/front_end/panels/recorder/{components/ControlButton.ts → ControlButton.ts} +9 -10
  97. package/front_end/panels/recorder/{components/CreateRecordingView.ts → CreateRecordingView.ts} +48 -47
  98. package/front_end/panels/recorder/{components/ExtensionView.ts → ExtensionView.ts} +8 -8
  99. package/front_end/panels/recorder/RecorderController.ts +302 -127
  100. package/front_end/panels/recorder/RecorderPanel.ts +1 -1
  101. package/front_end/panels/recorder/{components/RecordingListView.ts → RecordingListView.ts} +19 -20
  102. package/front_end/panels/recorder/{components/RecordingView.ts → RecordingView.ts} +88 -88
  103. package/front_end/panels/recorder/{components/ReplaySection.ts → ReplaySection.ts} +11 -11
  104. package/front_end/panels/recorder/{components/SelectorPicker.ts → SelectorPicker.ts} +13 -13
  105. package/front_end/panels/recorder/{components/StepEditor.ts → StepEditor.ts} +15 -15
  106. package/front_end/panels/recorder/{components/StepView.ts → StepView.ts} +10 -10
  107. package/front_end/panels/recorder/{components/TimelineSection.ts → TimelineSection.ts} +2 -2
  108. package/front_end/panels/recorder/recorder.ts +23 -1
  109. package/front_end/panels/recorder/util/util.ts +113 -0
  110. package/front_end/panels/sources/SourcesView.ts +0 -17
  111. package/front_end/panels/sources/TabbedEditorContainer.ts +1 -1
  112. package/front_end/panels/sources/UISourceCodeFrame.ts +42 -0
  113. package/front_end/panels/sources/sources.ts +0 -2
  114. package/front_end/panels/timeline/CompatibilityTracksAppender.ts +0 -17
  115. package/front_end/panels/timeline/IsolateSelector.ts +10 -8
  116. package/front_end/panels/timeline/ThreadAppender.ts +0 -106
  117. package/front_end/panels/timeline/TimelinePanel.ts +18 -7
  118. package/front_end/panels/timeline/TimelineUIUtils.ts +144 -129
  119. package/front_end/panels/timeline/timeline-meta.ts +3 -2
  120. package/front_end/third_party/chromium/README.chromium +1 -1
  121. package/front_end/ui/components/report_view/ReportView.ts +11 -5
  122. package/front_end/ui/components/report_view/report.css +4 -1
  123. package/front_end/ui/legacy/TextPrompt.ts +49 -1
  124. package/front_end/ui/legacy/Treeoutline.ts +3 -0
  125. package/front_end/ui/legacy/UIUtils.ts +11 -1
  126. package/front_end/ui/legacy/Widget.ts +14 -15
  127. package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +2 -2
  128. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +11 -7
  129. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +2 -1
  130. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +10 -1
  131. package/front_end/ui/legacy/textPrompt.css +10 -0
  132. package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
  133. package/package.json +1 -1
  134. package/front_end/models/issues_manager/AttributionReportingIssue.ts +0 -247
  135. package/front_end/models/issues_manager/descriptions/arInsecureContext.md +0 -7
  136. package/front_end/models/issues_manager/descriptions/arInvalidInfoHeader.md +0 -5
  137. package/front_end/models/issues_manager/descriptions/arInvalidRegisterOsSourceHeader.md +0 -5
  138. package/front_end/models/issues_manager/descriptions/arInvalidRegisterOsTriggerHeader.md +0 -5
  139. package/front_end/models/issues_manager/descriptions/arInvalidRegisterSourceHeader.md +0 -5
  140. package/front_end/models/issues_manager/descriptions/arInvalidRegisterTriggerHeader.md +0 -5
  141. package/front_end/models/issues_manager/descriptions/arNavigationRegistrationUniqueScopeAlreadySet.md +0 -5
  142. package/front_end/models/issues_manager/descriptions/arNavigationRegistrationWithoutTransientUserActivation.md +0 -6
  143. package/front_end/models/issues_manager/descriptions/arNoRegisterOsSourceHeader.md +0 -5
  144. package/front_end/models/issues_manager/descriptions/arNoRegisterOsTriggerHeader.md +0 -5
  145. package/front_end/models/issues_manager/descriptions/arNoRegisterSourceHeader.md +0 -5
  146. package/front_end/models/issues_manager/descriptions/arNoRegisterTriggerHeader.md +0 -5
  147. package/front_end/models/issues_manager/descriptions/arNoWebOrOsSupport.md +0 -4
  148. package/front_end/models/issues_manager/descriptions/arOsSourceIgnored.md +0 -18
  149. package/front_end/models/issues_manager/descriptions/arOsTriggerIgnored.md +0 -19
  150. package/front_end/models/issues_manager/descriptions/arPermissionPolicyDisabled.md +0 -8
  151. package/front_end/models/issues_manager/descriptions/arSourceAndTriggerHeaders.md +0 -9
  152. package/front_end/models/issues_manager/descriptions/arSourceIgnored.md +0 -13
  153. package/front_end/models/issues_manager/descriptions/arTriggerIgnored.md +0 -12
  154. package/front_end/models/issues_manager/descriptions/arUntrustworthyReportingOrigin.md +0 -10
  155. package/front_end/models/issues_manager/descriptions/arWebAndOsHeaders.md +0 -11
  156. package/front_end/models/trace/handlers/AuctionWorkletsHandler.ts +0 -183
  157. package/front_end/panels/application/InterestGroupStorageModel.ts +0 -81
  158. package/front_end/panels/application/InterestGroupStorageView.ts +0 -151
  159. package/front_end/panels/application/InterestGroupTreeElement.ts +0 -65
  160. package/front_end/panels/application/components/InterestGroupAccessGrid.ts +0 -135
  161. package/front_end/panels/application/components/interestGroupAccessGrid.css +0 -27
  162. package/front_end/panels/application/interestGroupStorageView.css +0 -9
  163. package/front_end/panels/issues/AttributionReportingIssueDetailsView.ts +0 -182
  164. package/front_end/panels/recorder/components/components.ts +0 -25
  165. package/front_end/panels/recorder/components/util.ts +0 -116
  166. package/front_end/panels/sources/InplaceFormatterEditorAction.ts +0 -149
  167. /package/front_end/panels/recorder/{components/controlButton.css → controlButton.css} +0 -0
  168. /package/front_end/panels/recorder/{components/createRecordingView.css → createRecordingView.css} +0 -0
  169. /package/front_end/panels/recorder/{components/extensionView.css → extensionView.css} +0 -0
  170. /package/front_end/panels/recorder/{components/recordingListView.css → recordingListView.css} +0 -0
  171. /package/front_end/panels/recorder/{components/recordingView.css → recordingView.css} +0 -0
  172. /package/front_end/panels/recorder/{components/replaySection.css → replaySection.css} +0 -0
  173. /package/front_end/panels/recorder/{components/selectorPicker.css → selectorPicker.css} +0 -0
  174. /package/front_end/panels/recorder/{components/startView.css → startView.css} +0 -0
  175. /package/front_end/panels/recorder/{components/stepEditor.css → stepEditor.css} +0 -0
  176. /package/front_end/panels/recorder/{components/stepView.css → stepView.css} +0 -0
  177. /package/front_end/panels/recorder/{components/timelineSection.css → timelineSection.css} +0 -0
@@ -148,12 +148,69 @@ export namespace Chrome {
148
148
 
149
149
  export interface ExtensionSidebarPane extends ExtensionView {
150
150
  setHeight(height: string): void;
151
+
152
+ /**
153
+ * Sets an object to be displayed in the sidebar pane.
154
+ *
155
+ * If a `callback` is provided, it is invoked when the object has been set
156
+ * and the method returns `void`. If no `callback` is provided, the method
157
+ * returns a `Promise`.
158
+ *
159
+ * @param jsonObject The JSON object to display in the pane (as a string).
160
+ * @param rootTitle Optional title of the root node.
161
+ * @param callback Optional callback to be invoked when the object has been set.
162
+ * @returns A Promise that resolves when the object has been set if no callback is
163
+ * provided, otherwise void. Rejects with an error object on failure.
164
+ */
165
+ setObject(jsonObject: string, rootTitle?: string): Promise<void>;
151
166
  setObject(jsonObject: string, rootTitle?: string, callback?: () => unknown): void;
167
+
168
+ /**
169
+ * Evaluates an expression in the context of the inspected page and displays the
170
+ * result in the sidebar pane.
171
+ *
172
+ * If a `callback` is provided, it is invoked when the expression has been evaluated
173
+ * and the method returns `void`. If no `callback` is provided, the method
174
+ * returns a `Promise`.
175
+ *
176
+ * @param expression The expression to evaluate.
177
+ * @param rootTitle Optional title of the root node.
178
+ * @param evaluateOptions Options for evaluating the expression.
179
+ * @param callback Optional callback to be invoked when the expression has been evaluated.
180
+ * @returns A Promise that resolves when the expression has been evaluated if no callback is
181
+ * provided, otherwise void. Rejects with an error object on failure.
182
+ */
183
+ setExpression(expression: string, rootTitle?: string, evaluateOptions?: {
184
+ frameURL?: string,
185
+ useContentScriptContext?: boolean,
186
+ scriptExecutionContext?: string,
187
+ }): Promise<void>;
188
+ setExpression(expression: string, rootTitle?: string, evaluateOptions?: {
189
+ frameURL?: string,
190
+ useContentScriptContext?: boolean,
191
+ scriptExecutionContext?: string,
192
+ },
193
+ callback?: () => unknown): void;
194
+
152
195
  setPage(path: string): void;
153
196
  }
154
197
 
155
198
  export interface PanelWithSidebar {
199
+ /**
200
+ * Creates a sidebar pane in the Elements or Sources panel.
201
+ *
202
+ * If a `callback` is provided, it is invoked with the sidebar pane
203
+ * and the method returns `void`. If no `callback` is provided, the method
204
+ * returns a `Promise`.
205
+ *
206
+ * @param title The title of the sidebar pane.
207
+ * @param callback Optional callback to be invoked when the sidebar pane has been created.
208
+ * @returns A Promise that resolves to the created ExtensionSidebarPane if no callback is
209
+ * provided, otherwise void. Rejects with an error object on failure.
210
+ */
211
+ createSidebarPane(title: string): Promise<ExtensionSidebarPane>;
156
212
  createSidebarPane(title: string, callback?: (result: ExtensionSidebarPane) => unknown): void;
213
+
157
214
  onSelectionChanged: EventSink<() => unknown>;
158
215
  }
159
216
 
@@ -163,7 +220,38 @@ export namespace Chrome {
163
220
  network: NetworkPanel;
164
221
  themeName: string;
165
222
 
223
+ /**
224
+ * Creates an extension panel.
225
+ *
226
+ * If a `callback` is provided, it is invoked with the panel
227
+ * and the method returns `void`. If no `callback` is provided, the method
228
+ * returns a `Promise`.
229
+ *
230
+ * @param title The title of the panel.
231
+ * @param iconPath The path to the icon for the panel.
232
+ * @param pagePath The path to the page for the panel.
233
+ * @param callback Optional callback to be invoked when the panel has been created.
234
+ * @returns A Promise that resolves to the created ExtensionPanel if no callback is
235
+ * provided, otherwise void. Rejects with an error object on failure.
236
+ */
237
+ create(title: string, iconPath: string, pagePath: string): Promise<ExtensionPanel>;
166
238
  create(title: string, iconPath: string, pagePath: string, callback?: (panel: ExtensionPanel) => unknown): void;
239
+
240
+ /**
241
+ * Opens a resource in the Sources panel.
242
+ *
243
+ * If a `callback` is provided, it is invoked when the resource has been opened
244
+ * and the method returns `void`. If no `callback` is provided, the method
245
+ * returns a `Promise`.
246
+ *
247
+ * @param url The URL of the resource.
248
+ * @param lineNumber The line number to highlight.
249
+ * @param columnNumber Optional column number to highlight.
250
+ * @param callback Optional callback to be invoked when the resource has been opened.
251
+ * @returns A Promise that resolves when the resource has been opened if no callback is
252
+ * provided, otherwise void. Rejects with an error object on failure.
253
+ */
254
+ openResource(url: string, lineNumber: number, columnNumber?: number): Promise<void>;
167
255
  openResource(url: string, lineNumber: number, columnNumber?: number, callback?: () => unknown): void;
168
256
 
169
257
  setOpenResourceHandler(
@@ -273,11 +273,6 @@ export interface SettingRegistration {
273
273
  * of the setting to be changed only if the user set it.
274
274
  */
275
275
  userActionCondition?: string;
276
- /**
277
- * The name of the experiment a setting is associated with. Enabling and disabling the declared
278
- * experiment will enable and disable the setting respectively.
279
- */
280
- experiment?: Root.ExperimentNames.ExperimentName;
281
276
  /**
282
277
  * A condition is a function that will make the setting available if it
283
278
  * returns true, and not available, otherwise. Make sure that objects you
@@ -112,6 +112,7 @@ export function isUnderTest(prefs?: Record<string, string>): boolean {
112
112
  return prefs['isUnderTest'] === 'true';
113
113
  }
114
114
  return Common.Settings.Settings.hasInstance() &&
115
+ // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
115
116
  Common.Settings.Settings.instance().createSetting('isUnderTest', false).get();
116
117
  }
117
118
 
@@ -168,11 +168,13 @@ export class InspectorFrontendHostStub implements InspectorFrontendHostAPI {
168
168
  }
169
169
 
170
170
  openSearchResultsInNewTab(_query: string): void {
171
+ // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
171
172
  Common.Console.Console.instance().error(
172
173
  'Search is not enabled in hosted mode. Please inspect using chrome://inspect');
173
174
  }
174
175
 
175
176
  showItemInFolder(_fileSystemPath: Platform.DevToolsPath.RawPathString): void {
177
+ // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
176
178
  Common.Console.Console.instance().error(
177
179
  'Show item in folder is not enabled in hosted mode. Please inspect using chrome://inspect');
178
180
  }
@@ -152,6 +152,16 @@ export function lowerBound<S, T, A extends S[]>(
152
152
  return r;
153
153
  }
154
154
 
155
+ /**
156
+ * Inserts a value into a sorted array in O(n) time (O(log n) search using the provided comparator and O(n) insertion).
157
+ * Returns the index at which the value was inserted.
158
+ */
159
+ export function insertWithComparator<T>(array: T[], value: T, comparator: (a: T, b: T) => number): number {
160
+ const index = lowerBound(array, value, comparator);
161
+ array.splice(index, 0, value);
162
+ return index;
163
+ }
164
+
155
165
  /**
156
166
  * Returns the index of the element closest to the needle that is greater than
157
167
  * it. Assumes that the provided array is sorted.
@@ -50,23 +50,39 @@ const escapedReplacements = new Map([
50
50
  ['</script', '\\x3C/script'],
51
51
  ]);
52
52
 
53
+ export const escapeUnicode = (content: string): string => {
54
+ return content.replaceAll(/[\p{Format}\p{Surrogate}]/gu, match => {
55
+ return match.split('').map(char => '\\u' + toHexadecimal(char.charCodeAt(0), 4)).join('');
56
+ });
57
+ };
58
+
53
59
  export const formatAsJSLiteral = (content: string): string => {
54
- const patternsToEscape = /(\\|<(?:!--|\/?script))|(\p{Control})|(\p{Surrogate})/gu;
55
- const patternsToEscapePlusSingleQuote = /(\\|'|<(?:!--|\/?script))|(\p{Control})|(\p{Surrogate})/gu;
60
+ const patternsToEscape = /(\\|<(?:!--|\/?script))|(\p{Control}|\p{Format})|(\p{Surrogate})/giu;
61
+ const patternsToEscapePlusSingleQuote = /(\\|'|<(?:!--|\/?script))|(\p{Control}|\p{Format})|(\p{Surrogate})/giu;
56
62
  const escapePattern = (match: string, pattern: string, controlChar: string, loneSurrogate: string): string => {
57
63
  if (controlChar) {
58
64
  if (escapedReplacements.has(controlChar)) {
59
65
  // @ts-expect-error https://github.com/microsoft/TypeScript/issues/13086
60
66
  return escapedReplacements.get(controlChar);
61
67
  }
62
- const twoDigitHex = toHexadecimal(controlChar.charCodeAt(0), 2);
63
- return '\\x' + twoDigitHex;
68
+ return controlChar.split('')
69
+ .map(char => {
70
+ const charCode = char.charCodeAt(0);
71
+ if (controlChar.length === 1 && charCode <= 0xFF) {
72
+ return '\\x' + toHexadecimal(charCode, 2);
73
+ }
74
+ return '\\u' + toHexadecimal(charCode, 4);
75
+ })
76
+ .join('');
64
77
  }
65
78
  if (loneSurrogate) {
66
79
  const fourDigitHex = toHexadecimal(loneSurrogate.charCodeAt(0), 4);
67
80
  return '\\u' + fourDigitHex;
68
81
  }
69
82
  if (pattern) {
83
+ if (pattern.startsWith('<')) {
84
+ return '\\x3C' + pattern.slice(1);
85
+ }
70
86
  return escapedReplacements.get(pattern) || '';
71
87
  }
72
88
  return match;
@@ -32,8 +32,10 @@ export class CPUThrottlingManager extends Common.ObjectWrapper.ObjectWrapper<Eve
32
32
  } = {forceNew: null}): CPUThrottlingManager {
33
33
  const {forceNew} = opts;
34
34
  if (!Root.DevToolsContext.globalInstance().has(CPUThrottlingManager) || forceNew) {
35
+ /* eslint-disable @devtools/no-instance-of-migrated-singletons */
35
36
  const manager = new CPUThrottlingManager(opts.settings ?? Common.Settings.Settings.instance(),
36
37
  opts.targetManager ?? TargetManager.instance());
38
+ /* eslint-enable @devtools/no-instance-of-migrated-singletons */
37
39
  manager.initialize();
38
40
  Root.DevToolsContext.globalInstance().set(CPUThrottlingManager, manager);
39
41
  }
@@ -537,6 +537,7 @@ export class DOMDebuggerManager implements SDKModelObserver<DOMDebuggerModel> {
537
537
  readonly #eventListenerBreakpoints: DOMEventListenerBreakpoint[] = [];
538
538
  readonly #targetManager: TargetManager;
539
539
 
540
+ // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
540
541
  constructor(targetManager: TargetManager = TargetManager.instance()) {
541
542
  this.#targetManager = targetManager;
542
543
  this.#xhrBreakpointsSetting = this.#targetManager.settings.createLocalSetting('xhr-breakpoints', []);
@@ -673,6 +674,7 @@ export class DOMDebuggerManager implements SDKModelObserver<DOMDebuggerModel> {
673
674
  } = {forceNew: null}): DOMDebuggerManager {
674
675
  const {forceNew, targetManager} = opts;
675
676
  if (!Root.DevToolsContext.globalInstance().has(DOMDebuggerManager) || forceNew) {
677
+ // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
676
678
  const manager = new DOMDebuggerManager(targetManager ?? TargetManager.instance());
677
679
  manager.initialize();
678
680
  Root.DevToolsContext.globalInstance().set(
@@ -2108,6 +2108,7 @@ export class DOMModel extends SDKModel<EventTypes> {
2108
2108
  if ('has' in context && typeof context.has === 'function' && context.has(DOMModelUndoStack)) {
2109
2109
  return context.get(DOMModelUndoStack);
2110
2110
  }
2111
+ // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
2111
2112
  return DOMModelUndoStack.instance();
2112
2113
  }
2113
2114
 
@@ -168,10 +168,10 @@ export class DebuggerModel extends SDKModel<EventTypes> {
168
168
  this.agent = target.debuggerAgent();
169
169
  this.#runtimeModel = (target.model(RuntimeModel) as RuntimeModel);
170
170
 
171
- this.#sourceMapManager = new SourceMapManager(
172
- target,
173
- (compiledURL, sourceMappingURL, payload, script) =>
174
- new SourceMap(compiledURL, sourceMappingURL, payload, script));
171
+ this.#sourceMapManager =
172
+ new SourceMapManager(target,
173
+ (compiledURL, sourceMappingURL, payload, script) => new SourceMap(
174
+ compiledURL, sourceMappingURL, payload, target.targetManager().getConsole(), script));
175
175
 
176
176
  const settings = this.target().targetManager().settings;
177
177
  settings.moduleSetting('pause-on-exception-enabled').addChangeListener(this.pauseOnExceptionStateChanged, this);
@@ -88,6 +88,7 @@ export class EventBreakpointsManager implements SDKModelObserver<EventBreakpoint
88
88
  readonly #eventListenerBreakpoints: EventListenerBreakpoint[] = [];
89
89
  readonly #targetManager: TargetManager;
90
90
 
91
+ // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
91
92
  constructor(targetManager: TargetManager = TargetManager.instance()) {
92
93
  this.#targetManager = targetManager;
93
94
  this.createInstrumentationBreakpoints(Category.AUCTION_WORKLET, [
@@ -152,6 +153,7 @@ export class EventBreakpointsManager implements SDKModelObserver<EventBreakpoint
152
153
  const {forceNew, targetManager} = opts;
153
154
  if (!Root.DevToolsContext.globalInstance().has(EventBreakpointsManager) || forceNew) {
154
155
  Root.DevToolsContext.globalInstance().set(EventBreakpointsManager,
156
+ // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
155
157
  new EventBreakpointsManager(targetManager ?? TargetManager.instance()));
156
158
  }
157
159
 
@@ -45,6 +45,7 @@ export class FrameManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes>
45
45
  forceNew: boolean,
46
46
  } = {forceNew: false}): FrameManager {
47
47
  if (!Root.DevToolsContext.globalInstance().has(FrameManager) || forceNew) {
48
+ // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
48
49
  Root.DevToolsContext.globalInstance().set(FrameManager, new FrameManager(TargetManager.instance()));
49
50
  }
50
51
  return Root.DevToolsContext.globalInstance().get(FrameManager);
@@ -20,6 +20,7 @@ export class IsolateManager extends Common.ObjectWrapper.ObjectWrapper<EventType
20
20
  #pollId = 0;
21
21
  readonly #targetManager: TargetManager;
22
22
 
23
+ // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
23
24
  constructor(targetManager: TargetManager = TargetManager.instance()) {
24
25
  super();
25
26
  this.#targetManager = targetManager;
@@ -2120,8 +2120,10 @@ export class MultitargetNetworkManager extends Common.ObjectWrapper.ObjectWrappe
2120
2120
  } = {forceNew: null}): MultitargetNetworkManager {
2121
2121
  const {forceNew, targetManager} = opts;
2122
2122
  if (!Root.DevToolsContext.globalInstance().has(MultitargetNetworkManager) || forceNew) {
2123
+ /* eslint-disable @devtools/no-instance-of-migrated-singletons */
2123
2124
  Root.DevToolsContext.globalInstance().set(
2124
2125
  MultitargetNetworkManager, new MultitargetNetworkManager(targetManager ?? TargetManager.instance()));
2126
+ /* eslint-enable @devtools/no-instance-of-migrated-singletons */
2125
2127
  }
2126
2128
 
2127
2129
  return Root.DevToolsContext.globalInstance().get(MultitargetNetworkManager);
@@ -309,6 +309,7 @@ export class NetworkRequest extends Common.ObjectWrapper.ObjectWrapper<EventType
309
309
  loaderId: Protocol.Network.LoaderId|null,
310
310
  initiator: Protocol.Network.Initiator|null,
311
311
  hasUserGesture?: boolean,
312
+ // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
312
313
  console: Common.Console.Console = Common.Console.Console.instance(),
313
314
  ) {
314
315
  super();
@@ -135,11 +135,13 @@ export class PageResourceLoader extends Common.ObjectWrapper.ObjectWrapper<Event
135
135
  loadOverride: null,
136
136
  }): PageResourceLoader {
137
137
  if (forceNew) {
138
+ /* eslint-disable @devtools/no-instance-of-migrated-singletons */
138
139
  Root.DevToolsContext.globalInstance().set(
139
140
  PageResourceLoader,
140
141
  new PageResourceLoader(
141
142
  targetManager ?? TargetManager.instance(), settings ?? Common.Settings.Settings.instance(),
142
143
  userAgentProvider ?? MultitargetNetworkManager.instance(), loadOverride, maxConcurrentLoads));
144
+ /* eslint-enable @devtools/no-instance-of-migrated-singletons */
143
145
  }
144
146
 
145
147
  return Root.DevToolsContext.globalInstance().get(PageResourceLoader);
@@ -138,25 +138,25 @@ export class SourceMap {
138
138
  readonly #debugId?: DebugId;
139
139
 
140
140
  #scopesFallbackPromise?: Promise<void>;
141
+ readonly #console: Common.Console.Console;
141
142
 
142
143
  /**
143
144
  * Implements Source Map V3 model. See https://github.com/google/closure-compiler/wiki/Source-Maps
144
145
  * for format description.
145
146
  */
146
- constructor(
147
- compiledURL: Platform.DevToolsPath.UrlString, sourceMappingURL: Platform.DevToolsPath.UrlString,
148
- payload: SourceMapV3, script?: Script) {
147
+ constructor(compiledURL: Platform.DevToolsPath.UrlString, sourceMappingURL: Platform.DevToolsPath.UrlString,
148
+ payload: SourceMapV3, console: Common.Console.Console, script?: Script) {
149
149
  this.#json = payload;
150
150
  this.#script = script;
151
151
  this.#compiledURL = compiledURL;
152
152
  this.#sourceMappingURL = sourceMappingURL;
153
153
  this.#baseURL = (Common.ParsedURL.schemeIs(sourceMappingURL, 'data:')) ? compiledURL : sourceMappingURL;
154
154
  this.#debugId = 'debugId' in payload ? (payload.debugId as DebugId | undefined) : undefined;
155
+ this.#console = console;
155
156
 
156
157
  if ('sections' in this.#json) {
157
158
  if (this.#json.sections.find(section => 'url' in section)) {
158
- Common.Console.Console.instance().warn(
159
- `SourceMap "${sourceMappingURL}" contains unsupported "URL" field in one of its sections.`);
159
+ this.#console.warn(`SourceMap "${sourceMappingURL}" contains unsupported "URL" field in one of its sections.`);
160
160
  }
161
161
  }
162
162
  this.eachSection(this.parseSources.bind(this));
@@ -28,8 +28,9 @@ export class SourceMapManager<T extends FrameAssociated> extends Common.ObjectWr
28
28
  super();
29
29
 
30
30
  this.#target = target;
31
- this.#factory =
32
- factory ?? ((compiledURL, sourceMappingURL, payload) => new SourceMap(compiledURL, sourceMappingURL, payload));
31
+ this.#factory = factory ??
32
+ ((compiledURL, sourceMappingURL, payload) =>
33
+ new SourceMap(compiledURL, sourceMappingURL, payload, this.#target.targetManager().getConsole()));
33
34
  }
34
35
 
35
36
  setEnabled(isEnabled: boolean): void {
@@ -37,6 +37,7 @@ export class TargetManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes
37
37
  // TODO(crbug.com/493763857): Remove fallback once all unit tests use TestUniverse.
38
38
  getConsole(): Common.Console.Console {
39
39
  if ('has' in this.context && typeof this.context.has === 'function' && !this.context.has(Common.Console.Console)) {
40
+ // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
40
41
  return Common.Console.Console.instance();
41
42
  }
42
43
  return this.context.get(Common.Console.Console);
@@ -45,6 +46,7 @@ export class TargetManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes
45
46
  // TODO(crbug.com/493763857): Remove fallback once all unit tests use TestUniverse.
46
47
  getFrameManager(): FrameManager {
47
48
  if ('has' in this.context && typeof this.context.has === 'function' && !this.context.has(FrameManager)) {
49
+ // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
48
50
  return FrameManager.instance();
49
51
  }
50
52
  return this.context.get(FrameManager);
@@ -54,6 +56,7 @@ export class TargetManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes
54
56
  getNetworkManager(): MultitargetNetworkManager {
55
57
  if ('has' in this.context && typeof this.context.has === 'function' &&
56
58
  !this.context.has(MultitargetNetworkManager)) {
59
+ // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
57
60
  return MultitargetNetworkManager.instance();
58
61
  }
59
62
  return this.context.get(MultitargetNetworkManager);
@@ -62,6 +65,7 @@ export class TargetManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes
62
65
  // TODO(crbug.com/493763857): Remove fallback once all unit tests use TestUniverse.
63
66
  getPageResourceLoader(): PageResourceLoader {
64
67
  if ('has' in this.context && typeof this.context.has === 'function' && !this.context.has(PageResourceLoader)) {
68
+ // eslint-disable-next-line @devtools/no-instance-of-migrated-singletons
65
69
  return PageResourceLoader.instance();
66
70
  }
67
71
  return this.context.get(PageResourceLoader);
@@ -445,7 +445,8 @@ export class MainImpl {
445
445
  IssuesManager.IssuesManager.IssuesManager.instance({
446
446
  forceNew: true,
447
447
  ensureFirst: true,
448
- showThirdPartyIssuesSetting: IssuesManager.Issue.getShowThirdPartyIssuesSetting(),
448
+ showThirdPartyIssuesSetting:
449
+ IssuesManager.Issue.getShowThirdPartyIssuesSetting(Common.Settings.Settings.instance()),
449
450
  hideIssueSetting: IssuesManager.IssuesManager.getHideIssueByCodeSetting(),
450
451
  });
451
452
 
@@ -8,3 +8,89 @@ As such, allowed use of APIs is restricted to what is available in both runtimes
8
8
  A `DevToolsUniverse` is a concrete, encapsulated instance of "foundation" scoped
9
9
  to a single root CDP target. It is valid to create multiple `DevToolsUniverse`
10
10
  instances simultaneously.
11
+
12
+ ## Architecture Shortcomings & Code Health Projects
13
+
14
+ The following is a prioritized list of architectural shortcomings and refactoring projects aimed at reducing coupling, eliminating global state, and improving the modularity of the DevTools foundation.
15
+
16
+ ### Priority 1: Move `models/text_utils` to `core/text_utils`
17
+ * **Problem**: 22 files in `front_end/core/sdk` depend directly on `front_end/models/text_utils` for basic text structures (layering violation).
18
+ * **Rationale**: `text_utils` contains fundamental, non-business-logic utilities (`TextRange`, `TextCursor`, `ContentData`, `ContentProvider`) that represent the base data structures of the editor, debugger, and network panels. It only depends on `core/common` and `core/platform`. Moving it to `core` is a natural fit and resolves the majority of `core` -> `models` layering violations.
19
+ * **Action**:
20
+ 1. Move the directory `front_end/models/text_utils` to `front_end/core/text_utils`.
21
+ 2. Update all imports across the codebase.
22
+
23
+ ### Priority 2: Break Circular Dependencies in Bindings (`ResourceMapping` <-> Bindings)
24
+ * **Problem**: Bidirectional dependencies between `ResourceMapping` and `DebuggerWorkspaceBinding`/`CSSWorkspaceBinding` prevent isolated testing.
25
+ * **Rationale**: Decoupling `ResourceMapping` from concrete bindings allows better testing and modularity.
26
+ * **Action**: Introduce abstract listener interfaces in `ResourceMapping` (Dependency Inversion). `DebuggerWorkspaceBinding` and `CSSWorkspaceBinding` should implement these interfaces and register themselves, allowing `ResourceMapping` to invoke them without depending on concrete classes.
27
+
28
+ ### Priority 3: Move `IgnoreListManager` from `workspace` to `bindings`
29
+ * **Problem**: `models/workspace` depends on `core/sdk` via `IgnoreListManager.ts`.
30
+ * **Rationale**: Ignore-listing is conceptually a debugger-binding concern, not a basic workspace/file-system concern.
31
+ * **Action**:
32
+ 1. Remove the convenience helper `UISourceCode.isIgnoreListed()` (and related methods in `UILocation`) from `models/workspace`.
33
+ 2. Update callers to query `IgnoreListManager` directly.
34
+ 3. Move `IgnoreListManager.ts` to `models/bindings`.
35
+ 4. This removes the value-level dependency of `workspace` on `sdk`.
36
+
37
+ ### Priority 4: Decouple `Workspace.Project` from `SDK.Target`
38
+ * **Problem**: `Workspace.Project` exposes `target()`, coupling the VFS to runtime targets.
39
+ * **Rationale**: A workspace should be able to exist without knowing about browser targets.
40
+ * **Action**:
41
+ 1. Remove `target()` from the `Project` interface and `ProjectStore` in `front_end/models/workspace/WorkspaceImpl.ts`.
42
+ 2. In the `bindings` module, maintain a private `WeakMap<Workspace.Project, SDK.Target.Target>` to associate projects with targets.
43
+ 3. Update `NetworkProject.targetForUISourceCode(uiSourceCode)` to look up the target from this `WeakMap`.
44
+
45
+ ### Priority 5: Decouple `core/sdk` from `models/formatter` (AST Scope Fallback)
46
+ * **Problem**: `SDK/SourceMap.ts` depends on `models/formatter` for fallback scope calculation.
47
+ * **Rationale**: `SDK` should not depend on high-level formatting/parsing worker pools.
48
+ * **Action**:
49
+ 1. Remove the fallback scope calculation logic from `SourceMap.ts` and expose a clean API (e.g., `setScopesInfo(...)`).
50
+ 2. Move the AST fallback scope calculation logic to `front_end/models/bindings` (e.g., in `DebuggerWorkspaceBinding`), which coordinates script and source map loading.
51
+ 3. Have the bindings layer calculate the fallback scopes and attach them to the `SourceMap` object.
52
+
53
+ ### Priority 6: Refactor Mapping Engines & Inner Helpers in Bindings
54
+ * **Problem**: Engines and helpers query global `DebuggerWorkspaceBinding.instance()` directly.
55
+ * **Rationale**: High coupling hinders testing and isolation.
56
+ * **Action**: Eliminate direct global singleton queries. Update helpers to access parent mapping engines or pass references via constructors.
57
+
58
+ ### Priority 7: Universe-scoped Embedder Host and HostConfig
59
+ * **Problem**: `InspectorFrontendHostInstance` and `Root.Runtime.hostConfig` are treated as global mutable singletons. Core classes (`Connections`, `IsolatedFileSystemManager`, `FileManager`) and UI components access them directly, leading to global state pollution and state leaks in tests.
60
+ * **Rationale**: The host interface and its configuration represent the boundary between DevTools and the Chromium browser. To support multiple isolated `DevToolsUniverse` instances, both the host interface and host configuration must be scoped to the universe context.
61
+ * **Action**:
62
+ 1. Store the scoped `InspectorFrontendHostAPI` (wrapped in `ScopedInspectorFrontendHost`) in the `DevToolsUniverse` context.
63
+ 2. Refactor core classes (`Connections`, `IsolatedFileSystemManager`, `FileManager`, `UserMetrics`) to receive the scoped host via constructor injection.
64
+ 3. Introduce a scoped `HostConfigProvider` service in the `Universe` context to manage `HostConfig` fetching and caching.
65
+ 4. Move polling and configuration update logic from `HostConfigTracker` in `AidaClient.ts` to `HostConfigProvider`.
66
+ 5. Provide a compatibility Proxy for `Root.Runtime.hostConfig` to allow gradual migration of the 200+ call sites.
67
+ 6. Remove the global side-effect initialization in `InspectorFrontendHost.ts`.
68
+
69
+ ### Priority 8: View-Level Dependency Injection (Universe-ification)
70
+ * **Problem**: UI panels query global `.instance()` for bindings, causing state leaks in tests.
71
+ * **Rationale**: DevTools is transitioning to a scoped "Universe" architecture where dependencies are injected. UI panels should receive their dependencies rather than querying globals.
72
+ * **Action**:
73
+ 1. Expose bindings on `Universe` and inject them via the view loading pipeline.
74
+ 2. Leverage the view loading pipeline (`-meta.ts` files) to pass these bindings to panel constructors upon initialization, avoiding global calls in UI panels.
75
+
76
+ ### Priority 9: Decouple `persistence` from `bindings`
77
+ * **Problem**: `models/persistence` depends on `models/bindings` to check if a target is Node.js.
78
+ * **Rationale**: `persistence` (which maps network files to local files) should ideally only depend on `workspace` and not on the complex debugger/bindings layer.
79
+ * **Action**: Introduce a capability/property on `Workspace.Project` (e.g., `isNodeProject`) to avoid direct target queries.
80
+
81
+ ### Priority 10: Move `SourceFrameIssuesManager` to `bindings`
82
+ * **Problem**: `models/issues_manager` depends on `workspace` and `bindings` only for placing issue badges.
83
+ * **Rationale**: Showing badges on source frames is a binding/presentation concern, similar to showing console messages. `issues_manager` itself should be a clean, independent leaf module.
84
+ * **Action**: Move `SourceFrameIssuesManager.ts` to `models/bindings/` and remove `workspace` and `bindings` dependencies from `issues_manager/BUILD.gn`.
85
+
86
+ ### Priority 11: Decouple UI via Interfaces / Revealers
87
+ * **Problem**: General UI components (like `Linkifier`) depend on heavy concrete bindings.
88
+ * **Rationale**: UI components should not be tightly coupled to complex mapping logic.
89
+ * **Action**: Use light interfaces or `Common.Revealer`.
90
+
91
+ ### Priority 12: Decouple Core Modules from `i18n` (UI Localization)
92
+ * **Problem**: Core infra/parser modules import `i18n` for localized strings.
93
+ * **Rationale**: Business logic and core infrastructure should not be tied to UI localization libraries.
94
+ * **Action**:
95
+ 1. Refactor parsers to return structured error data and let UI handle localization.
96
+ 2. Update registries to use string IDs/keys.