[tools] Add V8CustomElement.update method
Drive-by-fix: - Remove duplicated LazyTable - Introduce more pseudo private _* fields - Remove MapPanel.mapDetails getter - Rename MapDetails.setSelectedMap to .map Bug: v8:10644 Change-Id: I0f976ab86f24de2677e024e386e7d4169c9abbb3 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2523192 Commit-Queue: Camillo Bruni <cbruni@chromium.org> Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org> Cr-Commit-Position: refs/heads/master@{#71093}
This commit is contained in:
parent
7555761b9b
commit
6c69379497
@ -177,11 +177,15 @@ function $(id) {
|
||||
}
|
||||
|
||||
class V8CustomElement extends HTMLElement {
|
||||
_updateTimeoutId;
|
||||
_updateCallback = this._update.bind(this);
|
||||
|
||||
constructor(templateText) {
|
||||
super();
|
||||
const shadowRoot = this.attachShadow({mode: 'open'});
|
||||
shadowRoot.innerHTML = templateText;
|
||||
}
|
||||
|
||||
$(id) {
|
||||
return this.shadowRoot.querySelector(id);
|
||||
}
|
||||
@ -189,30 +193,16 @@ class V8CustomElement extends HTMLElement {
|
||||
querySelectorAll(query) {
|
||||
return this.shadowRoot.querySelectorAll(query);
|
||||
}
|
||||
}
|
||||
|
||||
class LazyTable {
|
||||
constructor(table, rowData, rowElementCreator) {
|
||||
this._table = table;
|
||||
this._rowData = rowData;
|
||||
this._rowElementCreator = rowElementCreator;
|
||||
const tbody = table.querySelector('tbody');
|
||||
table.replaceChild(document.createElement('tbody'), tbody);
|
||||
table.querySelector('tfoot td').onclick = (e) => this._addMoreRows();
|
||||
this._addMoreRows();
|
||||
update() {
|
||||
// Use timeout tasks to asynchronously update the UI without blocking.
|
||||
clearTimeout(this._updateTimeoutId);
|
||||
const kDelayMs = 5;
|
||||
this._updateTimeoutId = setTimeout(this._updateCallback, kDelayMs);
|
||||
}
|
||||
|
||||
_nextRowDataSlice() {
|
||||
return this._rowData.splice(0, 100);
|
||||
}
|
||||
|
||||
_addMoreRows() {
|
||||
const fragment = new DocumentFragment();
|
||||
for (let row of this._nextRowDataSlice()) {
|
||||
const tr = this._rowElementCreator(row);
|
||||
fragment.appendChild(tr);
|
||||
}
|
||||
this._table.querySelector('tbody').appendChild(fragment);
|
||||
_update() {
|
||||
throw Error('Subclass responsibility');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ DOM.defineCustomElement(
|
||||
console.assert(value !== undefined, 'timeline undefined!');
|
||||
this._timeline = value;
|
||||
this.selectedLogEntries = this._timeline.all;
|
||||
this.updateCount();
|
||||
this.update();
|
||||
}
|
||||
get groupKey() {
|
||||
return this.$('#group-key');
|
||||
@ -48,22 +48,21 @@ DOM.defineCustomElement(
|
||||
this.update();
|
||||
}
|
||||
|
||||
async update() {
|
||||
await delay(1);
|
||||
this.updateCount();
|
||||
this.updateTable();
|
||||
_update() {
|
||||
this._updateCount();
|
||||
this._updateTable();
|
||||
}
|
||||
|
||||
updateCount() {
|
||||
_updateCount() {
|
||||
this.count.innerHTML = `length=${this._selectedLogEntries.length}`;
|
||||
}
|
||||
|
||||
updateTable(event) {
|
||||
_updateTable(event) {
|
||||
let select = this.groupKey;
|
||||
let key = select.options[select.selectedIndex].text;
|
||||
DOM.removeAllChildren(this.tableBody);
|
||||
let groups = Group.groupBy(this._selectedLogEntries, key, true);
|
||||
this.render(groups, this.tableBody);
|
||||
this._render(groups, this.tableBody);
|
||||
}
|
||||
|
||||
escapeHtml(unsafe) {
|
||||
@ -102,7 +101,7 @@ DOM.defineCustomElement(
|
||||
this.dispatchEvent(new FocusEvent(sourcePosition));
|
||||
}
|
||||
|
||||
render(groups, parent) {
|
||||
_render(groups, parent) {
|
||||
const fragment = document.createDocumentFragment();
|
||||
const max = Math.min(1000, groups.length)
|
||||
const detailsClickHandler = this.handleDetailsClick.bind(this);
|
||||
@ -176,7 +175,7 @@ DOM.defineCustomElement(
|
||||
`Grouped by ${key} [top ${max} out of ${children.length}]`;
|
||||
td.appendChild(div);
|
||||
const table = DOM.table();
|
||||
this.render(children.slice(0, max), table, false)
|
||||
this._render(children.slice(0, max), table, false)
|
||||
td.appendChild(table);
|
||||
}
|
||||
|
||||
|
@ -17,11 +17,11 @@ DOM.defineCustomElement('log-file-reader',
|
||||
}
|
||||
|
||||
set error(message) {
|
||||
this.updateLabel(message);
|
||||
this._updateLabel(message);
|
||||
this.root.className = 'fail';
|
||||
}
|
||||
|
||||
updateLabel(text) {
|
||||
_updateLabel(text) {
|
||||
this.$('#label').innerText = text;
|
||||
}
|
||||
|
||||
@ -73,7 +73,7 @@ DOM.defineCustomElement('log-file-reader',
|
||||
|
||||
handleFileLoad(e, file) {
|
||||
const chunk = e.target.result;
|
||||
this.updateLabel(`Finished loading '${file.name}'.`);
|
||||
this._updateLabel(`Finished loading '${file.name}'.`);
|
||||
this.dispatchEvent(new CustomEvent('fileuploadend', {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
|
@ -21,7 +21,7 @@ DOM.defineCustomElement('map-panel',
|
||||
|
||||
handleUpdateMapDetails(e) {
|
||||
if (e.entry instanceof MapLogEntry) {
|
||||
this.mapDetailsPanel.mapDetails = e.entry;
|
||||
this.mapDetailsPanel.map = e.entry;
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,10 +41,6 @@ DOM.defineCustomElement('map-panel',
|
||||
return this.$('#searchBar');
|
||||
}
|
||||
|
||||
get mapDetails() {
|
||||
return this.mapDetailsPanel.mapDetails;
|
||||
}
|
||||
|
||||
set timeline(timeline) {
|
||||
this._timeline = timeline;
|
||||
}
|
||||
|
@ -7,13 +7,14 @@ import {DOM, V8CustomElement} from '../helper.mjs';
|
||||
DOM.defineCustomElement(
|
||||
'./map-panel/map-details',
|
||||
(templateText) => class MapDetails extends V8CustomElement {
|
||||
_map;
|
||||
|
||||
constructor() {
|
||||
super(templateText);
|
||||
this._filePositionNode.addEventListener(
|
||||
'click', e => this.handleFilePositionClick(e));
|
||||
this.selectedMap = undefined;
|
||||
this._filePositionNode.onclick = e => this._handleFilePositionClick(e);
|
||||
}
|
||||
get mapDetails() {
|
||||
|
||||
get _mapDetails() {
|
||||
return this.$('#mapDetails');
|
||||
}
|
||||
|
||||
@ -21,25 +22,26 @@ DOM.defineCustomElement(
|
||||
return this.$('#filePositionNode');
|
||||
}
|
||||
|
||||
setSelectedMap(value) {
|
||||
this.selectedMap = value;
|
||||
set map(map) {
|
||||
if (this._map === map) return;
|
||||
this._map = map;
|
||||
this.update();
|
||||
}
|
||||
|
||||
set mapDetails(map) {
|
||||
_update() {
|
||||
let details = '';
|
||||
let clickableDetails = '';
|
||||
if (map) {
|
||||
clickableDetails += `ID: ${map.id}`;
|
||||
clickableDetails += `\nSource location: ${map.filePosition}`;
|
||||
details += `\n${map.description}`;
|
||||
this.setSelectedMap(map);
|
||||
if (this._map) {
|
||||
clickableDetails = `ID: ${this._map.id}`;
|
||||
clickableDetails += `\nSource location: ${this._map.filePosition}`;
|
||||
details = this._map.description;
|
||||
}
|
||||
this._filePositionNode.innerText = clickableDetails;
|
||||
this._filePositionNode.classList.add('clickable');
|
||||
this.mapDetails.innerText = details;
|
||||
this._mapDetails.innerText = details;
|
||||
}
|
||||
|
||||
handleFilePositionClick() {
|
||||
this.dispatchEvent(new FocusEvent(this.selectedMap.sourcePosition));
|
||||
_handleFilePositionClick(event) {
|
||||
this.dispatchEvent(new FocusEvent(this._map.sourcePosition));
|
||||
}
|
||||
});
|
||||
|
@ -10,7 +10,7 @@ DOM.defineCustomElement('./map-panel/map-transitions',
|
||||
_map;
|
||||
_selectedMapLogEntries;
|
||||
_displayedMapsInTree;
|
||||
_showMapsUpdateId;
|
||||
|
||||
constructor() {
|
||||
super(templateText);
|
||||
this.transitionView.addEventListener(
|
||||
@ -45,7 +45,7 @@ DOM.defineCustomElement('./map-panel/map-transitions',
|
||||
}
|
||||
}
|
||||
|
||||
selectMap(map) {
|
||||
_selectMap(map) {
|
||||
this.dispatchEvent(new SelectionEvent([map]));
|
||||
}
|
||||
|
||||
@ -53,14 +53,10 @@ DOM.defineCustomElement('./map-panel/map-transitions',
|
||||
if (this.currentMap === this._map) return;
|
||||
this.currentMap = this._map;
|
||||
this.selectedMapLogEntries = [this._map];
|
||||
this.showMaps();
|
||||
this.update();
|
||||
}
|
||||
|
||||
showMaps() {
|
||||
clearTimeout(this._showMapsUpdateId);
|
||||
this._showMapsUpdateId = setTimeout(() => this._showMaps(), 250);
|
||||
}
|
||||
_showMaps() {
|
||||
_update() {
|
||||
this.transitionView.style.display = 'none';
|
||||
DOM.removeAllChildren(this.transitionView);
|
||||
this._displayedMapsInTree = new Set();
|
||||
@ -73,7 +69,7 @@ DOM.defineCustomElement('./map-panel/map-transitions',
|
||||
|
||||
set selectedMapLogEntries(list) {
|
||||
this._selectedMapLogEntries = list;
|
||||
this.showMaps();
|
||||
this.update();
|
||||
}
|
||||
|
||||
get selectedMapLogEntries() {
|
||||
@ -149,7 +145,7 @@ DOM.defineCustomElement('./map-panel/map-transitions',
|
||||
let node = DOM.div('map');
|
||||
if (map.edge) node.style.backgroundColor = typeToColor(map.edge);
|
||||
node.map = map;
|
||||
node.addEventListener('click', () => this.selectMap(map));
|
||||
node.addEventListener('click', () => this._selectMap(map));
|
||||
if (map.children.length > 1) {
|
||||
node.innerText = map.children.length;
|
||||
let showSubtree = DOM.div('showSubtransitions');
|
||||
|
@ -32,7 +32,7 @@ DOM.defineCustomElement(
|
||||
this._transitions = value;
|
||||
}
|
||||
|
||||
filterUniqueTransitions(filter) {
|
||||
_filterUniqueTransitions(filter) {
|
||||
// Returns a list of Maps whose parent is not in the list.
|
||||
return this._selectedLogEntries.filter((map) => {
|
||||
if (filter(map) === false) return false;
|
||||
@ -42,13 +42,12 @@ DOM.defineCustomElement(
|
||||
});
|
||||
}
|
||||
|
||||
async update() {
|
||||
await delay(1);
|
||||
this.updateGeneralStats();
|
||||
this.updateNamedTransitionsStats();
|
||||
_update() {
|
||||
this._updateGeneralStats();
|
||||
this._updateNamedTransitionsStats();
|
||||
}
|
||||
|
||||
updateGeneralStats() {
|
||||
_updateGeneralStats() {
|
||||
console.assert(this._timeline !== undefined, 'Timeline not set yet!');
|
||||
let pairs = [
|
||||
['Transitions', 'primary', (e) => e.edge && e.edge.isTransition()],
|
||||
@ -89,12 +88,12 @@ DOM.defineCustomElement(
|
||||
// lazily compute the stats
|
||||
let node = e.target.parentNode;
|
||||
if (node.maps == undefined) {
|
||||
node.maps = this.filterUniqueTransitions(filter);
|
||||
node.maps = this._filterUniqueTransitions(filter);
|
||||
}
|
||||
this.dispatchEvent(new SelectionEvent(node.maps));
|
||||
};
|
||||
row.appendChild(DOM.td(name));
|
||||
let count = this.count(filter);
|
||||
let count = this._count(filter);
|
||||
row.appendChild(DOM.td(count));
|
||||
let percent = Math.round((count / total) * 1000) / 10;
|
||||
row.appendChild(DOM.td(percent.toFixed(1) + '%'));
|
||||
@ -103,7 +102,7 @@ DOM.defineCustomElement(
|
||||
this.$('#typeTable').replaceChild(tbody, this.$('#typeTable tbody'));
|
||||
}
|
||||
|
||||
count(filter) {
|
||||
_count(filter) {
|
||||
let count = 0;
|
||||
for (const map of this._selectedLogEntries) {
|
||||
if (filter(map)) count++;
|
||||
@ -111,7 +110,7 @@ DOM.defineCustomElement(
|
||||
return count;
|
||||
}
|
||||
|
||||
updateNamedTransitionsStats() {
|
||||
_updateNamedTransitionsStats() {
|
||||
let rowData = Array.from(this._transitions.entries());
|
||||
rowData.sort((a, b) => b[1].length - a[1].length);
|
||||
new LazyTable(this.$('#nameTable'), rowData, ([name, maps]) => {
|
||||
|
@ -50,7 +50,6 @@ DOM.defineCustomElement(
|
||||
}
|
||||
for (const track of this.timelineTracks) {
|
||||
track.timeSelection = timeSelection;
|
||||
;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -167,9 +167,13 @@ DOM.defineCustomElement('./timeline/timeline-track',
|
||||
set data(value) {
|
||||
this._timeline = value;
|
||||
this._resetTypeToColorCache();
|
||||
this.updateChunks();
|
||||
this.updateTimeline();
|
||||
this.renderLegend();
|
||||
this.update();
|
||||
}
|
||||
|
||||
_update() {
|
||||
this._updateChunks();
|
||||
this._updateTimeline();
|
||||
this._renderLegend();
|
||||
}
|
||||
|
||||
_resetTypeToColorCache() {
|
||||
@ -186,15 +190,14 @@ DOM.defineCustomElement('./timeline/timeline-track',
|
||||
|
||||
set nofChunks(count) {
|
||||
this._nofChunks = count;
|
||||
this.updateChunks();
|
||||
this.updateTimeline();
|
||||
this.update();
|
||||
}
|
||||
|
||||
get nofChunks() {
|
||||
return this._nofChunks;
|
||||
}
|
||||
|
||||
updateChunks() {
|
||||
_updateChunks() {
|
||||
this._chunks = this.data.chunks(this.nofChunks);
|
||||
}
|
||||
|
||||
@ -219,7 +222,7 @@ DOM.defineCustomElement('./timeline/timeline-track',
|
||||
return this._typeToColor.get(type);
|
||||
}
|
||||
|
||||
renderLegend() {
|
||||
_renderLegend() {
|
||||
let timelineLegendContent = this.timelineLegendContent;
|
||||
DOM.removeAllChildren(timelineLegendContent);
|
||||
this._timeline.uniqueTypes.forEach((entries, type) => {
|
||||
@ -308,7 +311,7 @@ DOM.defineCustomElement('./timeline/timeline-track',
|
||||
node.style.backgroundImage = `url(${imageData})`;
|
||||
}
|
||||
|
||||
updateTimeline() {
|
||||
_updateTimeline() {
|
||||
let chunksNode = this.timelineChunks;
|
||||
DOM.removeAllChildren(chunksNode);
|
||||
let chunks = this.chunks;
|
||||
|
Loading…
Reference in New Issue
Block a user