chrome-devtools-frontend 1.0.1660788 → 1.0.1661063

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 (132) hide show
  1. package/.agents/skills/evaluate-ai-css-completion/SKILL.md +133 -0
  2. package/.agents/skills/evaluate-ai-css-completion/scripts/evaluate.js +76 -0
  3. package/eslint.config.mjs +7 -0
  4. package/extension-api/ExtensionAPI.d.ts +88 -0
  5. package/front_end/core/host/InspectorFrontendHost.ts +1 -0
  6. package/front_end/core/host/InspectorFrontendHostStub.ts +2 -0
  7. package/front_end/core/platform/StringUtilities.ts +20 -4
  8. package/front_end/core/sdk/CPUThrottlingManager.ts +2 -0
  9. package/front_end/core/sdk/DOMDebuggerModel.ts +2 -0
  10. package/front_end/core/sdk/DOMModel.ts +1 -0
  11. package/front_end/core/sdk/DebuggerModel.ts +4 -4
  12. package/front_end/core/sdk/EventBreakpointsModel.ts +2 -0
  13. package/front_end/core/sdk/FrameManager.ts +1 -0
  14. package/front_end/core/sdk/IsolateManager.ts +1 -0
  15. package/front_end/core/sdk/NetworkManager.ts +2 -0
  16. package/front_end/core/sdk/NetworkRequest.ts +1 -0
  17. package/front_end/core/sdk/PageResourceLoader.ts +2 -0
  18. package/front_end/core/sdk/SourceMap.ts +5 -5
  19. package/front_end/core/sdk/SourceMapManager.ts +3 -2
  20. package/front_end/core/sdk/TargetManager.ts +4 -0
  21. package/front_end/entrypoints/main/MainImpl.ts +2 -1
  22. package/front_end/models/bindings/CompilerScriptMapping.ts +5 -6
  23. package/front_end/models/bindings/ContentProviderBasedProject.ts +4 -4
  24. package/front_end/models/bindings/DebuggerLanguagePlugins.ts +3 -4
  25. package/front_end/models/bindings/DefaultScriptMapping.ts +3 -3
  26. package/front_end/models/bindings/NetworkProject.ts +1 -10
  27. package/front_end/models/bindings/ResourceMapping.ts +3 -4
  28. package/front_end/models/bindings/ResourceScriptMapping.ts +2 -3
  29. package/front_end/models/bindings/SASSSourceMapping.ts +3 -4
  30. package/front_end/models/bindings/StylesSourceMapping.ts +3 -3
  31. package/front_end/models/bindings/TempFile.ts +8 -3
  32. package/front_end/models/extensions/ExtensionAPI.ts +110 -46
  33. package/front_end/models/formatter/ScriptFormatter.ts +8 -11
  34. package/front_end/models/issues_manager/CookieIssue.ts +21 -9
  35. package/front_end/models/issues_manager/Issue.ts +3 -4
  36. package/front_end/models/issues_manager/IssueAggregator.ts +0 -9
  37. package/front_end/models/issues_manager/IssueResolver.ts +2 -2
  38. package/front_end/models/issues_manager/IssuesManager.ts +136 -137
  39. package/front_end/models/issues_manager/issues_manager.ts +0 -2
  40. package/front_end/models/persistence/AutomaticFileSystemWorkspaceBinding.ts +5 -0
  41. package/front_end/models/source_map_scopes/FunctionCodeResolver.ts +13 -10
  42. package/front_end/models/workspace/WorkspaceImpl.ts +10 -1
  43. package/front_end/models/workspace_diff/WorkspaceDiff.ts +10 -4
  44. package/front_end/panels/ai_assistance/components/ChatMessage.ts +2 -1
  45. package/front_end/panels/application/FrameDetailsView.ts +1 -1
  46. package/front_end/panels/application/WebMCPView.ts +38 -43
  47. package/front_end/panels/application/components/AdsView.ts +201 -30
  48. package/front_end/panels/application/components/adsView.css +25 -0
  49. package/front_end/panels/application/preloading/components/RuleSetDetailsView.ts +2 -2
  50. package/front_end/panels/console/ConsoleView.ts +2 -1
  51. package/front_end/panels/console/PromptBuilder.ts +2 -1
  52. package/front_end/panels/emulation/DeviceModeView.ts +52 -70
  53. package/front_end/panels/issues/IssueView.ts +0 -2
  54. package/front_end/panels/issues/IssuesPane.ts +1 -8
  55. package/front_end/panels/js_timeline/js_timeline-meta.ts +3 -2
  56. package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorController.ts +3 -3
  57. package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorPane.ts +5 -5
  58. package/front_end/panels/linear_memory_inspector/components/LinearMemoryHighlightChipList.ts +4 -4
  59. package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +2 -2
  60. package/front_end/panels/linear_memory_inspector/components/LinearMemoryNavigator.ts +6 -6
  61. package/front_end/panels/linear_memory_inspector/components/LinearMemoryValueInterpreter.ts +3 -3
  62. package/front_end/panels/linear_memory_inspector/components/ValueInterpreterDisplay.ts +8 -9
  63. package/front_end/panels/linear_memory_inspector/components/ValueInterpreterDisplayUtils.ts +2 -2
  64. package/front_end/panels/linear_memory_inspector/components/ValueInterpreterSettings.ts +1 -1
  65. package/front_end/panels/linear_memory_inspector/linear_memory_inspector-meta.ts +2 -2
  66. package/front_end/panels/network/RequestPayloadView.ts +15 -13
  67. package/front_end/panels/network/RequestTimingView.ts +95 -127
  68. package/front_end/panels/profiler/HeapSnapshotView.ts +1 -1
  69. package/front_end/panels/profiler/WritableProfileHeader.ts +2 -2
  70. package/front_end/panels/recorder/{components/ControlButton.ts → ControlButton.ts} +9 -10
  71. package/front_end/panels/recorder/{components/CreateRecordingView.ts → CreateRecordingView.ts} +48 -47
  72. package/front_end/panels/recorder/{components/ExtensionView.ts → ExtensionView.ts} +8 -8
  73. package/front_end/panels/recorder/RecorderController.ts +88 -77
  74. package/front_end/panels/recorder/{components/RecordingListView.ts → RecordingListView.ts} +19 -20
  75. package/front_end/panels/recorder/{components/RecordingView.ts → RecordingView.ts} +88 -88
  76. package/front_end/panels/recorder/{components/ReplaySection.ts → ReplaySection.ts} +11 -11
  77. package/front_end/panels/recorder/{components/SelectorPicker.ts → SelectorPicker.ts} +13 -13
  78. package/front_end/panels/recorder/{components/StepEditor.ts → StepEditor.ts} +15 -15
  79. package/front_end/panels/recorder/{components/StepView.ts → StepView.ts} +10 -10
  80. package/front_end/panels/recorder/{components/TimelineSection.ts → TimelineSection.ts} +2 -2
  81. package/front_end/panels/recorder/recorder.ts +23 -1
  82. package/front_end/panels/recorder/util/util.ts +113 -0
  83. package/front_end/panels/sources/InplaceFormatterEditorAction.ts +2 -2
  84. package/front_end/panels/sources/SourcesNavigator.ts +2 -3
  85. package/front_end/panels/sources/TabbedEditorContainer.ts +1 -1
  86. package/front_end/panels/timeline/IsolateSelector.ts +10 -8
  87. package/front_end/panels/timeline/TimelinePanel.ts +18 -7
  88. package/front_end/panels/timeline/TimelineUIUtils.ts +144 -129
  89. package/front_end/panels/timeline/timeline-meta.ts +3 -2
  90. package/front_end/third_party/chromium/README.chromium +1 -1
  91. package/front_end/ui/legacy/Treeoutline.ts +3 -0
  92. package/front_end/ui/legacy/Widget.ts +14 -15
  93. package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +11 -7
  94. package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +2 -1
  95. package/front_end/ui/legacy/components/utils/JSPresentationUtils.ts +10 -1
  96. package/package.json +1 -1
  97. package/front_end/models/issues_manager/AttributionReportingIssue.ts +0 -247
  98. package/front_end/models/issues_manager/descriptions/arInsecureContext.md +0 -7
  99. package/front_end/models/issues_manager/descriptions/arInvalidInfoHeader.md +0 -5
  100. package/front_end/models/issues_manager/descriptions/arInvalidRegisterOsSourceHeader.md +0 -5
  101. package/front_end/models/issues_manager/descriptions/arInvalidRegisterOsTriggerHeader.md +0 -5
  102. package/front_end/models/issues_manager/descriptions/arInvalidRegisterSourceHeader.md +0 -5
  103. package/front_end/models/issues_manager/descriptions/arInvalidRegisterTriggerHeader.md +0 -5
  104. package/front_end/models/issues_manager/descriptions/arNavigationRegistrationUniqueScopeAlreadySet.md +0 -5
  105. package/front_end/models/issues_manager/descriptions/arNavigationRegistrationWithoutTransientUserActivation.md +0 -6
  106. package/front_end/models/issues_manager/descriptions/arNoRegisterOsSourceHeader.md +0 -5
  107. package/front_end/models/issues_manager/descriptions/arNoRegisterOsTriggerHeader.md +0 -5
  108. package/front_end/models/issues_manager/descriptions/arNoRegisterSourceHeader.md +0 -5
  109. package/front_end/models/issues_manager/descriptions/arNoRegisterTriggerHeader.md +0 -5
  110. package/front_end/models/issues_manager/descriptions/arNoWebOrOsSupport.md +0 -4
  111. package/front_end/models/issues_manager/descriptions/arOsSourceIgnored.md +0 -18
  112. package/front_end/models/issues_manager/descriptions/arOsTriggerIgnored.md +0 -19
  113. package/front_end/models/issues_manager/descriptions/arPermissionPolicyDisabled.md +0 -8
  114. package/front_end/models/issues_manager/descriptions/arSourceAndTriggerHeaders.md +0 -9
  115. package/front_end/models/issues_manager/descriptions/arSourceIgnored.md +0 -13
  116. package/front_end/models/issues_manager/descriptions/arTriggerIgnored.md +0 -12
  117. package/front_end/models/issues_manager/descriptions/arUntrustworthyReportingOrigin.md +0 -10
  118. package/front_end/models/issues_manager/descriptions/arWebAndOsHeaders.md +0 -11
  119. package/front_end/panels/issues/AttributionReportingIssueDetailsView.ts +0 -182
  120. package/front_end/panels/recorder/components/components.ts +0 -25
  121. package/front_end/panels/recorder/components/util.ts +0 -116
  122. /package/front_end/panels/recorder/{components/controlButton.css → controlButton.css} +0 -0
  123. /package/front_end/panels/recorder/{components/createRecordingView.css → createRecordingView.css} +0 -0
  124. /package/front_end/panels/recorder/{components/extensionView.css → extensionView.css} +0 -0
  125. /package/front_end/panels/recorder/{components/recordingListView.css → recordingListView.css} +0 -0
  126. /package/front_end/panels/recorder/{components/recordingView.css → recordingView.css} +0 -0
  127. /package/front_end/panels/recorder/{components/replaySection.css → replaySection.css} +0 -0
  128. /package/front_end/panels/recorder/{components/selectorPicker.css → selectorPicker.css} +0 -0
  129. /package/front_end/panels/recorder/{components/startView.css → startView.css} +0 -0
  130. /package/front_end/panels/recorder/{components/stepEditor.css → stepEditor.css} +0 -0
  131. /package/front_end/panels/recorder/{components/stepView.css → stepView.css} +0 -0
  132. /package/front_end/panels/recorder/{components/timelineSection.css → timelineSection.css} +0 -0
