chrome-devtools-frontend 1.0.1153166 → 1.0.1155899
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config/gni/devtools_grd_files.gni +3 -2
- package/front_end/core/common/Revealer.ts +1 -1
- package/front_end/core/host/InspectorFrontendHostAPI.ts +2 -0
- package/front_end/core/host/UserMetrics.ts +32 -12
- package/front_end/core/platform/array-utilities.ts +25 -9
- package/front_end/core/sdk/ChildTargetManager.ts +2 -1
- package/front_end/core/sdk/FilmStripModel.ts +35 -25
- package/front_end/devtools_compatibility.js +2 -0
- package/front_end/entrypoints/lighthouse_worker/LighthouseWorkerService.ts +8 -2
- package/front_end/entrypoints/worker_app/worker_app.ts +0 -1
- package/front_end/generated/InspectorBackendCommands.js +2 -1
- package/front_end/generated/protocol.ts +36 -0
- package/front_end/models/bindings/PresentationConsoleMessageHelper.ts +90 -73
- package/front_end/models/issues_manager/IssuesManager.ts +5 -0
- package/front_end/models/issues_manager/SourceFrameIssuesManager.ts +31 -61
- package/front_end/models/issues_manager/StylesheetLoadingIssue.ts +69 -0
- package/front_end/models/issues_manager/descriptions/stylesheetLateImport.md +4 -0
- package/front_end/models/issues_manager/descriptions/stylesheetRequestFailed.md +3 -0
- package/front_end/models/issues_manager/issues_manager.ts +2 -0
- package/front_end/models/timeline_model/TimelineModel.ts +4 -0
- package/front_end/models/trace/ModelImpl.ts +1 -0
- package/front_end/models/trace/README.md +73 -17
- package/front_end/models/trace/handlers/NetworkRequestsHandler.ts +1 -1
- package/front_end/models/trace/handlers/RendererHandler.ts +33 -143
- package/front_end/models/trace/handlers/UserTimings.md +1 -1
- package/front_end/models/trace/types/TraceEvents.ts +3 -2
- package/front_end/panels/application/ApplicationPanelSidebar.ts +9 -6
- package/front_end/panels/application/PreloadingTreeElement.ts +25 -7
- package/front_end/panels/application/preloading/PreloadingView.ts +64 -31
- package/front_end/panels/application/preloading/components/UsedPreloadingView.ts +19 -9
- package/front_end/panels/console/ConsoleViewMessage.ts +14 -2
- package/front_end/panels/elements/ElementsPanel.ts +2 -3
- package/front_end/panels/elements/components/LayoutPane.ts +256 -60
- package/front_end/panels/elements/elements-legacy.ts +0 -3
- package/front_end/panels/elements/elements-meta.ts +10 -2
- package/front_end/panels/elements/elements.ts +0 -2
- package/front_end/panels/network/NetworkDataGridNode.ts +8 -0
- package/front_end/panels/network/NetworkLogView.ts +2 -1
- package/front_end/panels/network/NetworkPanel.ts +12 -1
- package/front_end/panels/recorder/components/ExtensionView.ts +1 -1
- package/front_end/panels/sources/DebuggerPlugin.ts +7 -4
- package/front_end/panels/sources/SourcesPanel.ts +1 -1
- package/front_end/panels/sources/components/BreakpointsView.ts +406 -89
- package/front_end/panels/sources/sources-meta.ts +13 -4
- package/front_end/panels/sources/sources.ts +0 -2
- package/front_end/panels/timeline/TimelineFlameChartDataProvider.ts +1 -1
- package/front_end/panels/timeline/TimelineFlameChartNetworkDataProvider.ts +106 -95
- package/front_end/panels/timeline/TimelineFlameChartView.ts +1 -1
- package/front_end/panels/timeline/TimelinePaintProfilerView.ts +5 -0
- package/front_end/panels/timeline/TimelinePanel.ts +8 -8
- package/front_end/ui/legacy/UIUtils.ts +1 -1
- package/front_end/ui/legacy/components/perf_ui/.eslintrc.js +18 -0
- package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +5 -1
- package/front_end/ui/legacy/components/perf_ui/TimelineOverviewPane.ts +5 -2
- package/front_end/ui/legacy/components/utils/Linkifier.ts +10 -0
- package/package.json +1 -1
- package/scripts/build/generate_deprecations.py +3 -0
- package/front_end/panels/elements/LayoutSidebarPane.ts +0 -249
- package/front_end/panels/sources/BreakpointsSidebarPane.ts +0 -480
- package/front_end/ui/components/docs/layout_pane/basic.html +0 -25
- package/front_end/ui/components/docs/layout_pane/basic.ts +0 -78
@@ -2,14 +2,20 @@
|
|
2
2
|
// Use of this source code is governed by a BSD-style license that can be
|
3
3
|
// found in the LICENSE file.
|
4
4
|
|
5
|
+
import * as Common from '../../../core/common/common.js';
|
5
6
|
import * as Host from '../../../core/host/host.js';
|
6
7
|
import * as i18n from '../../../core/i18n/i18n.js';
|
7
8
|
import * as Platform from '../../../core/platform/platform.js';
|
8
9
|
import {assertNotNullOrUndefined} from '../../../core/platform/platform.js';
|
9
10
|
import * as SDK from '../../../core/sdk/sdk.js';
|
11
|
+
import * as Bindings from '../../../models/bindings/bindings.js';
|
12
|
+
import * as Breakpoints from '../../../models/breakpoints/breakpoints.js';
|
13
|
+
import * as TextUtils from '../../../models/text_utils/text_utils.js';
|
14
|
+
import * as Workspace from '../../../models/workspace/workspace.js';
|
10
15
|
import * as ComponentHelpers from '../../../ui/components/helpers/helpers.js';
|
11
16
|
import * as IconButton from '../../../ui/components/icon_button/icon_button.js';
|
12
17
|
import * as Input from '../../../ui/components/input/input.js';
|
18
|
+
import * as LegacyWrapper from '../../../ui/components/legacy_wrapper/legacy_wrapper.js';
|
13
19
|
import * as Coordinator from '../../../ui/components/render_coordinator/render_coordinator.js';
|
14
20
|
import * as UI from '../../../ui/legacy/legacy.js';
|
15
21
|
import * as LitHtml from '../../../ui/lit-html/lit-html.js';
|
@@ -130,77 +136,408 @@ export const enum BreakpointStatus {
|
|
130
136
|
INDETERMINATE = 'INDETERMINATE',
|
131
137
|
}
|
132
138
|
|
133
|
-
|
134
|
-
|
135
|
-
|
139
|
+
let breakpointsViewInstance: LegacyWrapper.LegacyWrapper.LegacyWrapper<UI.Widget.Widget, BreakpointsView>|null;
|
140
|
+
let breakpointsViewControllerInstance: BreakpointsSidebarController|null;
|
141
|
+
|
142
|
+
export class BreakpointsSidebarController implements UI.ContextFlavorListener.ContextFlavorListener {
|
143
|
+
readonly #breakpointManager: Breakpoints.BreakpointManager.BreakpointManager;
|
144
|
+
readonly #breakpointItemToLocationMap =
|
145
|
+
new WeakMap<BreakpointItem, Breakpoints.BreakpointManager.BreakpointLocation[]>();
|
146
|
+
readonly #breakpointsActiveSetting: Common.Settings.Setting<boolean>;
|
147
|
+
readonly #pauseOnUncaughtExceptionSetting: Common.Settings.Setting<boolean>;
|
148
|
+
readonly #pauseOnCaughtExceptionSetting: Common.Settings.Setting<boolean>;
|
149
|
+
|
150
|
+
readonly #collapsedFilesSettings: Common.Settings.Setting<Platform.DevToolsPath.UrlString[]>;
|
151
|
+
readonly #collapsedFiles: Set<Platform.DevToolsPath.UrlString>;
|
152
|
+
|
153
|
+
// This is used to keep track of outstanding edits to breakpoints that were initiated
|
154
|
+
// by the breakpoint edit button (for UMA).
|
155
|
+
#outstandingBreakpointEdited: Breakpoints.BreakpointManager.Breakpoint|undefined;
|
156
|
+
#updateScheduled = false;
|
157
|
+
#updateRunning = false;
|
158
|
+
|
159
|
+
private constructor(
|
160
|
+
breakpointManager: Breakpoints.BreakpointManager.BreakpointManager, settings: Common.Settings.Settings) {
|
161
|
+
this.#collapsedFilesSettings = Common.Settings.Settings.instance().createSetting('collapsedFiles', []);
|
162
|
+
this.#collapsedFiles = new Set(this.#collapsedFilesSettings.get());
|
163
|
+
this.#breakpointManager = breakpointManager;
|
164
|
+
this.#breakpointManager.addEventListener(
|
165
|
+
Breakpoints.BreakpointManager.Events.BreakpointAdded, this.#onBreakpointAdded, this);
|
166
|
+
this.#breakpointManager.addEventListener(
|
167
|
+
Breakpoints.BreakpointManager.Events.BreakpointRemoved, this.#onBreakpointRemoved, this);
|
168
|
+
this.#breakpointsActiveSetting = settings.moduleSetting('breakpointsActive');
|
169
|
+
this.#breakpointsActiveSetting.addChangeListener(this.update, this);
|
170
|
+
this.#pauseOnUncaughtExceptionSetting = settings.moduleSetting('pauseOnUncaughtException');
|
171
|
+
this.#pauseOnUncaughtExceptionSetting.addChangeListener(this.update, this);
|
172
|
+
this.#pauseOnCaughtExceptionSetting = settings.moduleSetting('pauseOnCaughtException');
|
173
|
+
this.#pauseOnCaughtExceptionSetting.addChangeListener(this.update, this);
|
174
|
+
}
|
136
175
|
|
137
|
-
|
138
|
-
|
139
|
-
|
176
|
+
static instance({forceNew, breakpointManager, settings}: {
|
177
|
+
forceNew: boolean|null,
|
178
|
+
breakpointManager: Breakpoints.BreakpointManager.BreakpointManager,
|
179
|
+
settings: Common.Settings.Settings,
|
180
|
+
} = {
|
181
|
+
forceNew: null,
|
182
|
+
breakpointManager: Breakpoints.BreakpointManager.BreakpointManager.instance(),
|
183
|
+
settings: Common.Settings.Settings.instance(),
|
184
|
+
}): BreakpointsSidebarController {
|
185
|
+
if (!breakpointsViewControllerInstance || forceNew) {
|
186
|
+
breakpointsViewControllerInstance = new BreakpointsSidebarController(breakpointManager, settings);
|
187
|
+
}
|
188
|
+
return breakpointsViewControllerInstance;
|
140
189
|
}
|
141
|
-
}
|
142
190
|
|
143
|
-
|
144
|
-
|
145
|
-
|
191
|
+
static removeInstance(): void {
|
192
|
+
breakpointsViewControllerInstance = null;
|
193
|
+
}
|
146
194
|
|
147
|
-
|
148
|
-
|
149
|
-
|
195
|
+
static targetSupportsIndependentPauseOnExceptionToggles(): boolean {
|
196
|
+
const hasNodeTargets =
|
197
|
+
SDK.TargetManager.TargetManager.instance().targets().some(target => target.type() === SDK.Target.Type.Node);
|
198
|
+
return !hasNodeTargets;
|
150
199
|
}
|
151
|
-
}
|
152
200
|
|
153
|
-
|
154
|
-
|
155
|
-
|
201
|
+
flavorChanged(_object: Object|null): void {
|
202
|
+
void this.update();
|
203
|
+
}
|
156
204
|
|
157
|
-
|
158
|
-
|
159
|
-
|
205
|
+
breakpointEditFinished(breakpoint: Breakpoints.BreakpointManager.Breakpoint|null, edited: boolean): void {
|
206
|
+
if (this.#outstandingBreakpointEdited && this.#outstandingBreakpointEdited === breakpoint) {
|
207
|
+
if (edited) {
|
208
|
+
Host.userMetrics.actionTaken(Host.UserMetrics.Action.BreakpointConditionEditedFromSidebar);
|
209
|
+
}
|
210
|
+
this.#outstandingBreakpointEdited = undefined;
|
211
|
+
}
|
160
212
|
}
|
161
|
-
}
|
162
213
|
|
163
|
-
|
164
|
-
|
165
|
-
|
214
|
+
breakpointStateChanged(breakpointItem: BreakpointItem, checked: boolean): void {
|
215
|
+
const locations = this.#getLocationsForBreakpointItem(breakpointItem);
|
216
|
+
locations.forEach((value: Breakpoints.BreakpointManager.BreakpointLocation) => {
|
217
|
+
const breakpoint = value.breakpoint;
|
218
|
+
breakpoint.setEnabled(checked);
|
219
|
+
});
|
220
|
+
}
|
166
221
|
|
167
|
-
|
168
|
-
|
169
|
-
|
222
|
+
async breakpointEdited(breakpointItem: BreakpointItem, editButtonClicked: boolean): Promise<void> {
|
223
|
+
const locations = this.#getLocationsForBreakpointItem(breakpointItem);
|
224
|
+
let location: Breakpoints.BreakpointManager.BreakpointLocation|undefined;
|
225
|
+
for (const locationCandidate of locations) {
|
226
|
+
if (!location || locationCandidate.uiLocation.compareTo(location.uiLocation) < 0) {
|
227
|
+
location = locationCandidate;
|
228
|
+
}
|
229
|
+
}
|
230
|
+
if (location) {
|
231
|
+
if (editButtonClicked) {
|
232
|
+
this.#outstandingBreakpointEdited = location.breakpoint;
|
233
|
+
}
|
234
|
+
await Common.Revealer.reveal(location);
|
235
|
+
}
|
170
236
|
}
|
171
|
-
}
|
172
237
|
|
173
|
-
|
174
|
-
|
175
|
-
|
238
|
+
breakpointsRemoved(breakpointItems: BreakpointItem[]): void {
|
239
|
+
const locations = breakpointItems.flatMap(breakpointItem => this.#getLocationsForBreakpointItem(breakpointItem));
|
240
|
+
locations.forEach(location => location?.breakpoint.remove(false /* keepInStorage */));
|
241
|
+
}
|
242
|
+
|
243
|
+
expandedStateChanged(url: Platform.DevToolsPath.UrlString, expanded: boolean): void {
|
244
|
+
if (expanded) {
|
245
|
+
this.#collapsedFiles.delete(url);
|
246
|
+
} else {
|
247
|
+
this.#collapsedFiles.add(url);
|
248
|
+
}
|
176
249
|
|
177
|
-
|
178
|
-
super(BreakpointSelectedEvent.eventName);
|
179
|
-
this.data = {breakpointItem: breakpointItem};
|
250
|
+
this.#saveSettings();
|
180
251
|
}
|
181
|
-
}
|
182
252
|
|
183
|
-
|
184
|
-
|
185
|
-
|
253
|
+
async jumpToSource(breakpointItem: BreakpointItem): Promise<void> {
|
254
|
+
const uiLocations = this.#getLocationsForBreakpointItem(breakpointItem).map(location => location.uiLocation);
|
255
|
+
let uiLocation: Workspace.UISourceCode.UILocation|undefined;
|
256
|
+
for (const uiLocationCandidate of uiLocations) {
|
257
|
+
if (!uiLocation || uiLocationCandidate.compareTo(uiLocation) < 0) {
|
258
|
+
uiLocation = uiLocationCandidate;
|
259
|
+
}
|
260
|
+
}
|
261
|
+
if (uiLocation) {
|
262
|
+
await Common.Revealer.reveal(uiLocation);
|
263
|
+
}
|
264
|
+
}
|
186
265
|
|
187
|
-
|
188
|
-
|
189
|
-
|
266
|
+
setPauseOnUncaughtExceptions(value: boolean): void {
|
267
|
+
this.#pauseOnUncaughtExceptionSetting.set(value);
|
268
|
+
}
|
269
|
+
|
270
|
+
setPauseOnCaughtExceptions(value: boolean): void {
|
271
|
+
this.#pauseOnCaughtExceptionSetting.set(value);
|
272
|
+
}
|
273
|
+
|
274
|
+
async update(): Promise<void> {
|
275
|
+
this.#updateScheduled = true;
|
276
|
+
if (this.#updateRunning) {
|
277
|
+
return;
|
278
|
+
}
|
279
|
+
this.#updateRunning = true;
|
280
|
+
while (this.#updateScheduled) {
|
281
|
+
this.#updateScheduled = false;
|
282
|
+
const data = await this.getUpdatedBreakpointViewData();
|
283
|
+
BreakpointsView.instance().data = data;
|
284
|
+
}
|
285
|
+
this.#updateRunning = false;
|
286
|
+
}
|
287
|
+
|
288
|
+
async getUpdatedBreakpointViewData(): Promise<BreakpointsViewData> {
|
289
|
+
const breakpointsActive = this.#breakpointsActiveSetting.get();
|
290
|
+
const independentPauseToggles = BreakpointsSidebarController.targetSupportsIndependentPauseOnExceptionToggles();
|
291
|
+
const pauseOnUncaughtExceptions = this.#pauseOnUncaughtExceptionSetting.get();
|
292
|
+
const pauseOnCaughtExceptions = this.#pauseOnCaughtExceptionSetting.get();
|
293
|
+
|
294
|
+
const breakpointLocations = this.#getBreakpointLocations();
|
295
|
+
if (!breakpointLocations.length) {
|
296
|
+
return {
|
297
|
+
breakpointsActive,
|
298
|
+
pauseOnCaughtExceptions,
|
299
|
+
pauseOnUncaughtExceptions,
|
300
|
+
independentPauseToggles,
|
301
|
+
groups: [],
|
302
|
+
};
|
303
|
+
}
|
304
|
+
|
305
|
+
const locationsGroupedById = this.#groupBreakpointLocationsById(breakpointLocations);
|
306
|
+
const locationIdsByLineId = this.#getLocationIdsByLineId(breakpointLocations);
|
307
|
+
|
308
|
+
const [content, selectedUILocation] = await Promise.all([
|
309
|
+
this.#getContent(locationsGroupedById),
|
310
|
+
this.#getHitUILocation(),
|
311
|
+
]);
|
312
|
+
|
313
|
+
const scriptIdToGroup = new Map<string, BreakpointGroup>();
|
314
|
+
|
315
|
+
for (let idx = 0; idx < locationsGroupedById.length; idx++) {
|
316
|
+
const locations = locationsGroupedById[idx];
|
317
|
+
const fstLocation = locations[0];
|
318
|
+
const sourceURL = fstLocation.uiLocation.uiSourceCode.url();
|
319
|
+
const scriptId = fstLocation.uiLocation.uiSourceCode.canononicalScriptId();
|
320
|
+
const uiLocation = fstLocation.uiLocation;
|
321
|
+
|
322
|
+
const isHit = selectedUILocation !== null &&
|
323
|
+
locations.some(location => location.uiLocation.id() === selectedUILocation.id());
|
324
|
+
|
325
|
+
const numBreakpointsOnLine = locationIdsByLineId.get(uiLocation.lineId()).size;
|
326
|
+
const showColumn = numBreakpointsOnLine > 1;
|
327
|
+
const locationText = uiLocation.lineAndColumnText(showColumn) as string;
|
328
|
+
|
329
|
+
const text = content[idx];
|
330
|
+
const codeSnippet = text instanceof TextUtils.Text.Text ?
|
331
|
+
text.lineAt(uiLocation.lineNumber) :
|
332
|
+
text.lines[text.bytecodeOffsetToLineNumber(uiLocation.columnNumber ?? 0)] ?? '';
|
333
|
+
|
334
|
+
if (isHit && this.#collapsedFiles.has(sourceURL)) {
|
335
|
+
this.#collapsedFiles.delete(sourceURL);
|
336
|
+
this.#saveSettings();
|
337
|
+
}
|
338
|
+
const expanded = !this.#collapsedFiles.has(sourceURL);
|
339
|
+
|
340
|
+
const status: BreakpointStatus = this.#getBreakpointState(locations);
|
341
|
+
const {type, hoverText} = this.#getBreakpointTypeAndDetails(locations);
|
342
|
+
const item = {
|
343
|
+
id: fstLocation.breakpoint.breakpointStorageId(),
|
344
|
+
location: locationText,
|
345
|
+
codeSnippet,
|
346
|
+
isHit,
|
347
|
+
status,
|
348
|
+
type,
|
349
|
+
hoverText,
|
350
|
+
};
|
351
|
+
this.#breakpointItemToLocationMap.set(item, locations);
|
352
|
+
|
353
|
+
let group = scriptIdToGroup.get(scriptId);
|
354
|
+
if (group) {
|
355
|
+
group.breakpointItems.push(item);
|
356
|
+
group.expanded ||= expanded;
|
357
|
+
} else {
|
358
|
+
const editable = this.#breakpointManager.supportsConditionalBreakpoints(uiLocation.uiSourceCode);
|
359
|
+
group = {
|
360
|
+
url: sourceURL,
|
361
|
+
name: uiLocation.uiSourceCode.displayName(),
|
362
|
+
editable,
|
363
|
+
expanded,
|
364
|
+
breakpointItems: [item],
|
365
|
+
};
|
366
|
+
scriptIdToGroup.set(scriptId, group);
|
367
|
+
}
|
368
|
+
}
|
369
|
+
return {
|
370
|
+
breakpointsActive,
|
371
|
+
pauseOnCaughtExceptions,
|
372
|
+
pauseOnUncaughtExceptions,
|
373
|
+
independentPauseToggles,
|
374
|
+
groups: Array.from(scriptIdToGroup.values()),
|
375
|
+
};
|
376
|
+
}
|
377
|
+
|
378
|
+
#onBreakpointAdded(event: Common.EventTarget.EventTargetEvent<Breakpoints.BreakpointManager.BreakpointLocation>):
|
379
|
+
Promise<void> {
|
380
|
+
const breakpoint = event.data.breakpoint;
|
381
|
+
if (breakpoint.origin === Breakpoints.BreakpointManager.BreakpointOrigin.USER_ACTION &&
|
382
|
+
this.#collapsedFiles.has(breakpoint.url())) {
|
383
|
+
// Auto-expand if a new breakpoint was added to a collapsed group.
|
384
|
+
this.#collapsedFiles.delete(breakpoint.url());
|
385
|
+
this.#saveSettings();
|
386
|
+
}
|
387
|
+
return this.update();
|
388
|
+
}
|
389
|
+
|
390
|
+
#onBreakpointRemoved(event: Common.EventTarget.EventTargetEvent<Breakpoints.BreakpointManager.BreakpointLocation>):
|
391
|
+
Promise<void> {
|
392
|
+
const breakpoint = event.data.breakpoint;
|
393
|
+
if (this.#collapsedFiles.has(breakpoint.url())) {
|
394
|
+
const locations = Breakpoints.BreakpointManager.BreakpointManager.instance().allBreakpointLocations();
|
395
|
+
const otherBreakpointsOnSameFileExist =
|
396
|
+
locations.some(location => location.breakpoint.url() === breakpoint.url());
|
397
|
+
if (!otherBreakpointsOnSameFileExist) {
|
398
|
+
// Clear up the #collapsedFiles set from this url if no breakpoint is left in this group.
|
399
|
+
this.#collapsedFiles.delete(breakpoint.url());
|
400
|
+
this.#saveSettings();
|
401
|
+
}
|
402
|
+
}
|
403
|
+
return this.update();
|
404
|
+
}
|
405
|
+
|
406
|
+
#saveSettings(): void {
|
407
|
+
this.#collapsedFilesSettings.set(Array.from(this.#collapsedFiles.values()));
|
408
|
+
}
|
409
|
+
|
410
|
+
#getBreakpointTypeAndDetails(locations: Breakpoints.BreakpointManager.BreakpointLocation[]):
|
411
|
+
{type: SDK.DebuggerModel.BreakpointType, hoverText?: string} {
|
412
|
+
const breakpointWithCondition = locations.find(location => Boolean(location.breakpoint.condition()));
|
413
|
+
const breakpoint = breakpointWithCondition?.breakpoint;
|
414
|
+
if (!breakpoint || !breakpoint.condition()) {
|
415
|
+
return {type: SDK.DebuggerModel.BreakpointType.REGULAR_BREAKPOINT};
|
416
|
+
}
|
417
|
+
|
418
|
+
const condition = breakpoint.condition();
|
419
|
+
if (breakpoint.isLogpoint()) {
|
420
|
+
return {type: SDK.DebuggerModel.BreakpointType.LOGPOINT, hoverText: condition};
|
421
|
+
}
|
422
|
+
|
423
|
+
return {type: SDK.DebuggerModel.BreakpointType.CONDITIONAL_BREAKPOINT, hoverText: condition};
|
424
|
+
}
|
425
|
+
|
426
|
+
#getLocationsForBreakpointItem(breakpointItem: BreakpointItem): Breakpoints.BreakpointManager.BreakpointLocation[] {
|
427
|
+
const locations = this.#breakpointItemToLocationMap.get(breakpointItem);
|
428
|
+
assertNotNullOrUndefined(locations);
|
429
|
+
return locations;
|
430
|
+
}
|
431
|
+
|
432
|
+
async #getHitUILocation(): Promise<Workspace.UISourceCode.UILocation|null> {
|
433
|
+
const details = UI.Context.Context.instance().flavor(SDK.DebuggerModel.DebuggerPausedDetails);
|
434
|
+
if (details && details.callFrames.length) {
|
435
|
+
return await Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().rawLocationToUILocation(
|
436
|
+
details.callFrames[0].location());
|
437
|
+
}
|
438
|
+
return null;
|
439
|
+
}
|
440
|
+
|
441
|
+
#getBreakpointLocations(): Breakpoints.BreakpointManager.BreakpointLocation[] {
|
442
|
+
const locations = this.#breakpointManager.allBreakpointLocations().filter(
|
443
|
+
breakpointLocation =>
|
444
|
+
breakpointLocation.uiLocation.uiSourceCode.project().type() !== Workspace.Workspace.projectTypes.Debugger);
|
445
|
+
|
446
|
+
locations.sort((item1, item2) => item1.uiLocation.compareTo(item2.uiLocation));
|
447
|
+
|
448
|
+
const result = [];
|
449
|
+
let lastBreakpoint: Breakpoints.BreakpointManager.Breakpoint|null = null;
|
450
|
+
let lastLocation: Workspace.UISourceCode.UILocation|null = null;
|
451
|
+
for (const location of locations) {
|
452
|
+
if (location.breakpoint !== lastBreakpoint || (lastLocation && location.uiLocation.compareTo(lastLocation))) {
|
453
|
+
result.push(location);
|
454
|
+
lastBreakpoint = location.breakpoint;
|
455
|
+
lastLocation = location.uiLocation;
|
456
|
+
}
|
457
|
+
}
|
458
|
+
return result;
|
459
|
+
}
|
460
|
+
|
461
|
+
#groupBreakpointLocationsById(breakpointLocations: Breakpoints.BreakpointManager.BreakpointLocation[]):
|
462
|
+
Breakpoints.BreakpointManager.BreakpointLocation[][] {
|
463
|
+
const map = new Platform.MapUtilities.Multimap<string, Breakpoints.BreakpointManager.BreakpointLocation>();
|
464
|
+
for (const breakpointLocation of breakpointLocations) {
|
465
|
+
const uiLocation = breakpointLocation.uiLocation;
|
466
|
+
map.set(uiLocation.id(), breakpointLocation);
|
467
|
+
}
|
468
|
+
const arr: Breakpoints.BreakpointManager.BreakpointLocation[][] = [];
|
469
|
+
for (const id of map.keysArray()) {
|
470
|
+
const locations = Array.from(map.get(id));
|
471
|
+
if (locations.length) {
|
472
|
+
arr.push(locations);
|
473
|
+
}
|
474
|
+
}
|
475
|
+
return arr;
|
190
476
|
}
|
191
|
-
}
|
192
477
|
|
193
|
-
|
194
|
-
|
195
|
-
|
478
|
+
#getLocationIdsByLineId(breakpointLocations: Breakpoints.BreakpointManager.BreakpointLocation[]):
|
479
|
+
Platform.MapUtilities.Multimap<string, string> {
|
480
|
+
const result = new Platform.MapUtilities.Multimap<string, string>();
|
196
481
|
|
197
|
-
|
198
|
-
|
199
|
-
|
482
|
+
for (const breakpointLocation of breakpointLocations) {
|
483
|
+
const uiLocation = breakpointLocation.uiLocation;
|
484
|
+
result.set(uiLocation.lineId(), uiLocation.id());
|
485
|
+
}
|
486
|
+
|
487
|
+
return result;
|
488
|
+
}
|
489
|
+
|
490
|
+
#getBreakpointState(locations: Breakpoints.BreakpointManager.BreakpointLocation[]): BreakpointStatus {
|
491
|
+
const hasEnabled = locations.some(location => location.breakpoint.enabled());
|
492
|
+
const hasDisabled = locations.some(location => !location.breakpoint.enabled());
|
493
|
+
let status: BreakpointStatus;
|
494
|
+
if (hasEnabled) {
|
495
|
+
status = hasDisabled ? BreakpointStatus.INDETERMINATE : BreakpointStatus.ENABLED;
|
496
|
+
} else {
|
497
|
+
status = BreakpointStatus.DISABLED;
|
498
|
+
}
|
499
|
+
return status;
|
500
|
+
}
|
501
|
+
|
502
|
+
#getContent(locations: Breakpoints.BreakpointManager.BreakpointLocation[][]):
|
503
|
+
Promise<Array<TextUtils.Text.Text|Common.WasmDisassembly.WasmDisassembly>> {
|
504
|
+
// Use a cache to share the Text objects between all breakpoints. This way
|
505
|
+
// we share the cached line ending information that Text calculates. This
|
506
|
+
// was very slow to calculate with a lot of breakpoints in the same very
|
507
|
+
// large source file.
|
508
|
+
const contentToTextMap = new Map<string, TextUtils.Text.Text>();
|
509
|
+
|
510
|
+
return Promise.all(locations.map(async ([{uiLocation: {uiSourceCode}}]) => {
|
511
|
+
const deferredContent = await uiSourceCode.requestContent({cachedWasmOnly: true});
|
512
|
+
if ('wasmDisassemblyInfo' in deferredContent && deferredContent.wasmDisassemblyInfo) {
|
513
|
+
return deferredContent.wasmDisassemblyInfo;
|
514
|
+
}
|
515
|
+
const contentText = deferredContent.content || '';
|
516
|
+
if (contentToTextMap.has(contentText)) {
|
517
|
+
return contentToTextMap.get(contentText) as TextUtils.Text.Text;
|
518
|
+
}
|
519
|
+
const text = new TextUtils.Text.Text(contentText);
|
520
|
+
contentToTextMap.set(contentText, text);
|
521
|
+
return text;
|
522
|
+
}));
|
200
523
|
}
|
201
524
|
}
|
202
525
|
|
203
|
-
export class BreakpointsView extends
|
526
|
+
export class BreakpointsView extends LegacyWrapper.LegacyWrapper.WrappableComponent {
|
527
|
+
readonly #controller: BreakpointsSidebarController;
|
528
|
+
|
529
|
+
static instance(): BreakpointsView {
|
530
|
+
if (!breakpointsViewInstance) {
|
531
|
+
breakpointsViewInstance = LegacyWrapper.LegacyWrapper.legacyWrapper(UI.Widget.Widget, new BreakpointsView());
|
532
|
+
}
|
533
|
+
return breakpointsViewInstance.getComponent();
|
534
|
+
}
|
535
|
+
|
536
|
+
constructor() {
|
537
|
+
super();
|
538
|
+
this.#controller = BreakpointsSidebarController.instance();
|
539
|
+
}
|
540
|
+
|
204
541
|
static readonly litTagName = LitHtml.literal`devtools-breakpoint-view`;
|
205
542
|
readonly #shadow = this.attachShadow({mode: 'open'});
|
206
543
|
|
@@ -214,9 +551,6 @@ export class BreakpointsView extends HTMLElement {
|
|
214
551
|
#breakpointGroups: BreakpointGroup[] = [];
|
215
552
|
#urlToDifferentiatingPath: Map<Platform.DevToolsPath.UrlString, string> = new Map();
|
216
553
|
|
217
|
-
#scheduledRender = false;
|
218
|
-
#enqueuedRender = false;
|
219
|
-
|
220
554
|
set data(data: BreakpointsViewData) {
|
221
555
|
this.#pauseOnUncaughtExceptions = data.pauseOnUncaughtExceptions;
|
222
556
|
this.#pauseOnCaughtExceptions = data.pauseOnCaughtExceptions;
|
@@ -230,22 +564,14 @@ export class BreakpointsView extends HTMLElement {
|
|
230
564
|
}
|
231
565
|
this.#urlToDifferentiatingPath = getDifferentiatingPathMap(titleInfos);
|
232
566
|
|
233
|
-
void this
|
567
|
+
void this.render();
|
234
568
|
}
|
235
569
|
|
236
570
|
connectedCallback(): void {
|
237
571
|
this.#shadow.adoptedStyleSheets = [Input.checkboxStyles, breakpointsViewStyles];
|
238
572
|
}
|
239
573
|
|
240
|
-
async
|
241
|
-
if (this.#scheduledRender) {
|
242
|
-
// If we are already rendering, don't render again immediately, but
|
243
|
-
// enqueue it to be run after we're done on our current render.
|
244
|
-
this.#enqueuedRender = true;
|
245
|
-
return;
|
246
|
-
}
|
247
|
-
|
248
|
-
this.#scheduledRender = true;
|
574
|
+
override async render(): Promise<void> {
|
249
575
|
await coordinator.write('BreakpointsView render', () => {
|
250
576
|
const clickHandler = async(event: Event): Promise<void> => {
|
251
577
|
const currentTarget = event.currentTarget as HTMLElement;
|
@@ -296,15 +622,6 @@ export class BreakpointsView extends HTMLElement {
|
|
296
622
|
element?.setAttribute('tabindex', '0');
|
297
623
|
}
|
298
624
|
});
|
299
|
-
|
300
|
-
this.#scheduledRender = false;
|
301
|
-
|
302
|
-
// If render() was called when we were already mid-render, let's re-render
|
303
|
-
// to ensure we're not rendering any stale UI.
|
304
|
-
if (this.#enqueuedRender) {
|
305
|
-
this.#enqueuedRender = false;
|
306
|
-
return this.#render();
|
307
|
-
}
|
308
625
|
}
|
309
626
|
|
310
627
|
async #keyDownHandler(event: KeyboardEvent): Promise<void> {
|
@@ -388,7 +705,7 @@ export class BreakpointsView extends HTMLElement {
|
|
388
705
|
const clickHandler = (event: Event): void => {
|
389
706
|
Host.userMetrics.breakpointEditDialogRevealedFrom(
|
390
707
|
Host.UserMetrics.BreakpointEditDialogRevealedFrom.BreakpointSidebarEditButton);
|
391
|
-
this.
|
708
|
+
void this.#controller.breakpointEdited(breakpointItem, true /* editButtonClicked */);
|
392
709
|
event.consume();
|
393
710
|
};
|
394
711
|
const title = breakpointItem.type === SDK.DebuggerModel.BreakpointType.LOGPOINT ?
|
@@ -414,7 +731,7 @@ export class BreakpointsView extends HTMLElement {
|
|
414
731
|
breakpointItems: BreakpointItem[], tooltipText: string, action: Host.UserMetrics.Action): LitHtml.TemplateResult {
|
415
732
|
const clickHandler = (event: Event): void => {
|
416
733
|
Host.userMetrics.actionTaken(action);
|
417
|
-
this.
|
734
|
+
void this.#controller.breakpointsRemoved(breakpointItems);
|
418
735
|
event.consume();
|
419
736
|
};
|
420
737
|
// clang-format off
|
@@ -439,16 +756,16 @@ export class BreakpointsView extends HTMLElement {
|
|
439
756
|
|
440
757
|
menu.defaultSection().appendItem(i18nString(UIStrings.removeAllBreakpointsInFile), () => {
|
441
758
|
Host.userMetrics.actionTaken(Host.UserMetrics.Action.BreakpointsInFileRemovedFromContextMenu);
|
442
|
-
this.
|
759
|
+
void this.#controller.breakpointsRemoved(breakpointItems);
|
443
760
|
});
|
444
761
|
const otherGroups = this.#breakpointGroups.filter(group => group !== breakpointGroup);
|
445
762
|
menu.defaultSection().appendItem(i18nString(UIStrings.removeOtherBreakpoints), () => {
|
446
763
|
const breakpointItems = otherGroups.map(({breakpointItems}) => breakpointItems).flat();
|
447
|
-
this.
|
764
|
+
void this.#controller.breakpointsRemoved(breakpointItems);
|
448
765
|
}, otherGroups.length === 0);
|
449
766
|
menu.defaultSection().appendItem(i18nString(UIStrings.removeAllBreakpoints), () => {
|
450
767
|
const breakpointItems = this.#breakpointGroups.map(({breakpointItems}) => breakpointItems).flat();
|
451
|
-
this.
|
768
|
+
void this.#controller.breakpointsRemoved(breakpointItems);
|
452
769
|
});
|
453
770
|
|
454
771
|
const notEnabledItems =
|
@@ -456,7 +773,7 @@ export class BreakpointsView extends HTMLElement {
|
|
456
773
|
menu.debugSection().appendItem(i18nString(UIStrings.enableAllBreakpointsInFile), () => {
|
457
774
|
Host.userMetrics.actionTaken(Host.UserMetrics.Action.BreakpointsInFileEnabledDisabledFromContextMenu);
|
458
775
|
for (const breakpointItem of notEnabledItems) {
|
459
|
-
this.
|
776
|
+
this.#controller.breakpointStateChanged(breakpointItem, true);
|
460
777
|
}
|
461
778
|
}, notEnabledItems.length === 0);
|
462
779
|
const notDisabledItems =
|
@@ -464,7 +781,7 @@ export class BreakpointsView extends HTMLElement {
|
|
464
781
|
menu.debugSection().appendItem(i18nString(UIStrings.disableAllBreakpointsInFile), () => {
|
465
782
|
Host.userMetrics.actionTaken(Host.UserMetrics.Action.BreakpointsInFileEnabledDisabledFromContextMenu);
|
466
783
|
for (const breakpointItem of notDisabledItems) {
|
467
|
-
this.
|
784
|
+
this.#controller.breakpointStateChanged(breakpointItem, false);
|
468
785
|
}
|
469
786
|
}, notDisabledItems.length === 0);
|
470
787
|
|
@@ -479,7 +796,7 @@ export class BreakpointsView extends HTMLElement {
|
|
479
796
|
const toggleHandler = (event: Event): void => {
|
480
797
|
const htmlDetails = event.target as HTMLDetailsElement;
|
481
798
|
group.expanded = htmlDetails.open;
|
482
|
-
this.
|
799
|
+
void this.#controller.expandedStateChanged(group.url, group.expanded);
|
483
800
|
};
|
484
801
|
const clickHandler = async(event: Event): Promise<void> => {
|
485
802
|
const selected = event.currentTarget as HTMLElement;
|
@@ -528,7 +845,7 @@ export class BreakpointsView extends HTMLElement {
|
|
528
845
|
const updatedStatus = element.checked ? BreakpointStatus.ENABLED : BreakpointStatus.DISABLED;
|
529
846
|
const itemsToUpdate = group.breakpointItems.filter(item => item.status !== updatedStatus);
|
530
847
|
itemsToUpdate.forEach(item => {
|
531
|
-
this.
|
848
|
+
this.#controller.breakpointStateChanged(item, element.checked);
|
532
849
|
});
|
533
850
|
e.consume();
|
534
851
|
};
|
@@ -559,26 +876,26 @@ export class BreakpointsView extends HTMLElement {
|
|
559
876
|
menu.revealSection().appendItem(editBreakpointText, () => {
|
560
877
|
Host.userMetrics.breakpointEditDialogRevealedFrom(
|
561
878
|
Host.UserMetrics.BreakpointEditDialogRevealedFrom.BreakpointSidebarContextMenu);
|
562
|
-
this.
|
879
|
+
void this.#controller.breakpointEdited(breakpointItem, false /* editButtonClicked */);
|
563
880
|
}, !editable);
|
564
881
|
|
565
882
|
menu.defaultSection().appendItem(i18nString(UIStrings.removeBreakpoint), () => {
|
566
883
|
Host.userMetrics.actionTaken(Host.UserMetrics.Action.BreakpointRemovedFromContextMenu);
|
567
|
-
this.
|
884
|
+
void this.#controller.breakpointsRemoved([breakpointItem]);
|
568
885
|
});
|
569
886
|
const otherItems = this.#breakpointGroups.map(({breakpointItems}) => breakpointItems)
|
570
887
|
.flat()
|
571
888
|
.filter(item => item !== breakpointItem);
|
572
889
|
menu.defaultSection().appendItem(i18nString(UIStrings.removeOtherBreakpoints), () => {
|
573
|
-
this.
|
890
|
+
void this.#controller.breakpointsRemoved(otherItems);
|
574
891
|
}, otherItems.length === 0);
|
575
892
|
menu.defaultSection().appendItem(i18nString(UIStrings.removeAllBreakpoints), () => {
|
576
893
|
const breakpointItems = this.#breakpointGroups.map(({breakpointItems}) => breakpointItems).flat();
|
577
|
-
this.
|
894
|
+
void this.#controller.breakpointsRemoved(breakpointItems);
|
578
895
|
});
|
579
896
|
|
580
897
|
menu.editSection().appendItem(i18nString(UIStrings.revealLocation), () => {
|
581
|
-
this.
|
898
|
+
void this.#controller.jumpToSource(breakpointItem);
|
582
899
|
});
|
583
900
|
|
584
901
|
void menu.show();
|
@@ -588,7 +905,7 @@ export class BreakpointsView extends HTMLElement {
|
|
588
905
|
breakpointItem: BreakpointItem, editable: boolean, groupIndex: number,
|
589
906
|
breakpointItemIndex: number): LitHtml.TemplateResult {
|
590
907
|
const codeSnippetClickHandler = (event: Event): void => {
|
591
|
-
this.
|
908
|
+
void this.#controller.jumpToSource(breakpointItem);
|
592
909
|
event.consume();
|
593
910
|
};
|
594
911
|
const breakpointItemClickHandler = async(event: Event): Promise<void> => {
|
@@ -676,12 +993,12 @@ export class BreakpointsView extends HTMLElement {
|
|
676
993
|
|
677
994
|
#onCheckboxToggled(e: Event, item: BreakpointItem): void {
|
678
995
|
const element = e.target as HTMLInputElement;
|
679
|
-
this.
|
996
|
+
this.#controller.breakpointStateChanged(item, element.checked);
|
680
997
|
}
|
681
998
|
|
682
999
|
#onPauseOnCaughtExceptionsStateChanged(e: Event): void {
|
683
1000
|
const {checked} = e.target as HTMLInputElement;
|
684
|
-
this.
|
1001
|
+
this.#controller.setPauseOnCaughtExceptions(checked);
|
685
1002
|
}
|
686
1003
|
|
687
1004
|
#onPauseOnUncaughtExceptionsStateChanged(e: Event): void {
|
@@ -705,7 +1022,7 @@ export class BreakpointsView extends HTMLElement {
|
|
705
1022
|
}
|
706
1023
|
});
|
707
1024
|
}
|
708
|
-
this.
|
1025
|
+
this.#controller.setPauseOnUncaughtExceptions(checked);
|
709
1026
|
}
|
710
1027
|
}
|
711
1028
|
|