blob: e6e544095bd547d846e9a4c434351d96d31994f6 [file] [edit]
// Copyright (c) 2026, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import annotations from "./annotations.js";
import dom from "./dom.js";
import scales from "./scales.js";
import sidebar from "./sidebar.js";
import state from "./state.js";
import url from "./url.js";
var chart = null;
var dataProvider = null;
var filteredCommits = null;
function getBenchmarkColors(theChart) {
const benchmarkColors = {};
for (
var datasetIndex = 0;
datasetIndex < theChart.data.datasets.length;
datasetIndex++
) {
if (theChart.getDatasetMeta(datasetIndex).hidden) {
continue;
}
const dataset = theChart.data.datasets[datasetIndex];
const benchmark = dataset.benchmark;
const benchmarkColor = dataset.borderColor;
if (!(benchmark in benchmarkColors)) {
benchmarkColors[benchmark] = benchmarkColor;
}
}
return benchmarkColors;
}
function get() {
return chart;
}
function getChartData() {
return dataProvider(filteredCommits);
}
function getDataLabelFormatter(value, context) {
const percentageChange = getDataPercentageChange(context);
const commit = getFilteredCommit(context.dataIndex);
var label = "";
// For try commits, always include the initials in the data label.
if ("parent_hash" in commit) {
const initials = commit.author
.split(/\s/)
.reduce((initials, name) => (initials += name.slice(0, 1)), "");
label += initials;
}
if (percentageChange !== null && Math.abs(percentageChange) >= 0.1) {
const glyph = percentageChange < 0 ? "▼" : "▲";
label += glyph + " " + percentageChange.toFixed(2) + "%";
}
return label;
}
function getDataPercentageChange(context) {
var i = context.dataIndex;
var value = context.dataset.data[i];
var j = i;
var previousValue;
do {
if (j == 0) {
return null;
}
previousValue = context.dataset.data[--j];
} while (previousValue === undefined || isNaN(previousValue));
const benchmark = context.dataset.benchmark;
if (
benchmark &&
!state.hasSameDump(benchmark, getFilteredCommit(j), getFilteredCommit(i))
) {
return null;
}
return ((value - previousValue) / previousValue) * 100;
}
function getFilteredCommit(index) {
return filteredCommits[index];
}
function initializeChart(options) {
setFilteredCommits();
chart = new Chart(dom.canvas, {
data: getChartData(),
options: options,
plugins: [ChartDataLabels],
});
// Setup annotations.
annotations.configure(chart, filteredCommits);
// Hide disabled legends.
if (state.selectedLegends.size < state.legends.size) {
update(false, true);
} else {
update(false, false);
}
document.addEventListener("keydown", (e) => {
state.handleKeyDownEvent(e, () => update(true, false));
});
}
function setDataProvider(theDataProvider) {
dataProvider = theDataProvider;
}
function setFilteredCommits() {
filteredCommits = state.commits(state.zoom);
}
function update(dataChanged, legendsChanged) {
console.assert(state.zoom.left <= state.zoom.right);
// Update datasets.
if (dataChanged) {
setFilteredCommits();
Object.assign(chart.data, getChartData());
// Update annotations.
annotations.configure(chart, filteredCommits);
// Update chart.
chart.update();
}
// Update legends.
if (
legendsChanged ||
(dataChanged && state.selectedLegends.size < state.legends.size)
) {
for (
var datasetIndex = 0;
datasetIndex < chart.data.datasets.length;
datasetIndex++
) {
const datasetMeta = chart.getDatasetMeta(datasetIndex);
datasetMeta.hidden = !state.isLegendSelected(datasetMeta.label);
}
// Update scales.
scales.update(chart.options.scales);
// Update chart.
chart.update();
}
dom.updateBenchmarkColors(getBenchmarkColors(chart));
dom.updateChartNavigation();
sidebar.update((benchmark, additive) => {
if (additive) {
if (state.selectedBenchmarks.has(benchmark)) {
if (state.selectedBenchmarks.size > 1) {
state.selectedBenchmarks.delete(benchmark);
}
} else {
state.selectedBenchmarks.add(benchmark);
}
} else {
state.selectedBenchmarks.clear();
state.selectedBenchmarks.add(benchmark);
}
state.forEachBenchmark((name, selected) => {
const checkbox = document.getElementById(name);
if (checkbox) {
checkbox.checked = selected;
}
});
update(true, false);
});
url.updateHash(state);
}
export default {
get: get,
getDataLabelFormatter: getDataLabelFormatter,
getDataPercentageChange: getDataPercentageChange,
getFilteredCommit: getFilteredCommit,
initializeChart: initializeChart,
setDataProvider: setDataProvider,
update: update,
};