@@ -0,0 +1,133 @@
1
+ ---
2
+ name: evaluate-ai-css-completion
3
+ description: Expose a temporary evaluation hook in DevTools and run a Puppeteer script to validate CSS code completion trigger rates.
4
+ ---
5
+
6
+ # Evaluate CSS Completion Skill
7
+
8
+ This skill allows you to temporarily expose an evaluation hook in DevTools to measure CSS code completion trigger rates using a Puppeteer script.
9
+
10
+ > [!WARNING]
11
+ > **NEVER commit the `devtools_app.ts` patch.** It is only for local evaluation. Always revert it before uploading your CL.
12
+
13
+ ## Step 1: Apply the Temporary Patch
14
+
15
+ Modify `front_end/entrypoints/devtools_app/devtools_app.ts` to expose the global `testCssCompletion` hook.
16
+
17
+ Add the following code at the end of `front_end/entrypoints/devtools_app/devtools_app.ts`:
18
+
19
+ ```typescript
20
+ // --- TEMPORARY EVALUATION HOOK ---
21
+ // TEMPORARY PATCH - REMOVE BEFORE COMMIT
22
+
23
+ import * as Host from '../../core/host/host.js';
24
+ import * as AiCodeCompletion from '../../models/ai_code_completion/ai_code_completion.js';
25
+
26
+ (self as any).testCss = {
27
+ getCases() {
28
+ return [
29
+ {
30
+ name: 'Generic CSS Test Case',
31
+ url: null,
32
+ prefix: 'h1 { font-s',
33
+ suffix: ' }',
34
+ },
35
+ // Add more test cases here
36
+ ];
37
+ },
38
+
39
+ async evaluate(uiSourceCodeUrl: string | null, prefix: string, suffix: string, additionalFiles?: any[]) {
40
+ const aidaClient = new Host.AidaClient.AidaClient();
41
+ const completion = new AiCodeCompletion.AiCodeCompletion.AiCodeCompletion(
42
+ {aidaClient},
43
+ AiCodeCompletion.AiCodeCompletion.ContextFlavor.STYLES
44
+ );
45
+
46
+ const formattedAdditionalFiles = additionalFiles?.map(f => ({
47
+ path: f.path || f.name,
48
+ content: f.content || f.text,
49
+ included_reason: f.included_reason ?? Host.AidaClient.Reason.RELATED_FILE,
50
+ }));
51
+
52
+ const result = await completion.completeCode(
53
+ prefix,
54
+ suffix,
55
+ prefix.length,
56
+ Host.AidaClient.AidaInferenceLanguage.CSS,
57
+ formattedAdditionalFiles
58
+ );
59
+
60
+ return {
61
+ hasSuggestion: result.response !== null && result.response.generatedSamples.length > 0,
62
+ suggestions: result.response?.generatedSamples.map(s => s.generationString) ?? [],
63
+ injectedFiles: formattedAdditionalFiles?.map(f => f.path) ?? [],
64
+ };
65
+ }
66
+ };
67
+ // ----------------------------------
68
+ ```
69
+
70
+ ## Step 2: Launch Chrome with Local DevTools
71
+
72
+ Use the `npm start` script to build DevTools, launch Chrome Canary with remote debugging, and automatically load your local build.
73
+
74
+ You must specify a persistent user data directory so you can log in once and reuse the session:
75
+
76
+ ```bash
77
+ npm start -- --browser=canary --remote-debugging-port=9222 --user-data-dir=/tmp/devtools-ai-evaluate-css-completion
78
+ ```
79
+
80
+ > [!IMPORTANT]
81
+ > **Instructions for the Agent:**
82
+ > After launching Chrome, you MUST print the following checklist to the user and wait for their explicit confirmation before running the evaluation script:
83
+ > 1. Sign in to Chrome with your corporate account in the new window.
84
+ > 2. Open DevTools, go to **Settings** (gear icon) > **AI Innovations**, and ensure **Code Completions** is enabled.
85
+ > 3. Ask the user to reply when they are ready.
86
+
87
+ * Keep this process running (it will watch and rebuild changes).
88
+
89
+ ## Step 3: Configure Test Cases
90
+
91
+ Before running the evaluation, configure your test cases directly in `front_end/entrypoints/devtools_app/devtools_app.ts` inside the `getCases()` method of the patch you applied in Step 1.
92
+
93
+ For example, to test spacing sensitivity, update the returned array:
94
+ ```typescript
95
+ getCases() {
96
+ return [
97
+ {
98
+ name: 'With CSS Context',
99
+ url: null,
100
+ prefix: 'h1 { font-s',
101
+ suffix: ' }',
102
+ additionalFiles: [
103
+ {
104
+ path: 'other.css',
105
+ content: 'body { color: red; }',
106
+ }
107
+ ]
108
+ }
109
+ ];
110
+ }
111
+ ```
112
+
113
+ ## Step 4: Run the Evaluation Script
114
+
115
+ Run the Puppeteer script to execute the evaluation:
116
+
117
+ ```bash
118
+ node .agents/skills/evaluate-ai-css-completion/scripts/evaluate.js
119
+ ```
120
+
121
+ > [!IMPORTANT]
122
+ > **Instructions for the Agent:**
123
+ > Since the evaluation script runs asynchronously as a background task, you MUST use the `schedule` tool to check the log file of the evaluation task every 10 seconds until it completes. Do not poll using status checks in a loop.
124
+
125
+ The script will connect to the DevTools instance, trigger completions, and output the results.
126
+
127
+ ## Step 5: Revert the Patch
128
+
129
+ Once the evaluation is complete and you have recorded the results, revert the patch in `devtools_app.ts`:
130
+
131
+ ```bash
132
+ git checkout front_end/entrypoints/devtools_app/devtools_app.ts
133
+ ```
@@ -0,0 +1,76 @@
1
+ // Copyright 2026 The Chromium Authors
2
+ // Use of this source code is governed by a BSD-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ /* eslint-disable no-console */
6
+
7
+ const puppeteer = require('puppeteer-core');
8
+
9
+ async function runEvaluation() {
10
+ console.log('Connecting to Chrome...');
11
+ const browser = await puppeteer.connect({browserURL: 'http://127.0.0.1:9222', defaultViewport: null});
12
+
13
+ try {
14
+ console.log('Opening test page (example.com)...');
15
+ const testPage = await browser.newPage();
16
+ await testPage.goto('https://example.com');
17
+
18
+ console.log('Waiting for DevTools target...');
19
+ const devtoolsTarget = await browser.waitForTarget(t => {
20
+ return t.url().startsWith('devtools://') || t.url().includes('inspector.html');
21
+ }, {timeout: 10000});
22
+
23
+ console.log('Connecting to DevTools page...');
24
+ const devtoolsPage = await devtoolsTarget.page();
25
+ if (!devtoolsPage) {
26
+ throw new Error('Could not get DevTools page object. Make sure DevTools is undocked or opened in a tab.');
27
+ }
28
+ console.log('DevTools URL:', devtoolsPage.url());
29
+
30
+ console.log('Reloading DevTools to ensure patch is loaded...');
31
+ await devtoolsPage.reload();
32
+
33
+ console.log('Waiting for DevTools to initialize and hook to be available...');
34
+ try {
35
+ await devtoolsPage.waitForFunction(() => typeof self.testCss?.getCases === 'function', {timeout: 15000});
36
+ } catch {
37
+ throw new Error('testCss.getCases hook not found. Did you apply the patch and build? Is this the local build?');
38
+ }
39
+
40
+ console.log('Fetching test cases from DevTools...');
41
+ const testCases = await devtoolsPage.evaluate(() => self.testCss.getCases());
42
+ console.log(`Found ${testCases.length} test cases.`);
43
+
44
+ let testCount = 0;
45
+ for (const tc of testCases) {
46
+ console.log(`\nRunning: ${tc.name}`);
47
+ // Delay to avoid rate limiting
48
+ await new Promise(resolve => setTimeout(resolve, 1000));
49
+
50
+ try {
51
+ const result = await devtoolsPage.evaluate(async (url, prefix, suffix, additionalFiles) => {
52
+ return await self.testCss.evaluate(url, prefix, suffix, additionalFiles);
53
+ }, tc.url, tc.prefix, tc.suffix, tc.additionalFiles);
54
+
55
+ console.log(' Result:', result);
56
+ } catch (e) {
57
+ console.error(' Failed to run test case:', e.message);
58
+ }
59
+
60
+ testCount++;
61
+ if (testCount % 20 === 0 && testCount < testCases.length) {
62
+ console.log('\n[INFO] Pausing for 10 seconds to avoid rate limiting...');
63
+ await new Promise(resolve => setTimeout(resolve, 10000));
64
+ }
65
+ }
66
+
67
+ // Cleanup tabs
68
+ await devtoolsPage.close();
69
+ await testPage.close();
70
+ } finally {
71
+ console.log('Disconnecting from Chrome...');
72
+ await browser.disconnect();
73
+ }
74
+ }
75
+
76
+ runEvaluation().catch(console.error);
package/eslint.config.mjs CHANGED
@@ -691,6 +691,13 @@ export default defineConfig([
691
691
  'lit/quoted-expressions': ['error', 'never'],
692
692
  },
693
693
  },
