chrome-devtools-mcp 0.0.2 → 0.2.0
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/README.md +6 -3
- package/build/node_modules/chrome-devtools-frontend/front_end/core/common/Settings.js +3 -32
- package/build/node_modules/chrome-devtools-frontend/front_end/core/i18n/i18n.js +35 -8
- package/build/node_modules/chrome-devtools-frontend/front_end/core/root/Runtime.js +4 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/generated/InspectorBackendCommands.js +4 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/generated/SupportedCSSProperties.js +12 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.js +366 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AICallTree.js +366 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AIContext.js +64 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/ai_assistance/performance/AIQueries.js +105 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/CSSWorkspaceBinding.js +243 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/CompilerScriptMapping.js +407 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/ContentProviderBasedProject.js +128 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/DebuggerLanguagePlugins.js +992 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/DebuggerWorkspaceBinding.js +574 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/DefaultScriptMapping.js +112 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/FileUtils.js +186 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/LiveLocation.js +60 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/NetworkProject.js +107 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/PresentationConsoleMessageHelper.js +244 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/ResourceMapping.js +473 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/ResourceScriptMapping.js +399 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/ResourceUtils.js +87 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/SASSSourceMapping.js +181 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/StylesSourceMapping.js +268 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/TempFile.js +55 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/bindings.js +20 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/crux-manager/CrUXManager.js +283 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/crux-manager/crux-manager.js +4 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/emulation/DeviceModeModel.js +775 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/emulation/EmulatedDevices.js +1706 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/emulation/emulation.js +6 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/formatter/FormatterWorkerPool.js +131 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/formatter/ScriptFormatter.js +77 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/formatter/formatter.js +6 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/geometry/GeometryImpl.js +347 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/geometry/geometry.js +4 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/source_map_scopes/NamesResolver.js +626 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/source_map_scopes/ScopeChainModel.js +59 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/source_map_scopes/ScopeTreeCache.js +32 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/source_map_scopes/source_map_scopes.js +7 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/stack_trace/StackTrace.js +4 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/stack_trace/StackTraceImpl.js +67 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/stack_trace/StackTraceModel.js +97 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/stack_trace/Trie.js +113 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/stack_trace/stack_trace.js +5 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/stack_trace/stack_trace_impl.js +7 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/text_utils/TextUtils.js +23 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/Processor.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/helpers/Trace.js +1 -1
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace/insights/DocumentLatency.js +5 -4
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace_source_maps_resolver/SourceMapsResolver.js +199 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/trace_source_maps_resolver/trace_source_maps_resolver.js +4 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/workspace/FileManager.js +64 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/workspace/IgnoreListManager.js +511 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/workspace/SearchConfig.js +113 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/workspace/UISourceCode.js +563 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/workspace/WorkspaceImpl.js +204 -0
- package/build/node_modules/chrome-devtools-frontend/front_end/models/workspace/workspace.js +9 -0
- package/build/src/McpContext.js +24 -9
- package/build/src/McpResponse.js +3 -3
- package/build/src/browser.js +3 -1
- package/build/src/index.js +1 -1
- package/build/src/tools/input.js +7 -7
- package/build/src/tools/performance.js +29 -2
- package/build/src/tools/screenshot.js +1 -1
- package/build/src/tools/script.js +40 -14
- package/build/src/trace-processing/parse.js +26 -22
- package/package.json +9 -7
package/build/node_modules/chrome-devtools-frontend/front_end/models/bindings/ResourceMapping.js
ADDED
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
// Copyright 2017 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
|
+
import * as Common from '../../core/common/common.js';
|
|
5
|
+
import * as SDK from '../../core/sdk/sdk.js';
|
|
6
|
+
import * as TextUtils from '../text_utils/text_utils.js';
|
|
7
|
+
import * as Workspace from '../workspace/workspace.js';
|
|
8
|
+
import { ContentProviderBasedProject } from './ContentProviderBasedProject.js';
|
|
9
|
+
import { CSSWorkspaceBinding } from './CSSWorkspaceBinding.js';
|
|
10
|
+
import { DebuggerWorkspaceBinding } from './DebuggerWorkspaceBinding.js';
|
|
11
|
+
import { NetworkProject } from './NetworkProject.js';
|
|
12
|
+
import { resourceMetadata } from './ResourceUtils.js';
|
|
13
|
+
const styleSheetRangeMap = new WeakMap();
|
|
14
|
+
const scriptRangeMap = new WeakMap();
|
|
15
|
+
const boundUISourceCodes = new WeakSet();
|
|
16
|
+
function computeScriptRange(script) {
|
|
17
|
+
return new TextUtils.TextRange.TextRange(script.lineOffset, script.columnOffset, script.endLine, script.endColumn);
|
|
18
|
+
}
|
|
19
|
+
function computeStyleSheetRange(header) {
|
|
20
|
+
return new TextUtils.TextRange.TextRange(header.startLine, header.startColumn, header.endLine, header.endColumn);
|
|
21
|
+
}
|
|
22
|
+
export class ResourceMapping {
|
|
23
|
+
workspace;
|
|
24
|
+
#modelToInfo = new Map();
|
|
25
|
+
constructor(targetManager, workspace) {
|
|
26
|
+
this.workspace = workspace;
|
|
27
|
+
targetManager.observeModels(SDK.ResourceTreeModel.ResourceTreeModel, this);
|
|
28
|
+
}
|
|
29
|
+
modelAdded(resourceTreeModel) {
|
|
30
|
+
const info = new ModelInfo(this.workspace, resourceTreeModel);
|
|
31
|
+
this.#modelToInfo.set(resourceTreeModel, info);
|
|
32
|
+
}
|
|
33
|
+
modelRemoved(resourceTreeModel) {
|
|
34
|
+
const info = this.#modelToInfo.get(resourceTreeModel);
|
|
35
|
+
if (info) {
|
|
36
|
+
info.dispose();
|
|
37
|
+
this.#modelToInfo.delete(resourceTreeModel);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
infoForTarget(target) {
|
|
41
|
+
const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);
|
|
42
|
+
return resourceTreeModel ? this.#modelToInfo.get(resourceTreeModel) || null : null;
|
|
43
|
+
}
|
|
44
|
+
uiSourceCodeForScript(script) {
|
|
45
|
+
const info = this.infoForTarget(script.debuggerModel.target());
|
|
46
|
+
if (!info) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const project = info.getProject();
|
|
50
|
+
const uiSourceCode = project.uiSourceCodeForURL(script.sourceURL);
|
|
51
|
+
return uiSourceCode;
|
|
52
|
+
}
|
|
53
|
+
cssLocationToUILocation(cssLocation) {
|
|
54
|
+
const header = cssLocation.header();
|
|
55
|
+
if (!header) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
const info = this.infoForTarget(cssLocation.cssModel().target());
|
|
59
|
+
if (!info) {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
const uiSourceCode = info.getProject().uiSourceCodeForURL(cssLocation.url);
|
|
63
|
+
if (!uiSourceCode) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
const offset = styleSheetRangeMap.get(header) ?? computeStyleSheetRange(header);
|
|
67
|
+
const lineNumber = cssLocation.lineNumber + offset.startLine - header.startLine;
|
|
68
|
+
let columnNumber = cssLocation.columnNumber;
|
|
69
|
+
if (cssLocation.lineNumber === header.startLine) {
|
|
70
|
+
columnNumber += offset.startColumn - header.startColumn;
|
|
71
|
+
}
|
|
72
|
+
return uiSourceCode.uiLocation(lineNumber, columnNumber);
|
|
73
|
+
}
|
|
74
|
+
jsLocationToUILocation(jsLocation) {
|
|
75
|
+
const script = jsLocation.script();
|
|
76
|
+
if (!script) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
const info = this.infoForTarget(jsLocation.debuggerModel.target());
|
|
80
|
+
if (!info) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
const embedderName = script.embedderName();
|
|
84
|
+
if (!embedderName) {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
const uiSourceCode = info.getProject().uiSourceCodeForURL(embedderName);
|
|
88
|
+
if (!uiSourceCode) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
const { startLine, startColumn } = scriptRangeMap.get(script) ?? computeScriptRange(script);
|
|
92
|
+
let { lineNumber, columnNumber } = jsLocation;
|
|
93
|
+
if (lineNumber === script.lineOffset) {
|
|
94
|
+
columnNumber += startColumn - script.columnOffset;
|
|
95
|
+
}
|
|
96
|
+
lineNumber += startLine - script.lineOffset;
|
|
97
|
+
if (script.hasSourceURL) {
|
|
98
|
+
if (lineNumber === 0) {
|
|
99
|
+
columnNumber += script.columnOffset;
|
|
100
|
+
}
|
|
101
|
+
lineNumber += script.lineOffset;
|
|
102
|
+
}
|
|
103
|
+
return uiSourceCode.uiLocation(lineNumber, columnNumber);
|
|
104
|
+
}
|
|
105
|
+
uiLocationToJSLocations(uiSourceCode, lineNumber, columnNumber) {
|
|
106
|
+
if (!boundUISourceCodes.has(uiSourceCode)) {
|
|
107
|
+
return [];
|
|
108
|
+
}
|
|
109
|
+
const target = NetworkProject.targetForUISourceCode(uiSourceCode);
|
|
110
|
+
if (!target) {
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
const debuggerModel = target.model(SDK.DebuggerModel.DebuggerModel);
|
|
114
|
+
if (!debuggerModel) {
|
|
115
|
+
return [];
|
|
116
|
+
}
|
|
117
|
+
const locations = [];
|
|
118
|
+
for (const script of debuggerModel.scripts()) {
|
|
119
|
+
if (script.embedderName() !== uiSourceCode.url()) {
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
const range = scriptRangeMap.get(script) ?? computeScriptRange(script);
|
|
123
|
+
if (!range.containsLocation(lineNumber, columnNumber)) {
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
let scriptLineNumber = lineNumber;
|
|
127
|
+
let scriptColumnNumber = columnNumber;
|
|
128
|
+
if (script.hasSourceURL) {
|
|
129
|
+
scriptLineNumber -= range.startLine;
|
|
130
|
+
if (scriptLineNumber === 0) {
|
|
131
|
+
scriptColumnNumber -= range.startColumn;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
locations.push(debuggerModel.createRawLocation(script, scriptLineNumber, scriptColumnNumber));
|
|
135
|
+
}
|
|
136
|
+
return locations;
|
|
137
|
+
}
|
|
138
|
+
uiLocationRangeToJSLocationRanges(uiSourceCode, textRange) {
|
|
139
|
+
if (!boundUISourceCodes.has(uiSourceCode)) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
const target = NetworkProject.targetForUISourceCode(uiSourceCode);
|
|
143
|
+
if (!target) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
const debuggerModel = target.model(SDK.DebuggerModel.DebuggerModel);
|
|
147
|
+
if (!debuggerModel) {
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
const ranges = [];
|
|
151
|
+
for (const script of debuggerModel.scripts()) {
|
|
152
|
+
if (script.embedderName() !== uiSourceCode.url()) {
|
|
153
|
+
continue;
|
|
154
|
+
}
|
|
155
|
+
const scriptTextRange = scriptRangeMap.get(script) ?? computeScriptRange(script);
|
|
156
|
+
const range = scriptTextRange.intersection(textRange);
|
|
157
|
+
if (range.isEmpty()) {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
let { startLine, startColumn, endLine, endColumn } = range;
|
|
161
|
+
if (script.hasSourceURL) {
|
|
162
|
+
startLine -= range.startLine;
|
|
163
|
+
if (startLine === 0) {
|
|
164
|
+
startColumn -= range.startColumn;
|
|
165
|
+
}
|
|
166
|
+
endLine -= range.startLine;
|
|
167
|
+
if (endLine === 0) {
|
|
168
|
+
endColumn -= range.startColumn;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
const start = debuggerModel.createRawLocation(script, startLine, startColumn);
|
|
172
|
+
const end = debuggerModel.createRawLocation(script, endLine, endColumn);
|
|
173
|
+
ranges.push({ start, end });
|
|
174
|
+
}
|
|
175
|
+
return ranges;
|
|
176
|
+
}
|
|
177
|
+
getMappedLines(uiSourceCode) {
|
|
178
|
+
if (!boundUISourceCodes.has(uiSourceCode)) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
const target = NetworkProject.targetForUISourceCode(uiSourceCode);
|
|
182
|
+
if (!target) {
|
|
183
|
+
return null;
|
|
184
|
+
}
|
|
185
|
+
const debuggerModel = target.model(SDK.DebuggerModel.DebuggerModel);
|
|
186
|
+
if (!debuggerModel) {
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
const mappedLines = new Set();
|
|
190
|
+
for (const script of debuggerModel.scripts()) {
|
|
191
|
+
if (script.embedderName() !== uiSourceCode.url()) {
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
const { startLine, endLine } = scriptRangeMap.get(script) ?? computeScriptRange(script);
|
|
195
|
+
for (let line = startLine; line <= endLine; ++line) {
|
|
196
|
+
mappedLines.add(line);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return mappedLines;
|
|
200
|
+
}
|
|
201
|
+
uiLocationToCSSLocations(uiLocation) {
|
|
202
|
+
if (!boundUISourceCodes.has(uiLocation.uiSourceCode)) {
|
|
203
|
+
return [];
|
|
204
|
+
}
|
|
205
|
+
const target = NetworkProject.targetForUISourceCode(uiLocation.uiSourceCode);
|
|
206
|
+
if (!target) {
|
|
207
|
+
return [];
|
|
208
|
+
}
|
|
209
|
+
const cssModel = target.model(SDK.CSSModel.CSSModel);
|
|
210
|
+
if (!cssModel) {
|
|
211
|
+
return [];
|
|
212
|
+
}
|
|
213
|
+
return cssModel.createRawLocationsByURL(uiLocation.uiSourceCode.url(), uiLocation.lineNumber, uiLocation.columnNumber);
|
|
214
|
+
}
|
|
215
|
+
resetForTest(target) {
|
|
216
|
+
const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);
|
|
217
|
+
const info = resourceTreeModel ? this.#modelToInfo.get(resourceTreeModel) : null;
|
|
218
|
+
if (info) {
|
|
219
|
+
info.resetForTest();
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
class ModelInfo {
|
|
224
|
+
project;
|
|
225
|
+
#bindings = new Map();
|
|
226
|
+
#cssModel;
|
|
227
|
+
#eventListeners;
|
|
228
|
+
constructor(workspace, resourceTreeModel) {
|
|
229
|
+
const target = resourceTreeModel.target();
|
|
230
|
+
this.project = new ContentProviderBasedProject(workspace, 'resources:' + target.id(), Workspace.Workspace.projectTypes.Network, '', false /* isServiceProject */);
|
|
231
|
+
NetworkProject.setTargetForProject(this.project, target);
|
|
232
|
+
const cssModel = target.model(SDK.CSSModel.CSSModel);
|
|
233
|
+
console.assert(Boolean(cssModel));
|
|
234
|
+
this.#cssModel = cssModel;
|
|
235
|
+
for (const frame of resourceTreeModel.frames()) {
|
|
236
|
+
for (const resource of frame.getResourcesMap().values()) {
|
|
237
|
+
this.addResource(resource);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
this.#eventListeners = [
|
|
241
|
+
resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.ResourceAdded, this.resourceAdded, this),
|
|
242
|
+
resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.FrameWillNavigate, this.frameWillNavigate, this),
|
|
243
|
+
resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.FrameDetached, this.frameDetached, this),
|
|
244
|
+
this.#cssModel.addEventListener(SDK.CSSModel.Events.StyleSheetChanged, event => {
|
|
245
|
+
void this.styleSheetChanged(event);
|
|
246
|
+
}, this),
|
|
247
|
+
];
|
|
248
|
+
}
|
|
249
|
+
async styleSheetChanged(event) {
|
|
250
|
+
const header = this.#cssModel.styleSheetHeaderForId(event.data.styleSheetId);
|
|
251
|
+
if (!header || !header.isInline || (header.isInline && header.isMutable)) {
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const binding = this.#bindings.get(header.resourceURL());
|
|
255
|
+
if (!binding) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
await binding.styleSheetChanged(header, event.data.edit || null);
|
|
259
|
+
}
|
|
260
|
+
acceptsResource(resource) {
|
|
261
|
+
const resourceType = resource.resourceType();
|
|
262
|
+
// Only load selected resource types from resources.
|
|
263
|
+
if (resourceType !== Common.ResourceType.resourceTypes.Image &&
|
|
264
|
+
resourceType !== Common.ResourceType.resourceTypes.Font &&
|
|
265
|
+
resourceType !== Common.ResourceType.resourceTypes.Document &&
|
|
266
|
+
resourceType !== Common.ResourceType.resourceTypes.Manifest &&
|
|
267
|
+
resourceType !== Common.ResourceType.resourceTypes.Fetch &&
|
|
268
|
+
resourceType !== Common.ResourceType.resourceTypes.XHR) {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
// Ignore non-images and non-fonts.
|
|
272
|
+
if (resourceType === Common.ResourceType.resourceTypes.Image && resource.mimeType &&
|
|
273
|
+
!resource.mimeType.startsWith('image')) {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
if (resourceType === Common.ResourceType.resourceTypes.Font && resource.mimeType &&
|
|
277
|
+
!resource.mimeType.includes('font')) {
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
if ((resourceType === Common.ResourceType.resourceTypes.Image ||
|
|
281
|
+
resourceType === Common.ResourceType.resourceTypes.Font) &&
|
|
282
|
+
Common.ParsedURL.schemeIs(resource.contentURL(), 'data:')) {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
return true;
|
|
286
|
+
}
|
|
287
|
+
resourceAdded(event) {
|
|
288
|
+
this.addResource(event.data);
|
|
289
|
+
}
|
|
290
|
+
addResource(resource) {
|
|
291
|
+
if (!this.acceptsResource(resource)) {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
let binding = this.#bindings.get(resource.url);
|
|
295
|
+
if (!binding) {
|
|
296
|
+
binding = new Binding(this.project, resource);
|
|
297
|
+
this.#bindings.set(resource.url, binding);
|
|
298
|
+
}
|
|
299
|
+
else {
|
|
300
|
+
binding.addResource(resource);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
removeFrameResources(frame) {
|
|
304
|
+
for (const resource of frame.resources()) {
|
|
305
|
+
if (!this.acceptsResource(resource)) {
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
const binding = this.#bindings.get(resource.url);
|
|
309
|
+
if (!binding) {
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
if (binding.resources.size === 1) {
|
|
313
|
+
binding.dispose();
|
|
314
|
+
this.#bindings.delete(resource.url);
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
binding.removeResource(resource);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
frameWillNavigate(event) {
|
|
322
|
+
this.removeFrameResources(event.data);
|
|
323
|
+
}
|
|
324
|
+
frameDetached(event) {
|
|
325
|
+
this.removeFrameResources(event.data.frame);
|
|
326
|
+
}
|
|
327
|
+
resetForTest() {
|
|
328
|
+
for (const binding of this.#bindings.values()) {
|
|
329
|
+
binding.dispose();
|
|
330
|
+
}
|
|
331
|
+
this.#bindings.clear();
|
|
332
|
+
}
|
|
333
|
+
dispose() {
|
|
334
|
+
Common.EventTarget.removeEventListeners(this.#eventListeners);
|
|
335
|
+
for (const binding of this.#bindings.values()) {
|
|
336
|
+
binding.dispose();
|
|
337
|
+
}
|
|
338
|
+
this.#bindings.clear();
|
|
339
|
+
this.project.removeProject();
|
|
340
|
+
}
|
|
341
|
+
getProject() {
|
|
342
|
+
return this.project;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
class Binding {
|
|
346
|
+
resources;
|
|
347
|
+
#project;
|
|
348
|
+
#uiSourceCode;
|
|
349
|
+
#edits = [];
|
|
350
|
+
constructor(project, resource) {
|
|
351
|
+
this.resources = new Set([resource]);
|
|
352
|
+
this.#project = project;
|
|
353
|
+
this.#uiSourceCode = this.#project.createUISourceCode(resource.url, resource.contentType());
|
|
354
|
+
boundUISourceCodes.add(this.#uiSourceCode);
|
|
355
|
+
if (resource.frameId) {
|
|
356
|
+
NetworkProject.setInitialFrameAttribution(this.#uiSourceCode, resource.frameId);
|
|
357
|
+
}
|
|
358
|
+
this.#project.addUISourceCodeWithProvider(this.#uiSourceCode, this, resourceMetadata(resource), resource.mimeType);
|
|
359
|
+
void Promise.all([
|
|
360
|
+
...this.inlineScripts().map(script => DebuggerWorkspaceBinding.instance().updateLocations(script)),
|
|
361
|
+
...this.inlineStyles().map(style => CSSWorkspaceBinding.instance().updateLocations(style)),
|
|
362
|
+
]);
|
|
363
|
+
}
|
|
364
|
+
inlineStyles() {
|
|
365
|
+
const target = NetworkProject.targetForUISourceCode(this.#uiSourceCode);
|
|
366
|
+
const stylesheets = [];
|
|
367
|
+
if (!target) {
|
|
368
|
+
return stylesheets;
|
|
369
|
+
}
|
|
370
|
+
const cssModel = target.model(SDK.CSSModel.CSSModel);
|
|
371
|
+
if (cssModel) {
|
|
372
|
+
for (const headerId of cssModel.getStyleSheetIdsForURL(this.#uiSourceCode.url())) {
|
|
373
|
+
const header = cssModel.styleSheetHeaderForId(headerId);
|
|
374
|
+
if (header) {
|
|
375
|
+
stylesheets.push(header);
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
return stylesheets;
|
|
380
|
+
}
|
|
381
|
+
inlineScripts() {
|
|
382
|
+
const target = NetworkProject.targetForUISourceCode(this.#uiSourceCode);
|
|
383
|
+
if (!target) {
|
|
384
|
+
return [];
|
|
385
|
+
}
|
|
386
|
+
const debuggerModel = target.model(SDK.DebuggerModel.DebuggerModel);
|
|
387
|
+
if (!debuggerModel) {
|
|
388
|
+
return [];
|
|
389
|
+
}
|
|
390
|
+
return debuggerModel.scripts().filter(script => script.embedderName() === this.#uiSourceCode.url());
|
|
391
|
+
}
|
|
392
|
+
async styleSheetChanged(stylesheet, edit) {
|
|
393
|
+
this.#edits.push({ stylesheet, edit });
|
|
394
|
+
if (this.#edits.length > 1) {
|
|
395
|
+
return;
|
|
396
|
+
} // There is already a styleSheetChanged loop running
|
|
397
|
+
const content = await this.#uiSourceCode.requestContentData();
|
|
398
|
+
if (!TextUtils.ContentData.ContentData.isError(content)) {
|
|
399
|
+
await this.innerStyleSheetChanged(content.text);
|
|
400
|
+
}
|
|
401
|
+
this.#edits = [];
|
|
402
|
+
}
|
|
403
|
+
async innerStyleSheetChanged(content) {
|
|
404
|
+
const scripts = this.inlineScripts();
|
|
405
|
+
const styles = this.inlineStyles();
|
|
406
|
+
let text = new TextUtils.Text.Text(content);
|
|
407
|
+
for (const data of this.#edits) {
|
|
408
|
+
const edit = data.edit;
|
|
409
|
+
if (!edit) {
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
const stylesheet = data.stylesheet;
|
|
413
|
+
const startLocation = styleSheetRangeMap.get(stylesheet) ?? computeStyleSheetRange(stylesheet);
|
|
414
|
+
const oldRange = edit.oldRange.relativeFrom(startLocation.startLine, startLocation.startColumn);
|
|
415
|
+
const newRange = edit.newRange.relativeFrom(startLocation.startLine, startLocation.startColumn);
|
|
416
|
+
text = new TextUtils.Text.Text(text.replaceRange(oldRange, edit.newText));
|
|
417
|
+
const updatePromises = [];
|
|
418
|
+
for (const script of scripts) {
|
|
419
|
+
const range = scriptRangeMap.get(script) ?? computeScriptRange(script);
|
|
420
|
+
if (!range.follows(oldRange)) {
|
|
421
|
+
continue;
|
|
422
|
+
}
|
|
423
|
+
scriptRangeMap.set(script, range.rebaseAfterTextEdit(oldRange, newRange));
|
|
424
|
+
updatePromises.push(DebuggerWorkspaceBinding.instance().updateLocations(script));
|
|
425
|
+
}
|
|
426
|
+
for (const style of styles) {
|
|
427
|
+
const range = styleSheetRangeMap.get(style) ?? computeStyleSheetRange(style);
|
|
428
|
+
if (!range.follows(oldRange)) {
|
|
429
|
+
continue;
|
|
430
|
+
}
|
|
431
|
+
styleSheetRangeMap.set(style, range.rebaseAfterTextEdit(oldRange, newRange));
|
|
432
|
+
updatePromises.push(CSSWorkspaceBinding.instance().updateLocations(style));
|
|
433
|
+
}
|
|
434
|
+
await Promise.all(updatePromises);
|
|
435
|
+
}
|
|
436
|
+
this.#uiSourceCode.addRevision(text.value());
|
|
437
|
+
}
|
|
438
|
+
addResource(resource) {
|
|
439
|
+
this.resources.add(resource);
|
|
440
|
+
if (resource.frameId) {
|
|
441
|
+
NetworkProject.addFrameAttribution(this.#uiSourceCode, resource.frameId);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
removeResource(resource) {
|
|
445
|
+
this.resources.delete(resource);
|
|
446
|
+
if (resource.frameId) {
|
|
447
|
+
NetworkProject.removeFrameAttribution(this.#uiSourceCode, resource.frameId);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
dispose() {
|
|
451
|
+
this.#project.removeUISourceCode(this.#uiSourceCode.url());
|
|
452
|
+
void Promise.all([
|
|
453
|
+
...this.inlineScripts().map(script => DebuggerWorkspaceBinding.instance().updateLocations(script)),
|
|
454
|
+
...this.inlineStyles().map(style => CSSWorkspaceBinding.instance().updateLocations(style)),
|
|
455
|
+
]);
|
|
456
|
+
}
|
|
457
|
+
firstResource() {
|
|
458
|
+
console.assert(this.resources.size > 0);
|
|
459
|
+
return this.resources.values().next().value;
|
|
460
|
+
}
|
|
461
|
+
contentURL() {
|
|
462
|
+
return this.firstResource().contentURL();
|
|
463
|
+
}
|
|
464
|
+
contentType() {
|
|
465
|
+
return this.firstResource().contentType();
|
|
466
|
+
}
|
|
467
|
+
requestContentData() {
|
|
468
|
+
return this.firstResource().requestContentData();
|
|
469
|
+
}
|
|
470
|
+
searchInContent(query, caseSensitive, isRegex) {
|
|
471
|
+
return this.firstResource().searchInContent(query, caseSensitive, isRegex);
|
|
472
|
+
}
|
|
473
|
+
}
|