Skip to content

Commit b2570fa

Browse files
szuendDevtools-frontend LUCI CQ
authored andcommitted
[ui] Turn 'buildStackTracePreviewContents' into a widget
As part of the 'consistent stack traces' project we need to turn the JSPresentationUtils into a proper widget to keep track of updates to the stack trace. As a first step, lets turn the existing implementation into a widget. Once the new abstraction is available, we can then also address the UI vision violations. Not all use-sites are migrated by this CL but the ones in the network panel are, to show how this will look like. [email protected] Bug: 407752215,433162438 Change-Id: I0a822e4bc620cf34a90e54ccb76f5317c0a0d420 Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/6796893 Commit-Queue: Simon Zünd <[email protected]> Reviewed-by: Danil Somsikov <[email protected]>
1 parent b887cc6 commit b2570fa

File tree

4 files changed

+67
-15
lines changed

4 files changed

+67
-15
lines changed

front_end/panels/network/NetworkLogViewColumns.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,7 @@ export class NetworkLogViewColumns {
889889
if (!content) {
890890
return false;
891891
}
892-
popover.contentElement.appendChild(content.element);
892+
content.show(popover.contentElement);
893893
return true;
894894
},
895895
hide: this.popupLinkifier.reset.bind(this.popupLinkifier),

front_end/panels/network/RequestInitiatorView.ts

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,16 @@ export class RequestInitiatorView extends UI.Widget.VBox {
4848
}
4949

5050
static createStackTracePreview(
51-
request: SDK.NetworkRequest.NetworkRequest, linkifier: Components.Linkifier.Linkifier, focusableLink?: boolean): {
52-
element: Element,
53-
links: Element[],
54-
}|null {
51+
request: SDK.NetworkRequest.NetworkRequest, linkifier: Components.Linkifier.Linkifier,
52+
focusableLink?: boolean): Components.JSPresentationUtils.StackTracePreviewContent|null {
5553
const initiator = request.initiator();
5654
if (!initiator?.stack) {
5755
return null;
5856
}
5957
const networkManager = SDK.NetworkManager.NetworkManager.forRequest(request);
60-
const target = networkManager ? networkManager.target() : null;
61-
const stackTrace = Components.JSPresentationUtils.buildStackTracePreviewContents(
62-
target, linkifier, {stackTrace: initiator.stack, tabStops: focusableLink});
63-
return stackTrace;
58+
const target = networkManager ? networkManager.target() : undefined;
59+
return new Components.JSPresentationUtils.StackTracePreviewContent(
60+
undefined, target, linkifier, {stackTrace: initiator.stack, tabStops: focusableLink});
6461
}
6562

6663
private createTree(): UI.TreeOutline.TreeOutlineInShadow {
@@ -124,16 +121,20 @@ export class RequestInitiatorView extends UI.Widget.VBox {
124121
}
125122
}
126123

