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,491 @@
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 i18n from '../../core/i18n/i18n.js';
7
+ import * as Platform from '../../core/platform/platform.js';
8
+ import * as Root from '../../core/root/root.js';
9
+ import * as SDK from '../../core/sdk/sdk.js';
10
+ import * as Protocol from '../../generated/protocol.js';
11
+ import * as TextUtils from '../text_utils/text_utils.js';
12
+ import * as Workspace from '../workspace/workspace.js';
13
+
14
+ import {ContentProviderBasedProject} from './ContentProviderBasedProject.js';
15
+ import {type DebuggerSourceMapping, DebuggerWorkspaceBinding} from './DebuggerWorkspaceBinding.js';
16
+ import {NetworkProject} from './NetworkProject.js';
17
+ import {metadataForURL} from './ResourceUtils.js';
18
+
19
+ const UIStrings = {
20
+ /**
21
+ * @description Error text displayed in the console when editing a live script fails. LiveEdit is
22
+ *the name of the feature for editing code that is already running.
23
+ * @example {warning} PH1
24
+ */
25
+ liveEditFailed: '`LiveEdit` failed: {PH1}',
26
+ /**
27
+ * @description Error text displayed in the console when compiling a live-edited script fails. LiveEdit is
28
+ *the name of the feature for editing code that is already running.
29
+ * @example {connection lost} PH1
30
+ */
31
+ liveEditCompileFailed: '`LiveEdit` compile failed: {PH1}',
32
+ } as const;
33
+ const str_ = i18n.i18n.registerUIStrings('models/bindings/ResourceScriptMapping.ts', UIStrings);
34
+ const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
35
+
36
+ export class ResourceScriptMapping implements DebuggerSourceMapping {
37
+ readonly debuggerModel: SDK.DebuggerModel.DebuggerModel;
38
+ #workspace: Workspace.Workspace.WorkspaceImpl;
39
+ readonly debuggerWorkspaceBinding: DebuggerWorkspaceBinding;
40
+ readonly #uiSourceCodeToScriptFile: Map<Workspace.UISourceCode.UISourceCode, ResourceScriptFile>;
41
+ readonly #projects: Map<string, ContentProviderBasedProject>;
42
+ readonly #scriptToUISourceCode: Map<SDK.Script.Script, Workspace.UISourceCode.UISourceCode>;
43
+ readonly #eventListeners: Common.EventTarget.EventDescriptor[];
44
+
45
+ constructor(
46
+ debuggerModel: SDK.DebuggerModel.DebuggerModel, workspace: Workspace.Workspace.WorkspaceImpl,
47
+ debuggerWorkspaceBinding: DebuggerWorkspaceBinding) {
48
+ this.debuggerModel = debuggerModel;
49
+ this.#workspace = workspace;
50
+ this.debuggerWorkspaceBinding = debuggerWorkspaceBinding;
51
+ this.#uiSourceCodeToScriptFile = new Map();
52
+
53
+ this.#projects = new Map();
54
+
55
+ this.#scriptToUISourceCode = new Map();
56
+ const runtimeModel = debuggerModel.runtimeModel();
57
+ this.#eventListeners = [
58
+ this.debuggerModel.addEventListener(
59
+ SDK.DebuggerModel.Events.ParsedScriptSource, event => this.addScript(event.data), this),
60
+ this.debuggerModel.addEventListener(SDK.DebuggerModel.Events.GlobalObjectCleared, this.globalObjectCleared, this),
61
+ runtimeModel.addEventListener(
62
+ SDK.RuntimeModel.Events.ExecutionContextDestroyed, this.executionContextDestroyed, this),
63
+ runtimeModel.target().targetManager().addEventListener(
64
+ SDK.TargetManager.Events.INSPECTED_URL_CHANGED, this.inspectedURLChanged, this),
65
+ ];
66
+ }
67
+
68
+ private project(script: SDK.Script.Script): ContentProviderBasedProject {
69
+ const prefix = script.isContentScript() ? 'js:extensions:' : 'js::';
70
+ const projectId = prefix + this.debuggerModel.target().id() + ':' + script.frameId;
71
+ let project = this.#projects.get(projectId);
72
+ if (!project) {
73
+ const projectType = script.isContentScript() ? Workspace.Workspace.projectTypes.ContentScripts :
74
+ Workspace.Workspace.projectTypes.Network;
75
+ project = new ContentProviderBasedProject(
76
+ this.#workspace, projectId, projectType, '' /* displayName */, false /* isServiceProject */);
77
+ NetworkProject.setTargetForProject(project, this.debuggerModel.target());
78
+ this.#projects.set(projectId, project);
79
+ }
80
+ return project;
81
+ }
82
+
83
+ uiSourceCodeForScript(script: SDK.Script.Script): Workspace.UISourceCode.UISourceCode|null {
84
+ return this.#scriptToUISourceCode.get(script) ?? null;
85
+ }
86
+
87
+ rawLocationToUILocation(rawLocation: SDK.DebuggerModel.Location): Workspace.UISourceCode.UILocation|null {
88
+ const script = rawLocation.script();
89
+ if (!script) {
90
+ return null;
91
+ }
92
+ const uiSourceCode = this.#scriptToUISourceCode.get(script);
93
+ if (!uiSourceCode) {
94
+ return null;
95
+ }
96
+ const scriptFile = this.#uiSourceCodeToScriptFile.get(uiSourceCode);
97
+ if (!scriptFile) {
98
+ return null;
99
+ }
100
+ if ((scriptFile.hasDivergedFromVM() && !scriptFile.isMergingToVM()) || scriptFile.isDivergingFromVM()) {
101
+ return null;
102
+ }
103
+ if (scriptFile.script !== script) {
104
+ return null;
105
+ }
106
+ const {lineNumber, columnNumber = 0} = rawLocation;
107
+ return uiSourceCode.uiLocation(lineNumber, columnNumber);
108
+ }
109
+
110
+ uiLocationToRawLocations(uiSourceCode: Workspace.UISourceCode.UISourceCode, lineNumber: number, columnNumber: number):
111
+ SDK.DebuggerModel.Location[] {
112
+ const scriptFile = this.#uiSourceCodeToScriptFile.get(uiSourceCode);
113
+ if (!scriptFile) {
114
+ return [];
115
+ }
116
+
117
+ const {script} = scriptFile;
118
+ if (!script) {
119
+ return [];
120
+ }
121
+
122
+ return [this.debuggerModel.createRawLocation(script, lineNumber, columnNumber)];
123
+ }
124
+
125
+ uiLocationRangeToRawLocationRanges(
126
+ uiSourceCode: Workspace.UISourceCode.UISourceCode,
127
+ {startLine, startColumn, endLine, endColumn}: TextUtils.TextRange.TextRange):
128
+ SDK.DebuggerModel.LocationRange[]|null {
129
+ const scriptFile = this.#uiSourceCodeToScriptFile.get(uiSourceCode);
130
+ if (!scriptFile) {
131
+ return null;
132
+ }
133
+
134
+ const {script} = scriptFile;
135
+ if (!script) {
136
+ return null;
137
+ }
138
+
139
+ const start = this.debuggerModel.createRawLocation(script, startLine, startColumn);
140
+ const end = this.debuggerModel.createRawLocation(script, endLine, endColumn);
141
+ return [{start, end}];
142
+ }
143
+
144
+ private inspectedURLChanged(event: Common.EventTarget.EventTargetEvent<SDK.Target.Target>): void {
145
+ for (let target: SDK.Target.Target|null = this.debuggerModel.target(); target !== event.data;
146
+ target = target.parentTarget()) {
147
+ if (target === null) {
148
+ return;
149
+ }
150
+ }
151
+
152
+ // Just remove and readd all scripts to ensure their URLs are reflected correctly.
153
+ for (const script of Array.from(this.#scriptToUISourceCode.keys())) {
154
+ this.removeScripts([script]);
155
+ this.addScript(script);
156
+ }
157
+ }
158
+
159
+ private addScript(script: SDK.Script.Script): void {
160
+ // Ignore live edit scripts here.
161
+ if (script.isLiveEdit() || script.isBreakpointCondition) {
162
+ return;
163
+ }
164
+
165
+ let url = script.sourceURL;
166
+ if (!url) {
167
+ return;
168
+ }
169
+
170
+ if (script.hasSourceURL) {
171
+ // Try to resolve `//# sourceURL=` annotations relative to
172
+ // the base URL, according to the sourcemap specification.
173
+ url = SDK.SourceMapManager.SourceMapManager.resolveRelativeSourceURL(script.debuggerModel.target(), url);
174
+ } else {
175
+ // Ignore inline <script>s without `//# sourceURL` annotation here.
176
+ if (script.isInlineScript()) {
177
+ return;
178
+ }
179
+
180
+ // Filter out embedder injected content scripts.
181
+ if (script.isContentScript()) {
182
+ const parsedURL = new Common.ParsedURL.ParsedURL(url);
183
+ if (!parsedURL.isValid) {
184
+ return;
185
+ }
186
+ }
187
+ }
188
+
189
+ // Remove previous UISourceCode, if any
190
+ const project = this.project(script);
191
+ const oldUISourceCode = project.uiSourceCodeForURL(url);
192
+ if (oldUISourceCode) {
193
+ const oldScriptFile = this.#uiSourceCodeToScriptFile.get(oldUISourceCode);
194
+ if (oldScriptFile?.script) {
195
+ this.removeScripts([oldScriptFile.script]);
196
+ }
197
+ }
198
+
199
+ // Create UISourceCode.
200
+ const originalContentProvider = script.originalContentProvider();
201
+ const uiSourceCode = project.createUISourceCode(url, originalContentProvider.contentType());
202
+ NetworkProject.setInitialFrameAttribution(uiSourceCode, script.frameId);
203
+ const metadata = metadataForURL(this.debuggerModel.target(), script.frameId, url);
204
+
205
+ // Bind UISourceCode to scripts.
206
+ const scriptFile = new ResourceScriptFile(this, uiSourceCode, script);
207
+ this.#uiSourceCodeToScriptFile.set(uiSourceCode, scriptFile);
208
+ this.#scriptToUISourceCode.set(script, uiSourceCode);
209
+
210
+ const mimeType = script.isWasm() ? 'application/wasm' : 'text/javascript';
211
+ project.addUISourceCodeWithProvider(uiSourceCode, originalContentProvider, metadata, mimeType);
212
+ void this.debuggerWorkspaceBinding.updateLocations(script);
213
+ }
214
+
215
+ scriptFile(uiSourceCode: Workspace.UISourceCode.UISourceCode): ResourceScriptFile|null {
216
+ return this.#uiSourceCodeToScriptFile.get(uiSourceCode) || null;
217
+ }
218
+
219
+ private removeScripts(scripts: SDK.Script.Script[]): void {
220
+ const uiSourceCodesByProject =
221
+ new Platform.MapUtilities.Multimap<ContentProviderBasedProject, Workspace.UISourceCode.UISourceCode>();
222
+ for (const script of scripts) {
223
+ const uiSourceCode = this.#scriptToUISourceCode.get(script);
224
+ if (!uiSourceCode) {
225
+ continue;
226
+ }
227
+ const scriptFile = this.#uiSourceCodeToScriptFile.get(uiSourceCode);
228
+ if (scriptFile) {
229
+ scriptFile.dispose();
230
+ }
231
+
232
+ this.#uiSourceCodeToScriptFile.delete(uiSourceCode);
233
+ this.#scriptToUISourceCode.delete(script);
234
+
235
+ uiSourceCodesByProject.set(uiSourceCode.project() as ContentProviderBasedProject, uiSourceCode);
236
+ void this.debuggerWorkspaceBinding.updateLocations(script);
237
+ }
238
+ for (const project of uiSourceCodesByProject.keysArray()) {
239
+ const uiSourceCodes = uiSourceCodesByProject.get(project);
240
+ // Check if all the ui source codes in the project are in |uiSourceCodes|.
241
+ let allInProjectRemoved = true;
242
+ for (const projectSourceCode of project.uiSourceCodes()) {
243
+ if (!uiSourceCodes.has(projectSourceCode)) {
244
+ allInProjectRemoved = false;
245
+ break;
246
+ }
247
+ }
248
+ // Drop the whole project if no source codes are left in it.
249
+ if (allInProjectRemoved) {
250
+ this.#projects.delete(project.id());
251
+ project.removeProject();
252
+ } else {
253
+ // Otherwise, announce the removal of each UI source code individually.
254
+ uiSourceCodes.forEach(c => project.removeUISourceCode(c.url()));
255
+ }
256
+ }
257
+ }
258
+
259
+ private executionContextDestroyed(event: Common.EventTarget.EventTargetEvent<SDK.RuntimeModel.ExecutionContext>):
260
+ void {
261
+ const executionContext = event.data;
262
+ this.removeScripts(this.debuggerModel.scriptsForExecutionContext(executionContext));
263
+ }
264
+
265
+ private globalObjectCleared(): void {
266
+ const scripts = Array.from(this.#scriptToUISourceCode.keys());
267
+ this.removeScripts(scripts);
268
+ }
269
+
270
+ resetForTest(): void {
271
+ this.globalObjectCleared();
272
+ }
273
+
274
+ dispose(): void {
275
+ Common.EventTarget.removeEventListeners(this.#eventListeners);
276
+ this.globalObjectCleared();
277
+ }
278
+ }
279
+
280
+ export class ResourceScriptFile extends Common.ObjectWrapper.ObjectWrapper<ResourceScriptFile.EventTypes> {
281
+ readonly #resourceScriptMapping: ResourceScriptMapping;
282
+ readonly uiSourceCode: Workspace.UISourceCode.UISourceCode;
283
+ readonly script: SDK.Script.Script|null;
284
+ #scriptSource?: string|null;
285
+ #isDivergingFromVM?: boolean;
286
+ #hasDivergedFromVM?: boolean;
287
+ #isMergingToVM?: boolean;
288
+ #updateMutex = new Common.Mutex.Mutex();
289
+ constructor(
290
+ resourceScriptMapping: ResourceScriptMapping, uiSourceCode: Workspace.UISourceCode.UISourceCode,
291
+ script: SDK.Script.Script) {
292
+ super();
293
+ this.#resourceScriptMapping = resourceScriptMapping;
294
+ this.uiSourceCode = uiSourceCode;
295
+ this.script = this.uiSourceCode.contentType().isScript() ? script : null;
296
+
297
+ this.uiSourceCode.addEventListener(Workspace.UISourceCode.Events.WorkingCopyChanged, this.workingCopyChanged, this);
298
+ this.uiSourceCode.addEventListener(
299
+ Workspace.UISourceCode.Events.WorkingCopyCommitted, this.workingCopyCommitted, this);
300
+ }
301
+
302
+ private isDiverged(): boolean {
303
+ if (this.uiSourceCode.isDirty()) {
304
+ return true;
305
+ }
306
+ if (!this.script) {
307
+ return false;
308
+ }
309
+ if (typeof this.#scriptSource === 'undefined' || this.#scriptSource === null) {
310
+ return false;
311
+ }
312
+ const workingCopy = this.uiSourceCode.workingCopy();
313
+ if (!workingCopy) {
314
+ return false;
315
+ }
316
+
317
+ // Match ignoring sourceURL.
318
+ if (!workingCopy.startsWith(this.#scriptSource.trimEnd())) {
319
+ return true;
320
+ }
321
+ const suffix = this.uiSourceCode.workingCopy().substr(this.#scriptSource.length);
322
+ return Boolean(suffix.length) && !suffix.match(SDK.Script.sourceURLRegex);
323
+ }
324
+
325
+ private workingCopyChanged(): void {
326
+ void this.update();
327
+ }
328
+
329
+ private workingCopyCommitted(): void {
330
+ // This feature flag is for turning down live edit. If it's not present, we keep the feature enabled.
331
+ if (Root.Runtime.hostConfig.devToolsLiveEdit?.enabled === false) {
332
+ return;
333
+ }
334
+
335
+ if (this.uiSourceCode.project().canSetFileContent()) {
336
+ return;
337
+ }
338
+ if (!this.script) {
339
+ return;
340
+ }
341
+
342
+ const source = this.uiSourceCode.workingCopy();
343
+ void this.script.editSource(source).then(({status, exceptionDetails}) => {
344
+ void this.scriptSourceWasSet(source, status, exceptionDetails);
345
+ });
346
+ }
347
+
348
+ async scriptSourceWasSet(
349
+ source: string, status: Protocol.Debugger.SetScriptSourceResponseStatus,
350
+ exceptionDetails?: Protocol.Runtime.ExceptionDetails): Promise<void> {
351
+ if (status === Protocol.Debugger.SetScriptSourceResponseStatus.Ok) {
352
+ this.#scriptSource = source;
353
+ }
354
+ await this.update();
355
+
356
+ if (status === Protocol.Debugger.SetScriptSourceResponseStatus.Ok) {
357
+ return;
358
+ }
359
+
360
+ if (!exceptionDetails) {
361
+ // TODO(crbug.com/1334484): Instead of to the console, report these errors in an "info bar" at the bottom
362
+ // of the text editor, similar to e.g. source mapping errors.
363
+ Common.Console.Console.instance().addMessage(
364
+ i18nString(UIStrings.liveEditFailed, {PH1: getErrorText(status)}), Common.Console.MessageLevel.WARNING);
365
+ return;
366
+ }
367
+ const messageText = i18nString(UIStrings.liveEditCompileFailed, {PH1: exceptionDetails.text});
368
+ this.uiSourceCode.addLineMessage(
369
+ Workspace.UISourceCode.Message.Level.ERROR, messageText, exceptionDetails.lineNumber,
370
+ exceptionDetails.columnNumber);
371
+
372
+ function getErrorText(status: Protocol.Debugger.SetScriptSourceResponseStatus): string {
373
+ switch (status) {
374
+ case Protocol.Debugger.SetScriptSourceResponseStatus.BlockedByActiveFunction:
375
+ return 'Functions that are on the stack (currently being executed) can not be edited';
376
+ case Protocol.Debugger.SetScriptSourceResponseStatus.BlockedByActiveGenerator:
377
+ return 'Async functions/generators that are active can not be edited';
378
+ case Protocol.Debugger.SetScriptSourceResponseStatus.BlockedByTopLevelEsModuleChange:
379
+ return 'The top-level of ES modules can not be edited';
380
+ case Protocol.Debugger.SetScriptSourceResponseStatus.CompileError:
381
+ case Protocol.Debugger.SetScriptSourceResponseStatus.Ok:
382
+ throw new Error('Compile errors and Ok status must not be reported on the console');
383
+ }
384
+ }
385
+ }
386
+
387
+ private async update(): Promise<void> {
388
+ // Do not interleave "divergeFromVM" with "mergeToVM" calls.
389
+ const release = await this.#updateMutex.acquire();
390
+ const diverged = this.isDiverged();
391
+ if (diverged && !this.#hasDivergedFromVM) {
392
+ await this.divergeFromVM();
393
+ } else if (!diverged && this.#hasDivergedFromVM) {
394
+ await this.mergeToVM();
395
+ }
396
+ release();
397
+ }
398
+
399
+ private async divergeFromVM(): Promise<void> {
400
+ if (this.script) {
401
+ this.#isDivergingFromVM = true;
402
+ await this.#resourceScriptMapping.debuggerWorkspaceBinding.updateLocations(this.script);
403
+ this.#isDivergingFromVM = undefined;
404
+ this.#hasDivergedFromVM = true;
405
+ this.dispatchEventToListeners(ResourceScriptFile.Events.DID_DIVERGE_FROM_VM);
406
+ }
407
+ }
408
+
409
+ private async mergeToVM(): Promise<void> {
410
+ if (this.script) {
411
+ this.#hasDivergedFromVM = undefined;
412
+ this.#isMergingToVM = true;
413
+ await this.#resourceScriptMapping.debuggerWorkspaceBinding.updateLocations(this.script);
414
+ this.#isMergingToVM = undefined;
415
+ this.dispatchEventToListeners(ResourceScriptFile.Events.DID_MERGE_TO_VM);
416
+ }
417
+ }
418
+
419
+ hasDivergedFromVM(): boolean {
420
+ return Boolean(this.#hasDivergedFromVM);
421
+ }
422
+
423
+ isDivergingFromVM(): boolean {
424
+ return Boolean(this.#isDivergingFromVM);
425
+ }
426
+
427
+ isMergingToVM(): boolean {
428
+ return Boolean(this.#isMergingToVM);
429
+ }
430
+
431
+ checkMapping(): void {
432
+ if (!this.script || typeof this.#scriptSource !== 'undefined') {
433
+ this.mappingCheckedForTest();
434
+ return;
435
+ }
436
+ void this.script.requestContentData().then(content => {
437
+ this.#scriptSource = TextUtils.ContentData.ContentData.textOr(content, null);
438
+ void this.update().then(() => this.mappingCheckedForTest());
439
+ });
440
+ }
441
+
442
+ private mappingCheckedForTest(): void {
443
+ }
444
+
445
+ dispose(): void {
446
+ this.uiSourceCode.removeEventListener(
447
+ Workspace.UISourceCode.Events.WorkingCopyChanged, this.workingCopyChanged, this);
448
+ this.uiSourceCode.removeEventListener(
449
+ Workspace.UISourceCode.Events.WorkingCopyCommitted, this.workingCopyCommitted, this);
450
+ }
451
+
452
+ addSourceMapURL(sourceMapURL: Platform.DevToolsPath.UrlString): void {
453
+ if (!this.script) {
454
+ return;
455
+ }
456
+ this.script.debuggerModel.setSourceMapURL(this.script, sourceMapURL);
457
+ }
458
+
459
+ addDebugInfoURL(debugInfoURL: Platform.DevToolsPath.UrlString): void {
460
+ if (!this.script) {
461
+ return;
462
+ }
463
+ const {pluginManager} = DebuggerWorkspaceBinding.instance();
464
+ pluginManager.setDebugInfoURL(this.script, debugInfoURL);
465
+ }
466
+
467
+ hasSourceMapURL(): boolean {
468
+ return Boolean(this.script?.sourceMapURL);
469
+ }
470
+
471
+ async missingSymbolFiles(): Promise<SDK.DebuggerModel.MissingDebugFiles[]|null> {
472
+ if (!this.script) {
473
+ return null;
474
+ }
475
+ const {pluginManager} = this.#resourceScriptMapping.debuggerWorkspaceBinding;
476
+ const sources = await pluginManager.getSourcesForScript(this.script);
477
+ return sources && 'missingSymbolFiles' in sources ? sources.missingSymbolFiles : null;
478
+ }
479
+ }
480
+
481
+ export namespace ResourceScriptFile {
482
+ export const enum Events {
483
+ DID_MERGE_TO_VM = 'DidMergeToVM',
484
+ DID_DIVERGE_FROM_VM = 'DidDivergeFromVM',
485
+ }
486
+
487
+ export interface EventTypes {
488
+ [Events.DID_MERGE_TO_VM]: void;
489
+ [Events.DID_DIVERGE_FROM_VM]: void;
490
+ }
491
+ }
@@ -0,0 +1,103 @@
1
+ // Copyright 2021 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
+ /*
6
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
7
+ * Copyright (C) 2007 Matt Lilek (pewtermoose@gmail.com).
8
+ * Copyright (C) 2009 Joseph Pecoraro
9
+ *
10
+ * Redistribution and use in source and binary forms, with or without
11
+ * modification, are permitted provided that the following conditions are
12
+ * met:
13
+ *
14
+ * 1. Redistributions of source code must retain the above copyright
15
+ * notice, this list of conditions and the following disclaimer.
16
+ * 2. Redistributions in binary form must reproduce the above copyright
17
+ * notice, this list of conditions and the following disclaimer in the
18
+ * documentation and/or other materials provided with the distribution.
19
+ * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
20
+ * its contributors may be used to endorse or promote products derived
21
+ * from this software without specific prior written permission.
22
+ *
23
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
24
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
27
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
+ */
34
+
35
+ import * as Common from '../../core/common/common.js';
36
+ import * as Platform from '../../core/platform/platform.js';
37
+ import * as SDK from '../../core/sdk/sdk.js';
38
+ import type * as Protocol from '../../generated/protocol.js';
39
+ import * as Workspace from '../workspace/workspace.js';
40
+
41
+ export function resourceForURL(url: Platform.DevToolsPath.UrlString): SDK.Resource.Resource|null {
42
+ return SDK.ResourceTreeModel.ResourceTreeModel.resourceForURL(url);
43
+ }
44
+
45
+ export function displayNameForURL(url: Platform.DevToolsPath.UrlString): string {
46
+ if (!url) {
47
+ return '';
48
+ }
49
+
50
+ const uiSourceCode = Workspace.Workspace.WorkspaceImpl.instance().uiSourceCodeForURL(url);
51
+ if (uiSourceCode) {
52
+ return uiSourceCode.displayName();
53
+ }
54
+
55
+ const resource = resourceForURL(url);
56
+ if (resource) {
57
+ return resource.displayName;
58
+ }
59
+
60
+ const inspectedURL = SDK.TargetManager.TargetManager.instance().inspectedURL();
61
+ if (!inspectedURL) {
62
+ return Platform.StringUtilities.trimURL(url, '');
63
+ }
64
+
65
+ const parsedURL = Common.ParsedURL.ParsedURL.fromString(inspectedURL);
66
+ if (!parsedURL) {
67
+ return url;
68
+ }
69
+
70
+ const lastPathComponent = parsedURL.lastPathComponent;
71
+ const index = inspectedURL.indexOf(lastPathComponent);
72
+ if (index !== -1 && index + lastPathComponent.length === inspectedURL.length) {
73
+ const baseURL = inspectedURL.substring(0, index);
74
+ if (url.startsWith(baseURL) && url.length > index) {
75
+ return url.substring(index);
76
+ }
77
+ }
78
+
79
+ const displayName = Platform.StringUtilities.trimURL(url, parsedURL.host);
80
+ return displayName === '/' ? parsedURL.host + '/' : displayName;
81
+ }
82
+
83
+ export function metadataForURL(
84
+ target: SDK.Target.Target, frameId: Protocol.Page.FrameId,
85
+ url: Platform.DevToolsPath.UrlString): Workspace.UISourceCode.UISourceCodeMetadata|null {
86
+ const resourceTreeModel = target.model(SDK.ResourceTreeModel.ResourceTreeModel);
87
+ if (!resourceTreeModel) {
88
+ return null;
89
+ }
90
+ const frame = resourceTreeModel.frameForId(frameId);
91
+ if (!frame) {
92
+ return null;
93
+ }
94
+ return resourceMetadata(frame.resourceForURL(url));
95
+ }
96
+
97
+ export function resourceMetadata(resource: SDK.Resource.Resource|null): Workspace.UISourceCode.UISourceCodeMetadata|
98
+ null {
99
+ if (!resource || (typeof resource.contentSize() !== 'number' && !resource.lastModified())) {
100
+ return null;
101
+ }
102
+ return new Workspace.UISourceCode.UISourceCodeMetadata(resource.lastModified(), resource.contentSize());
103
+ }