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,240 @@
1
+ // Copyright 2023 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 type * as Platform from '../../core/platform/platform.js';
6
+ import * as SDK from '../../core/sdk/sdk.js';
7
+ import type * as Protocol from '../../generated/protocol.js';
8
+ import * as Bindings from '../bindings/bindings.js';
9
+ import * as SourceMapScopes from '../source_map_scopes/source_map_scopes.js';
10
+ import * as Trace from '../trace/trace.js';
11
+ import * as Workspace from '../workspace/workspace.js';
12
+
13
+ interface ResolvedCodeLocationData {
14
+ name: string|null;
15
+ devtoolsLocation: Workspace.UISourceCode.UILocation|null;
16
+ script: SDK.Script.Script|null;
17
+ }
18
+ export class SourceMappingsUpdated extends Event {
19
+ static readonly eventName = 'sourcemappingsupdated';
20
+ constructor() {
21
+ super(SourceMappingsUpdated.eventName, {composed: true, bubbles: true});
22
+ }
23
+ }
24
+
25
+ /** The code location key is created as a concatenation of its fields. **/
26
+ export const resolvedCodeLocationDataNames = new Map<string, ResolvedCodeLocationData|null>();
27
+
28
+ export class SourceMapsResolver extends EventTarget {
29
+ private executionContextNamesByOrigin = new Map<Platform.DevToolsPath.UrlString, string>();
30
+ #parsedTrace: Trace.TraceModel.ParsedTrace;
31
+ #entityMapper: Trace.EntityMapper.EntityMapper|null = null;
32
+
33
+ #isResolving = false;
34
+
35
+ // We need to gather up a list of all the DebuggerModels that we should
36
+ // listen to for source map attached events. For most pages this will be
37
+ // the debugger model for the primary page target, but if a trace has
38
+ // workers, we would also need to gather up the DebuggerModel instances for
39
+ // those workers too.
40
+ #debuggerModelsToListen = new Set<SDK.DebuggerModel.DebuggerModel>();
41
+
42
+ constructor(parsedTrace: Trace.TraceModel.ParsedTrace, entityMapper?: Trace.EntityMapper.EntityMapper) {
43
+ super();
44
+ this.#parsedTrace = parsedTrace;
45
+ this.#entityMapper = entityMapper ?? null;
46
+ }
47
+
48
+ static clearResolvedNodeNames(): void {
49
+ resolvedCodeLocationDataNames.clear();
50
+ }
51
+ static keyForCodeLocation(callFrame: Protocol.Runtime.CallFrame): string {
52
+ return `${callFrame.url}$$$${callFrame.scriptId}$$$${callFrame.functionName}$$$${callFrame.lineNumber}$$$${
53
+ callFrame.columnNumber}`;
54
+ }
55
+
56
+ /**
57
+ * For trace events containing a call frame / source location
58
+ * (f.e. a stack trace), attempts to obtain the resolved source
59
+ * location based on the those that have been resolved so far from
60
+ * listened source maps.
61
+ *
62
+ * Note that a single deployed URL can map to multiple authored URLs
63
+ * (f.e. if an app is bundled). Thus, beyond a URL we can use code
64
+ * location data like line and column numbers to obtain the specific
65
+ * authored code according to the source mappings.
66
+ *
67
+ * TODO(andoli): This can return incorrect scripts if the target page has been reloaded since the trace.
68
+ */
69
+ static resolvedCodeLocationForCallFrame(callFrame: Protocol.Runtime.CallFrame): ResolvedCodeLocationData|null {
70
+ const codeLocationKey = this.keyForCodeLocation(callFrame);
71
+ return resolvedCodeLocationDataNames.get(codeLocationKey) ?? null;
72
+ }
73
+
74
+ static resolvedCodeLocationForEntry(entry: Trace.Types.Events.Event): ResolvedCodeLocationData|null {
75
+ let callFrame = null;
76
+ if (Trace.Types.Events.isProfileCall(entry)) {
77
+ callFrame = entry.callFrame;
78
+ } else {
79
+ const topCallFrame = Trace.Helpers.Trace.getStackTraceTopCallFrameInEventPayload(entry);
80
+ if (!topCallFrame) {
81
+ return null;
82
+ }
83
+ callFrame = topCallFrame;
84
+ }
85
+ return SourceMapsResolver.resolvedCodeLocationForCallFrame(callFrame as Protocol.Runtime.CallFrame);
86
+ }
87
+
88
+ static resolvedURLForEntry(parsedTrace: Trace.TraceModel.ParsedTrace, entry: Trace.Types.Events.Event):
89
+ Platform.DevToolsPath.UrlString|null {
90
+ const resolvedCallFrameURL =
91
+ SourceMapsResolver.resolvedCodeLocationForEntry(entry)?.devtoolsLocation?.uiSourceCode.url();
92
+ if (resolvedCallFrameURL) {
93
+ return resolvedCallFrameURL;
94
+ }
95
+ // If no source mapping was found for an entry's URL, then default
96
+ // to the URL value contained in the event itself, if any.
97
+ const url = Trace.Handlers.Helpers.getNonResolvedURL(entry, parsedTrace.data);
98
+ if (url) {
99
+ return Workspace.Workspace.WorkspaceImpl.instance().uiSourceCodeForURL(url)?.url() ?? url;
100
+ }
101
+ return null;
102
+ }
103
+
104
+ static storeResolvedCodeDataForCallFrame(
105
+ callFrame: Protocol.Runtime.CallFrame, resolvedCodeLocationData: ResolvedCodeLocationData): void {
106
+ const keyForCallFrame = this.keyForCodeLocation(callFrame);
107
+ resolvedCodeLocationDataNames.set(keyForCallFrame, resolvedCodeLocationData);
108
+ }
109
+
110
+ async install(): Promise<void> {
111
+ for (const threadToProfileMap of this.#parsedTrace.data.Samples.profilesInProcess.values()) {
112
+ for (const [tid, profile] of threadToProfileMap) {
113
+ const nodes = profile.parsedProfile.nodes();
114
+ if (!nodes || nodes.length === 0) {
115
+ continue;
116
+ }
117
+
118
+ const target = this.#targetForThread(tid);
119
+ const debuggerModel = target?.model(SDK.DebuggerModel.DebuggerModel);
120
+ if (!debuggerModel) {
121
+ continue;
122
+ }
123
+ for (const node of nodes) {
124
+ const script = debuggerModel.scriptForId(String(node.callFrame.scriptId));
125
+ const shouldListenToSourceMap = !script || script.sourceMapURL;
126
+ if (!shouldListenToSourceMap) {
127
+ continue;
128
+ }
129
+ this.#debuggerModelsToListen.add(debuggerModel);
130
+ }
131
+ }
132
+ }
133
+
134
+ for (const debuggerModel of this.#debuggerModelsToListen) {
135
+ debuggerModel.sourceMapManager().addEventListener(
136
+ SDK.SourceMapManager.Events.SourceMapAttached, this.#onAttachedSourceMap, this);
137
+ }
138
+
139
+ this.#updateExtensionNames();
140
+
141
+ // Although we have added listeners for SourceMapAttached events, we also
142
+ // immediately try to resolve function names. This ensures we use any
143
+ // sourcemaps that were attached before we bound our event listener.
144
+ await this.#resolveMappingsForProfileNodes();
145
+ }
146
+
147
+ /**
148
+ * Removes the event listeners and stops tracking newly added sourcemaps.
149
+ * Should be called before destroying an instance of this class to avoid leaks
150
+ * with listeners.
151
+ */
152
+ uninstall(): void {
153
+ for (const debuggerModel of this.#debuggerModelsToListen) {
154
+ debuggerModel.sourceMapManager().removeEventListener(
155
+ SDK.SourceMapManager.Events.SourceMapAttached, this.#onAttachedSourceMap, this);
156
+ }
157
+ this.#debuggerModelsToListen.clear();
158
+ }
159
+
160
+ async #resolveMappingsForProfileNodes(): Promise<void> {
161
+ // Used to track if source mappings were updated when a source map
162
+ // is attach. If not, we do not notify the flamechart that mappings
163
+ // were updated, since that would trigger a rerender.
164
+ let updatedMappings = false;
165
+ for (const [, threadsInProcess] of this.#parsedTrace.data.Samples.profilesInProcess) {
166
+ for (const [tid, threadProfile] of threadsInProcess) {
167
+ const nodes = threadProfile.parsedProfile.nodes() ?? [];
168
+ const target = this.#targetForThread(tid);
169
+ if (!target) {
170
+ continue;
171
+ }
172
+ for (const node of nodes) {
173
+ const resolvedFunctionName =
174
+ await SourceMapScopes.NamesResolver.resolveProfileFrameFunctionName(node.callFrame, target);
175
+ updatedMappings ||= Boolean(resolvedFunctionName);
176
+ node.setFunctionName(resolvedFunctionName);
177
+
178
+ const debuggerModel = target.model(SDK.DebuggerModel.DebuggerModel);
179
+ const script = debuggerModel?.scriptForId(node.scriptId) || null;
180
+ const location = debuggerModel &&
181
+ new SDK.DebuggerModel.Location(
182
+ debuggerModel, node.callFrame.scriptId, node.callFrame.lineNumber, node.callFrame.columnNumber);
183
+ const uiLocation = location &&
184
+ await Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().rawLocationToUILocation(
185
+ location);
186
+ updatedMappings ||= Boolean(uiLocation);
187
+ if (uiLocation?.uiSourceCode.url() && this.#entityMapper) {
188
+ // Update mappings for the related events of the entity.
189
+ this.#entityMapper.updateSourceMapEntities(node.callFrame, uiLocation.uiSourceCode.url());
190
+ }
191
+
192
+ SourceMapsResolver.storeResolvedCodeDataForCallFrame(
193
+ node.callFrame, {name: resolvedFunctionName, devtoolsLocation: uiLocation, script});
194
+ }
195
+ }
196
+ }
197
+ if (!updatedMappings) {
198
+ return;
199
+ }
200
+ this.dispatchEvent(new SourceMappingsUpdated());
201
+ }
202
+
203
+ #onAttachedSourceMap(): void {
204
+ // Exit if we are already resolving so that we batch requests; if pages
205
+ // have a lot of sourcemaps we can get a lot of events at once.
206
+ if (this.#isResolving) {
207
+ return;
208
+ }
209
+
210
+ this.#isResolving = true;
211
+ // Resolving names triggers a repaint of the flame chart. Instead of attempting to resolve
212
+ // names every time a source map is attached, wait for some time once the first source map is
213
+ // attached. This way we allow for other source maps to be parsed before attempting a name
214
+ // resolving using the available source maps. Otherwise the UI is blocked when the number
215
+ // of source maps is particularly large.
216
+ setTimeout(async () => {
217
+ this.#isResolving = false;
218
+ await this.#resolveMappingsForProfileNodes();
219
+ }, 500);
220
+ }
221
+
222
+ // Figure out the target for the node. If it is in a worker thread,
223
+ // that is the target, otherwise we use the primary page target.
224
+ #targetForThread(tid: Trace.Types.Events.ThreadID): SDK.Target.Target|null {
225
+ const maybeWorkerId = this.#parsedTrace.data.Workers.workerIdByThread.get(tid);
226
+ if (maybeWorkerId) {
227
+ return SDK.TargetManager.TargetManager.instance().targetById(maybeWorkerId);
228
+ }
229
+ return SDK.TargetManager.TargetManager.instance().primaryPageTarget();
230
+ }
231
+
232
+ #updateExtensionNames(): void {
233
+ for (const runtimeModel of SDK.TargetManager.TargetManager.instance().models(SDK.RuntimeModel.RuntimeModel)) {
234
+ for (const context of runtimeModel.executionContexts()) {
235
+ this.executionContextNamesByOrigin.set(context.origin, context.name);
236
+ }
237
+ }
238
+ this.#entityMapper?.updateExtensionEntitiesWithName(this.executionContextNamesByOrigin);
239
+ }
240
+ }
@@ -0,0 +1,5 @@
1
+ // Copyright 2025 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
+ export * from './SourceMapsResolver.js';
@@ -0,0 +1,97 @@
1
+ // Copyright 2012 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 * as Host from '../../core/host/host.js';
7
+ import type * as Platform from '../../core/platform/platform.js';
8
+ import type * as TextUtils from '../text_utils/text_utils.js';
9
+
10
+ let fileManagerInstance: FileManager|null;
11
+
12
+ export interface SaveCallbackParam {
13
+ fileSystemPath?: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString;
14
+ }
15
+
16
+ export class FileManager extends Common.ObjectWrapper.ObjectWrapper<EventTypes> {
17
+ readonly #saveCallbacks = new Map<
18
+ Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString, (arg0: SaveCallbackParam|null) => void>();
19
+ private constructor() {
20
+ super();
21
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(
22
+ Host.InspectorFrontendHostAPI.Events.SavedURL, this.savedURL, this);
23
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(
24
+ Host.InspectorFrontendHostAPI.Events.CanceledSaveURL, this.#canceledSavedURL, this);
25
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.events.addEventListener(
26
+ Host.InspectorFrontendHostAPI.Events.AppendedToURL, this.appendedToURL, this);
27
+ }
28
+
29
+ static instance(opts: {forceNew: boolean|null} = {forceNew: null}): FileManager {
30
+ const {forceNew} = opts;
31
+ if (!fileManagerInstance || forceNew) {
32
+ fileManagerInstance = new FileManager();
33
+ }
34
+
35
+ return fileManagerInstance;
36
+ }
37
+
38
+ /**
39
+ * {@link FileManager.close | close} *must* be called, for the InspectorFrontendHostStub case, to complete the saving.
40
+ * @param url The url of the file to save. **NOTE:** The backend truncates this filename to 64 characters.
41
+ */
42
+ save(
43
+ url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString,
44
+ contentData: TextUtils.ContentData.ContentData,
45
+ forceSaveAs: boolean,
46
+ ): Promise<SaveCallbackParam|null> {
47
+ // Remove this url from the saved URLs while it is being saved.
48
+ const result = new Promise<SaveCallbackParam|null>(resolve => this.#saveCallbacks.set(url, resolve));
49
+ const {isTextContent} = contentData;
50
+ const content = isTextContent ? contentData.text : contentData.base64;
51
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.save(url, content, forceSaveAs, !isTextContent);
52
+ return result;
53
+ }
54
+
55
+ /**
56
+ * Used in web tests
57
+ */
58
+ private savedURL(event: Common.EventTarget.EventTargetEvent<Host.InspectorFrontendHostAPI.SavedURLEvent>): void {
59
+ const {url, fileSystemPath} = event.data;
60
+ const callback = this.#saveCallbacks.get(url);
61
+ this.#saveCallbacks.delete(url);
62
+ if (callback) {
63
+ callback({fileSystemPath});
64
+ }
65
+ }
66
+
67
+ #canceledSavedURL({data: url}: Common.EventTarget.EventTargetEvent<Platform.DevToolsPath.UrlString>): void {
68
+ const callback = this.#saveCallbacks.get(url);
69
+ this.#saveCallbacks.delete(url);
70
+ if (callback) {
71
+ callback(null);
72
+ }
73
+ }
74
+
75
+ append(url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString, content: string): void {
76
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.append(url, content);
77
+ }
78
+
79
+ close(url: Platform.DevToolsPath.RawPathString|Platform.DevToolsPath.UrlString): void {
80
+ Host.InspectorFrontendHost.InspectorFrontendHostInstance.close(url);
81
+ }
82
+
83
+ /**
84
+ * Used in web tests
85
+ */
86
+ private appendedToURL({data: url}: Common.EventTarget.EventTargetEvent<string>): void {
87
+ this.dispatchEventToListeners(Events.APPENDED_TO_URL, url);
88
+ }
89
+ }
90
+
91
+ export const enum Events {
92
+ APPENDED_TO_URL = 'AppendedToURL',
93
+ }
94
+
95
+ export interface EventTypes {
96
+ [Events.APPENDED_TO_URL]: string;
97
+ }