chrome-devtools-frontend 1.0.1525561 → 1.0.1526630
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/common/Settings.ts +1 -1
- package/front_end/core/i18n/i18nImpl.ts +1 -1
- package/front_end/core/sdk/ChildTargetManager.ts +2 -0
- package/front_end/core/sdk/PreloadingModel.ts +3 -0
- package/front_end/core/sdk/ResourceTreeModel.ts +1 -1
- package/front_end/core/sdk/SourceMapScopesInfo.ts +57 -0
- package/front_end/generated/InspectorBackendCommands.js +5 -5
- package/front_end/generated/SupportedCSSProperties.js +0 -19
- package/front_end/generated/protocol-mapping.d.ts +4 -2
- package/front_end/generated/protocol-proxy-api.d.ts +4 -2
- package/front_end/generated/protocol.ts +9 -8
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.snapshot.txt +43 -8
- package/front_end/models/ai_assistance/data_formatters/PerformanceInsightFormatter.ts +50 -32
- package/front_end/models/ai_assistance/data_formatters/PerformanceTraceFormatter.snapshot.txt +29 -29
- package/front_end/models/javascript_metadata/NativeFunctions.js +3 -8
- package/front_end/models/trace/handlers/UserTimingsHandler.ts +1 -1
- package/front_end/models/trace/insights/CLSCulprits.ts +2 -1
- package/front_end/models/trace/insights/Cache.ts +2 -1
- package/front_end/models/trace/insights/DOMSize.ts +2 -1
- package/front_end/models/trace/insights/DocumentLatency.ts +2 -1
- package/front_end/models/trace/insights/DuplicatedJavaScript.ts +2 -1
- package/front_end/models/trace/insights/FontDisplay.ts +2 -1
- package/front_end/models/trace/insights/ForcedReflow.ts +2 -1
- package/front_end/models/trace/insights/INPBreakdown.ts +2 -1
- package/front_end/models/trace/insights/ImageDelivery.ts +2 -1
- package/front_end/models/trace/insights/LCPBreakdown.ts +2 -1
- package/front_end/models/trace/insights/LCPDiscovery.ts +2 -1
- package/front_end/models/trace/insights/LegacyJavaScript.ts +2 -1
- package/front_end/models/trace/insights/ModernHTTP.ts +2 -1
- package/front_end/models/trace/insights/NetworkDependencyTree.ts +2 -1
- package/front_end/models/trace/insights/RenderBlocking.ts +2 -1
- package/front_end/models/trace/insights/SlowCSSSelector.ts +2 -1
- package/front_end/models/trace/insights/ThirdParties.ts +2 -1
- package/front_end/models/trace/insights/Viewport.ts +2 -1
- package/front_end/models/trace/insights/types.ts +2 -1
- package/front_end/panels/application/ReportingApiView.ts +8 -7
- package/front_end/panels/application/StorageView.ts +2 -1
- package/front_end/panels/application/preloading/components/PreloadingString.ts +2 -0
- package/front_end/panels/console/ConsolePrompt.ts +24 -4
- package/front_end/panels/coverage/CoverageListView.ts +125 -279
- package/front_end/panels/coverage/CoverageView.ts +109 -111
- package/front_end/panels/linear_memory_inspector/LinearMemoryInspectorPane.ts +11 -19
- package/front_end/panels/linear_memory_inspector/components/LinearMemoryInspector.ts +27 -43
- package/front_end/panels/network/RequestResponseView.ts +1 -1
- package/front_end/panels/timeline/TimelinePanel.ts +10 -8
- package/front_end/panels/timeline/components/ExportTraceOptions.ts +1 -1
- package/front_end/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/buttons/Button.ts +18 -1
- package/front_end/ui/legacy/EmptyWidget.ts +11 -1
- package/front_end/ui/legacy/SearchableView.ts +1 -1
- package/front_end/ui/legacy/Toolbar.ts +25 -4
- package/front_end/ui/legacy/UIUtils.ts +28 -2
- package/front_end/ui/legacy/Widget.ts +5 -0
- package/front_end/ui/legacy/components/data_grid/DataGridElement.ts +48 -5
- package/front_end/ui/legacy/components/perf_ui/FlameChart.ts +2 -2
- package/front_end/ui/legacy/components/source_frame/JSONView.ts +28 -0
- package/front_end/ui/legacy/components/source_frame/StreamingContentHexView.ts +7 -8
- package/package.json +22 -22
|
@@ -76,6 +76,7 @@ export type InsightModel<UIStrings extends Record<string, string> = Record<strin
|
|
|
76
76
|
strings: UIStrings,
|
|
77
77
|
title: Common.UIString.LocalizedString,
|
|
78
78
|
description: Common.UIString.LocalizedString,
|
|
79
|
+
docs: string,
|
|
79
80
|
category: InsightCategory,
|
|
80
81
|
state: 'pass' | 'fail' | 'informative',
|
|
81
82
|
/** Used by RelatedInsightChips.ts */
|
|
@@ -101,7 +102,7 @@ export type InsightModel<UIStrings extends Record<string, string> = Record<strin
|
|
|
101
102
|
};
|
|
102
103
|
|
|
103
104
|
export type PartialInsightModel<T> =
|
|
104
|
-
Omit<T, 'strings'|'title'|'description'|'category'|'state'|'insightKey'|'navigationId'|'frameId'>;
|
|
105
|
+
Omit<T, 'strings'|'title'|'description'|'docs'|'category'|'state'|'insightKey'|'navigationId'|'frameId'>;
|
|
105
106
|
|
|
106
107
|
/**
|
|
107
108
|
* Contains insights for a specific navigation. If a trace began after a navigation already started,
|
|
@@ -56,12 +56,11 @@ interface ViewInput {
|
|
|
56
56
|
onReportSelected: (id: string) => void;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
export const DEFAULT_VIEW: View = (input, _output, target) => {
|
|
59
|
+
export const DEFAULT_VIEW = (input: ViewInput, output: undefined, target: HTMLElement): void => {
|
|
62
60
|
if (input.hasReports || input.hasEndpoints) {
|
|
63
61
|
// clang-format off
|
|
64
62
|
render(html`
|
|
63
|
+
<style>${UI.inspectorCommonStyles}</style>
|
|
65
64
|
<devtools-split-view sidebar-position="second" sidebar-initial-size="150" jslog=${
|
|
66
65
|
VisualLogging.pane('reporting-api')}>
|
|
67
66
|
${input.hasReports ? html`
|
|
@@ -73,9 +72,9 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
|
|
|
73
72
|
</div>
|
|
74
73
|
<div slot="sidebar" class="vbox" jslog=${VisualLogging.pane('preview').track({resize: true})}>
|
|
75
74
|
${input.focusedReport ? html`
|
|
76
|
-
<devtools-widget .widgetConfig=${widgetConfig(
|
|
77
|
-
|
|
78
|
-
)}></devtools-widget>
|
|
75
|
+
<devtools-widget .widgetConfig=${widgetConfig(SourceFrame.JSONView.SearchableJsonView, {
|
|
76
|
+
jsonObject: input.focusedReport.body,
|
|
77
|
+
})}></devtools-widget>
|
|
79
78
|
` : html`
|
|
80
79
|
<devtools-widget .widgetConfig=${widgetConfig(UI.EmptyWidget.EmptyWidget, {
|
|
81
80
|
header: i18nString(UIStrings.noReportSelected),
|
|
@@ -112,6 +111,8 @@ export const DEFAULT_VIEW: View = (input, _output, target) => {
|
|
|
112
111
|
}
|
|
113
112
|
};
|
|
114
113
|
|
|
114
|
+
type View = typeof DEFAULT_VIEW;
|
|
115
|
+
|
|
115
116
|
export class ReportingApiView extends UI.Widget.VBox implements
|
|
116
117
|
SDK.TargetManager.SDKModelObserver<SDK.NetworkManager.NetworkManager> {
|
|
117
118
|
#endpoints: Map<string, Protocol.Network.ReportingApiEndpoint[]>;
|
|
@@ -164,7 +165,7 @@ export class ReportingApiView extends UI.Widget.VBox implements
|
|
|
164
165
|
focusedReport: this.#focusedReport,
|
|
165
166
|
onReportSelected: this.#onReportSelected.bind(this),
|
|
166
167
|
};
|
|
167
|
-
this.#view(viewInput,
|
|
168
|
+
this.#view(viewInput, undefined, this.element);
|
|
168
169
|
}
|
|
169
170
|
|
|
170
171
|
#onEndpointsChangedForOrigin({data}: {data: Protocol.Network.ReportingApiEndpointsChangedForOriginEvent}): void {
|
|
@@ -236,6 +236,7 @@ export class StorageView extends UI.ThrottledWidget.ThrottledWidget {
|
|
|
236
236
|
this.quotaOverrideCheckbox.addEventListener('click', this.onClickCheckbox.bind(this), false);
|
|
237
237
|
this.quotaOverrideControlRow = quota.appendRow();
|
|
238
238
|
this.quotaOverrideEditor = this.quotaOverrideControlRow.createChild('input', 'quota-override-notification-editor');
|
|
239
|
+
this.quotaOverrideEditor.setAttribute('placeholder', i18nString(UIStrings.pleaseEnterANumber));
|
|
239
240
|
this.quotaOverrideEditor.setAttribute(
|
|
240
241
|
'jslog', `${VisualLogging.textField('quota-override').track({change: true})}`);
|
|
241
242
|
this.quotaOverrideControlRow.appendChild(UI.UIUtils.createLabel(i18nString(UIStrings.mb)));
|
|
@@ -402,7 +403,7 @@ export class StorageView extends UI.ThrottledWidget.ThrottledWidget {
|
|
|
402
403
|
this.quotaOverrideControlRow.classList.remove('hidden');
|
|
403
404
|
this.quotaOverrideCheckbox.checked = true;
|
|
404
405
|
this.quotaOverrideEditor.value = this.previousOverrideFieldValue;
|
|
405
|
-
this.quotaOverrideEditor.focus();
|
|
406
|
+
window.setTimeout(() => this.quotaOverrideEditor.focus(), 500);
|
|
406
407
|
} else if (this.target && this.securityOrigin) {
|
|
407
408
|
this.quotaOverrideControlRow.classList.add('hidden');
|
|
408
409
|
this.quotaOverrideCheckbox.checked = false;
|
|
@@ -736,6 +736,8 @@ export function capitalizedAction(action: Protocol.Preload.SpeculationAction): C
|
|
|
736
736
|
return i18n.i18n.lockedString('Prefetch');
|
|
737
737
|
case Protocol.Preload.SpeculationAction.Prerender:
|
|
738
738
|
return i18n.i18n.lockedString('Prerender');
|
|
739
|
+
case Protocol.Preload.SpeculationAction.PrerenderUntilScript:
|
|
740
|
+
return i18n.i18n.lockedString('PrerenderUntilScript');
|
|
739
741
|
}
|
|
740
742
|
}
|
|
741
743
|
|
|
@@ -343,9 +343,29 @@ export class ConsolePrompt extends Common.ObjectWrapper.eventMixin<EventTypes, t
|
|
|
343
343
|
}
|
|
344
344
|
|
|
345
345
|
private editorKeymap(): readonly CodeMirror.KeyBinding[] {
|
|
346
|
-
const keymap = [
|
|
347
|
-
{
|
|
348
|
-
|
|
346
|
+
const keymap: CodeMirror.KeyBinding[] = [
|
|
347
|
+
{
|
|
348
|
+
// Handle the KeyboardEvent manually.
|
|
349
|
+
any: (_view, event) => {
|
|
350
|
+
// Events with `repeat=true` are excluded from altering the history state because
|
|
351
|
+
// they are often not intended as such. Example:
|
|
352
|
+
// Scrolling through long snippets.
|
|
353
|
+
if (event.repeat) {
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if (event.key === 'ArrowUp') {
|
|
358
|
+
return this.#editorHistory.moveHistory(Direction.BACKWARD);
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
if (event.key === 'ArrowDown') {
|
|
362
|
+
return this.#editorHistory.moveHistory(Direction.FORWARD);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
return false;
|
|
366
|
+
},
|
|
367
|
+
},
|
|
368
|
+
|
|
349
369
|
{mac: 'Ctrl-p', run: () => this.#editorHistory.moveHistory(Direction.BACKWARD, true)},
|
|
350
370
|
{mac: 'Ctrl-n', run: () => this.#editorHistory.moveHistory(Direction.FORWARD, true)},
|
|
351
371
|
{
|
|
@@ -372,7 +392,7 @@ export class ConsolePrompt extends Common.ObjectWrapper.eventMixin<EventTypes, t
|
|
|
372
392
|
if (this.isAiCodeCompletionEnabled()) {
|
|
373
393
|
keymap.push({
|
|
374
394
|
key: 'Tab',
|
|
375
|
-
run: ()
|
|
395
|
+
run: () => {
|
|
376
396
|
const {accepted, suggestion} = TextEditor.Config.acceptAiAutoCompleteSuggestion(this.editor.editor);
|
|
377
397
|
if (accepted) {
|
|
378
398
|
this.dispatchEventToListeners(
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
// Copyright 2017 The Chromium Authors
|
|
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
|
-
|
|
5
|
-
|
|
4
|
+
|
|
5
|
+
import '../../ui/components/highlighting/highlighting.js';
|
|
6
|
+
import '../../ui/legacy/components/data_grid/data_grid.js';
|
|
6
7
|
|
|
7
8
|
import * as Common from '../../core/common/common.js';
|
|
8
9
|
import * as i18n from '../../core/i18n/i18n.js';
|
|
9
10
|
import type * as Platform from '../../core/platform/platform.js';
|
|
10
|
-
import * as TextUtils from '../../models/text_utils/text_utils.js';
|
|
11
11
|
import * as Workspace from '../../models/workspace/workspace.js';
|
|
12
|
-
import * as DataGrid from '../../ui/legacy/components/data_grid/data_grid.js';
|
|
13
12
|
import * as UI from '../../ui/legacy/legacy.js';
|
|
14
|
-
import {Directives, html, nothing, render} from '../../ui/lit/lit.js';
|
|
13
|
+
import {Directives, html, nothing, render, type TemplateResult} from '../../ui/lit/lit.js';
|
|
15
14
|
|
|
16
15
|
import coverageListViewStyles from './coverageListView.css.js';
|
|
17
16
|
import {CoverageType} from './CoverageModel.js';
|
|
@@ -124,7 +123,7 @@ const UIStrings = {
|
|
|
124
123
|
} as const;
|
|
125
124
|
const str_ = i18n.i18n.registerUIStrings('panels/coverage/CoverageListView.ts', UIStrings);
|
|
126
125
|
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
127
|
-
const {styleMap} = Directives;
|
|
126
|
+
const {styleMap, repeat} = Directives;
|
|
128
127
|
|
|
129
128
|
export function coverageTypeToString(type: CoverageType): string {
|
|
130
129
|
const types = [];
|
|
@@ -139,163 +138,95 @@ export function coverageTypeToString(type: CoverageType): string {
|
|
|
139
138
|
return types.join('+');
|
|
140
139
|
}
|
|
141
140
|
|
|
141
|
+
interface ViewInput {
|
|
142
|
+
items: CoverageListItem[];
|
|
143
|
+
selectedUrl: Platform.DevToolsPath.UrlString|null;
|
|
144
|
+
maxSize: number;
|
|
145
|
+
onOpen: (url: Platform.DevToolsPath.UrlString) => void;
|
|
146
|
+
highlightRegExp: RegExp|null;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
type View = (input: ViewInput, output: object, target: HTMLElement) => void;
|
|
150
|
+
|
|
151
|
+
const formatBytes = (value: number|undefined): string => {
|
|
152
|
+
return getBytesFormatter().format(value ?? 0);
|
|
153
|
+
};
|
|
154
|
+
const formatPercent = (value: number|undefined): string => {
|
|
155
|
+
return getPercentageFormatter().format(value ?? 0);
|
|
156
|
+
};
|
|
157
|
+
export const DEFAULT_VIEW: View = (input, _output, target) => {
|
|
158
|
+
// clang-format off
|
|
159
|
+
render(html`
|
|
160
|
+
<style>${coverageListViewStyles}</style>
|
|
161
|
+
<devtools-data-grid class="flex-auto" name=${i18nString(UIStrings.codeCoverage)} striped autofocus resize="last"
|
|
162
|
+
.template=${html`
|
|
163
|
+
<table>
|
|
164
|
+
<tr>
|
|
165
|
+
<th id="url" width="250px" weight="3" sortable>${i18nString(UIStrings.url)}</th>
|
|
166
|
+
<th id="type" width="45px" weight="1" fixed sortable>${i18nString(UIStrings.type)}</th>
|
|
167
|
+
<th id="size" width="60px" align="right" weight="1" fixed sortable>${i18nString(UIStrings.totalBytes)}</th>
|
|
168
|
+
<th id="unused-size" width="100px" align="right" weight="1" fixed sortable sort="descending">${
|
|
169
|
+
i18nString(UIStrings.unusedBytes)}</th>
|
|
170
|
+
<th id="bars" width="250px" weight="1" sortable>${i18nString(UIStrings.usageVisualization)}</th>
|
|
171
|
+
</tr>
|
|
172
|
+
${repeat(input.items, info => info.url, info => renderItem(info, input))}
|
|
173
|
+
</table>`}>
|
|
174
|
+
</devtools-data-grid>`,
|
|
175
|
+
target);
|
|
176
|
+
// clang-format on
|
|
177
|
+
};
|
|
178
|
+
|
|
142
179
|
export class CoverageListView extends UI.Widget.VBox {
|
|
143
|
-
private readonly nodeForUrl: Map<Platform.DevToolsPath.UrlString, GridNode>;
|
|
144
180
|
private highlightRegExp: RegExp|null;
|
|
145
|
-
|
|
181
|
+
#coverageInfo: CoverageListItem[] = [];
|
|
182
|
+
#selectedUrl: Platform.DevToolsPath.UrlString|null = null;
|
|
183
|
+
#maxSize = 0;
|
|
184
|
+
#view: View;
|
|
146
185
|
|
|
147
|
-
constructor() {
|
|
148
|
-
super({useShadowDom: true});
|
|
149
|
-
this
|
|
150
|
-
this.nodeForUrl = new Map();
|
|
186
|
+
constructor(view = DEFAULT_VIEW) {
|
|
187
|
+
super({useShadowDom: true, delegatesFocus: true});
|
|
188
|
+
this.#view = view;
|
|
151
189
|
this.highlightRegExp = null;
|
|
152
|
-
|
|
153
|
-
const columns = [
|
|
154
|
-
{
|
|
155
|
-
id: 'url',
|
|
156
|
-
title: i18nString(UIStrings.url),
|
|
157
|
-
width: '250px',
|
|
158
|
-
weight: 3,
|
|
159
|
-
fixedWidth: false,
|
|
160
|
-
sortable: true,
|
|
161
|
-
disclosure: true,
|
|
162
|
-
},
|
|
163
|
-
{id: 'type', title: i18nString(UIStrings.type), width: '45px', weight: 1, fixedWidth: true, sortable: true},
|
|
164
|
-
{
|
|
165
|
-
id: 'size',
|
|
166
|
-
title: i18nString(UIStrings.totalBytes),
|
|
167
|
-
width: '60px',
|
|
168
|
-
fixedWidth: true,
|
|
169
|
-
sortable: true,
|
|
170
|
-
align: DataGrid.DataGrid.Align.RIGHT,
|
|
171
|
-
weight: 1,
|
|
172
|
-
},
|
|
173
|
-
{
|
|
174
|
-
id: 'unused-size',
|
|
175
|
-
title: i18nString(UIStrings.unusedBytes),
|
|
176
|
-
width: '100px',
|
|
177
|
-
fixedWidth: true,
|
|
178
|
-
sortable: true,
|
|
179
|
-
align: DataGrid.DataGrid.Align.RIGHT,
|
|
180
|
-
sort: DataGrid.DataGrid.Order.Descending,
|
|
181
|
-
weight: 1,
|
|
182
|
-
},
|
|
183
|
-
{
|
|
184
|
-
id: 'bars',
|
|
185
|
-
title: i18nString(UIStrings.usageVisualization),
|
|
186
|
-
width: '250px',
|
|
187
|
-
fixedWidth: false,
|
|
188
|
-
sortable: true,
|
|
189
|
-
weight: 1,
|
|
190
|
-
},
|
|
191
|
-
] as DataGrid.DataGrid.ColumnDescriptor[];
|
|
192
|
-
this.dataGrid =
|
|
193
|
-
DataGrid.SortableDataGrid.SortableDataGrid.create(['dummy'], [], i18nString(UIStrings.codeCoverage)) as
|
|
194
|
-
DataGrid.SortableDataGrid.SortableDataGrid<GridNode>;
|
|
195
|
-
this.dataGrid.removeColumn('dummy');
|
|
196
|
-
for (const column of columns) {
|
|
197
|
-
this.dataGrid.addColumn(column);
|
|
198
|
-
}
|
|
199
|
-
this.dataGrid.setColumnsVisibility(new Set(columns.map(column => column.id)));
|
|
200
|
-
this.dataGrid.setResizeMethod(DataGrid.DataGrid.ResizeMethod.LAST);
|
|
201
|
-
this.dataGrid.setStriped(true);
|
|
202
|
-
this.dataGrid.element.classList.add('flex-auto');
|
|
203
|
-
this.dataGrid.addEventListener(DataGrid.DataGrid.Events.OPENED_NODE, this.onOpenedNode, this);
|
|
204
|
-
|
|
205
|
-
const dataGridWidget = this.dataGrid.asWidget();
|
|
206
|
-
dataGridWidget.show(this.contentElement);
|
|
207
|
-
this.setDefaultFocusedChild(dataGridWidget);
|
|
208
190
|
}
|
|
209
191
|
|
|
210
192
|
update(coverageInfo: CoverageListItem[], highlightRegExp: RegExp|null): void {
|
|
211
193
|
this.highlightRegExp = highlightRegExp;
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
for (const [url, node] of this.nodeForUrl.entries()) {
|
|
216
|
-
if (!coverageUrls.has(url)) {
|
|
217
|
-
node.remove();
|
|
218
|
-
this.nodeForUrl.delete(url);
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
let hadUpdates = false;
|
|
223
|
-
for (const entry of coverageInfo) {
|
|
224
|
-
let node = this.nodeForUrl.get(entry.url);
|
|
225
|
-
if (node) {
|
|
226
|
-
hadUpdates = node.refreshIfNeeded(maxSize, entry) || hadUpdates;
|
|
227
|
-
if (entry.sources.length > 0) {
|
|
228
|
-
this.updateSourceNodes(entry.sources, maxSize, node);
|
|
229
|
-
}
|
|
230
|
-
node.setHighlight(this.highlightRegExp);
|
|
231
|
-
continue;
|
|
232
|
-
}
|
|
233
|
-
node = new GridNode(entry, maxSize);
|
|
234
|
-
this.nodeForUrl.set(entry.url, node);
|
|
235
|
-
this.appendNodeByType(node);
|
|
236
|
-
if (entry.sources.length > 0) {
|
|
237
|
-
this.updateSourceNodes(entry.sources, maxSize, node);
|
|
238
|
-
}
|
|
239
|
-
node.setHighlight(this.highlightRegExp);
|
|
240
|
-
hadUpdates = true;
|
|
241
|
-
}
|
|
242
|
-
if (hadUpdates) {
|
|
243
|
-
this.dataGrid.dispatchEventToListeners(DataGrid.DataGrid.Events.SORTING_CHANGED);
|
|
244
|
-
}
|
|
194
|
+
this.#maxSize = coverageInfo.reduce((acc, entry) => Math.max(acc, entry.size), 0);
|
|
195
|
+
this.#coverageInfo = coverageInfo;
|
|
196
|
+
this.requestUpdate();
|
|
245
197
|
}
|
|
246
198
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
}
|
|
257
|
-
}
|
|
199
|
+
override performUpdate(): void {
|
|
200
|
+
const input: ViewInput = {
|
|
201
|
+
items: this.#coverageInfo,
|
|
202
|
+
selectedUrl: this.#selectedUrl,
|
|
203
|
+
maxSize: this.#maxSize,
|
|
204
|
+
onOpen: this.selectByUrl.bind(this),
|
|
205
|
+
highlightRegExp: this.highlightRegExp,
|
|
206
|
+
};
|
|
207
|
+
this.#view(input, {}, this.contentElement);
|
|
258
208
|
}
|
|
259
209
|
|
|
260
210
|
reset(): void {
|
|
261
|
-
this
|
|
262
|
-
this
|
|
211
|
+
this.#coverageInfo = [];
|
|
212
|
+
this.#maxSize = 0;
|
|
213
|
+
this.requestUpdate();
|
|
263
214
|
}
|
|
264
215
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
parentNode?.appendChild(node);
|
|
269
|
-
} else {
|
|
270
|
-
this.dataGrid.rootNode().appendChild(node);
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
selectByUrl(url: string): void {
|
|
275
|
-
const node = this.nodeForUrl.get(url as Platform.DevToolsPath.UrlString);
|
|
276
|
-
if (node) {
|
|
277
|
-
node.revealAndSelect();
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
private onOpenedNode(): void {
|
|
282
|
-
void this.revealSourceForSelectedNode();
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
private async revealSourceForSelectedNode(): Promise<void> {
|
|
286
|
-
const node = this.dataGrid.selectedNode;
|
|
287
|
-
if (!node) {
|
|
216
|
+
selectByUrl(url: Platform.DevToolsPath.UrlString): void {
|
|
217
|
+
const info = this.#coverageInfo.find(info => info.url === url);
|
|
218
|
+
if (!info) {
|
|
288
219
|
return;
|
|
289
220
|
}
|
|
290
|
-
|
|
291
|
-
|
|
221
|
+
if (this.#selectedUrl !== url) {
|
|
222
|
+
this.#selectedUrl = url as Platform.DevToolsPath.UrlString;
|
|
223
|
+
this.requestUpdate();
|
|
224
|
+
}
|
|
225
|
+
const sourceCode = Workspace.Workspace.WorkspaceImpl.instance().uiSourceCodeForURL(url);
|
|
292
226
|
if (!sourceCode) {
|
|
293
227
|
return;
|
|
294
228
|
}
|
|
295
229
|
|
|
296
|
-
if (this.dataGrid.selectedNode !== node) {
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
230
|
void Common.Revealer.reveal(sourceCode);
|
|
300
231
|
}
|
|
301
232
|
}
|
|
@@ -321,148 +252,63 @@ function getBytesFormatter(): Intl.NumberFormat {
|
|
|
321
252
|
return bytesFormatter;
|
|
322
253
|
}
|
|
323
254
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
private maxSize: number;
|
|
329
|
-
private highlightRegExp: RegExp|null;
|
|
330
|
-
|
|
331
|
-
constructor(coverageInfo: CoverageListItem, maxSize: number) {
|
|
332
|
-
super();
|
|
333
|
-
this.coverageInfo = coverageInfo;
|
|
334
|
-
this.url = coverageInfo.url;
|
|
335
|
-
this.maxSize = maxSize;
|
|
336
|
-
this.highlightRegExp = null;
|
|
337
|
-
this.#updateData(coverageInfo);
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
#updateData(coverageInfo: CoverageListItem): void {
|
|
341
|
-
this.data['url'] = this.url;
|
|
342
|
-
this.data['type'] = coverageTypeToString(coverageInfo.type);
|
|
343
|
-
this.data['size'] = coverageInfo.size;
|
|
344
|
-
this.data['unused-size'] = coverageInfo.unusedSize;
|
|
345
|
-
this.data['bars'] = coverageInfo.unusedSize;
|
|
346
|
-
this.coverageInfo = coverageInfo;
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
setHighlight(highlightRegExp: RegExp|null): void {
|
|
350
|
-
if (this.highlightRegExp === highlightRegExp) {
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
this.highlightRegExp = highlightRegExp;
|
|
354
|
-
for (const child of this.children) {
|
|
355
|
-
(child as GridNode).setHighlight(this.highlightRegExp);
|
|
356
|
-
}
|
|
357
|
-
this.refresh();
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
refreshIfNeeded(maxSize: number, coverageInfo: CoverageListItem): boolean {
|
|
361
|
-
if (this.lastUsedSize === coverageInfo.usedSize && maxSize === this.maxSize) {
|
|
362
|
-
return false;
|
|
363
|
-
}
|
|
364
|
-
this.lastUsedSize = coverageInfo.usedSize;
|
|
365
|
-
this.maxSize = maxSize;
|
|
366
|
-
this.refresh();
|
|
367
|
-
this.#updateData(coverageInfo);
|
|
368
|
-
return true;
|
|
255
|
+
function renderItem(info: CoverageListItem, input: ViewInput): TemplateResult {
|
|
256
|
+
function highlightRange(textContent: string): string {
|
|
257
|
+
const matches = input.highlightRegExp?.exec(textContent);
|
|
258
|
+
return matches?.length ? `${matches.index},${matches[0].length}` : '';
|
|
369
259
|
}
|
|
370
260
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
break;
|
|
410
|
-
}
|
|
411
|
-
case 'unused-size': {
|
|
412
|
-
this.setCellAccessibleName(
|
|
413
|
-
i18nString(UIStrings.sBytesS, {n: info.unusedSize, percentage: formatPercent(info.unusedPercentage)}), cell,
|
|
414
|
-
columnId);
|
|
415
|
-
// clang-format off
|
|
416
|
-
render(html`
|
|
417
|
-
<span>${formatBytes(info.unusedSize)}</span>
|
|
418
|
-
<span class="percent-value">
|
|
419
|
-
${formatPercent(info.unusedPercentage)}
|
|
420
|
-
</span>`, cell);
|
|
421
|
-
// clang-format on
|
|
422
|
-
break;
|
|
423
|
-
}
|
|
424
|
-
case 'bars': {
|
|
425
|
-
this.setCellAccessibleName(
|
|
426
|
-
i18nString(
|
|
427
|
-
UIStrings.sOfFileUnusedSOfFileUsed,
|
|
428
|
-
{PH1: formatPercent(info.unusedPercentage), PH2: formatPercent(info.usedPercentage)}),
|
|
429
|
-
cell, columnId);
|
|
430
|
-
// clang-format off
|
|
431
|
-
render(html`
|
|
432
|
-
<div class="bar-container">
|
|
433
|
-
${info.unusedSize > 0 ? html`
|
|
434
|
-
<div class="bar bar-unused-size"
|
|
435
|
-
title=${
|
|
436
|
-
info.type & CoverageType.JAVA_SCRIPT_PER_FUNCTION ? i18nString(UIStrings.sBytesSBelongToFunctionsThatHave, {PH1: info.unusedSize, PH2: formatPercent(info.unusedPercentage)}) :
|
|
437
|
-
info.type & CoverageType.JAVA_SCRIPT ? i18nString(UIStrings.sBytesSBelongToBlocksOf, {PH1: info.unusedSize, PH2: formatPercent(info.unusedPercentage)}) :
|
|
438
|
-
''}
|
|
439
|
-
style=${styleMap({width: ((info.unusedSize / this.maxSize) * 100 || 0) + '%'})}>
|
|
440
|
-
</div>` : nothing}
|
|
441
|
-
${info.usedSize > 0 ? html`
|
|
261
|
+
const splitURL = /^(.*)(\/[^/]*)$/.exec(info.url);
|
|
262
|
+
// clang-format off
|
|
263
|
+
return html`
|
|
264
|
+
<style>${coverageListViewStyles}</style>
|
|
265
|
+
<tr data-url=${info.url} selected=${info.url === input.selectedUrl}
|
|
266
|
+
@open=${() => input.onOpen(info.url)}>
|
|
267
|
+
<td data-value=${info.url} title=${info.url} aria-label=${info.url}>
|
|
268
|
+
<devtools-highlight ranges=${highlightRange(info.url)} class="url-outer" aria-hidden="true">
|
|
269
|
+
<div class="url-prefix">${splitURL ? splitURL[1] : info.url}</div>
|
|
270
|
+
<div class="url-suffix">${splitURL ? splitURL[2] : ''}</div>
|
|
271
|
+
</devtools-highlight>
|
|
272
|
+
</td>
|
|
273
|
+
<td data-value=${coverageTypeToString(info.type)}
|
|
274
|
+
title=${info.type & CoverageType.JAVA_SCRIPT_PER_FUNCTION ? i18nString(UIStrings.jsCoverageWithPerFunction) :
|
|
275
|
+
info.type & CoverageType.JAVA_SCRIPT ? i18nString(UIStrings.jsCoverageWithPerBlock) :
|
|
276
|
+
''}>
|
|
277
|
+
${coverageTypeToString(info.type)}
|
|
278
|
+
</td>
|
|
279
|
+
<td data-value=${info.size} aria-label=${i18nString(UIStrings.sBytes, {n: info.size || 0})}>
|
|
280
|
+
<span>${formatBytes(info.size)}</span>
|
|
281
|
+
</td>
|
|
282
|
+
<td data-value=${info.unusedSize} aria-label=${i18nString(UIStrings.sBytesS, {n: info.unusedSize, percentage: formatPercent(info.unusedPercentage)})}>
|
|
283
|
+
<span>${formatBytes(info.unusedSize)}</span>
|
|
284
|
+
<span class="percent-value">
|
|
285
|
+
${formatPercent(info.unusedPercentage)}
|
|
286
|
+
</span>
|
|
287
|
+
</td>
|
|
288
|
+
<td data-value=${info.unusedSize} aria-label=${i18nString(UIStrings.sOfFileUnusedSOfFileUsed, {PH1: formatPercent(info.unusedPercentage), PH2: formatPercent(info.usedPercentage)})}>
|
|
289
|
+
<div class="bar-container">
|
|
290
|
+
${info.unusedSize > 0 ? html`
|
|
291
|
+
<div class="bar bar-unused-size"
|
|
292
|
+
title=${
|
|
293
|
+
info.type & CoverageType.JAVA_SCRIPT_PER_FUNCTION ? i18nString(UIStrings.sBytesSBelongToFunctionsThatHave, {PH1: info.unusedSize, PH2: formatPercent(info.unusedPercentage)}) :
|
|
294
|
+
info.type & CoverageType.JAVA_SCRIPT ? i18nString(UIStrings.sBytesSBelongToBlocksOf, {PH1: info.unusedSize, PH2: formatPercent(info.unusedPercentage)}) :
|
|
295
|
+
''}
|
|
296
|
+
style=${styleMap({width: ((info.unusedSize / input.maxSize) * 100 || 0) + '%'})}>
|
|
297
|
+
</div>` : nothing}
|
|
298
|
+
${info.usedSize > 0 ? html`
|
|
442
299
|
<div class="bar bar-used-size"
|
|
443
300
|
title=${
|
|
444
301
|
info.type & CoverageType.JAVA_SCRIPT_PER_FUNCTION ? i18nString(UIStrings.sBytesSBelongToFunctionsThatHaveExecuted, {PH1: info.usedSize, PH2: formatPercent(info.usedPercentage)}) :
|
|
445
302
|
info.type & CoverageType.JAVA_SCRIPT ? i18nString(UIStrings.sBytesSBelongToBlocksOfJavascript, {PH1: info.usedSize, PH2: formatPercent(info.usedPercentage)}) :
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
style=${styleMap({width:((info.usedSize / this.maxSize) * 100 || 0) + '%'})}>
|
|
303
|
+
''}
|
|
304
|
+
style=${styleMap({width:((info.usedSize / input.maxSize) * 100 || 0) + '%'})}>
|
|
449
305
|
</div>` : nothing}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
if (!this.highlightRegExp) {
|
|
459
|
-
return;
|
|
460
|
-
}
|
|
461
|
-
const matches = this.highlightRegExp.exec(textContent);
|
|
462
|
-
if (!matches?.length) {
|
|
463
|
-
return;
|
|
464
|
-
}
|
|
465
|
-
const range = new TextUtils.TextRange.SourceRange(matches.index, matches[0].length);
|
|
466
|
-
UI.UIUtils.highlightRangesWithStyleClass(element, [range], 'filter-highlight');
|
|
467
|
-
}
|
|
306
|
+
</div>
|
|
307
|
+
</td>
|
|
308
|
+
${info.sources.length > 0 ? html`
|
|
309
|
+
<td><table>
|
|
310
|
+
${repeat(info.sources, source => source.url, source => renderItem(source, input))}
|
|
311
|
+
</table></td>` : nothing}
|
|
312
|
+
</tr>`;
|
|
313
|
+
// clang-format on
|
|
468
314
|
}
|