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.
- package/.agents/skills/evaluate-ai-css-completion/SKILL.md +143 -0
- package/.agents/skills/evaluate-ai-css-completion/scripts/evaluate.js +104 -0
- package/.agents/skills/migrate-chromium-test/SKILL.md +7 -2
- package/.agents/skills/ui-eng-vision-local-lit-renderer/SKILL.md +7 -1
- package/docs/ui_engineering.md +75 -42
- package/eslint.config.mjs +7 -0
- package/extension-api/ExtensionAPI.d.ts +88 -0
- package/front_end/core/common/SettingRegistration.ts +0 -5
- package/front_end/core/host/InspectorFrontendHost.ts +1 -0
- package/front_end/core/host/InspectorFrontendHostStub.ts +2 -0
- package/front_end/core/platform/ArrayUtilities.ts +10 -0
- package/front_end/core/platform/StringUtilities.ts +20 -4
- package/front_end/core/sdk/CPUThrottlingManager.ts +2 -0
- package/front_end/core/sdk/DOMDebuggerModel.ts +2 -0
- package/front_end/core/sdk/DOMModel.ts +1 -0
- package/front_end/core/sdk/DebuggerModel.ts +4 -4
- package/front_end/core/sdk/EventBreakpointsModel.ts +2 -0
- package/front_end/core/sdk/FrameManager.ts +1 -0
- package/front_end/core/sdk/IsolateManager.ts +1 -0
- package/front_end/core/sdk/NetworkManager.ts +2 -0
- package/front_end/core/sdk/NetworkRequest.ts +1 -0
- package/front_end/core/sdk/PageResourceLoader.ts +2 -0
- package/front_end/core/sdk/SourceMap.ts +5 -5
- package/front_end/core/sdk/SourceMapManager.ts +3 -2
- package/front_end/core/sdk/TargetManager.ts +4 -0
- package/front_end/entrypoints/main/MainImpl.ts +2 -1
- package/front_end/foundation/README.md +86 -0
- package/front_end/generated/InspectorBackendCommands.ts +4 -5
- package/front_end/generated/protocol.ts +20 -38
- package/front_end/models/bindings/CompilerScriptMapping.ts +5 -5
- package/front_end/models/bindings/ContentProviderBasedProject.ts +2 -3
- package/front_end/models/bindings/DebuggerLanguagePlugins.ts +3 -3
- package/front_end/models/bindings/DefaultScriptMapping.ts +3 -3
- package/front_end/models/bindings/ResourceMapping.ts +3 -3
- package/front_end/models/bindings/ResourceScriptMapping.ts +2 -2
- package/front_end/models/bindings/SASSSourceMapping.ts +3 -3
- package/front_end/models/bindings/TempFile.ts +8 -3
- package/front_end/models/extensions/ExtensionAPI.ts +110 -46
- package/front_end/models/extensions/RecorderExtensionEndpoint.ts +7 -5
- package/front_end/models/formatter/ScriptFormatter.ts +8 -11
- package/front_end/models/heap_snapshot/HeapSnapshotProxy.ts +14 -5
- package/front_end/models/issues_manager/CheckFormsIssuesTrigger.ts +8 -9
- package/front_end/models/issues_manager/CookieIssue.ts +21 -9
- package/front_end/models/issues_manager/Issue.ts +3 -4
- package/front_end/models/issues_manager/IssueAggregator.ts +0 -9
- package/front_end/models/issues_manager/IssueResolver.ts +2 -2
- package/front_end/models/issues_manager/IssuesManager.ts +136 -137
- package/front_end/models/issues_manager/RelatedIssue.ts +10 -8
- package/front_end/models/issues_manager/issues_manager.ts +0 -2
- package/front_end/models/javascript_metadata/NativeFunctions.js +1 -1
- package/front_end/models/logs/RequestResolver.ts +2 -2
- package/front_end/models/source_map_scopes/FunctionCodeResolver.ts +12 -9
- package/front_end/models/trace/handlers/FramesHandler.ts +4 -7
- package/front_end/models/trace/handlers/ModelHandlers.ts +0 -1
- package/front_end/models/trace/handlers/RendererHandler.ts +2 -15
- package/front_end/models/trace/handlers/Threads.ts +4 -11
- package/front_end/models/trace/insights/DOMSize.ts +1 -1
- package/front_end/models/workspace_diff/WorkspaceDiff.ts +10 -4
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +2 -1
- package/front_end/panels/application/ApplicationPanelSidebar.ts +0 -44
- package/front_end/panels/application/CookieItemsView.ts +1 -1
- package/front_end/panels/application/ServiceWorkersView.ts +494 -411
- package/front_end/panels/application/WebMCPView.ts +38 -43
- package/front_end/panels/application/application.ts +0 -6
- package/front_end/panels/application/components/AdsView.ts +201 -30
- package/front_end/panels/application/components/adsView.css +25 -0
- package/front_end/panels/application/components/components.ts +0 -2
- package/front_end/panels/application/preloading/components/PreloadingDetailsReportView.ts +1 -1
- package/front_end/panels/application/preloading/components/RuleSetDetailsView.ts +2 -2
- package/front_end/panels/application/serviceWorkersView.css +40 -4
- package/front_end/panels/browser_debugger/XHRBreakpointsSidebarPane.ts +147 -123
- package/front_end/panels/common/ExtensionServer.ts +3 -3
- package/front_end/panels/console/ConsoleView.ts +3 -2
- package/front_end/panels/console/PromptBuilder.ts +2 -1
- package/front_end/panels/emulation/DeviceModeView.ts +164 -113
- package/front_end/panels/issues/AffectedResourcesView.ts +1 -1
- package/front_end/panels/issues/IssueView.ts +0 -2
- package/front_end/panels/issues/IssuesPane.ts +1 -8
- package/front_end/panels/js_timeline/js_timeline-meta.ts +3 -2
- package/front_end/panels/lighthouse/LighthouseProtocolService.ts +53 -12
- package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorController.ts +3 -3
- package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorPane.ts +5 -5
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryHighlightChipList.ts +4 -4
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +2 -2
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryNavigator.ts +6 -6
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryValueInterpreter.ts +3 -3
- package/front_end/panels/linear_memory_inspector/components/ValueInterpreterDisplay.ts +8 -9
- package/front_end/panels/linear_memory_inspector/components/ValueInterpreterDisplayUtils.ts +2 -2
- package/front_end/panels/linear_memory_inspector/components/ValueInterpreterSettings.ts +1 -1
- package/front_end/panels/linear_memory_inspector/linear_memory_inspector-meta.ts +2 -2
- package/front_end/panels/network/RequestPayloadView.ts +92 -52
- package/front_end/panels/network/RequestTimingView.ts +95 -127
- package/front_end/panels/network/components/ResponseHeaderSection.ts +5 -3
- package/front_end/panels/profiler/HeapSnapshotView.ts +3 -3
- package/front_end/panels/profiler/WritableProfileHeader.ts +2 -2
- package/front_end/panels/recorder/{components/ControlButton.ts → ControlButton.ts} +9 -10
- package/front_end/panels/recorder/{components/CreateRecordingView.ts → CreateRecordingView.ts} +48 -47
- package/front_end/panels/recorder/{components/ExtensionView.ts → ExtensionView.ts} +8 -8
- package/front_end/panels/recorder/RecorderController.ts +302 -127
- package/front_end/panels/recorder/RecorderPanel.ts +1 -1
- package/front_end/panels/recorder/{components/RecordingListView.ts → RecordingListView.ts} +19 -20
- package/front_end/panels/recorder/{components/RecordingView.ts → RecordingView.ts} +88 -88
- package/front_end/panels/recorder/{components/ReplaySection.ts → ReplaySection.ts} +11 -11
- package/front_end/panels/recorder/{components/SelectorPicker.ts → SelectorPicker.ts} +13 -13
- package/front_end/panels/recorder/{components/StepEditor.ts → StepEditor.ts} +15 -15
- package/front_end/panels/recorder/{components/StepView.ts → StepView.ts} +10 -10
- package/front_end/panels/recorder/{components/TimelineSection.ts → TimelineSection.ts} +2 -2
- package/front_end/panels/recorder/recorder.ts +23 -1
- package/front_end/panels/recorder/util/util.ts +113 -0
- package/front_end/panels/sources/SourcesView.ts +0 -17
- package/front_end/panels/sources/TabbedEditorContainer.ts +1 -1
- package/front_end/panels/sources/UISourceCodeFrame.ts +42 -0
- package/front_end/panels/sources/sources.ts +0 -2
- package/front_end/panels/timeline/CompatibilityTracksAppender.ts +0 -17
- package/front_end/panels/timeline/IsolateSelector.ts +10 -8
- package/front_end/panels/timeline/ThreadAppender.ts +0 -106
- package/front_end/panels/timeline/TimelinePanel.ts +18 -7
- package/front_end/panels/timeline/TimelineUIUtils.ts +144 -129
- package/front_end/panels/timeline/timeline-meta.ts +3 -2
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/report_view/ReportView.ts +11 -5
- package/front_end/ui/components/report_view/report.css +4 -1
- package/front_end/ui/legacy/TextPrompt.ts +49 -1
- package/front_end/ui/legacy/Treeoutline.ts +3 -0
- package/front_end/ui/legacy/UIUtils.ts +11 -1
- package/front_end/ui/legacy/Widget.ts +14 -15
- package/front_end/ui/legacy/components/cookie_table/CookiesTable.ts +2 -2
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +11 -7
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +2 -1
- package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +10 -1
- package/front_end/ui/legacy/textPrompt.css +10 -0
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/package.json +1 -1
- package/front_end/models/issues_manager/AttributionReportingIssue.ts +0 -247
- package/front_end/models/issues_manager/descriptions/arInsecureContext.md +0 -7
- package/front_end/models/issues_manager/descriptions/arInvalidInfoHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arInvalidRegisterOsSourceHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arInvalidRegisterOsTriggerHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arInvalidRegisterSourceHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arInvalidRegisterTriggerHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNavigationRegistrationUniqueScopeAlreadySet.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNavigationRegistrationWithoutTransientUserActivation.md +0 -6
- package/front_end/models/issues_manager/descriptions/arNoRegisterOsSourceHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNoRegisterOsTriggerHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNoRegisterSourceHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNoRegisterTriggerHeader.md +0 -5
- package/front_end/models/issues_manager/descriptions/arNoWebOrOsSupport.md +0 -4
- package/front_end/models/issues_manager/descriptions/arOsSourceIgnored.md +0 -18
- package/front_end/models/issues_manager/descriptions/arOsTriggerIgnored.md +0 -19
- package/front_end/models/issues_manager/descriptions/arPermissionPolicyDisabled.md +0 -8
- package/front_end/models/issues_manager/descriptions/arSourceAndTriggerHeaders.md +0 -9
- package/front_end/models/issues_manager/descriptions/arSourceIgnored.md +0 -13
- package/front_end/models/issues_manager/descriptions/arTriggerIgnored.md +0 -12
- package/front_end/models/issues_manager/descriptions/arUntrustworthyReportingOrigin.md +0 -10
- package/front_end/models/issues_manager/descriptions/arWebAndOsHeaders.md +0 -11
- package/front_end/models/trace/handlers/AuctionWorkletsHandler.ts +0 -183
- package/front_end/panels/application/InterestGroupStorageModel.ts +0 -81
- package/front_end/panels/application/InterestGroupStorageView.ts +0 -151
- package/front_end/panels/application/InterestGroupTreeElement.ts +0 -65
- package/front_end/panels/application/components/InterestGroupAccessGrid.ts +0 -135
- package/front_end/panels/application/components/interestGroupAccessGrid.css +0 -27
- package/front_end/panels/application/interestGroupStorageView.css +0 -9
- package/front_end/panels/issues/AttributionReportingIssueDetailsView.ts +0 -182
- package/front_end/panels/recorder/components/components.ts +0 -25
- package/front_end/panels/recorder/components/util.ts +0 -116
- package/front_end/panels/sources/InplaceFormatterEditorAction.ts +0 -149
- /package/front_end/panels/recorder/{components/controlButton.css → controlButton.css} +0 -0
- /package/front_end/panels/recorder/{components/createRecordingView.css → createRecordingView.css} +0 -0
- /package/front_end/panels/recorder/{components/extensionView.css → extensionView.css} +0 -0
- /package/front_end/panels/recorder/{components/recordingListView.css → recordingListView.css} +0 -0
- /package/front_end/panels/recorder/{components/recordingView.css → recordingView.css} +0 -0
- /package/front_end/panels/recorder/{components/replaySection.css → replaySection.css} +0 -0
- /package/front_end/panels/recorder/{components/selectorPicker.css → selectorPicker.css} +0 -0
- /package/front_end/panels/recorder/{components/startView.css → startView.css} +0 -0
- /package/front_end/panels/recorder/{components/stepEditor.css → stepEditor.css} +0 -0
- /package/front_end/panels/recorder/{components/stepView.css → stepView.css} +0 -0
- /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})/
|
|
55
|
-
const patternsToEscapePlusSingleQuote = /(\\|'|<(?:!--|\/?script))|(\p{Control})|(\p{Surrogate})/
|
|
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
|
-
|
|
63
|
-
|
|
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 =
|
|
172
|
-
target,
|
|
173
|
-
|
|
174
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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.
|