chrome-devtools-frontend 1.0.1576287 → 1.0.1576915
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/front_end/core/sdk/DebuggerModel.ts +14 -4
- package/front_end/generated/SupportedCSSProperties.js +37 -0
- package/front_end/models/bindings/DebuggerLanguagePlugins.ts +37 -38
- package/front_end/models/javascript_metadata/NativeFunctions.js +8 -0
- package/front_end/models/stack_trace/StackTrace.ts +19 -18
- package/front_end/panels/accessibility/AXBreadcrumbsPane.ts +5 -3
- package/front_end/panels/ai_assistance/components/ChatMessage.ts +5 -1
- package/front_end/panels/animation/AnimationGroupPreviewUI.ts +1 -1
- package/front_end/panels/application/ServiceWorkerUpdateCycleView.ts +1 -0
- package/front_end/panels/application/components/BackForwardCacheView.ts +4 -2
- package/front_end/panels/autofill/AutofillView.ts +1 -1
- package/front_end/panels/browser_debugger/XHRBreakpointsSidebarPane.ts +1 -0
- package/front_end/panels/console/ConsoleViewMessage.ts +1 -0
- package/front_end/panels/elements/ElementsTreeElement.ts +1 -0
- package/front_end/panels/elements/LayoutPane.ts +8 -7
- package/front_end/panels/elements/components/ElementsBreadcrumbs.ts +1 -1
- package/front_end/panels/elements/components/StylePropertyEditor.ts +2 -1
- package/front_end/panels/lighthouse/LighthouseReportRenderer.ts +1 -1
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryValueInterpreter.ts +1 -1
- package/front_end/panels/linear_memory_inspector/components/ValueInterpreterDisplay.ts +1 -1
- package/front_end/panels/media/PlayerListView.ts +1 -1
- package/front_end/panels/network/NetworkLogViewColumns.ts +2 -1
- package/front_end/panels/network/RequestPayloadView.ts +42 -91
- package/front_end/panels/network/ShowMoreDetailsWidget.ts +96 -0
- package/front_end/panels/network/components/RequestHeaderSection.ts +1 -1
- package/front_end/panels/network/network.ts +2 -0
- package/front_end/panels/protocol_monitor/JSONEditor.ts +1 -1
- package/front_end/panels/recorder/components/RecordingListView.ts +1 -1
- package/front_end/panels/recorder/components/StepEditor.ts +3 -3
- package/front_end/panels/settings/KeybindsSettingsTab.ts +2 -1
- package/front_end/panels/sources/CallStackSidebarPane.ts +58 -11
- package/front_end/panels/sources/DebuggerPlugin.ts +19 -22
- package/front_end/panels/sources/SourcesPanel.ts +6 -24
- package/front_end/panels/sources/components/HeadersView.ts +2 -2
- package/front_end/panels/timeline/components/BreadcrumbsUI.ts +1 -1
- package/front_end/panels/timeline/components/SidebarAnnotationsTab.ts +1 -1
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/report_view/ReportView.ts +2 -2
- package/front_end/ui/components/report_view/report.css +1 -0
- package/front_end/ui/components/suggestion_input/SuggestionInput.ts +7 -12
- package/front_end/ui/components/tree_outline/TreeOutline.ts +1 -1
- package/front_end/ui/legacy/ContextMenu.ts +12 -7
- package/front_end/ui/legacy/ListControl.ts +2 -1
- package/front_end/ui/legacy/ListWidget.ts +1 -1
- package/front_end/ui/legacy/SoftContextMenu.ts +2 -1
- package/front_end/ui/legacy/Treeoutline.ts +1 -0
- package/front_end/ui/legacy/components/data_grid/DataGrid.ts +4 -2
- package/front_end/ui/legacy/components/quick_open/FilteredListWidget.ts +1 -1
- package/front_end/ui/visual_logging/KnownContextValues.ts +1 -0
- package/package.json +1 -1
|
@@ -49,8 +49,10 @@ import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
|
49
49
|
|
|
50
50
|
import requestPayloadTreeStyles from './requestPayloadTree.css.js';
|
|
51
51
|
import requestPayloadViewStyles from './requestPayloadView.css.js';
|
|
52
|
+
import {ShowMoreDetailsWidget} from './ShowMoreDetailsWidget.js';
|
|
52
53
|
|
|
53
54
|
const {classMap} = Directives;
|
|
55
|
+
const {widgetConfig} = UI.Widget;
|
|
54
56
|
const UIStrings = {
|
|
55
57
|
/**
|
|
56
58
|
* @description A context menu item Payload View of the Network panel to copy a parsed value.
|
|
@@ -77,10 +79,6 @@ const UIStrings = {
|
|
|
77
79
|
* @description Text in Request Payload View of the Network panel
|
|
78
80
|
*/
|
|
79
81
|
formData: 'Form Data',
|
|
80
|
-
/**
|
|
81
|
-
* @description Text to show more content
|
|
82
|
-
*/
|
|
83
|
-
showMore: 'Show more',
|
|
84
82
|
/**
|
|
85
83
|
* @description Text for toggling the view of payload data (e.g. query string parameters) from source to parsed in the payload tab
|
|
86
84
|
*/
|
|
@@ -134,7 +132,7 @@ export class RequestPayloadView extends UI.Widget.VBox {
|
|
|
134
132
|
|
|
135
133
|
this.queryStringCategory = new Category(root, 'query-string');
|
|
136
134
|
this.formDataCategory = new Category(root, 'form-data');
|
|
137
|
-
this.requestPayloadCategory = new Category(root, 'request-payload'
|
|
135
|
+
this.requestPayloadCategory = new Category(root, 'request-payload');
|
|
138
136
|
}
|
|
139
137
|
|
|
140
138
|
override wasShown(): void {
|
|
@@ -200,45 +198,16 @@ export class RequestPayloadView extends UI.Widget.VBox {
|
|
|
200
198
|
}
|
|
201
199
|
}
|
|
202
200
|
|
|
203
|
-
private populateTreeElementWithSourceText(treeElement: UI.TreeOutline.TreeElement,
|
|
204
|
-
const
|
|
205
|
-
const text = (sourceText || '').trim();
|
|
206
|
-
const trim = text.length > MAX_LENGTH;
|
|
207
|
-
|
|
208
|
-
const sourceTextElement = document.createElement('span');
|
|
209
|
-
sourceTextElement.classList.add('payload-value');
|
|
210
|
-
sourceTextElement.classList.add('source-code');
|
|
211
|
-
sourceTextElement.textContent = trim ? text.substr(0, MAX_LENGTH) : text;
|
|
212
|
-
|
|
213
|
-
const sourceTreeElement = new UI.TreeOutline.TreeElement(sourceTextElement);
|
|
201
|
+
private populateTreeElementWithSourceText(treeElement: UI.TreeOutline.TreeElement, text: string): void {
|
|
202
|
+
const sourceTreeElement = new UI.TreeOutline.TreeElement();
|
|
214
203
|
|
|
215
204
|
treeElement.removeChildren();
|
|
216
205
|
treeElement.appendChild(sourceTreeElement);
|
|
217
206
|
this.addEntryContextMenuHandler(sourceTreeElement, i18nString(UIStrings.copyPayload), 'copy-payload', () => text);
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
const showMoreButton = new Buttons.Button.Button();
|
|
223
|
-
showMoreButton.data = {variant: Buttons.Button.Variant.OUTLINED, jslogContext: 'show-more'};
|
|
224
|
-
showMoreButton.innerText = i18nString(UIStrings.showMore);
|
|
225
|
-
showMoreButton.classList.add('request-payload-show-more-button');
|
|
226
|
-
|
|
227
|
-
function showMore(): void {
|
|
228
|
-
showMoreButton.remove();
|
|
229
|
-
sourceTextElement.textContent = text;
|
|
230
|
-
sourceTreeElement.listItemElement.removeEventListener('contextmenu', onContextMenuShowMore);
|
|
231
|
-
}
|
|
232
|
-
showMoreButton.addEventListener('click', showMore);
|
|
233
|
-
|
|
234
|
-
function onContextMenuShowMore(event: Event): void {
|
|
235
|
-
const contextMenu = new UI.ContextMenu.ContextMenu(event);
|
|
236
|
-
const section = contextMenu.newSection();
|
|
237
|
-
section.appendItem(i18nString(UIStrings.showMore), showMore, {jslogContext: 'show-more'});
|
|
238
|
-
void contextMenu.show();
|
|
239
|
-
}
|
|
240
|
-
sourceTreeElement.listItemElement.addEventListener('contextmenu', onContextMenuShowMore);
|
|
241
|
-
sourceTextElement.appendChild(showMoreButton);
|
|
207
|
+
render(
|
|
208
|
+
html`<devtools-widget class='payload-value source-code'
|
|
209
|
+
.widgetConfig=${widgetConfig(ShowMoreDetailsWidget, {text})}></devtools-widget>`,
|
|
210
|
+
sourceTreeElement.listItemElement);
|
|
242
211
|
}
|
|
243
212
|
|
|
244
213
|
private refreshParams(
|
|
@@ -306,7 +275,7 @@ export class RequestPayloadView extends UI.Widget.VBox {
|
|
|
306
275
|
|
|
307
276
|
paramsTreeElement.removeChildren();
|
|
308
277
|
if (shouldViewSource) {
|
|
309
|
-
this.populateTreeElementWithSourceText(paramsTreeElement, sourceText);
|
|
278
|
+
this.populateTreeElementWithSourceText(paramsTreeElement, (sourceText ?? '').trim());
|
|
310
279
|
paramsTreeElement.listItemElement.addEventListener('contextmenu', viewParsedContextMenu);
|
|
311
280
|
} else {
|
|
312
281
|
this.populateTreeElementWithParsedParameters(paramsTreeElement, params);
|
|
@@ -363,25 +332,6 @@ export class RequestPayloadView extends UI.Widget.VBox {
|
|
|
363
332
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
364
333
|
private refreshRequestJSONPayload(parsedObject: any, sourceText: string): void {
|
|
365
334
|
const rootListItem = this.requestPayloadCategory;
|
|
366
|
-
rootListItem.removeChildren();
|
|
367
|
-
|
|
368
|
-
const rootListItemElement = rootListItem.listItemElement;
|
|
369
|
-
rootListItemElement.removeChildren();
|
|
370
|
-
rootListItemElement.createChild('div', 'selection fill');
|
|
371
|
-
UI.UIUtils.createTextChild(rootListItemElement, this.requestPayloadCategory.title.toString());
|
|
372
|
-
|
|
373
|
-
if (viewSourceForItems.has(rootListItem)) {
|
|
374
|
-
this.appendJSONPayloadSource(rootListItem, parsedObject, sourceText);
|
|
375
|
-
} else {
|
|
376
|
-
this.appendJSONPayloadParsed(rootListItem, parsedObject, sourceText);
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
// TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
|
|
381
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
382
|
-
private appendJSONPayloadSource(rootListItem: Category, parsedObject: any, sourceText: string): void {
|
|
383
|
-
const rootListItemElement = rootListItem.listItemElement;
|
|
384
|
-
this.populateTreeElementWithSourceText(rootListItem, sourceText);
|
|
385
335
|
|
|
386
336
|
const viewParsed = function(this: RequestPayloadView, event: Event): void {
|
|
387
337
|
rootListItemElement.removeEventListener('contextmenu', viewParsedContextMenu);
|
|
@@ -390,9 +340,6 @@ export class RequestPayloadView extends UI.Widget.VBox {
|
|
|
390
340
|
event.consume();
|
|
391
341
|
};
|
|
392
342
|
|
|
393
|
-
const viewParsedButton = this.createViewSourceToggle(/* viewSource */ true, viewParsed.bind(this));
|
|
394
|
-
rootListItemElement.appendChild(viewParsedButton);
|
|
395
|
-
|
|
396
343
|
const viewParsedContextMenu = (event: Event): void => {
|
|
397
344
|
if (!rootListItem.expanded) {
|
|
398
345
|
return;
|
|
@@ -403,27 +350,6 @@ export class RequestPayloadView extends UI.Widget.VBox {
|
|
|
403
350
|
void contextMenu.show();
|
|
404
351
|
};
|
|
405
352
|
|
|
406
|
-
rootListItemElement.addEventListener('contextmenu', viewParsedContextMenu);
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
// TODO(crbug.com/1172300) Ignored during the jsdoc to ts migration)
|
|
410
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
411
|
-
private appendJSONPayloadParsed(rootListItem: Category, parsedObject: any, sourceText: string): void {
|
|
412
|
-
const object = (SDK.RemoteObject.RemoteObject.fromLocalObject(parsedObject) as SDK.RemoteObject.LocalJSONObject);
|
|
413
|
-
const section =
|
|
414
|
-
new ObjectUI.ObjectPropertiesSection.RootElement(new ObjectUI.ObjectPropertiesSection.ObjectTree(object));
|
|
415
|
-
section.title = (object.description);
|
|
416
|
-
section.expand();
|
|
417
|
-
// `editable` is not a valid property for `ObjectUI.ObjectPropertiesSection.RootElement`. Only for
|
|
418
|
-
// `ObjectUI.ObjectPropertiesSection.ObjectPropertiesSection`. We do not know if this assignment is
|
|
419
|
-
// safe to delete.
|
|
420
|
-
// @ts-expect-error
|
|
421
|
-
section.editable = false;
|
|
422
|
-
rootListItem.childrenListElement.classList.add('source-code', 'object-properties-section');
|
|
423
|
-
|
|
424
|
-
rootListItem.appendChild(section);
|
|
425
|
-
const rootListItemElement = rootListItem.listItemElement;
|
|
426
|
-
|
|
427
353
|
const viewSource = function(this: RequestPayloadView, event: Event): void {
|
|
428
354
|
rootListItemElement.removeEventListener('contextmenu', viewSourceContextMenu);
|
|
429
355
|
|
|
@@ -442,16 +368,41 @@ export class RequestPayloadView extends UI.Widget.VBox {
|
|
|
442
368
|
void contextMenu.show();
|
|
443
369
|
};
|
|
444
370
|
|
|
445
|
-
const
|
|
446
|
-
rootListItemElement.
|
|
371
|
+
const showSource = viewSourceForItems.has(rootListItem);
|
|
372
|
+
const rootListItemElement = rootListItem.listItemElement;
|
|
373
|
+
render(
|
|
374
|
+
html`<div class="selection fill"></div>${i18nString(UIStrings.requestPayload)}${
|
|
375
|
+
this.createViewSourceToggle(showSource, showSource ? viewParsed.bind(this) : viewSource.bind(this))}`,
|
|
376
|
+
rootListItemElement);
|
|
377
|
+
|
|
378
|
+
rootListItem.removeChildren();
|
|
379
|
+
if (showSource) {
|
|
380
|
+
this.populateTreeElementWithSourceText(rootListItem, sourceText);
|
|
381
|
+
rootListItemElement.addEventListener('contextmenu', viewParsedContextMenu);
|
|
382
|
+
} else {
|
|
383
|
+
rootListItem.childrenListElement.classList.add('source-code', 'object-properties-section');
|
|
384
|
+
this.populateTreeElementWithObject(rootListItem, parsedObject);
|
|
385
|
+
rootListItemElement.addEventListener('contextmenu', viewSourceContextMenu);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
447
388
|
|
|
448
|
-
|
|
389
|
+
private populateTreeElementWithObject(rootListItem: Category, parsedObject: object): void {
|
|
390
|
+
const object = new SDK.RemoteObject.LocalJSONObject(parsedObject);
|
|
391
|
+
const section =
|
|
392
|
+
new ObjectUI.ObjectPropertiesSection.RootElement(new ObjectUI.ObjectPropertiesSection.ObjectTree(object));
|
|
393
|
+
section.title = (object.description);
|
|
394
|
+
section.expand();
|
|
395
|
+
rootListItem.appendChild(section);
|
|
449
396
|
}
|
|
450
397
|
|
|
451
|
-
private createViewSourceToggle(viewSource: boolean, handler: (arg0: Event) => void):
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
398
|
+
private createViewSourceToggle(viewSource: boolean, handler: (arg0: Event) => void): LitTemplate {
|
|
399
|
+
return html`<devtools-button
|
|
400
|
+
class=payload-toggle
|
|
401
|
+
jslogi=${VisualLogging.action().track({click: true}).context('source-parse')}
|
|
402
|
+
.variant=${Buttons.Button.Variant.OUTLINED}
|
|
403
|
+
@click=${handler}>
|
|
404
|
+
${viewSource ? i18nString(UIStrings.viewParsed) : i18nString(UIStrings.viewSource)}
|
|
405
|
+
</devtools-button>`;
|
|
455
406
|
}
|
|
456
407
|
|
|
457
408
|
private toggleURLDecoding(event: Event): void {
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// Copyright 2026 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 i18n from '../../core/i18n/i18n.js';
|
|
6
|
+
import * as Buttons from '../../ui/components/buttons/buttons.js';
|
|
7
|
+
import * as UI from '../../ui/legacy/legacy.js';
|
|
8
|
+
import * as Lit from '../../ui/lit/lit.js';
|
|
9
|
+
const UIStrings = {
|
|
10
|
+
/**
|
|
11
|
+
* @description Text to show more content
|
|
12
|
+
*/
|
|
13
|
+
showMore: 'Show more',
|
|
14
|
+
} as const;
|
|
15
|
+
const str_ = i18n.i18n.registerUIStrings('panels/network/ShowMoreDetailsWidget.ts', UIStrings);
|
|
16
|
+
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
17
|
+
|
|
18
|
+
const {render, html} = Lit;
|
|
19
|
+
interface ViewInput {
|
|
20
|
+
text: string;
|
|
21
|
+
showMore: boolean;
|
|
22
|
+
onToggle: () => void;
|
|
23
|
+
copy: CopyMenuItem|null;
|
|
24
|
+
}
|
|
25
|
+
type View = (input: ViewInput, output: object, target: HTMLElement) => void;
|
|
26
|
+
const MAX_LENGTH = 3000;
|
|
27
|
+
|
|
28
|
+
export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
29
|
+
const onContextMenuShowMore = (event: Event): void => {
|
|
30
|
+
const contextMenu = new UI.ContextMenu.ContextMenu(event);
|
|
31
|
+
if (input.copy) {
|
|
32
|
+
contextMenu.clipboardSection().appendItem(input.copy.menuItem, input.copy.handler);
|
|
33
|
+
}
|
|
34
|
+
if (!input.showMore) {
|
|
35
|
+
contextMenu.newSection().appendItem(i18nString(UIStrings.showMore), input.onToggle, {jslogContext: 'show-more'});
|
|
36
|
+
}
|
|
37
|
+
void contextMenu.show();
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
render(html`<span
|
|
41
|
+
@contextmenu=${onContextMenuShowMore}
|
|
42
|
+
>${input.showMore ? input.text : input.text.substr(0, MAX_LENGTH)}</span>
|
|
43
|
+
${
|
|
44
|
+
!input.showMore && input.text.length > MAX_LENGTH ? html`<devtools-button
|
|
45
|
+
.variant=${Buttons.Button.Variant.OUTLINED}
|
|
46
|
+
.jslogContext=${'show-more'}
|
|
47
|
+
@click=${input.onToggle}>
|
|
48
|
+
${i18nString(UIStrings.showMore)}
|
|
49
|
+
</devtools-button>` :
|
|
50
|
+
Lit.nothing}`,
|
|
51
|
+
target);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
interface CopyMenuItem {
|
|
55
|
+
menuItem: UI.ContextMenu.Item;
|
|
56
|
+
handler: () => void;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export class ShowMoreDetailsWidget extends UI.Widget.Widget {
|
|
60
|
+
readonly #view: View;
|
|
61
|
+
#text = '';
|
|
62
|
+
#showMore = false;
|
|
63
|
+
#copy: CopyMenuItem|null = null;
|
|
64
|
+
constructor(target?: HTMLElement, view = DEFAULT_VIEW) {
|
|
65
|
+
super(target);
|
|
66
|
+
this.#view = view;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get text(): string {
|
|
70
|
+
return this.#text;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
set text(text: string) {
|
|
74
|
+
this.#text = text;
|
|
75
|
+
this.requestUpdate();
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
set copy(copy: CopyMenuItem) {
|
|
79
|
+
this.#copy = copy;
|
|
80
|
+
this.requestUpdate();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
override performUpdate(): void {
|
|
84
|
+
this.#view(
|
|
85
|
+
{
|
|
86
|
+
copy: this.#copy,
|
|
87
|
+
text: this.#text,
|
|
88
|
+
showMore: this.#showMore,
|
|
89
|
+
onToggle: () => {
|
|
90
|
+
this.#showMore = true;
|
|
91
|
+
this.requestUpdate();
|
|
92
|
+
},
|
|
93
|
+
},
|
|
94
|
+
{}, this.contentElement);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -59,7 +59,7 @@ export const DEFAULT_VIEW: View = (input, output, target) => {
|
|
|
59
59
|
${headers.map(header => html`
|
|
60
60
|
<devtools-header-section-row
|
|
61
61
|
.data=${{ header }}
|
|
62
|
-
jslog=${VisualLogging.item('request-header')}
|
|
62
|
+
jslog=${VisualLogging.item('request-header').track({resize: true})}
|
|
63
63
|
></devtools-header-section-row>
|
|
64
64
|
`)}
|
|
65
65
|
`, target);
|
|
@@ -52,6 +52,7 @@ import * as RequestResponseView from './RequestResponseView.js';
|
|
|
52
52
|
import * as RequestTimingView from './RequestTimingView.js';
|
|
53
53
|
import * as ResourceDirectSocketChunkView from './ResourceDirectSocketChunkView.js';
|
|
54
54
|
import * as ResourceWebSocketFrameView from './ResourceWebSocketFrameView.js';
|
|
55
|
+
import * as ShowMoreDetailsWidget from './ShowMoreDetailsWidget.js';
|
|
55
56
|
import * as SignedExchangeInfoView from './SignedExchangeInfoView.js';
|
|
56
57
|
|
|
57
58
|
export {
|
|
@@ -79,5 +80,6 @@ export {
|
|
|
79
80
|
RequestTimingView,
|
|
80
81
|
ResourceDirectSocketChunkView,
|
|
81
82
|
ResourceWebSocketFrameView,
|
|
83
|
+
ShowMoreDetailsWidget,
|
|
82
84
|
SignedExchangeInfoView,
|
|
83
85
|
};
|
|
@@ -990,7 +990,7 @@ function renderTargetSelectorRow(input: ViewInput): Lit.TemplateResult|undefined
|
|
|
990
990
|
jslog=${VisualLogging.dropDown('target-selector').track({change: true})}
|
|
991
991
|
@change=${input.onTargetSelected}>
|
|
992
992
|
${input.targets.map(target => html`
|
|
993
|
-
<option jslog=${VisualLogging.item('target').track({click: true})}
|
|
993
|
+
<option jslog=${VisualLogging.item('target').track({click: true, resize: true})}
|
|
994
994
|
value=${target.id()} ?selected=${target.id() === input.targetId}>
|
|
995
995
|
${target.name()} (${target.inspectedURL()})
|
|
996
996
|
</option>`)}
|
|
@@ -140,7 +140,7 @@ export const DEFAULT_VIEW = (input: ViewInput, _output: ViewOutput, target: HTML
|
|
|
140
140
|
@keydown=${(event: Event) => onKeyDown(recording.storageName, event)}
|
|
141
141
|
@click=${(event: Event) => onOpenClick(recording.storageName, event)}
|
|
142
142
|
jslog=${VisualLogging.item()
|
|
143
|
-
.track({ click: true })
|
|
143
|
+
.track({ click: true, resize: true })
|
|
144
144
|
.context('recording')}>
|
|
145
145
|
<div class="icon">
|
|
146
146
|
<devtools-icon name="flow">
|
|
@@ -646,7 +646,7 @@ export class StepEditor extends LitElement {
|
|
|
646
646
|
#renderTypeRow(editable: boolean): Lit.TemplateResult {
|
|
647
647
|
this.#renderedAttributes.add('type');
|
|
648
648
|
// clang-format off
|
|
649
|
-
return html`<div class="row attribute" data-attribute="type" jslog=${VisualLogging.treeItem('type')}>
|
|
649
|
+
return html`<div class="row attribute" data-attribute="type" jslog=${VisualLogging.treeItem('type').track({resize: true})}>
|
|
650
650
|
<div id="type">type<span class="separator">:</span></div>
|
|
651
651
|
<devtools-suggestion-input
|
|
652
652
|
aria-labelledby="type"
|
|
@@ -667,7 +667,7 @@ export class StepEditor extends LitElement {
|
|
|
667
667
|
return;
|
|
668
668
|
}
|
|
669
669
|
// clang-format off
|
|
670
|
-
return html`<div class="row attribute" data-attribute=${attribute} jslog=${VisualLogging.treeItem(Platform.StringUtilities.toKebabCase(attribute))}>
|
|
670
|
+
return html`<div class="row attribute" data-attribute=${attribute} jslog=${VisualLogging.treeItem(Platform.StringUtilities.toKebabCase(attribute)).track({resize: true})}>
|
|
671
671
|
<div id=${attribute}>${attribute}<span class="separator">:</span></div>
|
|
672
672
|
<devtools-suggestion-input
|
|
673
673
|
.disabled=${this.disabled}
|
|
@@ -706,7 +706,7 @@ export class StepEditor extends LitElement {
|
|
|
706
706
|
}
|
|
707
707
|
// clang-format off
|
|
708
708
|
return html`
|
|
709
|
-
<div class="attribute" data-attribute="frame" jslog=${VisualLogging.treeItem('frame')}>
|
|
709
|
+
<div class="attribute" data-attribute="frame" jslog=${VisualLogging.treeItem('frame').track({resize: true})}>
|
|
710
710
|
<div class="row">
|
|
711
711
|
<div id="frame">frame<span class="separator">:</span></div>
|
|
712
712
|
${this.#renderDeleteButton('frame')}
|
|
@@ -344,7 +344,8 @@ export class ShortcutListItem {
|
|
|
344
344
|
this.settingsTab = settingsTab;
|
|
345
345
|
this.item = item;
|
|
346
346
|
this.element = document.createElement('div');
|
|
347
|
-
this.element.setAttribute(
|
|
347
|
+
this.element.setAttribute(
|
|
348
|
+
'jslog', `${VisualLogging.item().context(item.id()).track({keydown: 'Escape', resize: true})}`);
|
|
348
349
|
this.editedShortcuts = new Map();
|
|
349
350
|
this.shortcutInputs = new Map();
|
|
350
351
|
this.shortcuts = UI.ShortcutRegistry.ShortcutRegistry.instance().shortcutsForAction(item.id());
|
|
@@ -88,6 +88,16 @@ const UIStrings = {
|
|
|
88
88
|
* The user opens this context menu by selecting a specific call frame in the call stack sidebar pane.
|
|
89
89
|
*/
|
|
90
90
|
restartFrame: 'Restart frame',
|
|
91
|
+
/**
|
|
92
|
+
* @description Error message that is displayed in UI debugging information cannot be found for a call frame
|
|
93
|
+
* @example {main} PH1
|
|
94
|
+
*/
|
|
95
|
+
failedToLoadDebugSymbolsForFunction: 'No debug information for function "{PH1}"',
|
|
96
|
+
/**
|
|
97
|
+
* @description Error message that is displayed in UI when a file needed for debugging information for a call frame is missing
|
|
98
|
+
* @example {mainp.debug.wasm.dwp} PH1
|
|
99
|
+
*/
|
|
100
|
+
debugSymbolsIncomplete: 'The debug information for function {PH1} is incomplete',
|
|
91
101
|
} as const;
|
|
92
102
|
const str_ = i18n.i18n.registerUIStrings('panels/sources/CallStackSidebarPane.ts', UIStrings);
|
|
93
103
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
@@ -253,10 +263,11 @@ export class CallStackSidebarPane extends UI.View.SimpleView implements UI.Conte
|
|
|
253
263
|
const itemPromises = [];
|
|
254
264
|
const uniqueWarnings = new Set<string>();
|
|
255
265
|
for (const frame of details.callFrames) {
|
|
256
|
-
const itemPromise =
|
|
266
|
+
const itemPromise =
|
|
267
|
+
Item.createForDebuggerCallFrame(frame, this.locationPool, this.refreshItem.bind(this), this.list);
|
|
257
268
|
itemPromises.push(itemPromise);
|
|
258
269
|
if (frame.missingDebugInfoDetails) {
|
|
259
|
-
uniqueWarnings.add(frame.missingDebugInfoDetails.details);
|
|
270
|
+
uniqueWarnings.add(convertMissingDebugInfo(frame.missingDebugInfoDetails, frame.functionName).details);
|
|
260
271
|
}
|
|
261
272
|
}
|
|
262
273
|
const items = await Promise.all(itemPromises);
|
|
@@ -272,7 +283,8 @@ export class CallStackSidebarPane extends UI.View.SimpleView implements UI.Conte
|
|
|
272
283
|
asyncStackTrace = stackTrace;
|
|
273
284
|
const title = UI.UIUtils.asyncStackTraceLabel(asyncStackTrace.description, previousStackTrace);
|
|
274
285
|
items.push(...await Item.createItemsForAsyncStack(
|
|
275
|
-
title, details.debuggerModel, asyncStackTrace.callFrames, this.locationPool, this.refreshItem.bind(this)
|
|
286
|
+
title, details.debuggerModel, asyncStackTrace.callFrames, this.locationPool, this.refreshItem.bind(this),
|
|
287
|
+
this.list));
|
|
276
288
|
previousStackTrace = asyncStackTrace.callFrames;
|
|
277
289
|
|
|
278
290
|
if (--maxAsyncStackChainDepth <= 0) {
|
|
@@ -367,9 +379,10 @@ export class CallStackSidebarPane extends UI.View.SimpleView implements UI.Conte
|
|
|
367
379
|
const icon = new Icon();
|
|
368
380
|
icon.name = 'warning-filled';
|
|
369
381
|
icon.classList.add('call-frame-warning-icon', 'small');
|
|
370
|
-
const
|
|
382
|
+
const {resources, details} = convertMissingDebugInfo(callframe.missingDebugInfoDetails, callframe.functionName);
|
|
383
|
+
const messages = resources.map(
|
|
371
384
|
r => i18nString(UIStrings.debugFileNotFound, {PH1: Common.ParsedURL.ParsedURL.extractName(r.resourceUrl)}));
|
|
372
|
-
UI.Tooltip.Tooltip.install(icon, [
|
|
385
|
+
UI.Tooltip.Tooltip.install(icon, [details, ...messages].join('\n'));
|
|
373
386
|
element.appendChild(icon);
|
|
374
387
|
}
|
|
375
388
|
return element;
|
|
@@ -541,12 +554,13 @@ export class Item {
|
|
|
541
554
|
updateDelegate: (arg0: Item) => void;
|
|
542
555
|
/** Only set for synchronous frames */
|
|
543
556
|
readonly frame?: SDK.DebuggerModel.CallFrame;
|
|
557
|
+
readonly list: UI.ListControl.ListControl<Item>;
|
|
544
558
|
|
|
545
559
|
static async createForDebuggerCallFrame(
|
|
546
560
|
frame: SDK.DebuggerModel.CallFrame, locationPool: Bindings.LiveLocation.LiveLocationPool,
|
|
547
|
-
updateDelegate: (arg0: Item) => void): Promise<Item> {
|
|
561
|
+
updateDelegate: (arg0: Item) => void, list: UI.ListControl.ListControl<Item>): Promise<Item> {
|
|
548
562
|
const name = frame.functionName;
|
|
549
|
-
const item = new Item(UI.UIUtils.beautifyFunctionName(name), updateDelegate, frame);
|
|
563
|
+
const item = new Item(UI.UIUtils.beautifyFunctionName(name), updateDelegate, frame, list);
|
|
550
564
|
await Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().createCallFrameLiveLocation(
|
|
551
565
|
frame.location(), item.update.bind(item), locationPool);
|
|
552
566
|
void SourceMapScopes.NamesResolver.resolveDebuggerFrameFunctionName(frame).then(functionName => {
|
|
@@ -563,16 +577,17 @@ export class Item {
|
|
|
563
577
|
|
|
564
578
|
static async createItemsForAsyncStack(
|
|
565
579
|
title: string, debuggerModel: SDK.DebuggerModel.DebuggerModel, frames: Protocol.Runtime.CallFrame[],
|
|
566
|
-
locationPool: Bindings.LiveLocation.LiveLocationPool, updateDelegate: (arg0: Item) => void
|
|
580
|
+
locationPool: Bindings.LiveLocation.LiveLocationPool, updateDelegate: (arg0: Item) => void,
|
|
581
|
+
list: UI.ListControl.ListControl<Item>): Promise<Item[]> {
|
|
567
582
|
const headerItemToItemsSet = new WeakMap<Item, Set<Item>>();
|
|
568
|
-
const asyncHeaderItem = new Item(title, updateDelegate);
|
|
583
|
+
const asyncHeaderItem = new Item(title, updateDelegate, undefined, list);
|
|
569
584
|
headerItemToItemsSet.set(asyncHeaderItem, new Set());
|
|
570
585
|
asyncHeaderItem.isAsyncHeader = true;
|
|
571
586
|
|
|
572
587
|
const asyncFrameItems = [];
|
|
573
588
|
const liveLocationPromises = [];
|
|
574
589
|
for (const frame of frames) {
|
|
575
|
-
const item = new Item(UI.UIUtils.beautifyFunctionName(frame.functionName), update);
|
|
590
|
+
const item = new Item(UI.UIUtils.beautifyFunctionName(frame.functionName), update, undefined, list);
|
|
576
591
|
const rawLocation =
|
|
577
592
|
debuggerModel.createRawLocationByScriptId(frame.scriptId, frame.lineNumber, frame.columnNumber);
|
|
578
593
|
liveLocationPromises.push(
|
|
@@ -613,7 +628,9 @@ export class Item {
|
|
|
613
628
|
}
|
|
614
629
|
}
|
|
615
630
|
|
|
616
|
-
constructor(
|
|
631
|
+
constructor(
|
|
632
|
+
title: string, updateDelegate: (arg0: Item) => void, frame: SDK.DebuggerModel.CallFrame|undefined,
|
|
633
|
+
list: UI.ListControl.ListControl<Item>) {
|
|
617
634
|
this.isIgnoreListed = false;
|
|
618
635
|
this.title = title;
|
|
619
636
|
this.linkText = '';
|
|
@@ -621,6 +638,7 @@ export class Item {
|
|
|
621
638
|
this.isAsyncHeader = false;
|
|
622
639
|
this.updateDelegate = updateDelegate;
|
|
623
640
|
this.frame = frame;
|
|
641
|
+
this.list = list;
|
|
624
642
|
}
|
|
625
643
|
|
|
626
644
|
private async update(liveLocation: Bindings.LiveLocation.LiveLocation): Promise<void> {
|
|
@@ -628,6 +646,35 @@ export class Item {
|
|
|
628
646
|
this.isIgnoreListed = Boolean(uiLocation?.isIgnoreListed());
|
|
629
647
|
this.linkText = uiLocation ? uiLocation.linkText() : '';
|
|
630
648
|
this.uiLocation = uiLocation;
|
|
649
|
+
|
|
650
|
+
if (this.frame && uiLocation && this === this.list.selectedItem()) {
|
|
651
|
+
UI.Context.Context.instance().setFlavor(
|
|
652
|
+
StackTrace.StackTrace.DebuggableFrameFlavor,
|
|
653
|
+
StackTrace.StackTrace.DebuggableFrameFlavor.for({
|
|
654
|
+
uiSourceCode: uiLocation.uiSourceCode,
|
|
655
|
+
line: uiLocation.lineNumber,
|
|
656
|
+
column: uiLocation.columnNumber ?? -1,
|
|
657
|
+
sdkFrame: this.frame,
|
|
658
|
+
}));
|
|
659
|
+
}
|
|
660
|
+
|
|
631
661
|
this.updateDelegate(this);
|
|
632
662
|
}
|
|
633
663
|
}
|
|
664
|
+
|
|
665
|
+
export function convertMissingDebugInfo(
|
|
666
|
+
missingDebugInfo: SDK.DebuggerModel.MissingDebugInfo, functionName: string|undefined):
|
|
667
|
+
{details: Platform.UIString.LocalizedString, resources: SDK.DebuggerModel.MissingDebugFiles[]} {
|
|
668
|
+
switch (missingDebugInfo.type) {
|
|
669
|
+
case SDK.DebuggerModel.MissingDebugInfoType.PARTIAL_INFO:
|
|
670
|
+
return {
|
|
671
|
+
details: i18nString(UIStrings.debugSymbolsIncomplete, {PH1: functionName ?? ''}),
|
|
672
|
+
resources: missingDebugInfo.missingDebugFiles
|
|
673
|
+
};
|
|
674
|
+
case SDK.DebuggerModel.MissingDebugInfoType.NO_INFO:
|
|
675
|
+
return {
|
|
676
|
+
details: i18nString(UIStrings.failedToLoadDebugSymbolsForFunction, {PH1: functionName ?? ''}),
|
|
677
|
+
resources: []
|
|
678
|
+
};
|
|
679
|
+
}
|
|
680
|
+
}
|
|
@@ -31,6 +31,7 @@ import * as VisualLogging from '../../ui/visual_logging/visual_logging.js';
|
|
|
31
31
|
import {AddDebugInfoURLDialog} from './AddSourceMapURLDialog.js';
|
|
32
32
|
import {BreakpointEditDialog} from './BreakpointEditDialog.js';
|
|
33
33
|
import {BreakpointsSidebarController} from './BreakpointsView.js';
|
|
34
|
+
import {convertMissingDebugInfo} from './CallStackSidebarPane.js';
|
|
34
35
|
import {Plugin} from './Plugin.js';
|
|
35
36
|
import {SourcesPanel} from './SourcesPanel.js';
|
|
36
37
|
|
|
@@ -201,7 +202,6 @@ export class DebuggerPlugin extends Plugin {
|
|
|
201
202
|
// truth for re-creating the breakpoints.
|
|
202
203
|
private breakpoints: BreakpointDescription[] = [];
|
|
203
204
|
private continueToLocations: Array<{from: number, to: number, async: boolean, click: () => void}>|null = null;
|
|
204
|
-
private readonly liveLocationPool: Bindings.LiveLocation.LiveLocationPool;
|
|
205
205
|
// When the editor content is changed by the user, this becomes
|
|
206
206
|
// true. When the plugin is muted, breakpoints show up as disabled
|
|
207
207
|
// and can't be manipulated. It is cleared again when the content is
|
|
@@ -252,7 +252,6 @@ export class DebuggerPlugin extends Plugin {
|
|
|
252
252
|
|
|
253
253
|
UI.Context.Context.instance().addFlavorChangeListener(
|
|
254
254
|
StackTrace.StackTrace.DebuggableFrameFlavor, this.callFrameChanged, this);
|
|
255
|
-
this.liveLocationPool = new Bindings.LiveLocation.LiveLocationPool();
|
|
256
255
|
|
|
257
256
|
this.updateScriptFiles();
|
|
258
257
|
|
|
@@ -1441,7 +1440,9 @@ export class DebuggerPlugin extends Plugin {
|
|
|
1441
1440
|
});
|
|
1442
1441
|
}
|
|
1443
1442
|
|
|
1444
|
-
private updateMissingDebugInfoInfobar(
|
|
1443
|
+
private updateMissingDebugInfoInfobar(
|
|
1444
|
+
warning: {resources: SDK.DebuggerModel.MissingDebugFiles[], details: Platform.UIString.LocalizedString}|
|
|
1445
|
+
null): void {
|
|
1445
1446
|
if (this.missingDebugInfoBar) {
|
|
1446
1447
|
return;
|
|
1447
1448
|
}
|
|
@@ -1655,25 +1656,22 @@ export class DebuggerPlugin extends Plugin {
|
|
|
1655
1656
|
}
|
|
1656
1657
|
|
|
1657
1658
|
private async callFrameChanged(): Promise<void> {
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1659
|
+
const frameFlavor = UI.Context.Context.instance().flavor(StackTrace.StackTrace.DebuggableFrameFlavor);
|
|
1660
|
+
if (frameFlavor?.frame.uiSourceCode?.canonicalScriptId() === this.uiSourceCode.canonicalScriptId()) {
|
|
1661
|
+
const uiLocation = new Workspace.UISourceCode.UILocation(
|
|
1662
|
+
frameFlavor.frame.uiSourceCode, frameFlavor.frame.line, frameFlavor.frame.column);
|
|
1663
|
+
this.setExecutionLocation(uiLocation);
|
|
1664
|
+
if (frameFlavor.sdkFrame.missingDebugInfoDetails) {
|
|
1665
|
+
this.updateMissingDebugInfoInfobar(
|
|
1666
|
+
convertMissingDebugInfo(frameFlavor.sdkFrame.missingDebugInfoDetails, frameFlavor.sdkFrame.functionName));
|
|
1667
|
+
} else {
|
|
1668
|
+
this.updateMissingDebugInfoInfobar(null);
|
|
1669
|
+
}
|
|
1670
|
+
// We are paused and the user is specifically looking at this UISourceCode either because
|
|
1671
|
+
// this file is on top of stack, or the user explicitly selected a stack frame for this UISourceCode.
|
|
1672
|
+
this.#recordSourcesPanelDebuggedMetrics();
|
|
1662
1673
|
} else {
|
|
1663
|
-
|
|
1664
|
-
await Bindings.DebuggerWorkspaceBinding.DebuggerWorkspaceBinding.instance().createCallFrameLiveLocation(
|
|
1665
|
-
callFrame.location(), async (liveLocation: Bindings.LiveLocation.LiveLocation) => {
|
|
1666
|
-
const uiLocation = await liveLocation.uiLocation();
|
|
1667
|
-
if (uiLocation && uiLocation.uiSourceCode.canonicalScriptId() === this.uiSourceCode.canonicalScriptId()) {
|
|
1668
|
-
this.setExecutionLocation(uiLocation);
|
|
1669
|
-
this.updateMissingDebugInfoInfobar(callFrame.missingDebugInfoDetails);
|
|
1670
|
-
// We are paused and the user is specifically looking at this UISourceCode either because
|
|
1671
|
-
// this file is on top of stack, or the user explicitly selected a stack frame for this UISourceCode.
|
|
1672
|
-
this.#recordSourcesPanelDebuggedMetrics();
|
|
1673
|
-
} else {
|
|
1674
|
-
this.setExecutionLocation(null);
|
|
1675
|
-
}
|
|
1676
|
-
}, this.liveLocationPool);
|
|
1674
|
+
this.setExecutionLocation(null);
|
|
1677
1675
|
}
|
|
1678
1676
|
}
|
|
1679
1677
|
|
|
@@ -1744,7 +1742,6 @@ export class DebuggerPlugin extends Plugin {
|
|
|
1744
1742
|
this.editor = undefined;
|
|
1745
1743
|
|
|
1746
1744
|
UI.Context.Context.instance().removeFlavorChangeListener(SDK.DebuggerModel.CallFrame, this.callFrameChanged, this);
|
|
1747
|
-
this.liveLocationPool.disposeAll();
|
|
1748
1745
|
}
|
|
1749
1746
|
|
|
1750
1747
|
/**
|