mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 828052 - Update Cleopatra and fix the issue with gJavaScriptOnly flag not working; r=past
This commit is contained in:
parent
23f70e6cd3
commit
e15b9dcc56
@ -277,7 +277,7 @@ ProfilerPanel.prototype = {
|
|||||||
* If the instance is already loaded, onLoad will be
|
* If the instance is already loaded, onLoad will be
|
||||||
* called synchronously.
|
* called synchronously.
|
||||||
*/
|
*/
|
||||||
switchToProfile: function PP_switchToProfile(profile, onLoad) {
|
switchToProfile: function PP_switchToProfile(profile, onLoad=function() {}) {
|
||||||
let doc = this.document;
|
let doc = this.document;
|
||||||
|
|
||||||
if (this.activeProfile) {
|
if (this.activeProfile) {
|
||||||
|
@ -47,14 +47,19 @@ function onParentMessage(event) {
|
|||||||
var stop = document.getElementById("stopWrapper");
|
var stop = document.getElementById("stopWrapper");
|
||||||
var msg = JSON.parse(event.data);
|
var msg = JSON.parse(event.data);
|
||||||
|
|
||||||
if (msg.task === "onStarted") {
|
switch (msg.task) {
|
||||||
|
case "onStarted":
|
||||||
start.style.display = "none";
|
start.style.display = "none";
|
||||||
start.querySelector("button").removeAttribute("disabled");
|
start.querySelector("button").removeAttribute("disabled");
|
||||||
stop.style.display = "inline";
|
stop.style.display = "inline";
|
||||||
} else if (msg.task === "onStopped") {
|
break;
|
||||||
|
case "onStopped":
|
||||||
stop.style.display = "none";
|
stop.style.display = "none";
|
||||||
stop.querySelector("button").removeAttribute("disabled");
|
stop.querySelector("button").removeAttribute("disabled");
|
||||||
start.style.display = "inline";
|
start.style.display = "inline";
|
||||||
|
break;
|
||||||
|
case "receiveProfileData":
|
||||||
|
loadProfile(JSON.stringify(msg.rawProfile));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +71,9 @@ window.addEventListener("message", onParentMessage);
|
|||||||
*/
|
*/
|
||||||
function initUI() {
|
function initUI() {
|
||||||
gLightMode = true;
|
gLightMode = true;
|
||||||
gJavaScriptOnly = true;
|
|
||||||
|
gFileList = { profileParsingFinished: function () {} };
|
||||||
|
gInfoBar = { display: function () {} };
|
||||||
|
|
||||||
var container = document.createElement("div");
|
var container = document.createElement("div");
|
||||||
container.id = "ui";
|
container.id = "ui";
|
||||||
@ -102,3 +109,103 @@ function initUI() {
|
|||||||
|
|
||||||
gMainArea.appendChild(controlPane);
|
gMainArea.appendChild(controlPane);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modified copy of Cleopatra's enterFinishedProfileUI.
|
||||||
|
* By overriding the function we don't need to modify ui.js which helps
|
||||||
|
* with updating from upstream.
|
||||||
|
*/
|
||||||
|
function enterFinishedProfileUI() {
|
||||||
|
var cover = document.createElement("div");
|
||||||
|
cover.className = "finishedProfilePaneBackgroundCover";
|
||||||
|
|
||||||
|
var pane = document.createElement("table");
|
||||||
|
var rowIndex = 0;
|
||||||
|
var currRow;
|
||||||
|
|
||||||
|
pane.style.width = "100%";
|
||||||
|
pane.style.height = "100%";
|
||||||
|
pane.border = "0";
|
||||||
|
pane.cellPadding = "0";
|
||||||
|
pane.cellSpacing = "0";
|
||||||
|
pane.borderCollapse = "collapse";
|
||||||
|
pane.className = "finishedProfilePane";
|
||||||
|
|
||||||
|
gBreadcrumbTrail = new BreadcrumbTrail();
|
||||||
|
currRow = pane.insertRow(rowIndex++);
|
||||||
|
currRow.insertCell(0).appendChild(gBreadcrumbTrail.getContainer());
|
||||||
|
|
||||||
|
gHistogramView = new HistogramView();
|
||||||
|
currRow = pane.insertRow(rowIndex++);
|
||||||
|
currRow.insertCell(0).appendChild(gHistogramView.getContainer());
|
||||||
|
|
||||||
|
if (gMeta && gMeta.videoCapture) {
|
||||||
|
gVideoPane = new VideoPane(gMeta.videoCapture);
|
||||||
|
gVideoPane.onTimeChange(videoPaneTimeChange);
|
||||||
|
currRow = pane.insertRow(rowIndex++);
|
||||||
|
currRow.insertCell(0).appendChild(gVideoPane.getContainer());
|
||||||
|
}
|
||||||
|
|
||||||
|
var tree = document.createElement("div");
|
||||||
|
tree.className = "treeContainer";
|
||||||
|
tree.style.width = "100%";
|
||||||
|
tree.style.height = "100%";
|
||||||
|
|
||||||
|
gTreeManager = new ProfileTreeManager();
|
||||||
|
gTreeManager.treeView.setColumns([
|
||||||
|
{ name: "sampleCount", title: "Running time" },
|
||||||
|
{ name: "selfSampleCount", title: "Self" },
|
||||||
|
{ name: "resource", title: "" },
|
||||||
|
]);
|
||||||
|
|
||||||
|
currRow = pane.insertRow(rowIndex++);
|
||||||
|
currRow.style.height = "100%";
|
||||||
|
|
||||||
|
var cell = currRow.insertCell(0);
|
||||||
|
cell.appendChild(tree);
|
||||||
|
tree.appendChild(gTreeManager.getContainer());
|
||||||
|
|
||||||
|
gPluginView = new PluginView();
|
||||||
|
tree.appendChild(gPluginView.getContainer());
|
||||||
|
|
||||||
|
gMainArea.appendChild(cover);
|
||||||
|
gMainArea.appendChild(pane);
|
||||||
|
|
||||||
|
var currentBreadcrumb = gSampleFilters;
|
||||||
|
gBreadcrumbTrail.add({
|
||||||
|
title: "Complete Profile",
|
||||||
|
enterCallback: function () {
|
||||||
|
gSampleFilters = [];
|
||||||
|
filtersChanged();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (currentBreadcrumb == null || currentBreadcrumb.length == 0) {
|
||||||
|
gTreeManager.restoreSerializedSelectionSnapshot(gRestoreSelection);
|
||||||
|
viewOptionsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < currentBreadcrumb.length; i++) {
|
||||||
|
var filter = currentBreadcrumb[i];
|
||||||
|
var forceSelection = null;
|
||||||
|
if (gRestoreSelection != null && i == currentBreadcrumb.length - 1) {
|
||||||
|
forceSelection = gRestoreSelection;
|
||||||
|
}
|
||||||
|
switch (filter.type) {
|
||||||
|
case "FocusedFrameSampleFilter":
|
||||||
|
focusOnSymbol(filter.name, filter.symbolName);
|
||||||
|
gBreadcrumbTrail.enterLastItem(forceSelection);
|
||||||
|
case "FocusedCallstackPrefixSampleFilter":
|
||||||
|
focusOnCallstack(filter.focusedCallstack, filter.name, false);
|
||||||
|
gBreadcrumbTrail.enterLastItem(forceSelection);
|
||||||
|
case "FocusedCallstackPostfixSampleFilter":
|
||||||
|
focusOnCallstack(filter.focusedCallstack, filter.name, true);
|
||||||
|
gBreadcrumbTrail.enterLastItem(forceSelection);
|
||||||
|
case "RangeSampleFilter":
|
||||||
|
gHistogramView.selectRange(filter.start, filter.end);
|
||||||
|
gBreadcrumbTrail.enterLastItem(forceSelection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleJavascriptOnly();
|
||||||
|
}
|
@ -239,16 +239,25 @@ function parseRawProfile(requestID, params, rawProfile) {
|
|||||||
var symbolicationTable = {};
|
var symbolicationTable = {};
|
||||||
var symbols = [];
|
var symbols = [];
|
||||||
var symbolIndices = {};
|
var symbolIndices = {};
|
||||||
|
var resources = {};
|
||||||
var functions = [];
|
var functions = [];
|
||||||
var functionIndices = {};
|
var functionIndices = {};
|
||||||
var samples = [];
|
var samples = [];
|
||||||
var meta = {};
|
var meta = {};
|
||||||
var armIncludePCIndex = {};
|
var armIncludePCIndex = {};
|
||||||
|
|
||||||
|
if (rawProfile == null) {
|
||||||
|
throw "rawProfile is null";
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof rawProfile == "string" && rawProfile[0] == "{") {
|
if (typeof rawProfile == "string" && rawProfile[0] == "{") {
|
||||||
// rawProfile is a JSON string.
|
// rawProfile is a JSON string.
|
||||||
rawProfile = JSON.parse(rawProfile);
|
rawProfile = JSON.parse(rawProfile);
|
||||||
|
if (rawProfile === null) {
|
||||||
|
throw "rawProfile couldn't not successfully be parsed using JSON.parse. Make sure that the profile is a valid JSON encoding.";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (rawProfile.profileJSON && !rawProfile.profileJSON.meta && rawProfile.meta) {
|
if (rawProfile.profileJSON && !rawProfile.profileJSON.meta && rawProfile.meta) {
|
||||||
rawProfile.profileJSON.meta = rawProfile.meta;
|
rawProfile.profileJSON.meta = rawProfile.meta;
|
||||||
@ -271,149 +280,217 @@ function parseRawProfile(requestID, params, rawProfile) {
|
|||||||
parseProfileString(rawProfile);
|
parseProfileString(rawProfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params.profileId) {
|
||||||
|
meta.profileId = params.profileId;
|
||||||
|
}
|
||||||
|
|
||||||
function cleanFunctionName(functionName) {
|
function cleanFunctionName(functionName) {
|
||||||
var ignoredPrefix = "non-virtual thunk to ";
|
var ignoredPrefix = "non-virtual thunk to ";
|
||||||
if (functionName.substr(0, ignoredPrefix.length) == ignoredPrefix)
|
if (functionName.startsWith(ignoredPrefix))
|
||||||
return functionName.substr(ignoredPrefix.length);
|
return functionName.substr(ignoredPrefix.length);
|
||||||
return functionName;
|
return functionName;
|
||||||
}
|
}
|
||||||
|
|
||||||
function resourceNameForAddon(addonID) {
|
function resourceNameForAddon(addon) {
|
||||||
for (var i in meta.addons) {
|
if (!addon)
|
||||||
var addon = meta.addons[i];
|
return "";
|
||||||
if (addon.id.toLowerCase() == addonID.toLowerCase()) {
|
|
||||||
var iconHTML = "";
|
var iconHTML = "";
|
||||||
if (addon.iconURL)
|
if (addon.iconURL)
|
||||||
iconHTML = "<img src=\"" + addon.iconURL + "\" style='width:12px; height:12px;'> "
|
iconHTML = "<img src=\"" + addon.iconURL + "\" style='width:12px; height:12px;'> "
|
||||||
return iconHTML + " " + (/@jetpack$/.exec(addonID) ? "Jetpack: " : "") + addon.name;
|
return iconHTML + " " + (/@jetpack$/.exec(addon.id) ? "Jetpack: " : "") + addon.name;
|
||||||
}
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseResourceName(url) {
|
function addonWithID(addonID) {
|
||||||
if (!url) {
|
return firstMatch(meta.addons, function addonHasID(addon) {
|
||||||
return "No URL";
|
return addon.id.toLowerCase() == addonID.toLowerCase();
|
||||||
}
|
})
|
||||||
if (url.startsWith("resource:///")) {
|
|
||||||
// Take the last URL from a chained list of URLs.
|
|
||||||
var urls = url.split(" -> ");
|
|
||||||
url = urls[urls.length - 1];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Fix me, this certainly doesn't handle all URLs formats
|
function resourceNameForAddonWithID(addonID) {
|
||||||
var match = /^.*:\/\/(.*?)\/.*$/.exec(url);
|
return resourceNameForAddon(addonWithID(addonID));
|
||||||
|
}
|
||||||
|
|
||||||
if (!match)
|
function findAddonForChromeURIHost(host) {
|
||||||
return url;
|
return firstMatch(meta.addons, function addonUsesChromeURIHost(addon) {
|
||||||
|
return addon.chromeURIHosts && addon.chromeURIHosts.indexOf(host) != -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var host = match[1];
|
function ensureResource(name, resourceDescription) {
|
||||||
|
if (!(name in resources)) {
|
||||||
|
resources[name] = resourceDescription;
|
||||||
|
}
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resourceNameFromLibrary(library) {
|
||||||
|
return ensureResource("lib_" + library, {
|
||||||
|
type: "library",
|
||||||
|
name: library
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function getAddonForScriptURI(url, host) {
|
||||||
|
if (!meta || !meta.addons)
|
||||||
|
return null;
|
||||||
|
|
||||||
if (meta && meta.addons) {
|
|
||||||
if (url.startsWith("resource:") && endsWith(host, "-at-jetpack")) {
|
if (url.startsWith("resource:") && endsWith(host, "-at-jetpack")) {
|
||||||
// Assume this is a jetpack url
|
// Assume this is a jetpack url
|
||||||
var jetpackID = host.substring(0, host.length - 11) + "@jetpack";
|
var jetpackID = host.substring(0, host.length - 11) + "@jetpack";
|
||||||
var resName = resourceNameForAddon(jetpackID);
|
return addonWithID(jetpackID);
|
||||||
if (resName)
|
|
||||||
return resName;
|
|
||||||
}
|
|
||||||
if (url.startsWith("file:///") && url.indexOf("/extensions/") != -1) {
|
|
||||||
var unpackedAddonNameMatch = /\/extensions\/(.*?)\//.exec(url);
|
|
||||||
if (unpackedAddonNameMatch) {
|
|
||||||
var resName = resourceNameForAddon(decodeURIComponent(unpackedAddonNameMatch[1]));
|
|
||||||
if (resName)
|
|
||||||
return resName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (url.startsWith("jar:file:///") && url.indexOf("/extensions/") != -1) {
|
|
||||||
var packedAddonNameMatch = /\/extensions\/(.*?).xpi/.exec(url);
|
|
||||||
if (packedAddonNameMatch) {
|
|
||||||
var resName = resourceNameForAddon(decodeURIComponent(packedAddonNameMatch[1]));
|
|
||||||
if (resName)
|
|
||||||
return resName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var iconHTML = "";
|
if (url.startsWith("file:///") && url.indexOf("/extensions/") != -1) {
|
||||||
if (url.indexOf("http://") == 0) {
|
var unpackedAddonNameMatch = /\/extensions\/(.*?)\//.exec(url);
|
||||||
iconHTML = "<img src=\"http://" + host + "/favicon.ico\" style='width:12px; height:12px;'> ";
|
if (unpackedAddonNameMatch)
|
||||||
} else if (url.indexOf("https://") == 0) {
|
return addonWithID(decodeURIComponent(unpackedAddonNameMatch[1]));
|
||||||
iconHTML = "<img src=\"https://" + host + "/favicon.ico\" style='width:12px; height:12px;'> ";
|
return null;
|
||||||
}
|
}
|
||||||
return iconHTML + host;
|
|
||||||
|
if (url.startsWith("jar:file:///") && url.indexOf("/extensions/") != -1) {
|
||||||
|
var packedAddonNameMatch = /\/extensions\/(.*?).xpi/.exec(url);
|
||||||
|
if (packedAddonNameMatch)
|
||||||
|
return addonWithID(decodeURIComponent(packedAddonNameMatch[1]));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.startsWith("chrome://")) {
|
||||||
|
var chromeURIMatch = /chrome\:\/\/(.*?)\//.exec(url);
|
||||||
|
if (chromeURIMatch)
|
||||||
|
return findAddonForChromeURIHost(chromeURIMatch[1]);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resourceNameFromURI(url) {
|
||||||
|
if (!url)
|
||||||
|
return ensureResource("unknown", {type: "unknown", name: "<unknown>"});
|
||||||
|
|
||||||
|
var match = /^(.*):\/\/(.*?)\//.exec(url);
|
||||||
|
|
||||||
|
if (!match) {
|
||||||
|
// Can this happen? If so, we should change the regular expression above.
|
||||||
|
return ensureResource("url_" + url, {type: "url", name: url});
|
||||||
|
}
|
||||||
|
|
||||||
|
var urlRoot = match[0];
|
||||||
|
var protocol = match[1];
|
||||||
|
var host = match[2];
|
||||||
|
|
||||||
|
var addon = getAddonForScriptURI(url, host);
|
||||||
|
if (addon) {
|
||||||
|
return ensureResource("addon_" + addon.id, {
|
||||||
|
type: "addon",
|
||||||
|
name: addon.name,
|
||||||
|
addonID: addon.id,
|
||||||
|
icon: addon.iconURL
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (protocol.startsWith("http")) {
|
||||||
|
return ensureResource("webhost_" + host, {
|
||||||
|
type: "webhost",
|
||||||
|
name: host,
|
||||||
|
icon: urlRoot + "favicon.ico"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return ensureResource("otherhost_" + host, {
|
||||||
|
type: "otherhost",
|
||||||
|
name: host
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseScriptFile(url) {
|
function parseScriptFile(url) {
|
||||||
// TODO Fix me, this certainly doesn't handle all URLs formats
|
var match = /([^\/]*)$/.exec(url);
|
||||||
var match = /^.*\/(.*)\.js$/.exec(url);
|
if (match && match[1])
|
||||||
|
return match[1];
|
||||||
|
|
||||||
if (!match)
|
|
||||||
return url;
|
return url;
|
||||||
|
|
||||||
return match[1] + ".js";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseScriptURI(url) {
|
// JS File information sometimes comes with multiple URIs which are chained
|
||||||
|
// with " -> ". We only want the last URI in this list.
|
||||||
|
function getRealScriptURI(url) {
|
||||||
if (url) {
|
if (url) {
|
||||||
var urlTokens = url.split(" ");
|
var urls = url.split(" -> ");
|
||||||
url = urlTokens[urlTokens.length-1];
|
return urls[urls.length - 1];
|
||||||
}
|
}
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFunctionInfo(fullName) {
|
function getFunctionInfo(fullName) {
|
||||||
var isJSFrame = false;
|
|
||||||
|
function getCPPFunctionInfo(fullName) {
|
||||||
var match =
|
var match =
|
||||||
/^(.*) \(in ([^\)]*)\) (\+ [0-9]+)$/.exec(fullName) ||
|
/^(.*) \(in ([^\)]*)\) (\+ [0-9]+)$/.exec(fullName) ||
|
||||||
/^(.*) \(in ([^\)]*)\) (\(.*:.*\))$/.exec(fullName) ||
|
/^(.*) \(in ([^\)]*)\) (\(.*:.*\))$/.exec(fullName) ||
|
||||||
/^(.*) \(in ([^\)]*)\)$/.exec(fullName);
|
/^(.*) \(in ([^\)]*)\)$/.exec(fullName);
|
||||||
// Try to parse a JS frame
|
|
||||||
var scriptLocation = null;
|
if (!match)
|
||||||
var jsMatch1 = match ||
|
return null;
|
||||||
/^(.*) \((.*):([0-9]+)\)$/.exec(fullName);
|
|
||||||
if (!match && jsMatch1) {
|
|
||||||
scriptLocation = {
|
|
||||||
scriptURI: parseScriptURI(jsMatch1[2]),
|
|
||||||
lineInformation: jsMatch1[3]
|
|
||||||
};
|
|
||||||
match = [0, jsMatch1[1]+"() @ "+parseScriptFile(jsMatch1[2]) + ":" + jsMatch1[3], parseResourceName(jsMatch1[2]), ""];
|
|
||||||
isJSFrame = true;
|
|
||||||
}
|
|
||||||
var jsMatch2 = match ||
|
|
||||||
/^(.*):([0-9]+)$/.exec(fullName);
|
|
||||||
if (!match && jsMatch2) {
|
|
||||||
scriptLocation = {
|
|
||||||
scriptURI: parseScriptURI(jsMatch2[1]),
|
|
||||||
lineInformation: jsMatch2[2]
|
|
||||||
};
|
|
||||||
match = [0, "<Anonymous> @ "+parseScriptFile(jsMatch2[1]) + ":" + jsMatch2[2], parseResourceName(jsMatch2[1]), ""];
|
|
||||||
isJSFrame = true;
|
|
||||||
}
|
|
||||||
if (!match) {
|
|
||||||
match = [fullName, fullName];
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
functionName: cleanFunctionName(match[1]),
|
functionName: cleanFunctionName(match[1]),
|
||||||
libraryName: match[2] || "",
|
libraryName: resourceNameFromLibrary(match[2]),
|
||||||
lineInformation: match[3] || "",
|
lineInformation: match[3] || "",
|
||||||
isJSFrame: isJSFrame,
|
isRoot: false,
|
||||||
scriptLocation: scriptLocation
|
isJSFrame: false
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function indexForFunction(symbol, functionName, libraryName, isJSFrame, scriptLocation) {
|
function getJSFunctionInfo(fullName) {
|
||||||
var resolve = functionName+"_LIBNAME_"+libraryName;
|
var jsMatch =
|
||||||
|
/^(.*) \((.*):([0-9]+)\)$/.exec(fullName) ||
|
||||||
|
/^()(.*):([0-9]+)$/.exec(fullName);
|
||||||
|
|
||||||
|
if (!jsMatch)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var functionName = jsMatch[1] || "<Anonymous>";
|
||||||
|
var scriptURI = getRealScriptURI(jsMatch[2]);
|
||||||
|
var lineNumber = jsMatch[3];
|
||||||
|
var scriptFile = parseScriptFile(scriptURI);
|
||||||
|
var resourceName = resourceNameFromURI(scriptURI);
|
||||||
|
|
||||||
|
return {
|
||||||
|
functionName: functionName + "() @ " + scriptFile + ":" + lineNumber,
|
||||||
|
libraryName: resourceName,
|
||||||
|
lineInformation: "",
|
||||||
|
isRoot: false,
|
||||||
|
isJSFrame: true,
|
||||||
|
scriptLocation: {
|
||||||
|
scriptURI: scriptURI,
|
||||||
|
lineInformation: lineNumber
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFallbackFunctionInfo(fullName) {
|
||||||
|
return {
|
||||||
|
functionName: cleanFunctionName(fullName),
|
||||||
|
libraryName: "",
|
||||||
|
lineInformation: "",
|
||||||
|
isRoot: fullName == "(root)",
|
||||||
|
isJSFrame: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return getCPPFunctionInfo(fullName) ||
|
||||||
|
getJSFunctionInfo(fullName) ||
|
||||||
|
getFallbackFunctionInfo(fullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
function indexForFunction(symbol, info) {
|
||||||
|
var resolve = info.functionName + "__" + info.libraryName;
|
||||||
if (resolve in functionIndices)
|
if (resolve in functionIndices)
|
||||||
return functionIndices[resolve];
|
return functionIndices[resolve];
|
||||||
var newIndex = functions.length;
|
var newIndex = functions.length;
|
||||||
functions[newIndex] = {
|
info.symbol = symbol;
|
||||||
symbol: symbol,
|
functions[newIndex] = info;
|
||||||
functionName: functionName,
|
|
||||||
libraryName: libraryName,
|
|
||||||
isJSFrame: isJSFrame,
|
|
||||||
scriptLocation: scriptLocation
|
|
||||||
};
|
|
||||||
functionIndices[resolve] = newIndex;
|
functionIndices[resolve] = newIndex;
|
||||||
return newIndex;
|
return newIndex;
|
||||||
}
|
}
|
||||||
@ -424,8 +501,9 @@ function parseRawProfile(requestID, params, rawProfile) {
|
|||||||
return {
|
return {
|
||||||
symbolName: symbol,
|
symbolName: symbol,
|
||||||
functionName: info.functionName,
|
functionName: info.functionName,
|
||||||
functionIndex: indexForFunction(symbol, info.functionName, info.libraryName, info.isJSFrame, info.scriptLocation),
|
functionIndex: indexForFunction(symbol, info),
|
||||||
lineInformation: info.lineInformation,
|
lineInformation: info.lineInformation,
|
||||||
|
isRoot: info.isRoot,
|
||||||
isJSFrame: info.isJSFrame,
|
isJSFrame: info.isJSFrame,
|
||||||
scriptLocation: info.scriptLocation
|
scriptLocation: info.scriptLocation
|
||||||
};
|
};
|
||||||
@ -582,6 +660,9 @@ function parseRawProfile(requestID, params, rawProfile) {
|
|||||||
if (sample.responsiveness) {
|
if (sample.responsiveness) {
|
||||||
sample.extraInfo["responsiveness"] = sample.responsiveness;
|
sample.extraInfo["responsiveness"] = sample.responsiveness;
|
||||||
}
|
}
|
||||||
|
if (sample.marker) {
|
||||||
|
sample.extraInfo["marker"] = sample.marker;
|
||||||
|
}
|
||||||
if (sample.time) {
|
if (sample.time) {
|
||||||
sample.extraInfo["time"] = sample.time;
|
sample.extraInfo["time"] = sample.time;
|
||||||
}
|
}
|
||||||
@ -600,17 +681,22 @@ function parseRawProfile(requestID, params, rawProfile) {
|
|||||||
if (!sample) continue;
|
if (!sample) continue;
|
||||||
// If length == 0 then the sample was filtered when saving the profile
|
// If length == 0 then the sample was filtered when saving the profile
|
||||||
if (sample.frames.length >= 1 && sample.frames[0] != rootIndex)
|
if (sample.frames.length >= 1 && sample.frames[0] != rootIndex)
|
||||||
sample.frames.splice(0, 0, rootIndex)
|
sample.frames.unshift(rootIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
progressReporter.finish();
|
progressReporter.finish();
|
||||||
var profileID = gNextProfileID++;
|
// Don't increment the profile ID now because (1) it's buggy
|
||||||
|
// and (2) for now there's no point in storing each profile
|
||||||
|
// here if we're storing them in the local storage.
|
||||||
|
//var profileID = gNextProfileID++;
|
||||||
|
var profileID = gNextProfileID;
|
||||||
gProfiles[profileID] = JSON.parse(JSON.stringify({
|
gProfiles[profileID] = JSON.parse(JSON.stringify({
|
||||||
meta: meta,
|
meta: meta,
|
||||||
symbols: symbols,
|
symbols: symbols,
|
||||||
functions: functions,
|
functions: functions,
|
||||||
|
resources: resources,
|
||||||
allSamples: samples
|
allSamples: samples
|
||||||
}));
|
}));
|
||||||
clearRegExpLastMatch();
|
clearRegExpLastMatch();
|
||||||
@ -619,7 +705,8 @@ function parseRawProfile(requestID, params, rawProfile) {
|
|||||||
numSamples: samples.length,
|
numSamples: samples.length,
|
||||||
profileID: profileID,
|
profileID: profileID,
|
||||||
symbols: symbols,
|
symbols: symbols,
|
||||||
functions: functions
|
functions: functions,
|
||||||
|
resources: resources
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -688,7 +775,6 @@ function convertToCallTree(samples, isReverse) {
|
|||||||
function areSamplesMultiroot(samples) {
|
function areSamplesMultiroot(samples) {
|
||||||
var previousRoot;
|
var previousRoot;
|
||||||
for (var i = 0; i < samples.length; ++i) {
|
for (var i = 0; i < samples.length; ++i) {
|
||||||
if (!samples[i].frames) continue;
|
|
||||||
if (!previousRoot) {
|
if (!previousRoot) {
|
||||||
previousRoot = samples[i].frames[0];
|
previousRoot = samples[i].frames[0];
|
||||||
continue;
|
continue;
|
||||||
@ -706,8 +792,6 @@ function convertToCallTree(samples, isReverse) {
|
|||||||
return new TreeNode("(empty)", null, 0);
|
return new TreeNode("(empty)", null, 0);
|
||||||
var firstRoot = null;
|
var firstRoot = null;
|
||||||
for (var i = 0; i < samples.length; ++i) {
|
for (var i = 0; i < samples.length; ++i) {
|
||||||
if (!samples[i].frames) continue;
|
|
||||||
sendError(null, "got root: " + samples[i].frames[0]);
|
|
||||||
firstRoot = samples[i].frames[0];
|
firstRoot = samples[i].frames[0];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -718,9 +802,6 @@ function convertToCallTree(samples, isReverse) {
|
|||||||
var treeRoot = new TreeNode((isReverse || multiRoot) ? "(total)" : firstRoot, null, 0);
|
var treeRoot = new TreeNode((isReverse || multiRoot) ? "(total)" : firstRoot, null, 0);
|
||||||
for (var i = 0; i < samples.length; ++i) {
|
for (var i = 0; i < samples.length; ++i) {
|
||||||
var sample = samples[i];
|
var sample = samples[i];
|
||||||
if (!sample.frames) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var callstack = sample.frames.slice(0);
|
var callstack = sample.frames.slice(0);
|
||||||
callstack.shift();
|
callstack.shift();
|
||||||
if (isReverse)
|
if (isReverse)
|
||||||
@ -764,69 +845,73 @@ function filterBySymbol(samples, symbolOrFunctionIndex) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterByCallstackPrefix(samples, callstack) {
|
function filterByCallstackPrefix(samples, symbols, functions, callstack, appliesToJS, useFunctions) {
|
||||||
return samples.map(function filterSample(origSample) {
|
var isJSFrameOrRoot = useFunctions ? function isJSFunctionOrRoot(functionIndex) {
|
||||||
if (!origSample)
|
return (functionIndex in functions) && (functions[functionIndex].isJSFrame || functions[functionIndex].isRoot);
|
||||||
|
} : function isJSSymbolOrRoot(symbolIndex) {
|
||||||
|
return (symbolIndex in symbols) && (symbols[symbolIndex].isJSFrame || symbols[symbolIndex].isRoot);
|
||||||
|
};
|
||||||
|
return samples.map(function filterSample(sample) {
|
||||||
|
if (!sample)
|
||||||
return null;
|
return null;
|
||||||
if (origSample.frames.length < callstack.length)
|
if (sample.frames.length < callstack.length)
|
||||||
return null;
|
return null;
|
||||||
var sample = cloneSample(origSample);
|
for (var i = 0, j = 0; j < callstack.length; i++) {
|
||||||
for (var i = 0; i < callstack.length; i++) {
|
if (i >= sample.frames.length)
|
||||||
if (sample.frames[i] != callstack[i])
|
|
||||||
return null;
|
return null;
|
||||||
|
if (appliesToJS && !isJSFrameOrRoot(sample.frames[i]))
|
||||||
|
continue;
|
||||||
|
if (sample.frames[i] != callstack[j])
|
||||||
|
return null;
|
||||||
|
j++;
|
||||||
}
|
}
|
||||||
sample.frames = sample.frames.slice(callstack.length - 1);
|
return makeSample(sample.frames.slice(i - 1), sample.extraInfo);
|
||||||
return sample;
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function filterByCallstackPostfix(samples, callstack) {
|
function filterByCallstackPostfix(samples, symbols, functions, callstack, appliesToJS, useFunctions) {
|
||||||
return samples.map(function filterSample(origSample) {
|
var isJSFrameOrRoot = useFunctions ? function isJSFunctionOrRoot(functionIndex) {
|
||||||
if (!origSample)
|
return (functionIndex in functions) && (functions[functionIndex].isJSFrame || functions[functionIndex].isRoot);
|
||||||
|
} : function isJSSymbolOrRoot(symbolIndex) {
|
||||||
|
return (symbolIndex in symbols) && (symbols[symbolIndex].isJSFrame || symbols[symbolIndex].isRoot);
|
||||||
|
};
|
||||||
|
return samples.map(function filterSample(sample) {
|
||||||
|
if (!sample)
|
||||||
return null;
|
return null;
|
||||||
if (origSample.frames.length < callstack.length)
|
if (sample.frames.length < callstack.length)
|
||||||
return null;
|
return null;
|
||||||
var sample = cloneSample(origSample);
|
for (var i = 0, j = 0; j < callstack.length; i++) {
|
||||||
for (var i = 0; i < callstack.length; i++) {
|
if (i >= sample.frames.length)
|
||||||
if (sample.frames[sample.frames.length - i - 1] != callstack[i])
|
|
||||||
return null;
|
return null;
|
||||||
|
if (appliesToJS && !isJSFrameOrRoot(sample.frames[sample.frames.length - i - 1]))
|
||||||
|
continue;
|
||||||
|
if (sample.frames[sample.frames.length - i - 1] != callstack[j])
|
||||||
|
return null;
|
||||||
|
j++;
|
||||||
}
|
}
|
||||||
sample.frames = sample.frames.slice(0, sample.frames.length - callstack.length + 1);
|
var newFrames = sample.frames.slice(0, sample.frames.length - i + 1);
|
||||||
return sample;
|
return makeSample(newFrames, sample.extraInfo);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function chargeNonJSToCallers(samples, symbols, functions, useFunctions) {
|
function chargeNonJSToCallers(samples, symbols, functions, useFunctions) {
|
||||||
function isJSFrame(index, useFunction) {
|
var isJSFrameOrRoot = useFunctions ? function isJSFunctionOrRoot(functionIndex) {
|
||||||
if (useFunctions) {
|
return (functionIndex in functions) && (functions[functionIndex].isJSFrame || functions[functionIndex].isRoot);
|
||||||
if (!(index in functions))
|
} : function isJSSymbolOrRoot(symbolIndex) {
|
||||||
return "";
|
return (symbolIndex in symbols) && (symbols[symbolIndex].isJSFrame || symbols[symbolIndex].isRoot);
|
||||||
return functions[index].isJSFrame;
|
};
|
||||||
}
|
|
||||||
if (!(index in symbols))
|
|
||||||
return "";
|
|
||||||
return symbols[index].isJSFrame;
|
|
||||||
}
|
|
||||||
samples = samples.slice(0);
|
samples = samples.slice(0);
|
||||||
for (var i = 0; i < samples.length; ++i) {
|
for (var i = 0; i < samples.length; ++i) {
|
||||||
var sample = samples[i];
|
var sample = samples[i];
|
||||||
if (!sample)
|
if (!sample)
|
||||||
continue;
|
continue;
|
||||||
var callstack = sample.frames;
|
var newFrames = sample.frames.filter(isJSFrameOrRoot);
|
||||||
var newFrames = [];
|
|
||||||
for (var j = 0; j < callstack.length; ++j) {
|
|
||||||
if (isJSFrame(callstack[j], useFunctions)) {
|
|
||||||
// Record Javascript frames
|
|
||||||
newFrames.push(callstack[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!newFrames.length) {
|
if (!newFrames.length) {
|
||||||
newFrames = null;
|
samples[i] = null;
|
||||||
} else {
|
} else {
|
||||||
newFrames.splice(0, 0, "(total)");
|
|
||||||
}
|
|
||||||
samples[i].frames = newFrames;
|
samples[i].frames = newFrames;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return samples;
|
return samples;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -912,26 +997,28 @@ function FocusedFrameSampleFilter(focusedSymbol) {
|
|||||||
this._focusedSymbol = focusedSymbol;
|
this._focusedSymbol = focusedSymbol;
|
||||||
}
|
}
|
||||||
FocusedFrameSampleFilter.prototype = {
|
FocusedFrameSampleFilter.prototype = {
|
||||||
filter: function FocusedFrameSampleFilter_filter(samples, symbols, functions) {
|
filter: function FocusedFrameSampleFilter_filter(samples, symbols, functions, useFunctions) {
|
||||||
return filterBySymbol(samples, this._focusedSymbol);
|
return filterBySymbol(samples, this._focusedSymbol);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function FocusedCallstackPrefixSampleFilter(focusedCallstack) {
|
function FocusedCallstackPrefixSampleFilter(focusedCallstack, appliesToJS) {
|
||||||
this._focusedCallstackPrefix = focusedCallstack;
|
this._focusedCallstackPrefix = focusedCallstack;
|
||||||
|
this._appliesToJS = appliesToJS;
|
||||||
}
|
}
|
||||||
FocusedCallstackPrefixSampleFilter.prototype = {
|
FocusedCallstackPrefixSampleFilter.prototype = {
|
||||||
filter: function FocusedCallstackPrefixSampleFilter_filter(samples, symbols, functions) {
|
filter: function FocusedCallstackPrefixSampleFilter_filter(samples, symbols, functions, useFunctions) {
|
||||||
return filterByCallstackPrefix(samples, this._focusedCallstackPrefix);
|
return filterByCallstackPrefix(samples, symbols, functions, this._focusedCallstackPrefix, this._appliesToJS, useFunctions);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function FocusedCallstackPostfixSampleFilter(focusedCallstack) {
|
function FocusedCallstackPostfixSampleFilter(focusedCallstack, appliesToJS) {
|
||||||
this._focusedCallstackPostfix = focusedCallstack;
|
this._focusedCallstackPostfix = focusedCallstack;
|
||||||
|
this._appliesToJS = appliesToJS;
|
||||||
}
|
}
|
||||||
FocusedCallstackPostfixSampleFilter.prototype = {
|
FocusedCallstackPostfixSampleFilter.prototype = {
|
||||||
filter: function FocusedCallstackPostfixSampleFilter_filter(samples, symbols, functions) {
|
filter: function FocusedCallstackPostfixSampleFilter_filter(samples, symbols, functions, useFunctions) {
|
||||||
return filterByCallstackPostfix(samples, this._focusedCallstackPostfix);
|
return filterByCallstackPostfix(samples, symbols, functions, this._focusedCallstackPostfix, this._appliesToJS, useFunctions);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -951,9 +1038,9 @@ function unserializeSampleFilters(filters) {
|
|||||||
case "FocusedFrameSampleFilter":
|
case "FocusedFrameSampleFilter":
|
||||||
return new FocusedFrameSampleFilter(filter.focusedSymbol);
|
return new FocusedFrameSampleFilter(filter.focusedSymbol);
|
||||||
case "FocusedCallstackPrefixSampleFilter":
|
case "FocusedCallstackPrefixSampleFilter":
|
||||||
return new FocusedCallstackPrefixSampleFilter(filter.focusedCallstack);
|
return new FocusedCallstackPrefixSampleFilter(filter.focusedCallstack, filter.appliesToJS);
|
||||||
case "FocusedCallstackPostfixSampleFilter":
|
case "FocusedCallstackPostfixSampleFilter":
|
||||||
return new FocusedCallstackPostfixSampleFilter(filter.focusedCallstack);
|
return new FocusedCallstackPostfixSampleFilter(filter.focusedCallstack, filter.appliesToJS);
|
||||||
case "RangeSampleFilter":
|
case "RangeSampleFilter":
|
||||||
return new RangeSampleFilter(filter.start, filter.end);
|
return new RangeSampleFilter(filter.start, filter.end);
|
||||||
case "PluginView":
|
case "PluginView":
|
||||||
@ -975,14 +1062,6 @@ function updateFilters(requestID, profileID, filters) {
|
|||||||
if (filters.mergeFunctions) {
|
if (filters.mergeFunctions) {
|
||||||
samples = discardLineLevelInformation(samples, symbols, functions);
|
samples = discardLineLevelInformation(samples, symbols, functions);
|
||||||
}
|
}
|
||||||
if (filters.javascriptOnly) {
|
|
||||||
try {
|
|
||||||
//samples = filterByName(samples, symbols, functions, "runScript", filters.mergeFunctions);
|
|
||||||
samples = chargeNonJSToCallers(samples, symbols, functions, filters.mergeFunctions);
|
|
||||||
} catch (e) {
|
|
||||||
dump("Could not filer by javascript: " + e + "\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (filters.nameFilter) {
|
if (filters.nameFilter) {
|
||||||
try {
|
try {
|
||||||
samples = filterByName(samples, symbols, functions, filters.nameFilter, filters.mergeFunctions);
|
samples = filterByName(samples, symbols, functions, filters.nameFilter, filters.mergeFunctions);
|
||||||
@ -992,16 +1071,19 @@ function updateFilters(requestID, profileID, filters) {
|
|||||||
}
|
}
|
||||||
samples = unserializeSampleFilters(filters.sampleFilters).reduce(function (filteredSamples, currentFilter) {
|
samples = unserializeSampleFilters(filters.sampleFilters).reduce(function (filteredSamples, currentFilter) {
|
||||||
if (currentFilter===null) return filteredSamples;
|
if (currentFilter===null) return filteredSamples;
|
||||||
return currentFilter.filter(filteredSamples, symbols, functions);
|
return currentFilter.filter(filteredSamples, symbols, functions, filters.mergeFunctions);
|
||||||
}, samples);
|
}, samples);
|
||||||
if (filters.jankOnly) {
|
if (filters.jankOnly) {
|
||||||
samples = filterByJank(samples, gJankThreshold);
|
samples = filterByJank(samples, gJankThreshold);
|
||||||
}
|
}
|
||||||
|
if (filters.javascriptOnly) {
|
||||||
|
samples = chargeNonJSToCallers(samples, symbols, functions, filters.mergeFunctions);
|
||||||
|
}
|
||||||
|
|
||||||
gProfiles[profileID].filterSettings = filters;
|
gProfiles[profileID].filterSettings = filters;
|
||||||
gProfiles[profileID].filteredSamples = samples;
|
gProfiles[profileID].filteredSamples = samples;
|
||||||
sendFinishedInChunks(requestID, samples, 40000,
|
sendFinishedInChunks(requestID, samples, 40000,
|
||||||
function (sample) { return (sample && sample.frames) ? sample.frames.length : 1; });
|
function (sample) { return sample ? sample.frames.length : 1; });
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateViewOptions(requestID, profileID, options) {
|
function updateViewOptions(requestID, profileID, options) {
|
||||||
@ -1039,7 +1121,7 @@ function calculateHistogramData(requestID, profileID) {
|
|||||||
for (var i = 0; i < data.length; ++i) {
|
for (var i = 0; i < data.length; ++i) {
|
||||||
if (!data[i])
|
if (!data[i])
|
||||||
continue;
|
continue;
|
||||||
var value = data[i].frames ? data[i].frames.length : 0;
|
var value = data[i].frames.length;
|
||||||
if (maxHeight < value)
|
if (maxHeight < value)
|
||||||
maxHeight = value;
|
maxHeight = value;
|
||||||
}
|
}
|
||||||
@ -1053,7 +1135,7 @@ function calculateHistogramData(requestID, profileID) {
|
|||||||
var frameStart = {};
|
var frameStart = {};
|
||||||
for (var i = 0; i < data.length; i++) {
|
for (var i = 0; i < data.length; i++) {
|
||||||
var step = data[i];
|
var step = data[i];
|
||||||
if (!step || !step.frames) {
|
if (!step) {
|
||||||
// Add a gap for the sample that was filtered out.
|
// Add a gap for the sample that was filtered out.
|
||||||
nextX += 1 / samplesPerStep;
|
nextX += 1 / samplesPerStep;
|
||||||
continue;
|
continue;
|
||||||
@ -1139,6 +1221,26 @@ var diagnosticList = [
|
|||||||
;
|
;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
image: "cache.png",
|
||||||
|
title: "Bug 717761 - Main thread can be blocked by IO on the cache thread",
|
||||||
|
bugNumber: "717761",
|
||||||
|
check: function(frames, symbols, meta) {
|
||||||
|
|
||||||
|
return stepContains('nsCacheEntryDescriptor::GetStoragePolicy', frames, symbols)
|
||||||
|
;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
image: "js.png",
|
||||||
|
title: "Web Content Shutdown Notification",
|
||||||
|
check: function(frames, symbols, meta) {
|
||||||
|
|
||||||
|
return stepContains('nsAppStartup::Quit', frames, symbols)
|
||||||
|
&& stepContains('nsDocShell::FirePageHideNotification', frames, symbols)
|
||||||
|
;
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
image: "js.png",
|
image: "js.png",
|
||||||
title: "Bug 789193 - AMI_startup() takes 200ms on startup",
|
title: "Bug 789193 - AMI_startup() takes 200ms on startup",
|
||||||
@ -1149,6 +1251,44 @@ var diagnosticList = [
|
|||||||
;
|
;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
image: "js.png",
|
||||||
|
title: "Bug 818296 - [Shutdown] js::NukeCrossCompartmentWrappers takes up 300ms on shutdown",
|
||||||
|
bugNumber: "818296",
|
||||||
|
check: function(frames, symbols, meta) {
|
||||||
|
return stepContains('js::NukeCrossCompartmentWrappers', frames, symbols)
|
||||||
|
&& (stepContains('WindowDestroyedEvent', frames, symbols) || stepContains('DoShutdown', frames, symbols))
|
||||||
|
;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
image: "js.png",
|
||||||
|
title: "Bug 818274 - [Shutdown] Telemetry takes ~10ms on shutdown",
|
||||||
|
bugNumber: "818274",
|
||||||
|
check: function(frames, symbols, meta) {
|
||||||
|
return stepContains('TelemetryPing.js', frames, symbols)
|
||||||
|
;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
image: "plugin.png",
|
||||||
|
title: "Bug 818265 - [Shutdown] Plug-in shutdown takes ~90ms on shutdown",
|
||||||
|
bugNumber: "818265",
|
||||||
|
check: function(frames, symbols, meta) {
|
||||||
|
return stepContains('PluginInstanceParent::Destroy', frames, symbols)
|
||||||
|
;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
image: "snapshot.png",
|
||||||
|
title: "Bug 720575 - Make thumbnailing faster and/or asynchronous",
|
||||||
|
bugNumber: "720575",
|
||||||
|
check: function(frames, symbols, meta) {
|
||||||
|
return stepContains('Thumbnails_capture()', frames, symbols)
|
||||||
|
;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
image: "js.png",
|
image: "js.png",
|
||||||
title: "Bug 789185 - LoginManagerStorage_mozStorage.init() takes 300ms on startup ",
|
title: "Bug 789185 - LoginManagerStorage_mozStorage.init() takes 300ms on startup ",
|
||||||
@ -1238,7 +1378,6 @@ var diagnosticList = [
|
|||||||
var ccEvent = findCCEvent(frames, symbols, meta, step);
|
var ccEvent = findCCEvent(frames, symbols, meta, step);
|
||||||
|
|
||||||
if (ccEvent) {
|
if (ccEvent) {
|
||||||
dump("Found\n");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1268,10 +1407,21 @@ var diagnosticList = [
|
|||||||
check: function(frames, symbols, meta) {
|
check: function(frames, symbols, meta) {
|
||||||
return stepContainsRegEx(/.*Collect.*Runtime.*Invocation.*/, frames, symbols)
|
return stepContainsRegEx(/.*Collect.*Runtime.*Invocation.*/, frames, symbols)
|
||||||
|| stepContains('GarbageCollectNow', frames, symbols) // Label
|
|| stepContains('GarbageCollectNow', frames, symbols) // Label
|
||||||
|
|| stepContains('JS_GC(', frames, symbols) // Label
|
||||||
|| stepContains('CycleCollect__', frames, symbols) // Label
|
|| stepContains('CycleCollect__', frames, symbols) // Label
|
||||||
;
|
;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
image: "cc.png",
|
||||||
|
title: "Cycle Collect",
|
||||||
|
check: function(frames, symbols, meta) {
|
||||||
|
return stepContains('nsCycleCollector::Collect', frames, symbols)
|
||||||
|
|| stepContains('CycleCollect__', frames, symbols) // Label
|
||||||
|
|| stepContains('nsCycleCollectorRunner::Collect', frames, symbols) // Label
|
||||||
|
;
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
image: "plugin.png",
|
image: "plugin.png",
|
||||||
title: "Sync Plugin Constructor",
|
title: "Sync Plugin Constructor",
|
||||||
@ -1296,6 +1446,7 @@ var diagnosticList = [
|
|||||||
check: function(frames, symbols, meta) {
|
check: function(frames, symbols, meta) {
|
||||||
return stepContains('__getdirentries64', frames, symbols)
|
return stepContains('__getdirentries64', frames, symbols)
|
||||||
|| stepContains('__open', frames, symbols)
|
|| stepContains('__open', frames, symbols)
|
||||||
|
|| stepContains('NtFlushBuffersFile', frames, symbols)
|
||||||
|| stepContains('storage:::Statement::ExecuteStep', frames, symbols)
|
|| stepContains('storage:::Statement::ExecuteStep', frames, symbols)
|
||||||
|| stepContains('__unlink', frames, symbols)
|
|| stepContains('__unlink', frames, symbols)
|
||||||
|| stepContains('fsync', frames, symbols)
|
|| stepContains('fsync', frames, symbols)
|
||||||
@ -1371,6 +1522,8 @@ function findGCSlice(frames, symbols, meta, step) {
|
|||||||
}
|
}
|
||||||
function stepContains(substring, frames, symbols) {
|
function stepContains(substring, frames, symbols) {
|
||||||
for (var i = 0; frames && i < frames.length; i++) {
|
for (var i = 0; frames && i < frames.length; i++) {
|
||||||
|
if (!(frames[i] in symbols))
|
||||||
|
continue;
|
||||||
var frameSym = symbols[frames[i]].functionName || symbols[frames[i]].symbolName;
|
var frameSym = symbols[frames[i]].functionName || symbols[frames[i]].symbolName;
|
||||||
if (frameSym.indexOf(substring) != -1) {
|
if (frameSym.indexOf(substring) != -1) {
|
||||||
return true;
|
return true;
|
||||||
@ -1380,6 +1533,8 @@ function stepContains(substring, frames, symbols) {
|
|||||||
}
|
}
|
||||||
function stepContainsRegEx(regex, frames, symbols) {
|
function stepContainsRegEx(regex, frames, symbols) {
|
||||||
for (var i = 0; frames && i < frames.length; i++) {
|
for (var i = 0; frames && i < frames.length; i++) {
|
||||||
|
if (!(frames[i] in symbols))
|
||||||
|
continue;
|
||||||
var frameSym = symbols[frames[i]].functionName || symbols[frames[i]].symbolName;
|
var frameSym = symbols[frames[i]].functionName || symbols[frames[i]].symbolName;
|
||||||
if (regex.exec(frameSym)) {
|
if (regex.exec(frameSym)) {
|
||||||
return true;
|
return true;
|
||||||
@ -1390,6 +1545,8 @@ function stepContainsRegEx(regex, frames, symbols) {
|
|||||||
function symbolSequence(symbolsOrder, frames, symbols) {
|
function symbolSequence(symbolsOrder, frames, symbols) {
|
||||||
var symbolIndex = 0;
|
var symbolIndex = 0;
|
||||||
for (var i = 0; frames && i < frames.length; i++) {
|
for (var i = 0; frames && i < frames.length; i++) {
|
||||||
|
if (!(frames[i] in symbols))
|
||||||
|
continue;
|
||||||
var frameSym = symbols[frames[i]].functionName || symbols[frames[i]].symbolName;
|
var frameSym = symbols[frames[i]].functionName || symbols[frames[i]].symbolName;
|
||||||
var substring = symbolsOrder[symbolIndex];
|
var substring = symbolsOrder[symbolIndex];
|
||||||
if (frameSym.indexOf(substring) != -1) {
|
if (frameSym.indexOf(substring) != -1) {
|
||||||
@ -1458,14 +1615,13 @@ function calculateDiagnosticItems(requestID, profileID, meta) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
data.forEach(function diagnoseStep(step, x) {
|
data.forEach(function diagnoseStep(step, x) {
|
||||||
if (!step)
|
if (step) {
|
||||||
return;
|
|
||||||
|
|
||||||
var frames = step.frames;
|
var frames = step.frames;
|
||||||
|
|
||||||
var diagnostic = firstMatch(diagnosticList, function (diagnostic) {
|
var diagnostic = firstMatch(diagnosticList, function (diagnostic) {
|
||||||
return diagnostic.check(frames, symbols, meta, step);
|
return diagnostic.check(frames, symbols, meta, step);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (!diagnostic) {
|
if (!diagnostic) {
|
||||||
finishPendingDiagnostic(x);
|
finishPendingDiagnostic(x);
|
||||||
|
@ -20,24 +20,20 @@ RegExp.escape = function(text) {
|
|||||||
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
|
||||||
}
|
}
|
||||||
|
|
||||||
var requestAnimationFrame_timeout = null;
|
|
||||||
var requestAnimationFrame = window.webkitRequestAnimationFrame ||
|
var requestAnimationFrame = window.webkitRequestAnimationFrame ||
|
||||||
window.mozRequestAnimationFrame ||
|
window.mozRequestAnimationFrame ||
|
||||||
window.oRequestAnimationFrame ||
|
window.oRequestAnimationFrame ||
|
||||||
window.msRequestAnimationFrame ||
|
window.msRequestAnimationFrame ||
|
||||||
function(callback, element) {
|
function(callback, element) {
|
||||||
window.setTimeout(callback, 1000 / 60);
|
return window.setTimeout(callback, 1000 / 60);
|
||||||
};
|
};
|
||||||
|
|
||||||
var cancelAnimationFrame = window.webkitCancelAnimationFrame ||
|
var cancelAnimationFrame = window.webkitCancelAnimationFrame ||
|
||||||
window.mozCancelAnimationFrame ||
|
window.mozCancelAnimationFrame ||
|
||||||
window.oCancelAnimationFrame ||
|
window.oCancelAnimationFrame ||
|
||||||
window.msCancelAnimationFrame ||
|
window.msCancelAnimationFrame ||
|
||||||
function(callback, element) {
|
function(req) {
|
||||||
if (requestAnimationFrame_timeout) {
|
window.clearTimeout(req);
|
||||||
window.clearTimeout(requestAnimationFrame_timeout);
|
|
||||||
requestAnimationFrame_timeout = null;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
function TreeView() {
|
function TreeView() {
|
||||||
@ -65,6 +61,10 @@ function TreeView() {
|
|||||||
this._horizontalScrollbox.className = "treeViewHorizontalScrollbox";
|
this._horizontalScrollbox.className = "treeViewHorizontalScrollbox";
|
||||||
this._verticalScrollbox.appendChild(this._horizontalScrollbox);
|
this._verticalScrollbox.appendChild(this._horizontalScrollbox);
|
||||||
|
|
||||||
|
this._styleElement = document.createElement("style");
|
||||||
|
this._styleElement.setAttribute("type", "text/css");
|
||||||
|
this._container.appendChild(this._styleElement);
|
||||||
|
|
||||||
this._contextMenu = document.createElement("menu");
|
this._contextMenu = document.createElement("menu");
|
||||||
this._contextMenu.setAttribute("type", "context");
|
this._contextMenu.setAttribute("type", "context");
|
||||||
this._contextMenu.id = "contextMenuForTreeView" + TreeView.instanceCounter++;
|
this._contextMenu.id = "contextMenuForTreeView" + TreeView.instanceCounter++;
|
||||||
@ -74,11 +74,17 @@ function TreeView() {
|
|||||||
this._busyCover.className = "busyCover";
|
this._busyCover.className = "busyCover";
|
||||||
this._container.appendChild(this._busyCover);
|
this._container.appendChild(this._busyCover);
|
||||||
this._abortToggleAll = false;
|
this._abortToggleAll = false;
|
||||||
|
this.initSelection = true;
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this._container.onkeydown = function (e) {
|
this._container.onkeydown = function (e) {
|
||||||
self._onkeypress(e);
|
self._onkeypress(e);
|
||||||
};
|
};
|
||||||
|
this._container.onkeypress = function (e) {
|
||||||
|
// on key down gives us '8' and mapping shift+8='*' may not be portable.
|
||||||
|
if (String.fromCharCode(e.charCode) == '*')
|
||||||
|
self._onkeypress(e);
|
||||||
|
};
|
||||||
this._container.onclick = function (e) {
|
this._container.onclick = function (e) {
|
||||||
self._onclick(e);
|
self._onclick(e);
|
||||||
};
|
};
|
||||||
@ -106,9 +112,11 @@ TreeView.prototype = {
|
|||||||
dataIsOutdated: function TreeView_dataIsOutdated() {
|
dataIsOutdated: function TreeView_dataIsOutdated() {
|
||||||
this._busyCover.classList.add("busy");
|
this._busyCover.classList.add("busy");
|
||||||
},
|
},
|
||||||
display: function TreeView_display(data, filterByName) {
|
display: function TreeView_display(data, resources, filterByName) {
|
||||||
this._busyCover.classList.remove("busy");
|
this._busyCover.classList.remove("busy");
|
||||||
this._filterByName = filterByName;
|
this._filterByName = filterByName;
|
||||||
|
this._resources = resources;
|
||||||
|
this._addResourceIconStyles();
|
||||||
this._filterByNameReg = null; // lazy init
|
this._filterByNameReg = null; // lazy init
|
||||||
if (this._filterByName === "")
|
if (this._filterByName === "")
|
||||||
this._filterByName = null;
|
this._filterByName = null;
|
||||||
@ -126,9 +134,12 @@ TreeView.prototype = {
|
|||||||
data: data[0].getData()
|
data: data[0].getData()
|
||||||
});
|
});
|
||||||
this._processPendingActionsChunk();
|
this._processPendingActionsChunk();
|
||||||
|
if (this._initSelection === true) {
|
||||||
|
this._initSelection = false;
|
||||||
this._select(this._horizontalScrollbox.firstChild);
|
this._select(this._horizontalScrollbox.firstChild);
|
||||||
this._toggle(this._horizontalScrollbox.firstChild);
|
this._toggle(this._horizontalScrollbox.firstChild);
|
||||||
this._container.focus();
|
}
|
||||||
|
changeFocus(this._container);
|
||||||
},
|
},
|
||||||
// Provide a snapshot of the reverse selection to restore with 'invert callback'
|
// Provide a snapshot of the reverse selection to restore with 'invert callback'
|
||||||
getReverseSelectionSnapshot: function TreeView__getReverseSelectionSnapshot(isJavascriptOnly) {
|
getReverseSelectionSnapshot: function TreeView__getReverseSelectionSnapshot(isJavascriptOnly) {
|
||||||
@ -142,8 +153,8 @@ TreeView.prototype = {
|
|||||||
snapshot.push(curr.name);
|
snapshot.push(curr.name);
|
||||||
//dump(JSON.stringify(curr.name) + "\n");
|
//dump(JSON.stringify(curr.name) + "\n");
|
||||||
}
|
}
|
||||||
if (curr.children && curr.children.length >= 1) {
|
if (curr.treeChildren && curr.treeChildren.length >= 1) {
|
||||||
curr = curr.children[0].getData();
|
curr = curr.treeChildren[0].getData();
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -171,6 +182,7 @@ TreeView.prototype = {
|
|||||||
},
|
},
|
||||||
// Take a selection snapshot and restore the selection
|
// Take a selection snapshot and restore the selection
|
||||||
restoreSelectionSnapshot: function TreeView_restoreSelectionSnapshot(snapshot, allowNonContigious) {
|
restoreSelectionSnapshot: function TreeView_restoreSelectionSnapshot(snapshot, allowNonContigious) {
|
||||||
|
//console.log("restore selection: " + JSON.stringify(snapshot));
|
||||||
var currNode = this._horizontalScrollbox.firstChild;
|
var currNode = this._horizontalScrollbox.firstChild;
|
||||||
if (currNode.data.name == snapshot[0] || snapshot[0] == "(total)") {
|
if (currNode.data.name == snapshot[0] || snapshot[0] == "(total)") {
|
||||||
snapshot.shift();
|
snapshot.shift();
|
||||||
@ -181,7 +193,7 @@ TreeView.prototype = {
|
|||||||
this._syncProcessPendingActionProcessing();
|
this._syncProcessPendingActionProcessing();
|
||||||
for (var i = 0; i < currNode.treeChildren.length; i++) {
|
for (var i = 0; i < currNode.treeChildren.length; i++) {
|
||||||
if (currNode.treeChildren[i].data.name == snapshot[0]) {
|
if (currNode.treeChildren[i].data.name == snapshot[0]) {
|
||||||
//dump("Found: " + currNode.treeChildren[i].data.name + "\n");
|
//console.log("Found: " + currNode.treeChildren[i].data.name + "\n");
|
||||||
snapshot.shift();
|
snapshot.shift();
|
||||||
this._toggle(currNode, false, true);
|
this._toggle(currNode, false, true);
|
||||||
currNode = currNode.treeChildren[i];
|
currNode = currNode.treeChildren[i];
|
||||||
@ -193,11 +205,11 @@ TreeView.prototype = {
|
|||||||
var pendingSearch = [currNode.data];
|
var pendingSearch = [currNode.data];
|
||||||
while (pendingSearch.length > 0) {
|
while (pendingSearch.length > 0) {
|
||||||
var node = pendingSearch.shift();
|
var node = pendingSearch.shift();
|
||||||
//dump("searching: " + node.name + " for: " + snapshot[0] + "\n");
|
//console.log("searching: " + node.name + " for: " + snapshot[0] + "\n");
|
||||||
if (!node.children)
|
if (!node.treeChildren)
|
||||||
continue;
|
continue;
|
||||||
for (var i = 0; i < node.children.length; i++) {
|
for (var i = 0; i < node.treeChildren.length; i++) {
|
||||||
var childNode = node.children[i].getData();
|
var childNode = node.treeChildren[i].getData();
|
||||||
if (childNode.name == snapshot[0]) {
|
if (childNode.name == snapshot[0]) {
|
||||||
//dump("found: " + childNode.name + "\n");
|
//dump("found: " + childNode.name + "\n");
|
||||||
snapshot.shift();
|
snapshot.shift();
|
||||||
@ -317,7 +329,13 @@ TreeView.prototype = {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
_scrollHeightChanged: function TreeView__scrollHeightChanged() {
|
_scrollHeightChanged: function TreeView__scrollHeightChanged() {
|
||||||
this._leftColumnBackground.style.height = this._horizontalScrollbox.getBoundingClientRect().height + 'px';
|
if (!this._pendingScrollHeightChanged) {
|
||||||
|
var self = this;
|
||||||
|
this._pendingScrollHeightChanged = setTimeout(function() {
|
||||||
|
self._leftColumnBackground.style.height = self._horizontalScrollbox.getBoundingClientRect().height + 'px';
|
||||||
|
self._pendingScrollHeightChanged = null;
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
_createTree: function TreeView__createTree(parentElement, parentNode, data) {
|
_createTree: function TreeView__createTree(parentElement, parentNode, data) {
|
||||||
var div = document.createElement("div");
|
var div = document.createElement("div");
|
||||||
@ -328,27 +346,49 @@ TreeView.prototype = {
|
|||||||
var treeLine = document.createElement("div");
|
var treeLine = document.createElement("div");
|
||||||
treeLine.className = "treeLine";
|
treeLine.className = "treeLine";
|
||||||
treeLine.innerHTML = this._HTMLForFunction(data);
|
treeLine.innerHTML = this._HTMLForFunction(data);
|
||||||
|
div.depth = parentNode ? parentNode.depth + 1 : 0;
|
||||||
|
div.style.marginLeft = div.depth + "em";
|
||||||
// When this item is toggled we will expand its children
|
// When this item is toggled we will expand its children
|
||||||
div.pendingExpand = [];
|
div.pendingExpand = [];
|
||||||
div.treeLine = treeLine;
|
div.treeLine = treeLine;
|
||||||
div.data = data;
|
div.data = data;
|
||||||
|
// Useful for debugging
|
||||||
|
//this.uniqueID = this.uniqueID || 0;
|
||||||
|
//div.id = "Node" + this.uniqueID++;
|
||||||
div.appendChild(treeLine);
|
div.appendChild(treeLine);
|
||||||
div.treeChildren = [];
|
div.treeChildren = [];
|
||||||
div.treeParent = parentNode;
|
div.treeParent = parentNode;
|
||||||
if (hasChildren) {
|
if (hasChildren) {
|
||||||
var parent = document.createElement("div");
|
|
||||||
parent.className = "treeViewNodeList";
|
|
||||||
for (var i = 0; i < data.children.length; ++i) {
|
for (var i = 0; i < data.children.length; ++i) {
|
||||||
div.pendingExpand.push({parentElement: parent, parentNode: div, data: data.children[i].getData() });
|
div.pendingExpand.push({parentElement: this._horizontalScrollbox, parentNode: div, data: data.children[i].getData() });
|
||||||
}
|
}
|
||||||
div.appendChild(parent);
|
|
||||||
}
|
}
|
||||||
if (parentNode) {
|
if (parentNode) {
|
||||||
parentNode.treeChildren.push(div);
|
parentNode.treeChildren.push(div);
|
||||||
}
|
}
|
||||||
|
if (parentNode != null) {
|
||||||
|
var nextTo;
|
||||||
|
if (parentNode.treeChildren.length > 1) {
|
||||||
|
nextTo = parentNode.treeChildren[parentNode.treeChildren.length-2].nextSibling;
|
||||||
|
} else {
|
||||||
|
nextTo = parentNode.nextSibling;
|
||||||
|
}
|
||||||
|
parentElement.insertBefore(div, nextTo);
|
||||||
|
} else {
|
||||||
parentElement.appendChild(div);
|
parentElement.appendChild(div);
|
||||||
|
}
|
||||||
return div;
|
return div;
|
||||||
},
|
},
|
||||||
|
_addResourceIconStyles: function TreeView__addResourceIconStyles() {
|
||||||
|
var styles = [];
|
||||||
|
for (var resourceName in this._resources) {
|
||||||
|
var resource = this._resources[resourceName];
|
||||||
|
if (resource.icon) {
|
||||||
|
styles.push('.resourceIcon[data-resource="' + resourceName + '"] { background-image: url("' + resource.icon + '"); }');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this._styleElement.textContent = styles.join("\n");
|
||||||
|
},
|
||||||
_populateContextMenu: function TreeView__populateContextMenu(event) {
|
_populateContextMenu: function TreeView__populateContextMenu(event) {
|
||||||
this._verticalScrollbox.setAttribute("contextmenu", "");
|
this._verticalScrollbox.setAttribute("contextmenu", "");
|
||||||
|
|
||||||
@ -385,9 +425,9 @@ TreeView.prototype = {
|
|||||||
_contextMenuForFunction: function TreeView__contextMenuForFunction(node) {
|
_contextMenuForFunction: function TreeView__contextMenuForFunction(node) {
|
||||||
// TODO move me outside tree.js
|
// TODO move me outside tree.js
|
||||||
var menu = [];
|
var menu = [];
|
||||||
if (node.library != null && (
|
if (node.library && (
|
||||||
node.library.toLowerCase() == "xul" ||
|
node.library.toLowerCase() == "lib_xul" ||
|
||||||
node.library.toLowerCase() == "xul.dll"
|
node.library.toLowerCase() == "lib_xul.dll"
|
||||||
)) {
|
)) {
|
||||||
menu.push("View Source");
|
menu.push("View Source");
|
||||||
}
|
}
|
||||||
@ -403,7 +443,8 @@ TreeView.prototype = {
|
|||||||
},
|
},
|
||||||
_HTMLForFunction: function TreeView__HTMLForFunction(node) {
|
_HTMLForFunction: function TreeView__HTMLForFunction(node) {
|
||||||
var nodeName = escapeHTML(node.name);
|
var nodeName = escapeHTML(node.name);
|
||||||
var libName = node.library;
|
var resource = this._resources[node.library] || {};
|
||||||
|
var libName = escapeHTML(resource.name || "");
|
||||||
if (this._filterByName) {
|
if (this._filterByName) {
|
||||||
if (!this._filterByNameReg) {
|
if (!this._filterByNameReg) {
|
||||||
this._filterByName = RegExp.escape(this._filterByName);
|
this._filterByName = RegExp.escape(this._filterByName);
|
||||||
@ -422,6 +463,7 @@ TreeView.prototype = {
|
|||||||
'<span class="sampleCount">' + node.counter + '</span> ' +
|
'<span class="sampleCount">' + node.counter + '</span> ' +
|
||||||
'<span class="samplePercentage">' + samplePercentage + '</span> ' +
|
'<span class="samplePercentage">' + samplePercentage + '</span> ' +
|
||||||
'<span class="selfSampleCount">' + node.selfCounter + '</span> ' +
|
'<span class="selfSampleCount">' + node.selfCounter + '</span> ' +
|
||||||
|
'<span class="resourceIcon" data-resource="' + node.library + '"></span> ' +
|
||||||
'<span class="functionName">' + nodeName + '</span>' +
|
'<span class="functionName">' + nodeName + '</span>' +
|
||||||
'<span class="libraryName">' + libName + '</span>' +
|
'<span class="libraryName">' + libName + '</span>' +
|
||||||
'<input type="button" value="Focus Callstack" title="Focus Callstack" class="focusCallstackButton" tabindex="-1">';
|
'<input type="button" value="Focus Callstack" title="Focus Callstack" class="focusCallstackButton" tabindex="-1">';
|
||||||
@ -434,15 +476,26 @@ TreeView.prototype = {
|
|||||||
this._schedulePendingActionProcessing();
|
this._schedulePendingActionProcessing();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
_showChild: function TreeView__showChild(div, isVisible) {
|
||||||
|
for (var i = 0; i < div.treeChildren.length; i++) {
|
||||||
|
div.treeChildren[i].style.display = isVisible?"":"none";
|
||||||
|
if (!isVisible) {
|
||||||
|
div.treeChildren[i].classList.add("collapsed");
|
||||||
|
this._showChild(div.treeChildren[i], isVisible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
_toggle: function TreeView__toggle(div, /* optional */ newCollapsedValue, /* optional */ suppressScrollHeightNotification) {
|
_toggle: function TreeView__toggle(div, /* optional */ newCollapsedValue, /* optional */ suppressScrollHeightNotification) {
|
||||||
var currentCollapsedValue = this._isCollapsed(div);
|
var currentCollapsedValue = this._isCollapsed(div);
|
||||||
if (newCollapsedValue === undefined)
|
if (newCollapsedValue === undefined)
|
||||||
newCollapsedValue = !currentCollapsedValue;
|
newCollapsedValue = !currentCollapsedValue;
|
||||||
if (newCollapsedValue) {
|
if (newCollapsedValue) {
|
||||||
div.classList.add("collapsed");
|
div.classList.add("collapsed");
|
||||||
|
this._showChild(div, false);
|
||||||
} else {
|
} else {
|
||||||
this._resolveChildren(div, true);
|
this._resolveChildren(div, true);
|
||||||
div.classList.remove("collapsed");
|
div.classList.remove("collapsed");
|
||||||
|
this._showChild(div, true);
|
||||||
}
|
}
|
||||||
if (!suppressScrollHeightNotification)
|
if (!suppressScrollHeightNotification)
|
||||||
this._scrollHeightChanged();
|
this._scrollHeightChanged();
|
||||||
@ -500,6 +553,19 @@ TreeView.prototype = {
|
|||||||
return this._getNextSib(div.treeParent);
|
return this._getNextSib(div.treeParent);
|
||||||
return div.treeParent.treeChildren[nodeIndex+1];
|
return div.treeParent.treeChildren[nodeIndex+1];
|
||||||
},
|
},
|
||||||
|
_scheduleScrollIntoView: function TreeView__scheduleScrollIntoView(element, maxImportantWidth) {
|
||||||
|
// Schedule this on the animation frame otherwise we may run this more then once per frames
|
||||||
|
// causing more work then needed.
|
||||||
|
var self = this;
|
||||||
|
if (self._pendingAnimationFrame != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self._pendingAnimationFrame = requestAnimationFrame(function anim_frame() {
|
||||||
|
cancelAnimationFrame(self._pendingAnimationFrame);
|
||||||
|
self._pendingAnimationFrame = null;
|
||||||
|
self._scrollIntoView(element, maxImportantWidth);
|
||||||
|
});
|
||||||
|
},
|
||||||
_scrollIntoView: function TreeView__scrollIntoView(element, maxImportantWidth) {
|
_scrollIntoView: function TreeView__scrollIntoView(element, maxImportantWidth) {
|
||||||
// Make sure that element is inside the visible part of our scrollbox by
|
// Make sure that element is inside the visible part of our scrollbox by
|
||||||
// adjusting the scroll positions. If element is wider or
|
// adjusting the scroll positions. If element is wider or
|
||||||
@ -541,9 +607,10 @@ TreeView.prototype = {
|
|||||||
li.treeLine.classList.add("selected");
|
li.treeLine.classList.add("selected");
|
||||||
this._selectedNode = li;
|
this._selectedNode = li;
|
||||||
var functionName = li.treeLine.querySelector(".functionName");
|
var functionName = li.treeLine.querySelector(".functionName");
|
||||||
this._scrollIntoView(functionName, 400);
|
this._scheduleScrollIntoView(functionName, 400);
|
||||||
this._fireEvent("select", li.data);
|
this._fireEvent("select", li.data);
|
||||||
}
|
}
|
||||||
|
updateDocumentURL();
|
||||||
},
|
},
|
||||||
_isCollapsed: function TreeView__isCollapsed(div) {
|
_isCollapsed: function TreeView__isCollapsed(div) {
|
||||||
return div.classList.contains("collapsed");
|
return div.classList.contains("collapsed");
|
||||||
@ -615,6 +682,7 @@ TreeView.prototype = {
|
|||||||
var isCollapsed = this._isCollapsed(selected);
|
var isCollapsed = this._isCollapsed(selected);
|
||||||
if (isCollapsed) {
|
if (isCollapsed) {
|
||||||
this._toggle(selected);
|
this._toggle(selected);
|
||||||
|
this._syncProcessPendingActionProcessing();
|
||||||
} else {
|
} else {
|
||||||
// Do KEY_DOWN
|
// Do KEY_DOWN
|
||||||
var nextSib = this._getNextSib(selected);
|
var nextSib = this._getNextSib(selected);
|
||||||
|
@ -59,26 +59,45 @@ FileList.prototype = {
|
|||||||
return this._container;
|
return this._container;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
clearFiles: function FileList_clearFiles() {
|
||||||
|
this.fileItemList = [];
|
||||||
|
this._selectedFileItem = null;
|
||||||
|
this._container.innerHTML = "";
|
||||||
|
},
|
||||||
|
|
||||||
loadProfileListFromLocalStorage: function FileList_loadProfileListFromLocalStorage() {
|
loadProfileListFromLocalStorage: function FileList_loadProfileListFromLocalStorage() {
|
||||||
var self = this;
|
var self = this;
|
||||||
gLocalStorage.getProfileList(function(profileList) {
|
gLocalStorage.getProfileList(function(profileList) {
|
||||||
for (var i = 0; i < profileList.length; i++) {
|
for (var i = profileList.length - 1; i >= 0; i--) {
|
||||||
(function closure() {
|
(function closure() {
|
||||||
// This only carries info about the profile and the access key to retrieve it.
|
// This only carries info about the profile and the access key to retrieve it.
|
||||||
var profileInfo = profileList[i];
|
var profileInfo = profileList[i];
|
||||||
//PROFILERTRACE("Profile list from local storage: " + JSON.stringify(profileInfo));
|
//PROFILERTRACE("Profile list from local storage: " + JSON.stringify(profileInfo));
|
||||||
var fileEntry = self.addFile(profileInfo.profileKey, "local storage", function fileEntryClick() {
|
var dateObj = new Date(profileInfo.date);
|
||||||
|
var fileEntry = self.addFile(profileInfo, dateObj.toLocaleString(), function fileEntryClick() {
|
||||||
|
PROFILERLOG("open: " + profileInfo.profileKey + "\n");
|
||||||
loadLocalStorageProfile(profileInfo.profileKey);
|
loadLocalStorageProfile(profileInfo.profileKey);
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
gLocalStorage.onProfileListChange(function(profileList) {
|
||||||
|
self.clearFiles();
|
||||||
|
self.loadProfileListFromLocalStorage();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
addFile: function FileList_addFile(fileName, description, onselect) {
|
addFile: function FileList_addFile(profileInfo, description, onselect) {
|
||||||
var li = document.createElement("li");
|
var li = document.createElement("li");
|
||||||
|
|
||||||
li.fileName = fileName || "New Profile";
|
var fileName;
|
||||||
|
if (profileInfo.profileKey && profileInfo.profileKey.indexOf("http://profile-store.commondatastorage.googleapis.com/") >= 0) {
|
||||||
|
fileName = profileInfo.profileKey.substring(54);
|
||||||
|
fileName = fileName.substring(0, 8) + "..." + fileName.substring(28);
|
||||||
|
} else {
|
||||||
|
fileName = profileInfo.name;
|
||||||
|
}
|
||||||
|
li.fileName = fileName || "(New Profile)";
|
||||||
li.description = description || "(empty)";
|
li.description = description || "(empty)";
|
||||||
|
|
||||||
li.className = "fileListItem";
|
li.className = "fileListItem";
|
||||||
@ -87,10 +106,11 @@ FileList.prototype = {
|
|||||||
this._selectedFileItem = li;
|
this._selectedFileItem = li;
|
||||||
}
|
}
|
||||||
|
|
||||||
li.onselect = onselect;
|
|
||||||
var self = this;
|
var self = this;
|
||||||
li.onclick = function() {
|
li.onclick = function() {
|
||||||
self.setSelection(li);
|
self.setSelection(li);
|
||||||
|
if (onselect)
|
||||||
|
onselect();
|
||||||
}
|
}
|
||||||
|
|
||||||
var fileListItemTitleSpan = document.createElement("span");
|
var fileListItemTitleSpan = document.createElement("span");
|
||||||
@ -121,8 +141,8 @@ FileList.prototype = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
profileParsingFinished: function FileList_profileParsingFinished() {
|
profileParsingFinished: function FileList_profileParsingFinished() {
|
||||||
this._container.querySelector(".fileListItemTitle").textContent = "Current Profile";
|
//this._container.querySelector(".fileListItemTitle").textContent = "Current Profile";
|
||||||
this._container.querySelector(".fileListItemDescription").textContent = gNumSamples + " Samples";
|
//this._container.querySelector(".fileListItemDescription").textContent = gNumSamples + " Samples";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,11 +155,15 @@ function ProfileTreeManager() {
|
|||||||
this.treeView.setColumns([
|
this.treeView.setColumns([
|
||||||
{ name: "sampleCount", title: "Running time" },
|
{ name: "sampleCount", title: "Running time" },
|
||||||
{ name: "selfSampleCount", title: "Self" },
|
{ name: "selfSampleCount", title: "Self" },
|
||||||
{ name: "symbolName", title: "Symbol Name"},
|
{ name: "resource", title: "" },
|
||||||
|
{ name: "symbolName", title: "Symbol Name"}
|
||||||
]);
|
]);
|
||||||
var self = this;
|
var self = this;
|
||||||
this.treeView.addEventListener("select", function (frameData) {
|
this.treeView.addEventListener("select", function (frameData) {
|
||||||
self.highlightFrame(frameData);
|
self.highlightFrame(frameData);
|
||||||
|
if (window.comparator_setSelection) {
|
||||||
|
window.comparator_setSelection(gTreeManager.serializeCurrentSelectionSnapshot(), frameData);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
this.treeView.addEventListener("contextMenuClick", function (e) {
|
this.treeView.addEventListener("contextMenuClick", function (e) {
|
||||||
self._onContextMenuClick(e);
|
self._onContextMenuClick(e);
|
||||||
@ -165,12 +189,21 @@ ProfileTreeManager.prototype = {
|
|||||||
dataIsOutdated: function ProfileTreeManager_dataIsOutdated() {
|
dataIsOutdated: function ProfileTreeManager_dataIsOutdated() {
|
||||||
this.treeView.dataIsOutdated();
|
this.treeView.dataIsOutdated();
|
||||||
},
|
},
|
||||||
saveSelectionSnapshot: function ProfileTreeManager_getSelectionSnapshot(isJavascriptOnly) {
|
saveSelectionSnapshot: function ProfileTreeManager_saveSelectionSnapshot(isJavascriptOnly) {
|
||||||
this._savedSnapshot = this.treeView.getSelectionSnapshot(isJavascriptOnly);
|
this._savedSnapshot = this.treeView.getSelectionSnapshot(isJavascriptOnly);
|
||||||
},
|
},
|
||||||
saveReverseSelectionSnapshot: function ProfileTreeManager_getReverseSelectionSnapshot(isJavascriptOnly) {
|
saveReverseSelectionSnapshot: function ProfileTreeManager_saveReverseSelectionSnapshot(isJavascriptOnly) {
|
||||||
this._savedSnapshot = this.treeView.getReverseSelectionSnapshot(isJavascriptOnly);
|
this._savedSnapshot = this.treeView.getReverseSelectionSnapshot(isJavascriptOnly);
|
||||||
},
|
},
|
||||||
|
hasNonTrivialSelection: function ProfileTreeManager_hasNonTrivialSelection() {
|
||||||
|
return this.treeView.getSelectionSnapshot().length > 1;
|
||||||
|
},
|
||||||
|
serializeCurrentSelectionSnapshot: function ProfileTreeManager_serializeCurrentSelectionSnapshot() {
|
||||||
|
return JSON.stringify(this.treeView.getSelectionSnapshot());
|
||||||
|
},
|
||||||
|
restoreSerializedSelectionSnapshot: function ProfileTreeManager_restoreSerializedSelectionSnapshot(selection) {
|
||||||
|
this._savedSnapshot = JSON.parse(selection);
|
||||||
|
},
|
||||||
_restoreSelectionSnapshot: function ProfileTreeManager__restoreSelectionSnapshot(snapshot, allowNonContigous) {
|
_restoreSelectionSnapshot: function ProfileTreeManager__restoreSelectionSnapshot(snapshot, allowNonContigous) {
|
||||||
return this.treeView.restoreSelectionSnapshot(snapshot, allowNonContigous);
|
return this.treeView.restoreSelectionSnapshot(snapshot, allowNonContigous);
|
||||||
},
|
},
|
||||||
@ -231,11 +264,12 @@ ProfileTreeManager.prototype = {
|
|||||||
setAllowNonContigous: function ProfileTreeManager_setAllowNonContigous() {
|
setAllowNonContigous: function ProfileTreeManager_setAllowNonContigous() {
|
||||||
this._allowNonContigous = true;
|
this._allowNonContigous = true;
|
||||||
},
|
},
|
||||||
display: function ProfileTreeManager_display(tree, symbols, functions, useFunctions, filterByName) {
|
display: function ProfileTreeManager_display(tree, symbols, functions, resources, useFunctions, filterByName) {
|
||||||
this.treeView.display(this.convertToJSTreeData(tree, symbols, functions, useFunctions), filterByName);
|
this.treeView.display(this.convertToJSTreeData(tree, symbols, functions, useFunctions), resources, filterByName);
|
||||||
if (this._savedSnapshot) {
|
if (this._savedSnapshot) {
|
||||||
|
var old = this._savedSnapshot.clone();
|
||||||
this._restoreSelectionSnapshot(this._savedSnapshot, this._allowNonContigous);
|
this._restoreSelectionSnapshot(this._savedSnapshot, this._allowNonContigous);
|
||||||
this._savedSnapshot = null;
|
this._savedSnapshot = old;
|
||||||
this._allowNonContigous = false;
|
this._allowNonContigous = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -252,7 +286,7 @@ ProfileTreeManager.prototype = {
|
|||||||
curObj.selfCounter = selfCounter;
|
curObj.selfCounter = selfCounter;
|
||||||
curObj.ratio = node.counter / totalSamples;
|
curObj.ratio = node.counter / totalSamples;
|
||||||
curObj.fullFrameNamesAsInSample = node.mergedNames ? node.mergedNames : [node.name];
|
curObj.fullFrameNamesAsInSample = node.mergedNames ? node.mergedNames : [node.name];
|
||||||
if (useFunctions ? !(node.name in functions) : !(node.name in symbols)) {
|
if (!(node.name in (useFunctions ? functions : symbols))) {
|
||||||
curObj.name = node.name;
|
curObj.name = node.name;
|
||||||
curObj.library = "";
|
curObj.library = "";
|
||||||
} else {
|
} else {
|
||||||
@ -302,7 +336,7 @@ function SampleBar() {
|
|||||||
this._header.alt = "This shows the heaviest leaf of the selected sample. Use this to get a quick glimpse of where the selection is spending most of its time.";
|
this._header.alt = "This shows the heaviest leaf of the selected sample. Use this to get a quick glimpse of where the selection is spending most of its time.";
|
||||||
this._container.appendChild(this._header);
|
this._container.appendChild(this._header);
|
||||||
|
|
||||||
this._text = document.createElement("span");
|
this._text = document.createElement("ul");
|
||||||
this._text.style.whiteSpace = "pre";
|
this._text.style.whiteSpace = "pre";
|
||||||
this._text.innerHTML = "Sample text";
|
this._text.innerHTML = "Sample text";
|
||||||
this._container.appendChild(this._text);
|
this._container.appendChild(this._text);
|
||||||
@ -322,11 +356,12 @@ SampleBar.prototype = {
|
|||||||
var functionObj = gMergeFunctions ? gFunctions[sample[i]] : gFunctions[symbols[sample[i]].functionIndex];
|
var functionObj = gMergeFunctions ? gFunctions[sample[i]] : gFunctions[symbols[sample[i]].functionIndex];
|
||||||
if (!functionObj)
|
if (!functionObj)
|
||||||
continue;
|
continue;
|
||||||
|
var functionItem = document.createElement("li");
|
||||||
var functionLink = document.createElement("a");
|
var functionLink = document.createElement("a");
|
||||||
functionLink.textContent = "- " + functionObj.functionName;
|
functionLink.textContent = functionLink.title = functionObj.functionName;
|
||||||
functionLink.href = "#";
|
functionLink.href = "#";
|
||||||
this._text.appendChild(functionLink);
|
functionItem.appendChild(functionLink);
|
||||||
this._text.appendChild(document.createElement("br"));
|
this._text.appendChild(functionItem);
|
||||||
list.push(functionObj.functionName);
|
list.push(functionObj.functionName);
|
||||||
functionLink.selectIndex = i;
|
functionLink.selectIndex = i;
|
||||||
functionLink.onclick = function() {
|
functionLink.onclick = function() {
|
||||||
@ -378,11 +413,9 @@ PluginView.prototype = {
|
|||||||
this._iframe.src = "js/plugins/" + pluginName + "/index.html";
|
this._iframe.src = "js/plugins/" + pluginName + "/index.html";
|
||||||
var self = this;
|
var self = this;
|
||||||
this._iframe.onload = function() {
|
this._iframe.onload = function() {
|
||||||
console.log("Pluginview '" + pluginName + " iframe onload");
|
|
||||||
self._iframe.contentWindow.initCleopatraPlugin(data, param, gSymbols);
|
self._iframe.contentWindow.initCleopatraPlugin(data, param, gSymbols);
|
||||||
}
|
}
|
||||||
this.show();
|
this.show();
|
||||||
//console.log(gSymbols);
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -417,6 +450,9 @@ HistogramView.prototype = {
|
|||||||
getContainer: function HistogramView_getContainer() {
|
getContainer: function HistogramView_getContainer() {
|
||||||
return this._container;
|
return this._container;
|
||||||
},
|
},
|
||||||
|
selectRange: function HistogramView_selectRange(start, end) {
|
||||||
|
this._rangeSelector._finishSelection(start, end);
|
||||||
|
},
|
||||||
showVideoFramePosition: function HistogramView_showVideoFramePosition(frame) {
|
showVideoFramePosition: function HistogramView_showVideoFramePosition(frame) {
|
||||||
if (!this._frameStart || !this._frameStart[frame])
|
if (!this._frameStart || !this._frameStart[frame])
|
||||||
return;
|
return;
|
||||||
@ -453,15 +489,12 @@ HistogramView.prototype = {
|
|||||||
histogramClick: function HistogramView_histogramClick(index) {
|
histogramClick: function HistogramView_histogramClick(index) {
|
||||||
var sample = this._histogramData[index];
|
var sample = this._histogramData[index];
|
||||||
var frames = sample.frames;
|
var frames = sample.frames;
|
||||||
if (gSampleBar) {
|
|
||||||
var list = gSampleBar.setSample(frames[0]);
|
var list = gSampleBar.setSample(frames[0]);
|
||||||
gTreeManager.setSelection(list);
|
gTreeManager.setSelection(list);
|
||||||
setHighlightedCallstack(frames[0], frames[0]);
|
setHighlightedCallstack(frames[0], frames[0]);
|
||||||
}
|
|
||||||
},
|
},
|
||||||
display: function HistogramView_display(histogramData, frameStart, widthSum, highlightedCallstack) {
|
display: function HistogramView_display(histogramData, frameStart, widthSum, highlightedCallstack) {
|
||||||
this._histogramData = histogramData;
|
this._histogramData = histogramData;
|
||||||
PROFILERTRACE("FRAME START: " + frameStart + "\n");
|
|
||||||
this._frameStart = frameStart;
|
this._frameStart = frameStart;
|
||||||
this._widthSum = widthSum;
|
this._widthSum = widthSum;
|
||||||
this._widthMultiplier = this._calculateWidthMultiplier();
|
this._widthMultiplier = this._calculateWidthMultiplier();
|
||||||
@ -469,13 +502,26 @@ HistogramView.prototype = {
|
|||||||
this._render(highlightedCallstack);
|
this._render(highlightedCallstack);
|
||||||
this._busyCover.classList.remove("busy");
|
this._busyCover.classList.remove("busy");
|
||||||
},
|
},
|
||||||
|
_scheduleRender: function HistogramView__scheduleRender(highlightedCallstack) {
|
||||||
|
var self = this;
|
||||||
|
if (self._pendingAnimationFrame != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
self._pendingAnimationFrame = requestAnimationFrame(function anim_frame() {
|
||||||
|
cancelAnimationFrame(self._pendingAnimationFrame);
|
||||||
|
self._pendingAnimationFrame = null;
|
||||||
|
self._render(highlightedCallstack);
|
||||||
|
});
|
||||||
|
},
|
||||||
_render: function HistogramView__render(highlightedCallstack) {
|
_render: function HistogramView__render(highlightedCallstack) {
|
||||||
var ctx = this._canvas.getContext("2d");
|
var ctx = this._canvas.getContext("2d");
|
||||||
var height = this._canvas.height;
|
var height = this._canvas.height;
|
||||||
ctx.setTransform(this._widthMultiplier, 0, 0, 1, 0, 0);
|
ctx.setTransform(this._widthMultiplier, 0, 0, 1, 0, 0);
|
||||||
|
ctx.font = "20px Georgia";
|
||||||
ctx.clearRect(0, 0, this._widthSum, height);
|
ctx.clearRect(0, 0, this._widthSum, height);
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
var markerCount = 0;
|
||||||
for (var i = 0; i < this._histogramData.length; i++) {
|
for (var i = 0; i < this._histogramData.length; i++) {
|
||||||
var step = this._histogramData[i];
|
var step = this._histogramData[i];
|
||||||
var isSelected = self._isStepSelected(step, highlightedCallstack);
|
var isSelected = self._isStepSelected(step, highlightedCallstack);
|
||||||
@ -489,12 +535,22 @@ HistogramView.prototype = {
|
|||||||
}
|
}
|
||||||
var roundedHeight = Math.round(step.value * height);
|
var roundedHeight = Math.round(step.value * height);
|
||||||
ctx.fillRect(step.x, height - roundedHeight, step.width, roundedHeight);
|
ctx.fillRect(step.x, height - roundedHeight, step.width, roundedHeight);
|
||||||
|
if (step.marker) {
|
||||||
|
var x = step.x + step.width + 2;
|
||||||
|
var endPoint = x + ctx.measureText(step.marker).width;
|
||||||
|
var lastDataPoint = this._histogramData[this._histogramData.length-1];
|
||||||
|
if (endPoint >= lastDataPoint.x + lastDataPoint.width) {
|
||||||
|
x -= endPoint - (lastDataPoint.x + lastDataPoint.width) - 1;
|
||||||
|
}
|
||||||
|
ctx.fillText(step.marker, x, 15 + ((markerCount % 2) == 0 ? 0 : 20));
|
||||||
|
markerCount++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._finishedRendering = true;
|
this._finishedRendering = true;
|
||||||
},
|
},
|
||||||
highlightedCallstackChanged: function HistogramView_highlightedCallstackChanged(highlightedCallstack) {
|
highlightedCallstackChanged: function HistogramView_highlightedCallstackChanged(highlightedCallstack) {
|
||||||
this._render(highlightedCallstack);
|
this._scheduleRender(highlightedCallstack);
|
||||||
},
|
},
|
||||||
_isInRangeSelector: function HistogramView_isInRangeSelector(index) {
|
_isInRangeSelector: function HistogramView_isInRangeSelector(index) {
|
||||||
return false;
|
return false;
|
||||||
@ -502,29 +558,33 @@ HistogramView.prototype = {
|
|||||||
_isStepSelected: function HistogramView__isStepSelected(step, highlightedCallstack) {
|
_isStepSelected: function HistogramView__isStepSelected(step, highlightedCallstack) {
|
||||||
if ("marker" in step)
|
if ("marker" in step)
|
||||||
return false;
|
return false;
|
||||||
return step.frames.some(function isCallstackSelected(frames) {
|
|
||||||
|
search_frames: for (var i = 0; i < step.frames.length; i++) {
|
||||||
|
var frames = step.frames[i];
|
||||||
|
|
||||||
if (frames.length < highlightedCallstack.length ||
|
if (frames.length < highlightedCallstack.length ||
|
||||||
highlightedCallstack.length <= (gInvertCallstack ? 0 : 1))
|
highlightedCallstack.length <= (gInvertCallstack ? 0 : 1))
|
||||||
return false;
|
continue;
|
||||||
|
|
||||||
var compareFrames = frames;
|
var compareFrames = frames;
|
||||||
if (gInvertCallstack) {
|
if (gInvertCallstack) {
|
||||||
for (var j = 0; j < highlightedCallstack.length; j++) {
|
for (var j = 0; j < highlightedCallstack.length; j++) {
|
||||||
var compareFrameIndex = compareFrames.length - 1 - j;
|
var compareFrameIndex = compareFrames.length - 1 - j;
|
||||||
if (highlightedCallstack[j] != compareFrames[compareFrameIndex]) {
|
if (highlightedCallstack[j] != compareFrames[compareFrameIndex]) {
|
||||||
return false;
|
continue search_frames;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (var j = 0; j < highlightedCallstack.length; j++) {
|
for (var j = 0; j < highlightedCallstack.length; j++) {
|
||||||
var compareFrameIndex = j;
|
var compareFrameIndex = j;
|
||||||
if (highlightedCallstack[j] != compareFrames[compareFrameIndex]) {
|
if (highlightedCallstack[j] != compareFrames[compareFrameIndex]) {
|
||||||
return false;
|
continue search_frames;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
};
|
||||||
|
return false;
|
||||||
},
|
},
|
||||||
getHistogramData: function HistogramView__getHistogramData() {
|
getHistogramData: function HistogramView__getHistogramData() {
|
||||||
return this._histogramData;
|
return this._histogramData;
|
||||||
@ -606,6 +666,9 @@ RangeSelector.prototype = {
|
|||||||
var isDrawingRectangle = false;
|
var isDrawingRectangle = false;
|
||||||
var origX, origY;
|
var origX, origY;
|
||||||
var self = this;
|
var self = this;
|
||||||
|
// Compute this on the mouse down rather then forcing a sync reflow
|
||||||
|
// every frame.
|
||||||
|
var boundingRect = null;
|
||||||
function histogramClick(clickX, clickY) {
|
function histogramClick(clickX, clickY) {
|
||||||
clickX = Math.min(clickX, graph.parentNode.getBoundingClientRect().right);
|
clickX = Math.min(clickX, graph.parentNode.getBoundingClientRect().right);
|
||||||
clickX = clickX - graph.parentNode.getBoundingClientRect().left;
|
clickX = clickX - graph.parentNode.getBoundingClientRect().left;
|
||||||
@ -613,8 +676,8 @@ RangeSelector.prototype = {
|
|||||||
self._histogram.histogramClick(index);
|
self._histogram.histogramClick(index);
|
||||||
}
|
}
|
||||||
function updateHiliteRectangle(newX, newY) {
|
function updateHiliteRectangle(newX, newY) {
|
||||||
newX = Math.min(newX, graph.parentNode.getBoundingClientRect().right);
|
newX = Math.min(newX, boundingRect.right);
|
||||||
var startX = Math.min(newX, origX) - graph.parentNode.getBoundingClientRect().left;
|
var startX = Math.min(newX, origX) - boundingRect.left;
|
||||||
var startY = 0;
|
var startY = 0;
|
||||||
var width = Math.abs(newX - origX);
|
var width = Math.abs(newX - origX);
|
||||||
var height = graph.parentNode.clientHeight;
|
var height = graph.parentNode.clientHeight;
|
||||||
@ -637,6 +700,7 @@ RangeSelector.prototype = {
|
|||||||
self.beginHistogramSelection();
|
self.beginHistogramSelection();
|
||||||
origX = e.pageX;
|
origX = e.pageX;
|
||||||
origY = e.pageY;
|
origY = e.pageY;
|
||||||
|
boundingRect = graph.parentNode.getBoundingClientRect();
|
||||||
if (this.setCapture)
|
if (this.setCapture)
|
||||||
this.setCapture();
|
this.setCapture();
|
||||||
// Reset the highlight rectangle
|
// Reset the highlight rectangle
|
||||||
@ -659,14 +723,12 @@ RangeSelector.prototype = {
|
|||||||
var index = self._sampleIndexFromPoint(e.pageX - graph.parentNode.getBoundingClientRect().left);
|
var index = self._sampleIndexFromPoint(e.pageX - graph.parentNode.getBoundingClientRect().left);
|
||||||
// TODO Select this sample in the tree view
|
// TODO Select this sample in the tree view
|
||||||
var sample = gCurrentlyShownSampleData[index];
|
var sample = gCurrentlyShownSampleData[index];
|
||||||
console.log("Should select: " + sample);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
graph.addEventListener("mousemove", function(e) {
|
graph.addEventListener("mousemove", function(e) {
|
||||||
this._movedDuringClick = true;
|
this._movedDuringClick = true;
|
||||||
if (isDrawingRectangle) {
|
if (isDrawingRectangle) {
|
||||||
console.log(e.pageX);
|
|
||||||
updateMouseMarker(-1); // Clear
|
updateMouseMarker(-1); // Clear
|
||||||
updateHiliteRectangle(e.pageX, e.pageY);
|
updateHiliteRectangle(e.pageX, e.pageY);
|
||||||
} else {
|
} else {
|
||||||
@ -744,6 +806,7 @@ function videoPaneTimeChange(video) {
|
|||||||
|
|
||||||
|
|
||||||
window.onpopstate = function(ev) {
|
window.onpopstate = function(ev) {
|
||||||
|
return; // Conflicts with document url
|
||||||
if (!gBreadcrumbTrail)
|
if (!gBreadcrumbTrail)
|
||||||
return;
|
return;
|
||||||
console.log("pop: " + JSON.stringify(ev.state));
|
console.log("pop: " + JSON.stringify(ev.state));
|
||||||
@ -820,10 +883,17 @@ BreadcrumbTrail.prototype = {
|
|||||||
if (this._breadcrumbs.length-2 >= 0)
|
if (this._breadcrumbs.length-2 >= 0)
|
||||||
this._enter(this._breadcrumbs.length-2);
|
this._enter(this._breadcrumbs.length-2);
|
||||||
},
|
},
|
||||||
_enter: function BreadcrumbTrail__select(index) {
|
enterLastItem: function BreadcrumbTrail_enterLastItem(forceSelection) {
|
||||||
|
this._enter(this._breadcrumbs.length-1, forceSelection);
|
||||||
|
},
|
||||||
|
_enter: function BreadcrumbTrail__select(index, forceSelection) {
|
||||||
if (index == this._selectedBreadcrumbIndex)
|
if (index == this._selectedBreadcrumbIndex)
|
||||||
return;
|
return;
|
||||||
|
if (forceSelection) {
|
||||||
|
gTreeManager.restoreSerializedSelectionSnapshot(forceSelection);
|
||||||
|
} else {
|
||||||
gTreeManager.saveSelectionSnapshot();
|
gTreeManager.saveSelectionSnapshot();
|
||||||
|
}
|
||||||
var prevSelected = this._breadcrumbs[this._selectedBreadcrumbIndex];
|
var prevSelected = this._breadcrumbs[this._selectedBreadcrumbIndex];
|
||||||
if (prevSelected)
|
if (prevSelected)
|
||||||
prevSelected.classList.remove("selected");
|
prevSelected.classList.remove("selected");
|
||||||
@ -935,7 +1005,7 @@ function copyProfile() {
|
|||||||
|
|
||||||
function saveProfileToLocalStorage() {
|
function saveProfileToLocalStorage() {
|
||||||
Parser.getSerializedProfile(true, function (serializedProfile) {
|
Parser.getSerializedProfile(true, function (serializedProfile) {
|
||||||
gLocalStorage.storeLocalProfile(serializedProfile, function profileSaved() {
|
gLocalStorage.storeLocalProfile(serializedProfile, gMeta.profileId, function profileSaved() {
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -947,13 +1017,85 @@ function downloadProfile() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function promptUploadProfile(selected) {
|
||||||
|
var overlay = document.createElement("div");
|
||||||
|
overlay.style.position = "absolute";
|
||||||
|
overlay.style.top = 0;
|
||||||
|
overlay.style.left = 0;
|
||||||
|
overlay.style.width = "100%";
|
||||||
|
overlay.style.height = "100%";
|
||||||
|
overlay.style.backgroundColor = "transparent";
|
||||||
|
|
||||||
|
var bg = document.createElement("div");
|
||||||
|
bg.style.position = "absolute";
|
||||||
|
bg.style.top = 0;
|
||||||
|
bg.style.left = 0;
|
||||||
|
bg.style.width = "100%";
|
||||||
|
bg.style.height = "100%";
|
||||||
|
bg.style.opacity = "0.6";
|
||||||
|
bg.style.backgroundColor = "#aaaaaa";
|
||||||
|
overlay.appendChild(bg);
|
||||||
|
|
||||||
|
var contentDiv = document.createElement("div");
|
||||||
|
contentDiv.className = "sideBar";
|
||||||
|
contentDiv.style.position = "absolute";
|
||||||
|
contentDiv.style.top = "50%";
|
||||||
|
contentDiv.style.left = "50%";
|
||||||
|
contentDiv.style.width = "40em";
|
||||||
|
contentDiv.style.height = "20em";
|
||||||
|
contentDiv.style.marginLeft = "-20em";
|
||||||
|
contentDiv.style.marginTop = "-10em";
|
||||||
|
contentDiv.style.padding = "10px";
|
||||||
|
contentDiv.style.border = "2px solid black";
|
||||||
|
contentDiv.style.backgroundColor = "rgb(219, 223, 231)";
|
||||||
|
overlay.appendChild(contentDiv);
|
||||||
|
|
||||||
|
var noticeHTML = "";
|
||||||
|
noticeHTML += "<center><h2 style='font-size: 2em'>Upload Profile - Privacy Notice</h2></center>";
|
||||||
|
noticeHTML += "You're about to upload your profile publicly where anyone will be able to access it. ";
|
||||||
|
noticeHTML += "To better diagnose performance problems profiles include the following information:";
|
||||||
|
noticeHTML += "<ul>";
|
||||||
|
noticeHTML += " <li>The <b>URLs</b> and scripts of the tabs that were executing.</li>";
|
||||||
|
noticeHTML += " <li>The <b>metadata of all your Add-ons</b> to identify slow Add-ons.</li>";
|
||||||
|
noticeHTML += " <li>Firefox build and runtime configuration.</li>";
|
||||||
|
noticeHTML += "</ul><br>";
|
||||||
|
noticeHTML += "To view all the information you can download the full profile to a file and open the json structure with a text editor.<br><br>";
|
||||||
|
contentDiv.innerHTML = noticeHTML;
|
||||||
|
|
||||||
|
var cancelButton = document.createElement("input");
|
||||||
|
cancelButton.style.position = "absolute";
|
||||||
|
cancelButton.style.bottom = "10px";
|
||||||
|
cancelButton.type = "button";
|
||||||
|
cancelButton.value = "Cancel";
|
||||||
|
cancelButton.onclick = function() {
|
||||||
|
document.body.removeChild(overlay);
|
||||||
|
}
|
||||||
|
contentDiv.appendChild(cancelButton);
|
||||||
|
|
||||||
|
var uploadButton = document.createElement("input");
|
||||||
|
uploadButton.style.position = "absolute";
|
||||||
|
uploadButton.style.right = "10px";
|
||||||
|
uploadButton.style.bottom = "10px";
|
||||||
|
uploadButton.type = "button";
|
||||||
|
uploadButton.value = "Upload";
|
||||||
|
uploadButton.onclick = function() {
|
||||||
|
document.body.removeChild(overlay);
|
||||||
|
uploadProfile(selected);
|
||||||
|
}
|
||||||
|
contentDiv.appendChild(uploadButton);
|
||||||
|
|
||||||
|
document.body.appendChild(overlay);
|
||||||
|
}
|
||||||
|
|
||||||
function uploadProfile(selected) {
|
function uploadProfile(selected) {
|
||||||
Parser.getSerializedProfile(!selected, function (dataToUpload) {
|
Parser.getSerializedProfile(!selected, function (dataToUpload) {
|
||||||
var oXHR = new XMLHttpRequest();
|
var oXHR = new XMLHttpRequest();
|
||||||
oXHR.open("POST", "http://profile-store.appspot.com/store", true);
|
|
||||||
oXHR.onload = function (oEvent) {
|
oXHR.onload = function (oEvent) {
|
||||||
if (oXHR.status == 200) {
|
if (oXHR.status == 200) {
|
||||||
document.getElementById("upload_status").innerHTML = "Success! Use this <a href='" + document.URL.split('?')[0] + "?report=" + oXHR.responseText + "'>link</a>";
|
gReportID = oXHR.responseText;
|
||||||
|
updateDocumentURL();
|
||||||
|
document.getElementById("upload_status").innerHTML = "Success! Use this <a id='linkElem'>link</a>";
|
||||||
|
document.getElementById("linkElem").href = document.URL;
|
||||||
} else {
|
} else {
|
||||||
document.getElementById("upload_status").innerHTML = "Error " + oXHR.status + " occurred uploading your file.";
|
document.getElementById("upload_status").innerHTML = "Error " + oXHR.status + " occurred uploading your file.";
|
||||||
}
|
}
|
||||||
@ -961,22 +1103,28 @@ function uploadProfile(selected) {
|
|||||||
oXHR.onerror = function (oEvent) {
|
oXHR.onerror = function (oEvent) {
|
||||||
document.getElementById("upload_status").innerHTML = "Error " + oXHR.status + " occurred uploading your file.";
|
document.getElementById("upload_status").innerHTML = "Error " + oXHR.status + " occurred uploading your file.";
|
||||||
}
|
}
|
||||||
oXHR.onprogress = function (oEvent) {
|
oXHR.upload.onprogress = function(oEvent) {
|
||||||
if (oEvent.lengthComputable) {
|
if (oEvent.lengthComputable) {
|
||||||
document.getElementById("upload_status").innerHTML = "Uploading: " + ((oEvent.loaded / oEvent.total)*100) + "%";
|
var progress = Math.round((oEvent.loaded / oEvent.total)*100);
|
||||||
|
if (progress == 100) {
|
||||||
|
document.getElementById("upload_status").innerHTML = "Uploading: Waiting for server side compression";
|
||||||
|
} else {
|
||||||
|
document.getElementById("upload_status").innerHTML = "Uploading: " + Math.round((oEvent.loaded / oEvent.total)*100) + "%";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
var dataSize;
|
var dataSize;
|
||||||
if (dataToUpload.length > 1024*1024) {
|
if (dataToUpload.length > 1024*1024) {
|
||||||
dataSize = (dataToUpload.length/1024/1024) + " MB(s)";
|
dataSize = (dataToUpload.length/1024/1024).toFixed(1) + " MB(s)";
|
||||||
} else {
|
} else {
|
||||||
dataSize = (dataToUpload.length/1024) + " KB(s)";
|
dataSize = (dataToUpload.length/1024).toFixed(1) + " KB(s)";
|
||||||
}
|
}
|
||||||
|
|
||||||
var formData = new FormData();
|
var formData = new FormData();
|
||||||
formData.append("file", dataToUpload);
|
formData.append("file", dataToUpload);
|
||||||
document.getElementById("upload_status").innerHTML = "Uploading Profile (" + dataSize + ")";
|
document.getElementById("upload_status").innerHTML = "Uploading Profile (" + dataSize + ")";
|
||||||
|
oXHR.open("POST", "http://profile-store.appspot.com/store", true);
|
||||||
oXHR.send(formData);
|
oXHR.send(formData);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1018,7 +1166,7 @@ function filterUpdate() {
|
|||||||
|
|
||||||
var filterNameInput = document.getElementById("filterName");
|
var filterNameInput = document.getElementById("filterName");
|
||||||
if (filterNameInput != null) {
|
if (filterNameInput != null) {
|
||||||
filterNameInput.focus();
|
changeFocus(filterNameInput);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1083,15 +1231,15 @@ InfoBar.prototype = {
|
|||||||
infoText += "<h2>Pre Filtering</h2>\n";
|
infoText += "<h2>Pre Filtering</h2>\n";
|
||||||
// Disable for now since it's buggy and not useful
|
// Disable for now since it's buggy and not useful
|
||||||
//infoText += "<label><input type='checkbox' id='mergeFunctions' " + (gMergeFunctions ?" checked='true' ":" ") + " onchange='toggleMergeFunctions()'/>Functions, not lines</label><br>\n";
|
//infoText += "<label><input type='checkbox' id='mergeFunctions' " + (gMergeFunctions ?" checked='true' ":" ") + " onchange='toggleMergeFunctions()'/>Functions, not lines</label><br>\n";
|
||||||
infoText += "<label><input type='checkbox' id='showJS' " + (gJavascriptOnly ?" checked='true' ":" ") + " onchange='toggleJavascriptOnly()'/>Javascript only</label><br>\n";
|
|
||||||
|
|
||||||
var filterNameInputOld = document.getElementById("filterName");
|
var filterNameInputOld = document.getElementById("filterName");
|
||||||
infoText += "<label>Filter:\n";
|
infoText += "<a>Filter:\n";
|
||||||
infoText += "<input type='search' id='filterName' oninput='filterOnChange()'/></label>\n";
|
infoText += "<input type='search' id='filterName' oninput='filterOnChange()'/></a>\n";
|
||||||
|
|
||||||
infoText += "<h2>Post Filtering</h2>\n";
|
infoText += "<h2>Post Filtering</h2>\n";
|
||||||
infoText += "<label><input type='checkbox' id='showJank' " + (gJankOnly ?" checked='true' ":" ") + " onchange='toggleJank()'/>Show Jank only</label>\n";
|
infoText += "<label><input type='checkbox' id='showJank' " + (gJankOnly ?" checked='true' ":" ") + " onchange='toggleJank()'/>Show Jank only</label>\n";
|
||||||
infoText += "<h2>View Options</h2>\n";
|
infoText += "<h2>View Options</h2>\n";
|
||||||
|
infoText += "<label><input type='checkbox' id='showJS' " + (gJavascriptOnly ?" checked='true' ":" ") + " onchange='toggleJavascriptOnly()'/>Javascript only</label><br>\n";
|
||||||
infoText += "<label><input type='checkbox' id='mergeUnbranched' " + (gMergeUnbranched ?" checked='true' ":" ") + " onchange='toggleMergeUnbranched()'/>Merge unbranched call paths</label><br>\n";
|
infoText += "<label><input type='checkbox' id='mergeUnbranched' " + (gMergeUnbranched ?" checked='true' ":" ") + " onchange='toggleMergeUnbranched()'/>Merge unbranched call paths</label><br>\n";
|
||||||
infoText += "<label><input type='checkbox' id='invertCallstack' " + (gInvertCallstack ?" checked='true' ":" ") + " onchange='toggleInvertCallStack()'/>Invert callstack</label><br>\n";
|
infoText += "<label><input type='checkbox' id='invertCallstack' " + (gInvertCallstack ?" checked='true' ":" ") + " onchange='toggleInvertCallStack()'/>Invert callstack</label><br>\n";
|
||||||
|
|
||||||
@ -1101,6 +1249,9 @@ InfoBar.prototype = {
|
|||||||
infoText += "<input type='button' id='upload_select' value='Upload view'><br>\n";
|
infoText += "<input type='button' id='upload_select' value='Upload view'><br>\n";
|
||||||
infoText += "<input type='button' id='download' value='Download full profile'>\n";
|
infoText += "<input type='button' id='download' value='Download full profile'>\n";
|
||||||
|
|
||||||
|
infoText += "<h2>Compare</h2>\n";
|
||||||
|
infoText += "<input type='button' id='compare' value='Compare'>\n";
|
||||||
|
|
||||||
//infoText += "<br>\n";
|
//infoText += "<br>\n";
|
||||||
//infoText += "Skip functions:<br>\n";
|
//infoText += "Skip functions:<br>\n";
|
||||||
//infoText += "<select size=8 id='skipsymbol'></select><br />"
|
//infoText += "<select size=8 id='skipsymbol'></select><br />"
|
||||||
@ -1114,13 +1265,19 @@ InfoBar.prototype = {
|
|||||||
if (filterNameInputOld != null && filterNameInputNew != null) {
|
if (filterNameInputOld != null && filterNameInputNew != null) {
|
||||||
filterNameInputNew.parentNode.replaceChild(filterNameInputOld, filterNameInputNew);
|
filterNameInputNew.parentNode.replaceChild(filterNameInputOld, filterNameInputNew);
|
||||||
//filterNameInputNew.value = filterNameInputOld.value;
|
//filterNameInputNew.value = filterNameInputOld.value;
|
||||||
|
} else if (gQueryParamFilterName != null) {
|
||||||
|
filterNameInputNew.value = gQueryParamFilterName;
|
||||||
|
gQueryParamFilterName = null;
|
||||||
|
}
|
||||||
|
document.getElementById('compare').onclick = function() {
|
||||||
|
openProfileCompare();
|
||||||
}
|
}
|
||||||
document.getElementById('upload').onclick = function() {
|
document.getElementById('upload').onclick = function() {
|
||||||
uploadProfile(false);
|
promptUploadProfile(false);
|
||||||
};
|
};
|
||||||
document.getElementById('download').onclick = downloadProfile;
|
document.getElementById('download').onclick = downloadProfile;
|
||||||
document.getElementById('upload_select').onclick = function() {
|
document.getElementById('upload_select').onclick = function() {
|
||||||
uploadProfile(true);
|
promptUploadProfile(true);
|
||||||
};
|
};
|
||||||
//document.getElementById('delete_skipsymbol').onclick = delete_skip_symbol;
|
//document.getElementById('delete_skipsymbol').onclick = delete_skip_symbol;
|
||||||
//document.getElementById('add_skipsymbol').onclick = add_skip_symbol;
|
//document.getElementById('add_skipsymbol').onclick = add_skip_symbol;
|
||||||
@ -1129,13 +1286,13 @@ InfoBar.prototype = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// in light mode we simplify the UI by default
|
|
||||||
var gLightMode = false;
|
|
||||||
var gNumSamples = 0;
|
var gNumSamples = 0;
|
||||||
var gMeta = null;
|
var gMeta = null;
|
||||||
var gSymbols = {};
|
var gSymbols = {};
|
||||||
var gFunctions = {};
|
var gFunctions = {};
|
||||||
|
var gResources = {};
|
||||||
var gHighlightedCallstack = [];
|
var gHighlightedCallstack = [];
|
||||||
|
var gFrameView = null;
|
||||||
var gTreeManager = null;
|
var gTreeManager = null;
|
||||||
var gSampleBar = null;
|
var gSampleBar = null;
|
||||||
var gBreadcrumbTrail = null;
|
var gBreadcrumbTrail = null;
|
||||||
@ -1149,6 +1306,9 @@ var gMainArea = null;
|
|||||||
var gCurrentlyShownSampleData = null;
|
var gCurrentlyShownSampleData = null;
|
||||||
var gSkipSymbols = ["test2", "test1"];
|
var gSkipSymbols = ["test2", "test1"];
|
||||||
var gAppendVideoCapture = null;
|
var gAppendVideoCapture = null;
|
||||||
|
var gQueryParamFilterName = null;
|
||||||
|
var gRestoreSelection = null;
|
||||||
|
var gReportID = null;
|
||||||
|
|
||||||
function getTextData() {
|
function getTextData() {
|
||||||
var data = [];
|
var data = [];
|
||||||
@ -1190,7 +1350,7 @@ function loadLocalStorageProfile(profileKey) {
|
|||||||
|
|
||||||
gLocalStorage.getProfile(profileKey, function(profile) {
|
gLocalStorage.getProfile(profileKey, function(profile) {
|
||||||
subreporters.fileLoading.finish();
|
subreporters.fileLoading.finish();
|
||||||
loadRawProfile(subreporters.parsing, JSON.stringify(profile));
|
loadRawProfile(subreporters.parsing, profile, profileKey);
|
||||||
});
|
});
|
||||||
subreporters.fileLoading.begin("Reading local storage...");
|
subreporters.fileLoading.begin("Reading local storage...");
|
||||||
}
|
}
|
||||||
@ -1254,14 +1414,18 @@ function loadProfileURL(url) {
|
|||||||
xhr.open("GET", url, true);
|
xhr.open("GET", url, true);
|
||||||
xhr.responseType = "text";
|
xhr.responseType = "text";
|
||||||
xhr.onreadystatechange = function (e) {
|
xhr.onreadystatechange = function (e) {
|
||||||
if (xhr.readyState === 4 && xhr.status === 200) {
|
if (xhr.readyState === 4 && (xhr.status === 200 || xhr.status === 0)) {
|
||||||
subreporters.fileLoading.finish();
|
subreporters.fileLoading.finish();
|
||||||
PROFILERLOG("Got profile from '" + url + "'.");
|
PROFILERLOG("Got profile from '" + url + "'.");
|
||||||
loadRawProfile(subreporters.parsing, xhr.responseText);
|
if (xhr.responseText == null || xhr.responseText === "") {
|
||||||
|
subreporters.fileLoading.begin("Profile '" + url + "' is empty. Did you set the CORS headers?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loadRawProfile(subreporters.parsing, xhr.responseText, url);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
xhr.onerror = function (e) {
|
xhr.onerror = function (e) {
|
||||||
subreporters.fileLoading.begin("Error fetching profile :(. URL: " + url);
|
subreporters.fileLoading.begin("Error fetching profile :(. URL: '" + url + "'. Did you set the CORS headers?");
|
||||||
}
|
}
|
||||||
xhr.onprogress = function (e) {
|
xhr.onprogress = function (e) {
|
||||||
if (e.lengthComputable && (e.loaded <= e.total)) {
|
if (e.lengthComputable && (e.loaded <= e.total)) {
|
||||||
@ -1281,12 +1445,17 @@ function loadProfile(rawProfile) {
|
|||||||
loadRawProfile(reporter, rawProfile);
|
loadRawProfile(reporter, rawProfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadRawProfile(reporter, rawProfile) {
|
function loadRawProfile(reporter, rawProfile, profileId) {
|
||||||
PROFILERLOG("Parse raw profile: ~" + rawProfile.length + " bytes");
|
PROFILERLOG("Parse raw profile: ~" + rawProfile.length + " bytes");
|
||||||
reporter.begin("Parsing...");
|
reporter.begin("Parsing...");
|
||||||
|
if (rawProfile == null || rawProfile.length === 0) {
|
||||||
|
reporter.begin("Profile is null or empty");
|
||||||
|
return;
|
||||||
|
}
|
||||||
var startTime = Date.now();
|
var startTime = Date.now();
|
||||||
var parseRequest = Parser.parse(rawProfile, {
|
var parseRequest = Parser.parse(rawProfile, {
|
||||||
appendVideoCapture : gAppendVideoCapture,
|
appendVideoCapture : gAppendVideoCapture,
|
||||||
|
profileId: profileId,
|
||||||
});
|
});
|
||||||
gVideoCapture = null;
|
gVideoCapture = null;
|
||||||
parseRequest.addEventListener("progress", function (progress, action) {
|
parseRequest.addEventListener("progress", function (progress, action) {
|
||||||
@ -1301,8 +1470,8 @@ function loadRawProfile(reporter, rawProfile) {
|
|||||||
gNumSamples = result.numSamples;
|
gNumSamples = result.numSamples;
|
||||||
gSymbols = result.symbols;
|
gSymbols = result.symbols;
|
||||||
gFunctions = result.functions;
|
gFunctions = result.functions;
|
||||||
|
gResources = result.resources;
|
||||||
enterFinishedProfileUI();
|
enterFinishedProfileUI();
|
||||||
if (gFileList)
|
|
||||||
gFileList.profileParsingFinished();
|
gFileList.profileParsingFinished();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -1330,16 +1499,9 @@ window.addEventListener("message", function messageFromAddon(msg) {
|
|||||||
case "importFromAddonFinish":
|
case "importFromAddonFinish":
|
||||||
importFromAddonFinish(o.rawProfile);
|
importFromAddonFinish(o.rawProfile);
|
||||||
break;
|
break;
|
||||||
case "receiveProfileData":
|
|
||||||
receiveProfileData(o.rawProfile);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function receiveProfileData(data) {
|
|
||||||
loadProfile(JSON.stringify(data));
|
|
||||||
}
|
|
||||||
|
|
||||||
function importFromAddonFinish(rawProfile) {
|
function importFromAddonFinish(rawProfile) {
|
||||||
gImportFromAddonSubreporters.import.finish();
|
gImportFromAddonSubreporters.import.finish();
|
||||||
loadRawProfile(gImportFromAddonSubreporters.parsing, rawProfile);
|
loadRawProfile(gImportFromAddonSubreporters.parsing, rawProfile);
|
||||||
@ -1393,7 +1555,7 @@ function toggleJavascriptOnly() {
|
|||||||
|
|
||||||
var gSampleFilters = [];
|
var gSampleFilters = [];
|
||||||
function focusOnSymbol(focusSymbol, name) {
|
function focusOnSymbol(focusSymbol, name) {
|
||||||
var newFilterChain = gSampleFilters.concat([{type: "FocusedFrameSampleFilter", focusedSymbol: focusSymbol}]);
|
var newFilterChain = gSampleFilters.concat([{type: "FocusedFrameSampleFilter", name: name, focusedSymbol: focusSymbol}]);
|
||||||
gBreadcrumbTrail.addAndEnter({
|
gBreadcrumbTrail.addAndEnter({
|
||||||
title: name,
|
title: name,
|
||||||
enterCallback: function () {
|
enterCallback: function () {
|
||||||
@ -1403,10 +1565,16 @@ function focusOnSymbol(focusSymbol, name) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function focusOnCallstack(focusedCallstack, name) {
|
function focusOnCallstack(focusedCallstack, name, overwriteCallstack) {
|
||||||
|
var invertCallback = gInvertCallstack;
|
||||||
|
if (overwriteCallstack != null) {
|
||||||
|
invertCallstack = overwriteCallstack;
|
||||||
|
}
|
||||||
var filter = {
|
var filter = {
|
||||||
type: gInvertCallstack ? "FocusedCallstackPostfixSampleFilter" : "FocusedCallstackPrefixSampleFilter",
|
type: !invertCallstack ? "FocusedCallstackPostfixSampleFilter" : "FocusedCallstackPrefixSampleFilter",
|
||||||
focusedCallstack: focusedCallstack
|
name: name,
|
||||||
|
focusedCallstack: focusedCallstack,
|
||||||
|
appliesToJS: gJavascriptOnly
|
||||||
};
|
};
|
||||||
var newFilterChain = gSampleFilters.concat([filter]);
|
var newFilterChain = gSampleFilters.concat([filter]);
|
||||||
gBreadcrumbTrail.addAndEnter({
|
gBreadcrumbTrail.addAndEnter({
|
||||||
@ -1450,30 +1618,24 @@ function setHighlightedCallstack(samples, heaviestSample) {
|
|||||||
// Always show heavy
|
// Always show heavy
|
||||||
heaviestSample = heaviestSample.clone().reverse();
|
heaviestSample = heaviestSample.clone().reverse();
|
||||||
}
|
}
|
||||||
if (gSampleBar)
|
|
||||||
|
if (gSampleBar) {
|
||||||
gSampleBar.setSample(heaviestSample);
|
gSampleBar.setSample(heaviestSample);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function enterMainUI(isLightMode) {
|
function enterMainUI() {
|
||||||
if (isLightMode !== undefined) {
|
|
||||||
gLightMode = isLightMode;
|
|
||||||
if (gLightMode) {
|
|
||||||
gJavascriptOnly = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var uiContainer = document.createElement("div");
|
var uiContainer = document.createElement("div");
|
||||||
uiContainer.id = "ui";
|
uiContainer.id = "ui";
|
||||||
|
|
||||||
//gFileList.loadProfileListFromLocalStorage();
|
|
||||||
if (!gLightMode) {
|
|
||||||
gFileList = new FileList();
|
gFileList = new FileList();
|
||||||
uiContainer.appendChild(gFileList.getContainer());
|
uiContainer.appendChild(gFileList.getContainer());
|
||||||
|
|
||||||
gFileList.addFile();
|
//gFileList.addFile();
|
||||||
|
gFileList.loadProfileListFromLocalStorage();
|
||||||
|
|
||||||
gInfoBar = new InfoBar();
|
gInfoBar = new InfoBar();
|
||||||
uiContainer.appendChild(gInfoBar.getContainer());
|
uiContainer.appendChild(gInfoBar.getContainer());
|
||||||
}
|
|
||||||
|
|
||||||
gMainArea = document.createElement("div");
|
gMainArea = document.createElement("div");
|
||||||
gMainArea.id = "mainarea";
|
gMainArea.id = "mainarea";
|
||||||
@ -1522,9 +1684,7 @@ function enterProgressUI() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function enterFinishedProfileUI() {
|
function enterFinishedProfileUI() {
|
||||||
//dump("prepare to save\n");
|
saveProfileToLocalStorage();
|
||||||
//saveProfileToLocalStorage();
|
|
||||||
//dump("prepare to saved\n");
|
|
||||||
|
|
||||||
var finishedProfilePaneBackgroundCover = document.createElement("div");
|
var finishedProfilePaneBackgroundCover = document.createElement("div");
|
||||||
finishedProfilePaneBackgroundCover.className = "finishedProfilePaneBackgroundCover";
|
finishedProfilePaneBackgroundCover.className = "finishedProfilePaneBackgroundCover";
|
||||||
@ -1544,7 +1704,7 @@ function enterFinishedProfileUI() {
|
|||||||
// until some actions happen such as focusing this box
|
// until some actions happen such as focusing this box
|
||||||
var filterNameInput = document.getElementById("filterName");
|
var filterNameInput = document.getElementById("filterName");
|
||||||
if (filterNameInput != null) {
|
if (filterNameInput != null) {
|
||||||
filterNameInput.focus();
|
changeFocus(filterNameInput);
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
@ -1556,7 +1716,13 @@ function enterFinishedProfileUI() {
|
|||||||
currRow = finishedProfilePane.insertRow(rowIndex++);
|
currRow = finishedProfilePane.insertRow(rowIndex++);
|
||||||
currRow.insertCell(0).appendChild(gHistogramView.getContainer());
|
currRow.insertCell(0).appendChild(gHistogramView.getContainer());
|
||||||
|
|
||||||
if (typeof DiagnosticBar !== "undefined") {
|
if (false && gLocation.indexOf("file:") == 0) {
|
||||||
|
// Local testing for frameView
|
||||||
|
gFrameView = new FrameView();
|
||||||
|
currRow = finishedProfilePane.insertRow(rowIndex++);
|
||||||
|
currRow.insertCell(0).appendChild(gFrameView.getContainer());
|
||||||
|
}
|
||||||
|
|
||||||
gDiagnosticBar = new DiagnosticBar();
|
gDiagnosticBar = new DiagnosticBar();
|
||||||
gDiagnosticBar.setDetailsListener(function(details) {
|
gDiagnosticBar.setDetailsListener(function(details) {
|
||||||
if (details.indexOf("bug ") == 0) {
|
if (details.indexOf("bug ") == 0) {
|
||||||
@ -1569,14 +1735,13 @@ function enterFinishedProfileUI() {
|
|||||||
});
|
});
|
||||||
currRow = finishedProfilePane.insertRow(rowIndex++);
|
currRow = finishedProfilePane.insertRow(rowIndex++);
|
||||||
currRow.insertCell(0).appendChild(gDiagnosticBar.getContainer());
|
currRow.insertCell(0).appendChild(gDiagnosticBar.getContainer());
|
||||||
}
|
|
||||||
|
|
||||||
// For testing:
|
// For testing:
|
||||||
//gMeta.videoCapture = {
|
//gMeta.videoCapture = {
|
||||||
// src: "http://videos-cdn.mozilla.net/brand/Mozilla_Firefox_Manifesto_v0.2_640.webm",
|
// src: "http://videos-cdn.mozilla.net/brand/Mozilla_Firefox_Manifesto_v0.2_640.webm",
|
||||||
//};
|
//};
|
||||||
|
|
||||||
if (!gLightMode && gMeta && gMeta.videoCapture) {
|
if (gMeta && gMeta.videoCapture) {
|
||||||
gVideoPane = new VideoPane(gMeta.videoCapture);
|
gVideoPane = new VideoPane(gMeta.videoCapture);
|
||||||
gVideoPane.onTimeChange(videoPaneTimeChange);
|
gVideoPane.onTimeChange(videoPaneTimeChange);
|
||||||
currRow = finishedProfilePane.insertRow(rowIndex++);
|
currRow = finishedProfilePane.insertRow(rowIndex++);
|
||||||
@ -1595,22 +1760,19 @@ function enterFinishedProfileUI() {
|
|||||||
cell.appendChild(treeContainerDiv);
|
cell.appendChild(treeContainerDiv);
|
||||||
treeContainerDiv.appendChild(gTreeManager.getContainer());
|
treeContainerDiv.appendChild(gTreeManager.getContainer());
|
||||||
|
|
||||||
if (!gLightMode) {
|
|
||||||
gSampleBar = new SampleBar();
|
gSampleBar = new SampleBar();
|
||||||
treeContainerDiv.appendChild(gSampleBar.getContainer());
|
treeContainerDiv.appendChild(gSampleBar.getContainer());
|
||||||
}
|
|
||||||
|
|
||||||
// sampleBar
|
// sampleBar
|
||||||
|
|
||||||
if (!gLightMode) {
|
|
||||||
gPluginView = new PluginView();
|
gPluginView = new PluginView();
|
||||||
//currRow = finishedProfilePane.insertRow(4);
|
//currRow = finishedProfilePane.insertRow(4);
|
||||||
treeContainerDiv.appendChild(gPluginView.getContainer());
|
treeContainerDiv.appendChild(gPluginView.getContainer());
|
||||||
}
|
|
||||||
|
|
||||||
gMainArea.appendChild(finishedProfilePaneBackgroundCover);
|
gMainArea.appendChild(finishedProfilePaneBackgroundCover);
|
||||||
gMainArea.appendChild(finishedProfilePane);
|
gMainArea.appendChild(finishedProfilePane);
|
||||||
|
|
||||||
|
var currentBreadcrumb = gSampleFilters;
|
||||||
gBreadcrumbTrail.add({
|
gBreadcrumbTrail.add({
|
||||||
title: "Complete Profile",
|
title: "Complete Profile",
|
||||||
enterCallback: function () {
|
enterCallback: function () {
|
||||||
@ -1618,16 +1780,66 @@ function enterFinishedProfileUI() {
|
|||||||
filtersChanged();
|
filtersChanged();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
if (currentBreadcrumb == null || currentBreadcrumb.length == 0) {
|
||||||
|
gTreeManager.restoreSerializedSelectionSnapshot(gRestoreSelection);
|
||||||
|
viewOptionsChanged();
|
||||||
|
}
|
||||||
|
for (var i = 0; i < currentBreadcrumb.length; i++) {
|
||||||
|
var filter = currentBreadcrumb[i];
|
||||||
|
var forceSelection = null;
|
||||||
|
if (gRestoreSelection != null && i == currentBreadcrumb.length - 1) {
|
||||||
|
forceSelection = gRestoreSelection;
|
||||||
|
}
|
||||||
|
switch (filter.type) {
|
||||||
|
case "FocusedFrameSampleFilter":
|
||||||
|
focusOnSymbol(filter.name, filter.symbolName);
|
||||||
|
gBreadcrumbTrail.enterLastItem(forceSelection);
|
||||||
|
case "FocusedCallstackPrefixSampleFilter":
|
||||||
|
focusOnCallstack(filter.focusedCallstack, filter.name, false);
|
||||||
|
gBreadcrumbTrail.enterLastItem(forceSelection);
|
||||||
|
case "FocusedCallstackPostfixSampleFilter":
|
||||||
|
focusOnCallstack(filter.focusedCallstack, filter.name, true);
|
||||||
|
gBreadcrumbTrail.enterLastItem(forceSelection);
|
||||||
|
case "RangeSampleFilter":
|
||||||
|
gHistogramView.selectRange(filter.start, filter.end);
|
||||||
|
gBreadcrumbTrail.enterLastItem(forceSelection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make all focus change events go through this function.
|
||||||
|
// This function will mediate the focus changes in case
|
||||||
|
// that we're in a compare view. In a compare view an inactive
|
||||||
|
// instance of cleopatra should not steal focus from the active
|
||||||
|
// cleopatra instance.
|
||||||
|
function changeFocus(elem) {
|
||||||
|
if (window.comparator_changeFocus) {
|
||||||
|
window.comparator_changeFocus(elem);
|
||||||
|
} else {
|
||||||
|
PROFILERLOG("FOCUS\n\n\n\n\n\n\n\n\n");
|
||||||
|
elem.focus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function comparator_receiveSelection(snapshot, frameData) {
|
||||||
|
gTreeManager.restoreSerializedSelectionSnapshot(snapshot);
|
||||||
|
if (frameData)
|
||||||
|
gTreeManager.highlightFrame(frameData);
|
||||||
|
viewOptionsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
function filtersChanged() {
|
function filtersChanged() {
|
||||||
|
if (window.comparator_setSelection) {
|
||||||
|
// window.comparator_setSelection(gTreeManager.serializeCurrentSelectionSnapshot(), null);
|
||||||
|
}
|
||||||
|
updateDocumentURL();
|
||||||
var data = { symbols: {}, functions: {}, samples: [] };
|
var data = { symbols: {}, functions: {}, samples: [] };
|
||||||
|
|
||||||
gHistogramView.dataIsOutdated();
|
gHistogramView.dataIsOutdated();
|
||||||
var filterNameInput = document.getElementById("filterName");
|
var filterNameInput = document.getElementById("filterName");
|
||||||
var updateRequest = Parser.updateFilters({
|
var updateRequest = Parser.updateFilters({
|
||||||
mergeFunctions: gMergeFunctions,
|
mergeFunctions: gMergeFunctions,
|
||||||
nameFilter: (filterNameInput && filterNameInput.value) || "",
|
nameFilter: (filterNameInput && filterNameInput.value) || gQueryParamFilterName || "",
|
||||||
sampleFilters: gSampleFilters,
|
sampleFilters: gSampleFilters,
|
||||||
jankOnly: gJankOnly,
|
jankOnly: gJankOnly,
|
||||||
javascriptOnly: gJavascriptOnly
|
javascriptOnly: gJavascriptOnly
|
||||||
@ -1636,15 +1848,14 @@ function filtersChanged() {
|
|||||||
updateRequest.addEventListener("finished", function (filteredSamples) {
|
updateRequest.addEventListener("finished", function (filteredSamples) {
|
||||||
console.log("profile filtering (in worker): " + (Date.now() - start) + "ms.");
|
console.log("profile filtering (in worker): " + (Date.now() - start) + "ms.");
|
||||||
gCurrentlyShownSampleData = filteredSamples;
|
gCurrentlyShownSampleData = filteredSamples;
|
||||||
if (gInfoBar)
|
|
||||||
gInfoBar.display();
|
gInfoBar.display();
|
||||||
|
|
||||||
if (gPluginView && gSampleFilters.length > 0 && gSampleFilters[gSampleFilters.length-1].type === "PluginView") {
|
if (gSampleFilters.length > 0 && gSampleFilters[gSampleFilters.length-1].type === "PluginView") {
|
||||||
start = Date.now();
|
start = Date.now();
|
||||||
gPluginView.display(gSampleFilters[gSampleFilters.length-1].pluginName, gSampleFilters[gSampleFilters.length-1].param,
|
gPluginView.display(gSampleFilters[gSampleFilters.length-1].pluginName, gSampleFilters[gSampleFilters.length-1].param,
|
||||||
gCurrentlyShownSampleData, gHighlightedCallstack);
|
gCurrentlyShownSampleData, gHighlightedCallstack);
|
||||||
console.log("plugin displaying: " + (Date.now() - start) + "ms.");
|
console.log("plugin displaying: " + (Date.now() - start) + "ms.");
|
||||||
} else if (gPluginView) {
|
} else {
|
||||||
gPluginView.hide();
|
gPluginView.hide();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -1653,6 +1864,8 @@ function filtersChanged() {
|
|||||||
histogramRequest.addEventListener("finished", function (data) {
|
histogramRequest.addEventListener("finished", function (data) {
|
||||||
start = Date.now();
|
start = Date.now();
|
||||||
gHistogramView.display(data.histogramData, data.frameStart, data.widthSum, gHighlightedCallstack);
|
gHistogramView.display(data.histogramData, data.frameStart, data.widthSum, gHighlightedCallstack);
|
||||||
|
if (gFrameView)
|
||||||
|
gFrameView.display(data.histogramData, data.frameStart, data.widthSum, gHighlightedCallstack);
|
||||||
console.log("histogram displaying: " + (Date.now() - start) + "ms.");
|
console.log("histogram displaying: " + (Date.now() - start) + "ms.");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1677,7 +1890,118 @@ function viewOptionsChanged() {
|
|||||||
});
|
});
|
||||||
updateViewOptionsRequest.addEventListener("finished", function (calltree) {
|
updateViewOptionsRequest.addEventListener("finished", function (calltree) {
|
||||||
var start = Date.now();
|
var start = Date.now();
|
||||||
gTreeManager.display(calltree, gSymbols, gFunctions, gMergeFunctions, filterNameInput && filterNameInput.value);
|
gTreeManager.display(calltree, gSymbols, gFunctions, gResources, gMergeFunctions, filterNameInput && filterNameInput.value);
|
||||||
console.log("tree displaying: " + (Date.now() - start) + "ms.");
|
console.log("tree displaying: " + (Date.now() - start) + "ms.");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function loadQueryData(queryData) {
|
||||||
|
var isFiltersChanged = false;
|
||||||
|
var queryDataOriginal = queryData;
|
||||||
|
var queryData = {};
|
||||||
|
for (var i in queryDataOriginal) {
|
||||||
|
queryData[i] = unQueryEscape(queryDataOriginal[i]);
|
||||||
|
}
|
||||||
|
if (queryData.search) {
|
||||||
|
gQueryParamFilterName = queryData.search;
|
||||||
|
isFiltersChanged = true;
|
||||||
|
}
|
||||||
|
if (queryData.jankOnly) {
|
||||||
|
gJankOnly = queryData.jankOnly;
|
||||||
|
isFiltersChanged = true;
|
||||||
|
}
|
||||||
|
if (queryData.javascriptOnly) {
|
||||||
|
gJavascriptOnly = queryData.javascriptOnly;
|
||||||
|
isFiltersChanged = true;
|
||||||
|
}
|
||||||
|
if (queryData.mergeUnbranched) {
|
||||||
|
gMergeUnbranched = queryData.mergeUnbranched;
|
||||||
|
isFiltersChanged = true;
|
||||||
|
}
|
||||||
|
if (queryData.invertCallback) {
|
||||||
|
gInvertCallstack = queryData.invertCallback;
|
||||||
|
isFiltersChanged = true;
|
||||||
|
}
|
||||||
|
if (queryData.report) {
|
||||||
|
gReportID = queryData.report;
|
||||||
|
}
|
||||||
|
if (queryData.filter) {
|
||||||
|
var filterChain = JSON.parse(queryData.filter);
|
||||||
|
gSampleFilters = filterChain;
|
||||||
|
}
|
||||||
|
if (queryData.selection) {
|
||||||
|
var selection = queryData.selection;
|
||||||
|
gRestoreSelection = selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFiltersChanged) {
|
||||||
|
//filtersChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function unQueryEscape(str) {
|
||||||
|
return decodeURIComponent(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
function queryEscape(str) {
|
||||||
|
return encodeURIComponent(encodeURIComponent(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateDocumentURL() {
|
||||||
|
location.hash = getDocumentHashString();
|
||||||
|
return document.location;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDocumentHashString() {
|
||||||
|
var query = "";
|
||||||
|
if (gReportID) {
|
||||||
|
if (query != "")
|
||||||
|
query += "&";
|
||||||
|
query += "report=" + queryEscape(gReportID);
|
||||||
|
}
|
||||||
|
if (document.getElementById("filterName") != null &&
|
||||||
|
document.getElementById("filterName").value != null &&
|
||||||
|
document.getElementById("filterName").value != "") {
|
||||||
|
if (query != "")
|
||||||
|
query += "&";
|
||||||
|
query += "search=" + queryEscape(document.getElementById("filterName").value);
|
||||||
|
}
|
||||||
|
// For now don't restore the view rest
|
||||||
|
return query;
|
||||||
|
if (gJankOnly) {
|
||||||
|
if (query != "")
|
||||||
|
query += "&";
|
||||||
|
query += "jankOnly=" + queryEscape(gJankOnly);
|
||||||
|
}
|
||||||
|
if (gJavascriptOnly) {
|
||||||
|
if (query != "")
|
||||||
|
query += "&";
|
||||||
|
query += "javascriptOnly=" + queryEscape(gJavascriptOnly);
|
||||||
|
}
|
||||||
|
if (gMergeUnbranched) {
|
||||||
|
if (query != "")
|
||||||
|
query += "&";
|
||||||
|
query += "mergeUnbranched=" + queryEscape(gMergeUnbranched);
|
||||||
|
}
|
||||||
|
if (gInvertCallstack) {
|
||||||
|
if (query != "")
|
||||||
|
query += "&";
|
||||||
|
query += "invertCallback=" + queryEscape(gInvertCallstack);
|
||||||
|
}
|
||||||
|
if (gSampleFilters && gSampleFilters.length != 0) {
|
||||||
|
if (query != "")
|
||||||
|
query += "&";
|
||||||
|
query += "filter=" + queryEscape(JSON.stringify(gSampleFilters));
|
||||||
|
}
|
||||||
|
if (gTreeManager.hasNonTrivialSelection()) {
|
||||||
|
if (query != "")
|
||||||
|
query += "&";
|
||||||
|
query += "selection=" + queryEscape(gTreeManager.serializeCurrentSelectionSnapshot());
|
||||||
|
}
|
||||||
|
if (!gReportID) {
|
||||||
|
query = "uploadProfileFirst!";
|
||||||
|
}
|
||||||
|
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user