127-
private buildStackTraceSection(content: Element, title: string, tree: UI.TreeOutline.TreeOutlineInShadow): void {
124+
private buildStackTraceSection(
125+
stackTracePreview: Components.JSPresentationUtils.StackTracePreviewContent, title: string,
126+
tree: UI.TreeOutline.TreeOutlineInShadow): void {
128127
const root = new UI.TreeOutline.TreeElement(title);
129128
tree.appendChild(root);
130129

131130
if (root.titleElement instanceof HTMLElement) {
132131
root.titleElement.classList.add('request-initiator-view-section-title');
133132
}
134133

135-
const contentElement = new UI.TreeOutline.TreeElement(content, false);
134+
const contentElement = new UI.TreeOutline.TreeElement(undefined, false);
136135
contentElement.selectable = false;
136+
stackTracePreview.markAsRoot();
137+
stackTracePreview.show(contentElement.listItemElement);
137138

138139
root.appendChild(contentElement);
139140
root.expand();
@@ -151,7 +152,7 @@ export class RequestInitiatorView extends UI.Widget.VBox {
151152

152153
if (stackTracePreview) {
153154
initiatorDataPresent = true;
154-
this.buildStackTraceSection(stackTracePreview.element, i18nString(UIStrings.requestCallStack), containerTree);
155+
this.buildStackTraceSection(stackTracePreview, i18nString(UIStrings.requestCallStack), containerTree);
155156
}
156157

157158
const initiatorGraph = Logs.NetworkLog.NetworkLog.instance().initiatorGraphForRequest(this.request);

front_end/ui/legacy/components/utils/JSPresentationUtils.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ describeWithMockConnection('JSPresentationUtils', () => {
3232
const callFrame = {scriptId: 'scriptId', functionName: 'func', url, lineNumber: 0, columnNumber: 0};
3333
const stackTrace = {callFrames: [callFrame]};
3434
const options = {tabStops: false, stackTrace} as Components.JSPresentationUtils.Options;
35-
const {links} = Components.JSPresentationUtils.buildStackTracePreviewContents(target, linkifier, options);
35+
const {linkElements: links} =
36+
new Components.JSPresentationUtils.StackTracePreviewContent(undefined, target, linkifier, options);
3637
assert.lengthOf(links, 1);
3738
assert.strictEqual(links[0].textContent, expectedLinkContent);
3839
}

front_end/ui/legacy/components/utils/JSPresentationUtils.ts

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
import * as Common from '../../../../core/common/common.js';
3838
import * as i18n from '../../../../core/i18n/i18n.js';
39+
import * as Platform from '../../../../core/platform/platform.js';
3940
import * as SDK from '../../../../core/sdk/sdk.js';
4041
import type * as Protocol from '../../../../generated/protocol.js';
4142
import * as Bindings from '../../../../models/bindings/bindings.js';
@@ -156,6 +157,7 @@ export function buildStackTraceRows(
156157
return stackTraceRows;
157158
}
158159

160+
/** @deprecated Use {@link StackTracePreviewContent} widget instead. */
159161
export function buildStackTracePreviewContents(
160162
target: SDK.Target.Target|null, linkifier: Linkifier, options: Options = {
161163
widthConstrained: false,
@@ -245,8 +247,8 @@ function renderStackTraceTable(
245247
}
246248

247249
export interface Options {
248-
stackTrace: Protocol.Runtime.StackTrace|undefined;
249-
tabStops: boolean|undefined;
250+
stackTrace?: Protocol.Runtime.StackTrace;
251+
tabStops?: boolean;
250252
// Whether the width of stack trace preview
251253
// is constrained to its container or whether
252254
// it can grow the container.
@@ -262,3 +264,51 @@ export interface StackTraceRegularRow {
262264
export interface StackTraceAsyncRow {
263265
asyncDescription: string;
264266
}
267+
268+
export class StackTracePreviewContent extends UI.Widget.Widget {
269+
#target?: SDK.Target.Target;
270+
#linkifier?: Linkifier;
271+
#options: Options;
272+
#links: HTMLElement[] = [];
273+
274+
readonly #table: HTMLElement;
275+
276+
constructor(element?: HTMLElement, target?: SDK.Target.Target, linkifier?: Linkifier, options?: Options) {
277+
super(true, undefined, element);
278+
279+
this.#target = target;
280+
this.#linkifier = linkifier;
281+
this.#options = options || {
282+
widthConstrained: false,
283+
};
284+
285+
this.element.classList.add('monospace');
286+
this.element.classList.add('stack-preview-container');
287+
this.element.classList.toggle('width-constrained', this.#options.widthConstrained ?? false);
288+
this.element.style.display = 'inline-block';
289+
290+
Platform.DOMUtilities.appendStyle(this.element.shadowRoot as ShadowRoot, jsUtilsStyles);
291+
292+
this.#table = this.contentElement.createChild('table', 'stack-preview-container');
293+
this.#table.classList.toggle('width-constrained', this.#options.widthConstrained ?? false);
294+
295+
this.performUpdate();
296+
}
297+
298+
override performUpdate(): void {
299+
if (!this.#linkifier) {
300+
return;
301+
}
302+
303+
const {stackTrace, tabStops} = this.#options;
304+
const updateCallback = renderStackTraceTable.bind(null, this.#table, this.element);
305+
const stackTraceRows = buildStackTraceRows(
306+
stackTrace ?? {callFrames: []}, this.#target ?? null, this.#linkifier, tabStops, updateCallback,
307+
this.#options.showColumnNumber);
308+
this.#links = renderStackTraceTable(this.#table, this.element, stackTraceRows);
309+
}
310+
311+
get linkElements(): readonly HTMLElement[] {
312+
return this.#links;
313+
}
314+
}

0 commit comments

Comments
 (0)