chrome-devtools-frontend 1.0.1526203 → 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/i18n/i18nImpl.ts +1 -1
- package/front_end/core/sdk/ChildTargetManager.ts +2 -0
- package/front_end/generated/InspectorBackendCommands.js +1 -1
- package/front_end/generated/protocol-mapping.d.ts +3 -1
- package/front_end/generated/protocol-proxy-api.d.ts +3 -1
- 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/third_party/chromium/README.chromium +1 -1
- package/front_end/ui/components/buttons/Button.ts +1 -1
- package/front_end/ui/legacy/EmptyWidget.ts +11 -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 +1 -1
- package/front_end/ui/legacy/components/source_frame/StreamingContentHexView.ts +7 -8
- package/package.json +1 -1
|
@@ -68,7 +68,7 @@ export async function fetchAndRegisterLocaleData(
|
|
|
68
68
|
locale: Intl.UnicodeBCP47LocaleIdentifier, location = self.location.toString()): Promise<void> {
|
|
69
69
|
const localeDataTextPromise = fetch(getLocaleFetchUrl(locale, location)).then(result => result.json());
|
|
70
70
|
const timeoutPromise =
|
|
71
|
-
new Promise<never>((_, reject) => window.setTimeout(() => reject(new Error('timed out fetching locale')),
|
|
71
|
+
new Promise<never>((_, reject) => window.setTimeout(() => reject(new Error('timed out fetching locale')), 2500));
|
|
72
72
|
const localeData = await Promise.race([timeoutPromise, localeDataTextPromise]);
|
|
73
73
|
i18nInstance.registerLocaleData(locale, localeData);
|
|
74
74
|
}
|
|
@@ -177,6 +177,8 @@ export class ChildTargetManager extends SDKModel<EventTypes> implements Protocol
|
|
|
177
177
|
type = Type.FRAME;
|
|
178
178
|
} else if (targetInfo.type === 'page') {
|
|
179
179
|
type = Type.FRAME;
|
|
180
|
+
} else if (targetInfo.type === 'browser_ui') {
|
|
181
|
+
type = Type.FRAME;
|
|
180
182
|
} else if (targetInfo.type === 'worker') {
|
|
181
183
|
type = Type.Worker;
|
|
182
184
|
} else if (targetInfo.type === 'worklet') {
|
|
@@ -858,7 +858,7 @@ inspectorBackend.registerCommand("Network.continueInterceptedRequest", [{"name":
|
|
|
858
858
|
inspectorBackend.registerCommand("Network.deleteCookies", [{"name": "name", "type": "string", "optional": false, "description": "Name of the cookies to remove.", "typeRef": null}, {"name": "url", "type": "string", "optional": true, "description": "If specified, deletes all the cookies with the given name where domain and path match provided URL.", "typeRef": null}, {"name": "domain", "type": "string", "optional": true, "description": "If specified, deletes only cookies with the exact domain.", "typeRef": null}, {"name": "path", "type": "string", "optional": true, "description": "If specified, deletes only cookies with the exact path.", "typeRef": null}, {"name": "partitionKey", "type": "object", "optional": true, "description": "If specified, deletes only cookies with the the given name and partitionKey where all partition key attributes match the cookie partition key attribute.", "typeRef": "Network.CookiePartitionKey"}], [], "Deletes browser cookies with matching name and url or domain/path/partitionKey pair.");
|
|
859
859
|
inspectorBackend.registerCommand("Network.disable", [], [], "Disables network tracking, prevents network events from being sent to the client.");
|
|
860
860
|
inspectorBackend.registerCommand("Network.emulateNetworkConditions", [{"name": "offline", "type": "boolean", "optional": false, "description": "True to emulate internet disconnection.", "typeRef": null}, {"name": "latency", "type": "number", "optional": false, "description": "Minimum latency from request sent to response headers received (ms).", "typeRef": null}, {"name": "downloadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated download throughput (bytes/sec). -1 disables download throttling.", "typeRef": null}, {"name": "uploadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated upload throughput (bytes/sec). -1 disables upload throttling.", "typeRef": null}, {"name": "connectionType", "type": "string", "optional": true, "description": "Connection type if known.", "typeRef": "Network.ConnectionType"}, {"name": "packetLoss", "type": "number", "optional": true, "description": "WebRTC packet loss (percent, 0-100). 0 disables packet loss emulation, 100 drops all the packets.", "typeRef": null}, {"name": "packetQueueLength", "type": "number", "optional": true, "description": "WebRTC packet queue length (packet). 0 removes any queue length limitations.", "typeRef": null}, {"name": "packetReordering", "type": "boolean", "optional": true, "description": "WebRTC packetReordering feature.", "typeRef": null}], [], "Activates emulation of network conditions. This command is deprecated in favor of the emulateNetworkConditionsByRule and overrideNetworkState commands, which can be used together to the same effect.");
|
|
861
|
-
inspectorBackend.registerCommand("Network.emulateNetworkConditionsByRule", [{"name": "offline", "type": "boolean", "optional": false, "description": "True to emulate internet disconnection.", "typeRef": null}, {"name": "matchedNetworkConditions", "type": "array", "optional": false, "description": "Configure conditions for matching requests. If multiple entries match a request, the first entry wins. Global conditions can be configured by leaving the urlPattern for the conditions empty. These global conditions are also applied for throttling of p2p connections.", "typeRef": "Network.NetworkConditions"}], ["ruleIds"], "Activates emulation of network conditions for individual requests using URL match patterns.");
|
|
861
|
+
inspectorBackend.registerCommand("Network.emulateNetworkConditionsByRule", [{"name": "offline", "type": "boolean", "optional": false, "description": "True to emulate internet disconnection.", "typeRef": null}, {"name": "matchedNetworkConditions", "type": "array", "optional": false, "description": "Configure conditions for matching requests. If multiple entries match a request, the first entry wins. Global conditions can be configured by leaving the urlPattern for the conditions empty. These global conditions are also applied for throttling of p2p connections.", "typeRef": "Network.NetworkConditions"}], ["ruleIds"], "Activates emulation of network conditions for individual requests using URL match patterns. Unlike the deprecated Network.emulateNetworkConditions this method does not affect `navigator` state. Use Network.overrideNetworkState to explicitly modify `navigator` behavior.");
|
|
862
862
|
inspectorBackend.registerCommand("Network.overrideNetworkState", [{"name": "offline", "type": "boolean", "optional": false, "description": "True to emulate internet disconnection.", "typeRef": null}, {"name": "latency", "type": "number", "optional": false, "description": "Minimum latency from request sent to response headers received (ms).", "typeRef": null}, {"name": "downloadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated download throughput (bytes/sec). -1 disables download throttling.", "typeRef": null}, {"name": "uploadThroughput", "type": "number", "optional": false, "description": "Maximal aggregated upload throughput (bytes/sec). -1 disables upload throttling.", "typeRef": null}, {"name": "connectionType", "type": "string", "optional": true, "description": "Connection type if known.", "typeRef": "Network.ConnectionType"}], [], "Override the state of navigator.onLine and navigator.connection.");
|
|
863
863
|
inspectorBackend.registerCommand("Network.enable", [{"name": "maxTotalBufferSize", "type": "number", "optional": true, "description": "Buffer size in bytes to use when preserving network payloads (XHRs, etc).", "typeRef": null}, {"name": "maxResourceBufferSize", "type": "number", "optional": true, "description": "Per-resource buffer size in bytes to use when preserving network payloads (XHRs, etc).", "typeRef": null}, {"name": "maxPostDataSize", "type": "number", "optional": true, "description": "Longest post body size (in bytes) that would be included in requestWillBeSent notification", "typeRef": null}, {"name": "reportDirectSocketTraffic", "type": "boolean", "optional": true, "description": "Whether DirectSocket chunk send/receive events should be reported.", "typeRef": null}, {"name": "enableDurableMessages", "type": "boolean", "optional": true, "description": "Enable storing response bodies outside of renderer, so that these survive a cross-process navigation. Requires maxTotalBufferSize to be set. Currently defaults to false.", "typeRef": null}], [], "Enables network tracking, network events will now be delivered to the client.");
|
|
864
864
|
inspectorBackend.registerCommand("Network.getAllCookies", [], ["cookies"], "Returns all browser cookies. Depending on the backend support, will return detailed cookie information in the `cookies` field. Deprecated. Use Storage.getCookies instead.");
|
|
@@ -3349,7 +3349,9 @@ export namespace ProtocolMapping {
|
|
|
3349
3349
|
returnType: void;
|
|
3350
3350
|
};
|
|
3351
3351
|
/**
|
|
3352
|
-
* Activates emulation of network conditions for individual requests using URL match patterns.
|
|
3352
|
+
* Activates emulation of network conditions for individual requests using URL match patterns. Unlike the deprecated
|
|
3353
|
+
* Network.emulateNetworkConditions this method does not affect `navigator` state. Use Network.overrideNetworkState to
|
|
3354
|
+
* explicitly modify `navigator` behavior.
|
|
3353
3355
|
*/
|
|
3354
3356
|
'Network.emulateNetworkConditionsByRule': {
|
|
3355
3357
|
paramsType: [Protocol.Network.EmulateNetworkConditionsByRuleRequest];
|
|
@@ -2523,7 +2523,9 @@ declare namespace ProtocolProxyApi {
|
|
|
2523
2523
|
invoke_emulateNetworkConditions(params: Protocol.Network.EmulateNetworkConditionsRequest): Promise<Protocol.ProtocolResponseWithError>;
|
|
2524
2524
|
|
|
2525
2525
|
/**
|
|
2526
|
-
* Activates emulation of network conditions for individual requests using URL match patterns.
|
|
2526
|
+
* Activates emulation of network conditions for individual requests using URL match patterns. Unlike the deprecated
|
|
2527
|
+
* Network.emulateNetworkConditions this method does not affect `navigator` state. Use Network.overrideNetworkState to
|
|
2528
|
+
* explicitly modify `navigator` behavior.
|
|
2527
2529
|
*/
|
|
2528
2530
|
invoke_emulateNetworkConditionsByRule(params: Protocol.Network.EmulateNetworkConditionsByRuleRequest): Promise<Protocol.Network.EmulateNetworkConditionsByRuleResponse>;
|
|
2529
2531
|
|
|
@@ -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
|
}
|