devtools-tracing 1.0.1 → 1.1.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.
Files changed (132) hide show
  1. package/generate.ts +32 -26
  2. package/index.ts +2 -1
  3. package/lib/extension-api/ExtensionAPI.d.ts +357 -0
  4. package/lib/front_end/models/bindings/CSSWorkspaceBinding.ts +318 -0
  5. package/lib/front_end/models/bindings/CompilerScriptMapping.ts +536 -0
  6. package/lib/front_end/models/bindings/ContentProviderBasedProject.ts +187 -0
  7. package/lib/front_end/models/bindings/DebuggerLanguagePlugins.ts +1197 -0
  8. package/lib/front_end/models/bindings/DebuggerWorkspaceBinding.ts +733 -0
  9. package/lib/front_end/models/bindings/DefaultScriptMapping.ts +141 -0
  10. package/lib/front_end/models/bindings/FileUtils.ts +228 -0
  11. package/lib/front_end/models/bindings/LiveLocation.ts +81 -0
  12. package/lib/front_end/models/bindings/NetworkProject.ts +157 -0
  13. package/lib/front_end/models/bindings/PresentationConsoleMessageHelper.ts +312 -0
  14. package/lib/front_end/models/bindings/ResourceMapping.ts +539 -0
  15. package/lib/front_end/models/bindings/ResourceScriptMapping.ts +491 -0
  16. package/lib/front_end/models/bindings/ResourceUtils.ts +103 -0
  17. package/lib/front_end/models/bindings/SASSSourceMapping.ts +222 -0
  18. package/lib/front_end/models/bindings/StylesSourceMapping.ts +316 -0
  19. package/lib/front_end/models/bindings/TempFile.ts +67 -0
  20. package/lib/front_end/models/bindings/bindings.ts +39 -0
  21. package/lib/front_end/models/source_map_scopes/NamesResolver.ts +765 -0
  22. package/lib/front_end/models/source_map_scopes/ScopeChainModel.ts +84 -0
  23. package/lib/front_end/models/source_map_scopes/source_map_scopes.ts +11 -0
  24. package/lib/front_end/models/stack_trace/StackTrace.ts +53 -0
  25. package/lib/front_end/models/stack_trace/StackTraceImpl.ts +85 -0
  26. package/lib/front_end/models/stack_trace/StackTraceModel.ts +128 -0
  27. package/lib/front_end/models/stack_trace/Trie.ts +163 -0
  28. package/lib/front_end/models/stack_trace/stack_trace.ts +9 -0
  29. package/lib/front_end/models/stack_trace/stack_trace_impl.ts +13 -0
  30. package/lib/front_end/models/trace_source_maps_resolver/SourceMapsResolver.ts +240 -0
  31. package/lib/front_end/models/trace_source_maps_resolver/trace_source_maps_resolver.ts +5 -0
  32. package/lib/front_end/models/workspace/FileManager.ts +97 -0
  33. package/lib/front_end/models/workspace/IgnoreListManager.ts +628 -0
  34. package/lib/front_end/models/workspace/SearchConfig.ts +149 -0
  35. package/lib/front_end/models/workspace/UISourceCode.ts +698 -0
  36. package/lib/front_end/models/workspace/WorkspaceImpl.ts +339 -0
  37. package/lib/front_end/models/workspace/workspace.ts +17 -0
  38. package/lib/front_end/panels/timeline/TimelineUIUtils.ts +1029 -0
  39. package/lib/front_end/panels/timeline/extensions/ExtensionUI.ts +49 -0
  40. package/lib/front_end/panels/timeline/extensions/extensions.ts +9 -0
  41. package/lib/front_end/third_party/codemirror.next/LICENSE +21 -0
  42. package/lib/front_end/third_party/codemirror.next/README.chromium +30 -0
  43. package/lib/front_end/third_party/codemirror.next/bundle-tsconfig.json +24 -0
  44. package/lib/front_end/third_party/codemirror.next/bundle.ts +135 -0
  45. package/lib/front_end/third_party/codemirror.next/chunk/angular.js +2 -0
  46. package/lib/front_end/third_party/codemirror.next/chunk/angular.js.map +1 -0
  47. package/lib/front_end/third_party/codemirror.next/chunk/codemirror.js +2 -0
  48. package/lib/front_end/third_party/codemirror.next/chunk/codemirror.js.map +1 -0
  49. package/lib/front_end/third_party/codemirror.next/chunk/cpp.js +2 -0
  50. package/lib/front_end/third_party/codemirror.next/chunk/cpp.js.map +1 -0
  51. package/lib/front_end/third_party/codemirror.next/chunk/css.js +2 -0
  52. package/lib/front_end/third_party/codemirror.next/chunk/html.js +4 -0
  53. package/lib/front_end/third_party/codemirror.next/chunk/java.js +2 -0
  54. package/lib/front_end/third_party/codemirror.next/chunk/java.js.map +1 -0
  55. package/lib/front_end/third_party/codemirror.next/chunk/javascript.js +2 -0
  56. package/lib/front_end/third_party/codemirror.next/chunk/legacy.js +2 -0
  57. package/lib/front_end/third_party/codemirror.next/chunk/legacy.js.map +1 -0
  58. package/lib/front_end/third_party/codemirror.next/chunk/less.js +2 -0
  59. package/lib/front_end/third_party/codemirror.next/chunk/less.js.map +1 -0
  60. package/lib/front_end/third_party/codemirror.next/chunk/markdown.js +2 -0
  61. package/lib/front_end/third_party/codemirror.next/chunk/markdown.js.map +1 -0
  62. package/lib/front_end/third_party/codemirror.next/chunk/php.js +2 -0
  63. package/lib/front_end/third_party/codemirror.next/chunk/php.js.map +1 -0
  64. package/lib/front_end/third_party/codemirror.next/chunk/python.js +2 -0
  65. package/lib/front_end/third_party/codemirror.next/chunk/python.js.map +1 -0
  66. package/lib/front_end/third_party/codemirror.next/chunk/sass.js +2 -0
  67. package/lib/front_end/third_party/codemirror.next/chunk/sass.js.map +1 -0
  68. package/lib/front_end/third_party/codemirror.next/chunk/svelte.js +2 -0
  69. package/lib/front_end/third_party/codemirror.next/chunk/svelte.js.map +1 -0
  70. package/lib/front_end/third_party/codemirror.next/chunk/vue.js +2 -0
  71. package/lib/front_end/third_party/codemirror.next/chunk/vue.js.map +1 -0
  72. package/lib/front_end/third_party/codemirror.next/chunk/wast.js +2 -0
  73. package/lib/front_end/third_party/codemirror.next/chunk/wast.js.map +1 -0
  74. package/lib/front_end/third_party/codemirror.next/chunk/xml.js +2 -0
  75. package/lib/front_end/third_party/codemirror.next/chunk/xml.js.map +1 -0
  76. package/lib/front_end/third_party/codemirror.next/codemirror.next.d.ts +8057 -0
  77. package/lib/front_end/third_party/codemirror.next/codemirror.next.js +2 -0
  78. package/lib/front_end/third_party/codemirror.next/codemirror.next.js.map +1 -0
  79. package/lib/front_end/third_party/codemirror.next/package.json +43 -0
  80. package/lib/front_end/third_party/codemirror.next/rebuild.sh +6 -0
  81. package/lib/front_end/third_party/codemirror.next/rollup.config.mjs +49 -0
  82. package/lib/front_end/third_party/source-map-scopes-codec/LICENSE +26 -0
  83. package/lib/front_end/third_party/source-map-scopes-codec/README.chromium +31 -0
  84. package/lib/front_end/third_party/source-map-scopes-codec/package/CONTRIBUTING.md +33 -0
  85. package/lib/front_end/third_party/source-map-scopes-codec/package/LICENSE +26 -0
  86. package/lib/front_end/third_party/source-map-scopes-codec/package/README.md +64 -0
  87. package/lib/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/builder.d.ts +62 -0
  88. package/lib/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/builder.d.ts.map +1 -0
  89. package/lib/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/safe_builder.d.ts +37 -0
  90. package/lib/front_end/third_party/source-map-scopes-codec/package/_dist/src/builder/safe_builder.d.ts.map +1 -0
  91. package/lib/front_end/third_party/source-map-scopes-codec/package/_dist/src/decode/decode.d.ts +29 -0
  92. package/lib/front_end/third_party/source-map-scopes-codec/package/_dist/src/decode/decode.d.ts.map +1 -0
  93. package/lib/front_end/third_party/source-map-scopes-codec/package/_dist/src/encode/encode.d.ts +8 -0
  94. package/lib/front_end/third_party/source-map-scopes-codec/package/_dist/src/encode/encode.d.ts.map +1 -0
  95. package/lib/front_end/third_party/source-map-scopes-codec/package/_dist/src/mod.d.ts +6 -0
  96. package/lib/front_end/third_party/source-map-scopes-codec/package/_dist/src/mod.d.ts.map +1 -0
  97. package/lib/front_end/third_party/source-map-scopes-codec/package/deno.json +21 -0
  98. package/lib/front_end/third_party/source-map-scopes-codec/package/package.json +14 -0
  99. package/lib/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.js +196 -0
  100. package/lib/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.js.map +1 -0
  101. package/lib/front_end/third_party/source-map-scopes-codec/package/src/builder/builder.ts +262 -0
  102. package/lib/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.js +235 -0
  103. package/lib/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.js.map +1 -0
  104. package/lib/front_end/third_party/source-map-scopes-codec/package/src/builder/safe_builder.ts +359 -0
  105. package/lib/front_end/third_party/source-map-scopes-codec/package/src/codec.js +39 -0
  106. package/lib/front_end/third_party/source-map-scopes-codec/package/src/codec.js.map +1 -0
  107. package/lib/front_end/third_party/source-map-scopes-codec/package/src/codec.ts +53 -0
  108. package/lib/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.js +438 -0
  109. package/lib/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.js.map +1 -0
  110. package/lib/front_end/third_party/source-map-scopes-codec/package/src/decode/decode.ts +539 -0
  111. package/lib/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.js +23 -0
  112. package/lib/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.js.map +1 -0
  113. package/lib/front_end/third_party/source-map-scopes-codec/package/src/encode/encode.ts +35 -0
  114. package/lib/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.js +257 -0
  115. package/lib/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.js.map +1 -0
  116. package/lib/front_end/third_party/source-map-scopes-codec/package/src/encode/encoder.ts +348 -0
  117. package/lib/front_end/third_party/source-map-scopes-codec/package/src/mod.js +8 -0
  118. package/lib/front_end/third_party/source-map-scopes-codec/package/src/mod.js.map +1 -0
  119. package/lib/front_end/third_party/source-map-scopes-codec/package/src/mod.ts +20 -0
  120. package/lib/front_end/third_party/source-map-scopes-codec/package/src/scopes-tsconfig.json +8 -0
  121. package/lib/front_end/third_party/source-map-scopes-codec/package/src/scopes.d.ts +184 -0
  122. package/lib/front_end/third_party/source-map-scopes-codec/package/src/util.js +9 -0
  123. package/lib/front_end/third_party/source-map-scopes-codec/package/src/util.js.map +1 -0
  124. package/lib/front_end/third_party/source-map-scopes-codec/package/src/util.ts +12 -0
  125. package/lib/front_end/third_party/source-map-scopes-codec/package/src/vlq.js +82 -0
  126. package/lib/front_end/third_party/source-map-scopes-codec/package/src/vlq.js.map +1 -0
  127. package/lib/front_end/third_party/source-map-scopes-codec/package/src/vlq.ts +99 -0
  128. package/lib/front_end/third_party/source-map-scopes-codec/source-map-scopes-codec.ts +5 -0
  129. package/lib/front_end/ui/legacy/theme_support/ThemeSupport.ts +222 -0
  130. package/lib/front_end/ui/legacy/theme_support/theme_support.ts +5 -0
  131. package/package.json +4 -3
  132. package/patches/chrome-devtools-frontend+1.0.1533544.patch +1549 -20