694
+ {
695
+ name: 'Front-end core files',
696
+ files: ['front_end/core/**/*.ts'],
697
+ rules: {
698
+ '@devtools/no-instance-of-migrated-singletons': 'error',
699
+ },
700
+ },
694
701
  {
695
702
  name: 'Front-end meta files',
696
703
  files: ['front_end/**/*-meta.ts'],
@@ -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(
@@ -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
  }
@@ -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
 
@@ -55,9 +55,9 @@ export class CompilerScriptMapping implements DebuggerSourceMapping {
55
55
  this.#debuggerModel = debuggerModel;
56
56
  this.#ignoreListManager = debuggerWorkspaceBinding.ignoreListManager;
57
57
 
58
- this.#stubProject = new ContentProviderBasedProject(
59
- workspace, 'jsSourceMaps:stub:' + debuggerModel.target().id(), Workspace.Workspace.projectTypes.Service, '',
60
- true /* isServiceProject */);
58
+ this.#stubProject = new ContentProviderBasedProject(workspace, 'jsSourceMaps:stub:' + debuggerModel.target().id(),
59
+ Workspace.Workspace.projectTypes.Service, '',
60
+ true /* isServiceProject */, debuggerModel.target());
61
61
  this.#eventListeners = [
62
62
  this.#sourceMapManager.addEventListener(
63
63
  SDK.SourceMapManager.Events.SourceMapWillAttach, this.sourceMapWillAttach, this),
@@ -463,9 +463,8 @@ export class CompilerScriptMapping implements DebuggerSourceMapping {
463
463
  if (!project) {
464
464
  const projectType = script.isContentScript() ? Workspace.Workspace.projectTypes.ContentScripts :
465
465
  Workspace.Workspace.projectTypes.Network;
466
- project = new ContentProviderBasedProject(
467
- this.#stubProject.workspace(), projectId, projectType, /* displayName */ '', /* isServiceProject */ false);
468
- NetworkProject.setTargetForProject(project, target);
466
+ project = new ContentProviderBasedProject(this.#stubProject.workspace(), projectId, projectType,
467
+ /* displayName */ '', /* isServiceProject */ false, target);
469
468
  this.#projects.set(projectId, project);
470
469
  }
471
470
  this.#sourceMapToProject.set(sourceMap, project);