172 строки
4.2 KiB
JavaScript
172 строки
4.2 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
function cleanFunc(func) {
|
|
let dllIndex = func.indexOf(".dll@");
|
|
|
|
if (dllIndex != -1) {
|
|
return func.substring(0, dllIndex + 4);
|
|
}
|
|
|
|
return func;
|
|
}
|
|
|
|
function generateGraph(signature) {
|
|
if (!signature) {
|
|
return;
|
|
}
|
|
|
|
let query;
|
|
|
|
if (signature.startsWith("https://crash-stats.mozilla.org/")) {
|
|
if (signature.startsWith("https://crash-stats.mozilla.org/search/")) {
|
|
signature =
|
|
"https://crash-stats.mozilla.org/api/SuperSearch/" +
|
|
signature.substring("https://crash-stats.mozilla.org/search/".length);
|
|
}
|
|
|
|
query = new URL(signature);
|
|
|
|
query.searchParams.set("_facets", "proto_signature");
|
|
query.searchParams.set("_facets_size", 50);
|
|
query.searchParams.set("_results_number", 0);
|
|
} else {
|
|
query = new URL(
|
|
"https://crash-stats.mozilla.org/api/SuperSearch/?signature=%3D" +
|
|
signature +
|
|
"&_results_number=0&_facets=proto_signature&_facets_size=50"
|
|
);
|
|
}
|
|
|
|
console.log(query.href);
|
|
|
|
fetch(query.href)
|
|
.then((response) => response.json())
|
|
.then((data) => {
|
|
let addedNodes = new Map();
|
|
let addedEdges = new Map();
|
|
|
|
for (let proto_signature of data["facets"]["proto_signature"]) {
|
|
let funcs = proto_signature["term"].split(" | ");
|
|
let stack_count = proto_signature["count"];
|
|
|
|
for (let i = funcs.length - 1; i > 0; i--) {
|
|
let func = cleanFunc(funcs[i]);
|
|
|
|
if (!addedNodes.has(func)) {
|
|
addedNodes.set(func, stack_count);
|
|
} else {
|
|
addedNodes.set(func, addedNodes.get(func) + stack_count);
|
|
}
|
|
|
|
if (i != 0) {
|
|
let edge = func + "|" + cleanFunc(funcs[i - 1]);
|
|
|
|
if (!addedEdges.has(edge)) {
|
|
addedEdges.set(edge, stack_count);
|
|
} else {
|
|
addedEdges.set(edge, addedEdges.get(edge) + stack_count);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
let nodes = [];
|
|
for (let node of addedNodes) {
|
|
nodes.push({
|
|
id: node[0],
|
|
label: node[0],
|
|
value: node[1],
|
|
});
|
|
}
|
|
|
|
let edges = [];
|
|
for (let edge of addedEdges) {
|
|
let from_to = edge[0].split("|");
|
|
edges.push({
|
|
from: from_to[0],
|
|
to: from_to[1],
|
|
value: edge[1],
|
|
});
|
|
}
|
|
|
|
console.log(nodes.length);
|
|
console.log(edges.length);
|
|
|
|
var data = {
|
|
nodes: nodes,
|
|
edges: edges,
|
|
};
|
|
|
|
var opts = {
|
|
layout: {
|
|
hierarchical: {
|
|
direction: "UD",
|
|
sortMethod: "directed",
|
|
nodeSpacing: 1,
|
|
blockShifting: false,
|
|
},
|
|
},
|
|
edges: {
|
|
arrows: {
|
|
to: true,
|
|
},
|
|
},
|
|
nodes: {
|
|
shape: "box",
|
|
font: {
|
|
face: "monospace",
|
|
},
|
|
scaling: {
|
|
label: {
|
|
enabled: true,
|
|
min: 5,
|
|
max: 40,
|
|
maxVisible: 40,
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
let network = new vis.Network(
|
|
document.getElementById("graph"),
|
|
data,
|
|
opts
|
|
);
|
|
|
|
network.on("stabilizationIterationsDone", function () {
|
|
network.setOptions({
|
|
physics: false,
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
new Promise((resolve, reject) => (window.onload = resolve))
|
|
.then(function () {
|
|
let elem = document.getElementById("signature");
|
|
|
|
let queryVars = new URL(location.href).search.substring(1).split("&");
|
|
|
|
for (let queryVar of queryVars) {
|
|
if (queryVar.startsWith("s=")) {
|
|
elem.value = decodeURIComponent(queryVar.substring("s=".length));
|
|
break;
|
|
}
|
|
}
|
|
|
|
document.getElementById("signatureButton").onclick = function () {
|
|
let s = elem.value.trim();
|
|
let url = new URL(location.href);
|
|
url.searchParams.set("s", s);
|
|
history.replaceState({}, document.title, url.href);
|
|
generateGraph(s);
|
|
};
|
|
|
|
generateGraph(elem.value.trim());
|
|
})
|
|
.catch(function (err) {
|
|
console.error(err);
|
|
});
|