39d0c5e761
Also manually reformat some files with the clang-format change. Rolling v8/build:e10cf1a..c8ec41b
Rolling v8/buildtools:c2e4795..113378f
Rolling v8/buildtools/linux64: git_revision:7c8e511229f0fc06f6250367d51156bb6f578258..git_revision:48b013c9d9debc0f5fc1dd71a257b3c38c5acb43 Rolling v8/buildtools/third_party/libc++abi/trunk:518fd76..c7888dd
Rolling v8/buildtools/third_party/libunwind/trunk:705543f..d8a4746
Rolling v8/third_party/catapult: https://chromium.googlesource.com/catapult/+log/88422dc..9ba02ee Rolling v8/third_party/depot_tools:dc8ca44..fccf35c
Rolling v8/third_party/zlib:32e65ef..961141d
Rolling v8/tools/clang:3c4a622..75625c6
Rolling v8/tools/luci-go: git_revision:6da0608e4fa8a3c6d1fa4f855485c0038b05bf72..git_revision:2aa3d7e5e8662c5193059a490f07b7d91331933e Rolling v8/tools/luci-go: git_revision:6da0608e4fa8a3c6d1fa4f855485c0038b05bf72..git_revision:2aa3d7e5e8662c5193059a490f07b7d91331933e R=v8-waterfall-sheriff@grotations.appspotmail.com,mtv-sf-v8-sheriff@grotations.appspotmail.com Change-Id: I00a09d42cf91f226c661e97915d5a95fff84b079 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3615245 Reviewed-by: Michael Achenbach <machenbach@chromium.org> Commit-Queue: Leszek Swirski <leszeks@chromium.org> Owners-Override: Leszek Swirski <leszeks@chromium.org> Cr-Commit-Position: refs/heads/main@{#80343}
196 lines
5.5 KiB
JavaScript
196 lines
5.5 KiB
JavaScript
// Copyright 2020 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import {App} from '../index.mjs'
|
|
|
|
import {FocusEvent, ToolTipEvent} from './events.mjs';
|
|
import {CollapsableElement, DOM, groupBy, LazyTable} from './helper.mjs';
|
|
|
|
DOM.defineCustomElement('view/list-panel',
|
|
(templateText) =>
|
|
class ListPanel extends CollapsableElement {
|
|
_selectedLogEntries = [];
|
|
_displayedLogEntries = [];
|
|
_timeline;
|
|
|
|
_detailsClickHandler = this._handleDetailsClick.bind(this);
|
|
_logEntryClickHandler = this._handleLogEntryClick.bind(this);
|
|
_logEntryMouseOverHandler = this._logEntryMouseOverHandler.bind(this);
|
|
|
|
constructor() {
|
|
super(templateText);
|
|
this.groupKey.addEventListener('change', e => this.requestUpdate());
|
|
this.showAllRadio.onclick = _ => this._showEntries(this._timeline);
|
|
this.showTimerangeRadio.onclick = _ =>
|
|
this._showEntries(this._timeline.selectionOrSelf);
|
|
this.showSelectionRadio.onclick = _ =>
|
|
this._showEntries(this._selectedLogEntries);
|
|
}
|
|
|
|
static get observedAttributes() {
|
|
return ['title'];
|
|
}
|
|
|
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
if (name == 'title') {
|
|
this.$('#title').innerHTML = newValue;
|
|
}
|
|
}
|
|
|
|
set timeline(timeline) {
|
|
console.assert(timeline !== undefined, 'timeline undefined!');
|
|
this._timeline = timeline;
|
|
this.$('.panel').style.display = timeline.isEmpty() ? 'none' : 'inherit';
|
|
this._initGroupKeySelect();
|
|
}
|
|
|
|
set selectedLogEntries(entries) {
|
|
if (entries === this._timeline) {
|
|
this.showAllRadio.click();
|
|
} else if (entries === this._timeline.selection) {
|
|
this.showTimerangeRadio.click();
|
|
} else {
|
|
this._selectedLogEntries = entries;
|
|
this.showSelectionRadio.click();
|
|
}
|
|
}
|
|
|
|
get entryClass() {
|
|
return this._timeline.at(0)?.constructor;
|
|
}
|
|
|
|
get groupKey() {
|
|
return this.$('#group-key');
|
|
}
|
|
|
|
get table() {
|
|
return this.$('#table');
|
|
}
|
|
|
|
get showAllRadio() {
|
|
return this.$('#show-all');
|
|
}
|
|
|
|
get showTimerangeRadio() {
|
|
return this.$('#show-timerange');
|
|
}
|
|
|
|
get showSelectionRadio() {
|
|
return this.$('#show-selection');
|
|
}
|
|
|
|
get _propertyNames() {
|
|
return this.entryClass?.propertyNames ?? [];
|
|
}
|
|
|
|
_initGroupKeySelect() {
|
|
const select = this.groupKey;
|
|
select.options.length = 0;
|
|
for (const propertyName of this._propertyNames) {
|
|
const option = DOM.element('option');
|
|
option.text = propertyName;
|
|
select.add(option);
|
|
}
|
|
}
|
|
|
|
_showEntries(entries) {
|
|
this._displayedLogEntries = entries;
|
|
this.requestUpdate();
|
|
}
|
|
|
|
_update() {
|
|
if (this._timeline.isEmpty()) return;
|
|
DOM.removeAllChildren(this.table);
|
|
if (this._displayedLogEntries.length == 0) return;
|
|
const propertyName = this.groupKey.selectedOptions[0].text;
|
|
const groups =
|
|
groupBy(this._displayedLogEntries, each => each[propertyName], true);
|
|
this._render(groups, this.table);
|
|
}
|
|
|
|
createSubgroups(group) {
|
|
const map = new Map();
|
|
const tempGroups = [];
|
|
for (let propertyName of this._propertyNames) {
|
|
map.set(
|
|
propertyName,
|
|
groupBy(group.entries, each => each[propertyName], true));
|
|
}
|
|
return map;
|
|
}
|
|
|
|
_handleLogEntryClick(e) {
|
|
const group = e.currentTarget.group;
|
|
this.dispatchEvent(new FocusEvent(group.key));
|
|
}
|
|
|
|
_logEntryMouseOverHandler(e) {
|
|
const group = e.currentTarget.group;
|
|
this.dispatchEvent(new ToolTipEvent(group.key, e.currentTarget));
|
|
}
|
|
|
|
_handleDetailsClick(event) {
|
|
event.stopPropagation();
|
|
const tr = event.target.parentNode;
|
|
const group = tr.group;
|
|
// Create subgroup in-place if the don't exist yet.
|
|
if (tr.groups === undefined) {
|
|
const groups = tr.groups = this.createSubgroups(group);
|
|
this.renderDrilldown(groups, tr);
|
|
}
|
|
const detailsTr = tr.nextSibling;
|
|
if (tr.classList.contains('open')) {
|
|
tr.classList.remove('open');
|
|
detailsTr.style.display = 'none';
|
|
} else {
|
|
tr.classList.add('open');
|
|
detailsTr.style.display = 'table-row';
|
|
}
|
|
}
|
|
|
|
renderDrilldown(groups, previousSibling) {
|
|
const tr = DOM.tr('entry-details');
|
|
tr.style.display = 'none';
|
|
// indent by one td.
|
|
tr.appendChild(DOM.td());
|
|
const td = DOM.td();
|
|
td.colSpan = 3;
|
|
groups.forEach((group, key) => {
|
|
this.renderDrilldownGroup(td, group, key);
|
|
});
|
|
tr.appendChild(td);
|
|
// Append the new TR after previousSibling.
|
|
previousSibling.parentNode.insertBefore(tr, previousSibling.nextSibling);
|
|
}
|
|
|
|
renderDrilldownGroup(td, groups, key) {
|
|
const div = DOM.div('drilldown-group-title');
|
|
div.textContent = `Grouped by ${key}: ${groups[0]?.parentTotal ?? 0}#`;
|
|
td.appendChild(div);
|
|
const table = DOM.table();
|
|
this._render(groups, table, false)
|
|
td.appendChild(table);
|
|
}
|
|
|
|
_render(groups, table) {
|
|
let last;
|
|
new LazyTable(table, groups, group => {
|
|
last = group;
|
|
const tr = DOM.tr();
|
|
tr.group = group;
|
|
const details = tr.appendChild(DOM.td('', 'toggle'));
|
|
details.onclick = this._detailsClickHandler;
|
|
tr.appendChild(DOM.td(`${group.percent.toFixed(2)}%`, 'percentage'));
|
|
tr.appendChild(DOM.td(group.length, 'count'));
|
|
const valueTd = tr.appendChild(DOM.td(group.key?.toString(), 'key'));
|
|
if (App.isClickable(group.key)) {
|
|
tr.onclick = this._logEntryClickHandler;
|
|
tr.onmouseover = this._logEntryMouseOverHandler;
|
|
valueTd.classList.add('clickable');
|
|
}
|
|
return tr;
|
|
}, 10);
|
|
}
|
|
});
|