@@ -0,0 +1,539 @@
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
+
5
+ import * as Common from '../../core/common/common.js';
6
+ import type * as Platform from '../../core/platform/platform.js';
7
+ import * as SDK from '../../core/sdk/sdk.js';
8
+ import * as TextUtils from '../text_utils/text_utils.js';
9
+ import * as Workspace from '../workspace/workspace.js';
10
+
11
+ import {ContentProviderBasedProject} from './ContentProviderBasedProject.js';
12
+ import {CSSWorkspaceBinding} from './CSSWorkspaceBinding.js';
13
+ import {DebuggerWorkspaceBinding} from './DebuggerWorkspaceBinding.js';
14
+ import {NetworkProject} from './NetworkProject.js';
15
+ import {resourceMetadata} from './ResourceUtils.js';
16
+
17
+ const styleSheetRangeMap = new WeakMap<SDK.CSSStyleSheetHeader.CSSStyleSheetHeader, TextUtils.TextRange.TextRange>();
18
+ const scriptRangeMap = new WeakMap<SDK.Script.Script, TextUtils.TextRange.TextRange>();
19
+ const boundUISourceCodes = new WeakSet<Workspace.UISourceCode.UISourceCode>();
20
+
21
+ function computeScriptRange(script: SDK.Script.Script): TextUtils.TextRange.TextRange {
22
+ return new TextUtils.TextRange.TextRange(script.lineOffset, script.columnOffset, script.endLine, script.endColumn);
23
+ }
24
+
25
+ function computeStyleSheetRange(header: SDK.CSSStyleSheetHeader.CSSStyleSheetHeader): TextUtils.TextRange.TextRange {
26
+ return new TextUtils.TextRange.TextRange(header.startLine, header.startColumn, header.endLine, header.endColumn);
27
+ }
28
+
29
+ export class ResourceMapping implements SDK.TargetManager.SDKModelObserver<SDK.ResourceTreeModel.ResourceTreeModel> {
30
+ readonly workspace: Workspace.Workspace.WorkspaceImpl;
31
+ readonly #modelToInfo = new Map<SDK.ResourceTreeModel.ResourceTreeModel, ModelInfo>();
32
+
33
+ constructor(targetManager: SDK.TargetManager.TargetManager, workspace: Workspace.Workspace.WorkspaceImpl) {
34
+ this.workspace = workspace;
35
+ targetManager.observeModels(SDK.ResourceTreeModel.ResourceTreeModel, this);
36
+ }
37
+
38
+ modelAdded(resourceTreeModel: SDK.ResourceTreeModel.ResourceTreeModel): void {
39
+ const info = new ModelInfo(this.workspace, resourceTreeModel);
40
+ this.#modelToInfo.set(resourceTreeModel, info);
41
+ }
42
+
43
+ modelRemoved(resourceTreeModel: SDK.ResourceTreeModel.ResourceTreeModel): void {
44
+ const info = this.#modelToInfo.get(resourceTreeModel);
45
+ if (info) {
46
+ info.dispose();
47
+ this.#modelToInfo.delete(resourceTreeModel);
48
+ }
49
+ }
50
+
51
+ private infoForTarget(target: SDK.Target.Target): ModelInfo|null {
52
+ const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);
53
+ return resourceTreeModel ? this.#modelToInfo.get(resourceTreeModel) || null : null;
54
+ }
55
+
56
+ uiSourceCodeForScript(script: SDK.Script.Script): Workspace.UISourceCode.UISourceCode|null {
57
+ const info = this.infoForTarget(script.debuggerModel.target());
58
+ if (!info) {
59
+ return null;
60
+ }
61
+
62
+ const project = info.getProject();
63
+ const uiSourceCode = project.uiSourceCodeForURL(script.sourceURL);
64
+ return uiSourceCode;
65
+ }
66
+
67
+ cssLocationToUILocation(cssLocation: SDK.CSSModel.CSSLocation): Workspace.UISourceCode.UILocation|null {
68
+ const header = cssLocation.header();
69
+ if (!header) {
70
+ return null;
71
+ }
72
+ const info = this.infoForTarget(cssLocation.cssModel().target());
73
+ if (!info) {
74
+ return null;
75
+ }
76
+ const uiSourceCode = info.getProject().uiSourceCodeForURL(cssLocation.url);
77
+ if (!uiSourceCode) {
78
+ return null;
79
+ }
80
+ const offset = styleSheetRangeMap.get(header) ?? computeStyleSheetRange(header);
81
+ const lineNumber = cssLocation.lineNumber + offset.startLine - header.startLine;
82
+ let columnNumber = cssLocation.columnNumber;
83
+ if (cssLocation.lineNumber === header.startLine) {
84
+ columnNumber += offset.startColumn - header.startColumn;
85
+ }
86
+ return uiSourceCode.uiLocation(lineNumber, columnNumber);
87
+ }
88
+
89
+ jsLocationToUILocation(jsLocation: SDK.DebuggerModel.Location): Workspace.UISourceCode.UILocation|null {
90
+ const script = jsLocation.script();
91
+ if (!script) {
92
+ return null;
93
+ }
94
+ const info = this.infoForTarget(jsLocation.debuggerModel.target());
95
+ if (!info) {
96
+ return null;
97
+ }
98
+ const embedderName = script.embedderName();
99
+ if (!embedderName) {
100
+ return null;
101
+ }
102
+ const uiSourceCode = info.getProject().uiSourceCodeForURL(embedderName);
103
+ if (!uiSourceCode) {
104
+ return null;
105
+ }
106
+ const {startLine, startColumn} = scriptRangeMap.get(script) ?? computeScriptRange(script);
107
+ let {lineNumber, columnNumber} = jsLocation;
108
+ if (lineNumber === script.lineOffset) {
109
+ columnNumber += startColumn - script.columnOffset;
110
+ }
111
+ lineNumber += startLine - script.lineOffset;
112
+ if (script.hasSourceURL) {
113
+ if (lineNumber === 0) {
114
+ columnNumber += script.columnOffset;
115
+ }
116
+ lineNumber += script.lineOffset;
117
+ }
118
+ return uiSourceCode.uiLocation(lineNumber, columnNumber);
119
+ }
120
+
121
+ uiLocationToJSLocations(uiSourceCode: Workspace.UISourceCode.UISourceCode, lineNumber: number, columnNumber: number):
122
+ SDK.DebuggerModel.Location[] {
123
+ if (!boundUISourceCodes.has(uiSourceCode)) {
124
+ return [];
125
+ }
126
+ const target = NetworkProject.targetForUISourceCode(uiSourceCode);
127
+ if (!target) {
128
+ return [];
129
+ }
130
+ const debuggerModel = target.model(SDK.DebuggerModel.DebuggerModel);
131
+ if (!debuggerModel) {
132
+ return [];
133
+ }
134
+ const locations = [];
135
+ for (const script of debuggerModel.scripts()) {
136
+ if (script.embedderName() !== uiSourceCode.url()) {
137
+ continue;
138
+ }
139
+ const range = scriptRangeMap.get(script) ?? computeScriptRange(script);
140
+ if (!range.containsLocation(lineNumber, columnNumber)) {
141
+ continue;
142
+ }
143
+ let scriptLineNumber = lineNumber;
144
+ let scriptColumnNumber = columnNumber;
145
+ if (script.hasSourceURL) {
146
+ scriptLineNumber -= range.startLine;
147
+ if (scriptLineNumber === 0) {
148
+ scriptColumnNumber -= range.startColumn;
149
+ }
150
+ }
151
+ locations.push(debuggerModel.createRawLocation(script, scriptLineNumber, scriptColumnNumber));
152
+ }
153
+ return locations;
154
+ }
155
+
156
+ uiLocationRangeToJSLocationRanges(
157
+ uiSourceCode: Workspace.UISourceCode.UISourceCode,
158
+ textRange: TextUtils.TextRange.TextRange): SDK.DebuggerModel.LocationRange[]|null {
159
+ if (!boundUISourceCodes.has(uiSourceCode)) {
160
+ return null;
161
+ }
162
+ const target = NetworkProject.targetForUISourceCode(uiSourceCode);
163
+ if (!target) {
164
+ return null;
165
+ }
166
+ const debuggerModel = target.model(SDK.DebuggerModel.DebuggerModel);
167
+ if (!debuggerModel) {
168
+ return null;
169
+ }
170
+ const ranges = [];
171
+ for (const script of debuggerModel.scripts()) {
172
+ if (script.embedderName() !== uiSourceCode.url()) {
173
+ continue;
174
+ }
175
+ const scriptTextRange = scriptRangeMap.get(script) ?? computeScriptRange(script);
176
+ const range = scriptTextRange.intersection(textRange);
177
+ if (range.isEmpty()) {
178
+ continue;
179
+ }
180
+ let {startLine, startColumn, endLine, endColumn} = range;
181
+ if (script.hasSourceURL) {
182
+ startLine -= range.startLine;
183
+ if (startLine === 0) {
184
+ startColumn -= range.startColumn;
185
+ }
186
+ endLine -= range.startLine;
187
+ if (endLine === 0) {
188
+ endColumn -= range.startColumn;
189
+ }
190
+ }
191
+ const start = debuggerModel.createRawLocation(script, startLine, startColumn);
192
+ const end = debuggerModel.createRawLocation(script, endLine, endColumn);
193
+ ranges.push({start, end});
194
+ }
195
+ return ranges;
196
+ }
197
+
198
+ getMappedLines(uiSourceCode: Workspace.UISourceCode.UISourceCode): Set<number>|null {
199
+ if (!boundUISourceCodes.has(uiSourceCode)) {
200
+ return null;
201
+ }
202
+ const target = NetworkProject.targetForUISourceCode(uiSourceCode);
203
+ if (!target) {
204
+ return null;
205
+ }
206
+ const debuggerModel = target.model(SDK.DebuggerModel.DebuggerModel);
207
+ if (!debuggerModel) {
208
+ return null;
209
+ }
210
+ const mappedLines = new Set<number>();
211
+ for (const script of debuggerModel.scripts()) {
212
+ if (script.embedderName() !== uiSourceCode.url()) {
213
+ continue;
214
+ }
215
+ const {startLine, endLine} = scriptRangeMap.get(script) ?? computeScriptRange(script);
216
+ for (let line = startLine; line <= endLine; ++line) {
217
+ mappedLines.add(line);
218
+ }
219
+ }
220
+ return mappedLines;
221
+ }
222
+
223
+ uiLocationToCSSLocations(uiLocation: Workspace.UISourceCode.UILocation): SDK.CSSModel.CSSLocation[] {
224
+ if (!boundUISourceCodes.has(uiLocation.uiSourceCode)) {
225
+ return [];
226
+ }
227
+ const target = NetworkProject.targetForUISourceCode(uiLocation.uiSourceCode);
228
+ if (!target) {
229
+ return [];
230
+ }
231
+ const cssModel = target.model(SDK.CSSModel.CSSModel);
232
+ if (!cssModel) {
233
+ return [];
234
+ }
235
+ return cssModel.createRawLocationsByURL(
236
+ uiLocation.uiSourceCode.url(), uiLocation.lineNumber, uiLocation.columnNumber);
237
+ }
238
+
239
+ resetForTest(target: SDK.Target.Target): void {
240
+ const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);
241
+ const info = resourceTreeModel ? this.#modelToInfo.get(resourceTreeModel) : null;
242
+ if (info) {
243
+ info.resetForTest();
244
+ }
245
+ }
246
+ }
247
+
248
+ class ModelInfo {
249
+ project: ContentProviderBasedProject;
250
+ readonly #bindings = new Map<string, Binding>();
251
+ readonly #cssModel: SDK.CSSModel.CSSModel;
252
+ readonly #eventListeners: Common.EventTarget.EventDescriptor[];
253
+ constructor(
254
+ workspace: Workspace.Workspace.WorkspaceImpl, resourceTreeModel: SDK.ResourceTreeModel.ResourceTreeModel) {
255
+ const target = resourceTreeModel.target();
256
+ this.project = new ContentProviderBasedProject(
257
+ workspace, 'resources:' + target.id(), Workspace.Workspace.projectTypes.Network, '',
258
+ false /* isServiceProject */);
259
+ NetworkProject.setTargetForProject(this.project, target);
260
+
261
+ const cssModel = target.model(SDK.CSSModel.CSSModel);
262
+ console.assert(Boolean(cssModel));
263
+ this.#cssModel = (cssModel as SDK.CSSModel.CSSModel);
264
+ for (const frame of resourceTreeModel.frames()) {
265
+ for (const resource of frame.getResourcesMap().values()) {
266
+ this.addResource(resource);
267
+ }
268
+ }
269
+ this.#eventListeners = [
270
+ resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.ResourceAdded, this.resourceAdded, this),
271
+ resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.FrameWillNavigate, this.frameWillNavigate, this),
272
+ resourceTreeModel.addEventListener(SDK.ResourceTreeModel.Events.FrameDetached, this.frameDetached, this),
273
+ this.#cssModel.addEventListener(
274
+ SDK.CSSModel.Events.StyleSheetChanged,
275
+ event => {
276
+ void this.styleSheetChanged(event);
277
+ },
278
+ this),
279
+ ];
280
+ }
281
+
282
+ private async styleSheetChanged(event: Common.EventTarget.EventTargetEvent<SDK.CSSModel.StyleSheetChangedEvent>):
283
+ Promise<void> {
284
+ const header = this.#cssModel.styleSheetHeaderForId(event.data.styleSheetId);
285
+ if (!header || !header.isInline || (header.isInline && header.isMutable)) {
286
+ return;
287
+ }
288
+ const binding = this.#bindings.get(header.resourceURL());
289
+ if (!binding) {
290
+ return;
291
+ }
292
+ await binding.styleSheetChanged(header, event.data.edit || null);
293
+ }
294
+
295
+ private acceptsResource(resource: SDK.Resource.Resource): boolean {
296
+ const resourceType = resource.resourceType();
297
+ // Only load selected resource types from resources.
298
+ if (resourceType !== Common.ResourceType.resourceTypes.Image &&
299
+ resourceType !== Common.ResourceType.resourceTypes.Font &&
300
+ resourceType !== Common.ResourceType.resourceTypes.Document &&
301
+ resourceType !== Common.ResourceType.resourceTypes.Manifest &&
302
+ resourceType !== Common.ResourceType.resourceTypes.Fetch &&
303
+ resourceType !== Common.ResourceType.resourceTypes.XHR) {
304
+ return false;
305
+ }
306
+
307
+ // Ignore non-images and non-fonts.
308
+ if (resourceType === Common.ResourceType.resourceTypes.Image && resource.mimeType &&
309
+ !resource.mimeType.startsWith('image')) {
310
+ return false;
311
+ }
312
+ if (resourceType === Common.ResourceType.resourceTypes.Font && resource.mimeType &&
313
+ !resource.mimeType.includes('font')) {
314
+ return false;
315
+ }
316
+ if ((resourceType === Common.ResourceType.resourceTypes.Image ||
317
+ resourceType === Common.ResourceType.resourceTypes.Font) &&
318
+ Common.ParsedURL.schemeIs(resource.contentURL(), 'data:')) {
319
+ return false;
320
+ }
321
+ return true;
322
+ }
323
+
324
+ private resourceAdded(event: Common.EventTarget.EventTargetEvent<SDK.Resource.Resource>): void {
325
+ this.addResource(event.data);
326
+ }
327
+
328
+ private addResource(resource: SDK.Resource.Resource): void {
329
+ if (!this.acceptsResource(resource)) {
330
+ return;
331
+ }
332
+
333
+ let binding = this.#bindings.get(resource.url);
334
+ if (!binding) {
335
+ binding = new Binding(this.project, resource);
336
+ this.#bindings.set(resource.url, binding);
337
+ } else {
338
+ binding.addResource(resource);
339
+ }
340
+ }
341
+
342
+ private removeFrameResources(frame: SDK.ResourceTreeModel.ResourceTreeFrame): void {
343
+ for (const resource of frame.resources()) {
344
+ if (!this.acceptsResource(resource)) {
345
+ continue;
346
+ }
347
+ const binding = this.#bindings.get(resource.url);
348
+ if (!binding) {
349
+ continue;
350
+ }
351
+ if (binding.resources.size === 1) {
352
+ binding.dispose();
353
+ this.#bindings.delete(resource.url);
354
+ } else {
355
+ binding.removeResource(resource);
356
+ }
357
+ }
358
+ }
359
+
360
+ private frameWillNavigate(event: Common.EventTarget.EventTargetEvent<SDK.ResourceTreeModel.ResourceTreeFrame>): void {
361
+ this.removeFrameResources(event.data);
362
+ }
363
+
364
+ private frameDetached(
365
+ event: Common.EventTarget.EventTargetEvent<{frame: SDK.ResourceTreeModel.ResourceTreeFrame, isSwap: boolean}>):
366
+ void {
367
+ this.removeFrameResources(event.data.frame);
368
+ }
369
+
370
+ resetForTest(): void {
371
+ for (const binding of this.#bindings.values()) {
372
+ binding.dispose();
373
+ }
374
+ this.#bindings.clear();
375
+ }
376
+
377
+ dispose(): void {
378
+ Common.EventTarget.removeEventListeners(this.#eventListeners);
379
+ for (const binding of this.#bindings.values()) {
380
+ binding.dispose();
381
+ }
382
+ this.#bindings.clear();
383
+ this.project.removeProject();
384
+ }
385
+
386
+ getProject(): ContentProviderBasedProject {
387
+ return this.project;
388
+ }
389
+ }
390
+
391
+ class Binding implements TextUtils.ContentProvider.ContentProvider {
392
+ readonly resources: Set<SDK.Resource.Resource>;
393
+ readonly #project: ContentProviderBasedProject;
394
+ readonly #uiSourceCode: Workspace.UISourceCode.UISourceCode;
395
+ #edits: Array<{
396
+ stylesheet: SDK.CSSStyleSheetHeader.CSSStyleSheetHeader,
397
+ edit: SDK.CSSModel.Edit|null,
398
+ }> = [];
399
+ constructor(project: ContentProviderBasedProject, resource: SDK.Resource.Resource) {
400
+ this.resources = new Set([resource]);
401
+ this.#project = project;
402
+ this.#uiSourceCode = this.#project.createUISourceCode(resource.url, resource.contentType());
403
+ boundUISourceCodes.add(this.#uiSourceCode);
404
+ if (resource.frameId) {
405
+ NetworkProject.setInitialFrameAttribution(this.#uiSourceCode, resource.frameId);
406
+ }
407
+ this.#project.addUISourceCodeWithProvider(this.#uiSourceCode, this, resourceMetadata(resource), resource.mimeType);
408
+
409
+ void Promise.all([
410
+ ...this.inlineScripts().map(script => DebuggerWorkspaceBinding.instance().updateLocations(script)),
411
+ ...this.inlineStyles().map(style => CSSWorkspaceBinding.instance().updateLocations(style)),
412
+ ]);
413
+ }
414
+
415
+ private inlineStyles(): SDK.CSSStyleSheetHeader.CSSStyleSheetHeader[] {
416
+ const target = NetworkProject.targetForUISourceCode(this.#uiSourceCode);
417
+ const stylesheets: SDK.CSSStyleSheetHeader.CSSStyleSheetHeader[] = [];
418
+ if (!target) {
419
+ return stylesheets;
420
+ }
421
+ const cssModel = target.model(SDK.CSSModel.CSSModel);
422
+ if (cssModel) {
423
+ for (const headerId of cssModel.getStyleSheetIdsForURL(this.#uiSourceCode.url())) {
424
+ const header = cssModel.styleSheetHeaderForId(headerId);
425
+ if (header) {
426
+ stylesheets.push(header);
427
+ }
428
+ }
429
+ }
430
+ return stylesheets;
431
+ }
432
+
433
+ private inlineScripts(): SDK.Script.Script[] {
434
+ const target = NetworkProject.targetForUISourceCode(this.#uiSourceCode);
435
+ if (!target) {
436
+ return [];
437
+ }
438
+ const debuggerModel = target.model(SDK.DebuggerModel.DebuggerModel);
439
+ if (!debuggerModel) {
440
+ return [];
441
+ }
442
+ return debuggerModel.scripts().filter(script => script.embedderName() === this.#uiSourceCode.url());
443
+ }
444
+
445
+ async styleSheetChanged(stylesheet: SDK.CSSStyleSheetHeader.CSSStyleSheetHeader, edit: SDK.CSSModel.Edit|null):
446
+ Promise<void> {
447
+ this.#edits.push({stylesheet, edit});
448
+ if (this.#edits.length > 1) {
449
+ return;
450
+ } // There is already a styleSheetChanged loop running
451
+
452
+ const content = await this.#uiSourceCode.requestContentData();
453
+ if (!TextUtils.ContentData.ContentData.isError(content)) {
454
+ await this.innerStyleSheetChanged(content.text);
455
+ }
456
+ this.#edits = [];
457
+ }
458
+
459
+ private async innerStyleSheetChanged(content: string): Promise<void> {
460
+ const scripts = this.inlineScripts();
461
+ const styles = this.inlineStyles();
462
+ let text: TextUtils.Text.Text = new TextUtils.Text.Text(content);
463
+ for (const data of this.#edits) {
464
+ const edit = data.edit;
465
+ if (!edit) {
466
+ continue;
467
+ }
468
+ const stylesheet = data.stylesheet;
469
+ const startLocation = styleSheetRangeMap.get(stylesheet) ?? computeStyleSheetRange(stylesheet);
470
+
471
+ const oldRange = edit.oldRange.relativeFrom(startLocation.startLine, startLocation.startColumn);
472
+ const newRange = edit.newRange.relativeFrom(startLocation.startLine, startLocation.startColumn);
473
+ text = new TextUtils.Text.Text(text.replaceRange(oldRange, edit.newText));
474
+ const updatePromises = [];
475
+ for (const script of scripts) {
476
+ const range = scriptRangeMap.get(script) ?? computeScriptRange(script);
477
+ if (!range.follows(oldRange)) {
478
+ continue;
479
+ }
480
+ scriptRangeMap.set(script, range.rebaseAfterTextEdit(oldRange, newRange));
481
+ updatePromises.push(DebuggerWorkspaceBinding.instance().updateLocations(script));
482
+ }
483
+ for (const style of styles) {
484
+ const range = styleSheetRangeMap.get(style) ?? computeStyleSheetRange(style);
485
+ if (!range.follows(oldRange)) {
486
+ continue;
487
+ }
488
+ styleSheetRangeMap.set(style, range.rebaseAfterTextEdit(oldRange, newRange));
489
+ updatePromises.push(CSSWorkspaceBinding.instance().updateLocations(style));
490
+ }
491
+ await Promise.all(updatePromises);
492
+ }
493
+ this.#uiSourceCode.addRevision(text.value());
494
+ }
495
+
496
+ addResource(resource: SDK.Resource.Resource): void {
497
+ this.resources.add(resource);
498
+ if (resource.frameId) {
499
+ NetworkProject.addFrameAttribution(this.#uiSourceCode, resource.frameId);
500
+ }
501
+ }
502
+
503
+ removeResource(resource: SDK.Resource.Resource): void {
504
+ this.resources.delete(resource);
505
+ if (resource.frameId) {
506
+ NetworkProject.removeFrameAttribution(this.#uiSourceCode, resource.frameId);
507
+ }
508
+ }
509
+
510
+ dispose(): void {
511
+ this.#project.removeUISourceCode(this.#uiSourceCode.url());
512
+ void Promise.all([
513
+ ...this.inlineScripts().map(script => DebuggerWorkspaceBinding.instance().updateLocations(script)),
514
+ ...this.inlineStyles().map(style => CSSWorkspaceBinding.instance().updateLocations(style)),
515
+ ]);
516
+ }
517
+
518
+ private firstResource(): SDK.Resource.Resource {
519
+ console.assert(this.resources.size > 0);
520
+ return this.resources.values().next().value as SDK.Resource.Resource;
521
+ }
522
+
523
+ contentURL(): Platform.DevToolsPath.UrlString {
524
+ return this.firstResource().contentURL();
525
+ }
526
+
527
+ contentType(): Common.ResourceType.ResourceType {
528
+ return this.firstResource().contentType();
529
+ }
530
+
531
+ requestContentData(): Promise<TextUtils.ContentData.ContentDataOrError> {
532
+ return this.firstResource().requestContentData();
533
+ }
534
+
535
+ searchInContent(query: string, caseSensitive: boolean, isRegex: boolean):
536
+ Promise<TextUtils.ContentProvider.SearchMatch[]> {
537
+ return this.firstResource().searchInContent(query, caseSensitive, isRegex);
538
+ }
539
+ }