mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1326331 - Fix Eslint errors in devtools/shared/heapsnapshot/. r=jryans
This commit is contained in:
parent
390377b549
commit
984e39dd2c
@ -130,7 +130,6 @@ devtools/server/tests/browser/storage-*.html
|
||||
devtools/server/tests/browser/stylesheets-nested-iframes.html
|
||||
devtools/server/tests/mochitest/**
|
||||
devtools/server/tests/unit/**
|
||||
devtools/shared/heapsnapshot/**
|
||||
devtools/shared/platform/content/test/test_clipboard.html
|
||||
devtools/shared/qrcode/tests/mochitest/test_decode.html
|
||||
devtools/shared/tests/mochitest/*.html
|
||||
|
@ -141,8 +141,9 @@ function recursiveWalk(breakdown, edge, report, visitor) {
|
||||
visitor.exit(breakdown, report, edge);
|
||||
} else {
|
||||
visitor.enter(breakdown, report, edge);
|
||||
for (let { edge, referent, breakdown: subBreakdown } of getReportEdges(breakdown, report)) {
|
||||
recursiveWalk(subBreakdown, edge, referent, visitor);
|
||||
for (let { edge: ed, referent, breakdown: subBreakdown }
|
||||
of getReportEdges(breakdown, report)) {
|
||||
recursiveWalk(subBreakdown, ed, referent, visitor);
|
||||
}
|
||||
visitor.exit(breakdown, report, edge);
|
||||
}
|
||||
@ -236,8 +237,6 @@ DiffVisitor.prototype._set = function (report, edge, val) {
|
||||
* @overrides Visitor.prototype.enter
|
||||
*/
|
||||
DiffVisitor.prototype.enter = function (breakdown, report, edge) {
|
||||
const isFirstTimeEntering = this._results === null;
|
||||
|
||||
const newResults = breakdown.by === "allocationStack" ? new Map() : {};
|
||||
let newOther;
|
||||
|
||||
@ -274,8 +273,8 @@ DiffVisitor.prototype.exit = function (breakdown, report, edge) {
|
||||
.map(e => e.edge)
|
||||
.filter(e => !visited.has(e));
|
||||
const results = this._resultsStack[this._resultsStack.length - 1];
|
||||
for (let edge of unvisited) {
|
||||
this._set(results, edge, this._get(other, edge));
|
||||
for (let edg of unvisited) {
|
||||
this._set(results, edg, this._get(other, edg));
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,9 +375,7 @@ exports.diff = diff;
|
||||
*
|
||||
* @return {Object<number, TreeNode>}
|
||||
*/
|
||||
const createParentMap = exports.createParentMap = function (node,
|
||||
getId = node => node.id,
|
||||
aggregator = Object.create(null)) {
|
||||
const createParentMap = function (node, getId = n => n.id, aggregator = {}) {
|
||||
if (node.children) {
|
||||
for (let i = 0, length = node.children.length; i < length; i++) {
|
||||
const child = node.children[i];
|
||||
@ -386,9 +383,9 @@ const createParentMap = exports.createParentMap = function (node,
|
||||
createParentMap(child, getId, aggregator);
|
||||
}
|
||||
}
|
||||
|
||||
return aggregator;
|
||||
};
|
||||
exports.createParentMap = createParentMap;
|
||||
|
||||
const BUCKET = Object.freeze({ by: "bucket" });
|
||||
|
||||
|
@ -237,7 +237,7 @@ DominatorTreeNode.partialTraversal = function (dominatorTree,
|
||||
*
|
||||
* @returns {DominatorTreeNode}
|
||||
*/
|
||||
DominatorTreeNode.insert = function (tree, path, newChildren, moreChildrenAvailable) {
|
||||
DominatorTreeNode.insert = function (nodeTree, path, newChildren, moreChildrenAvailable) {
|
||||
function insert(tree, i) {
|
||||
if (tree.nodeId !== path[i]) {
|
||||
return tree;
|
||||
@ -257,7 +257,7 @@ DominatorTreeNode.insert = function (tree, path, newChildren, moreChildrenAvaila
|
||||
: tree;
|
||||
}
|
||||
|
||||
return insert(tree, 0);
|
||||
return insert(nodeTree, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -8,6 +8,8 @@
|
||||
// HeapAnalysesWorker is owned and communicated with by a HeapAnalysesClient
|
||||
// instance. See HeapAnalysesClient.js.
|
||||
|
||||
/* global importScripts, workerHelper, self */
|
||||
|
||||
"use strict";
|
||||
|
||||
importScripts("resource://gre/modules/workers/require.js");
|
||||
@ -70,7 +72,8 @@ workerHelper.createTask(self, "deleteHeapSnapshot", ({ snapshotFilePath }) => {
|
||||
/**
|
||||
* @see HeapAnalysesClient.prototype.takeCensus
|
||||
*/
|
||||
workerHelper.createTask(self, "takeCensus", ({ snapshotFilePath, censusOptions, requestOptions }) => {
|
||||
workerHelper.createTask(self, "takeCensus", (
|
||||
{ snapshotFilePath, censusOptions, requestOptions }) => {
|
||||
if (!snapshots[snapshotFilePath]) {
|
||||
throw new Error(`No known heap snapshot for '${snapshotFilePath}'`);
|
||||
}
|
||||
@ -206,7 +209,7 @@ workerHelper.createTask(self, "getDominatorTree", request => {
|
||||
maxRetainingPaths,
|
||||
} = request;
|
||||
|
||||
if (!(0 <= dominatorTreeId && dominatorTreeId < dominatorTrees.length)) {
|
||||
if (!(dominatorTreeId >= 0 && dominatorTreeId < dominatorTrees.length)) {
|
||||
throw new Error(
|
||||
`There does not exist a DominatorTree with the id ${dominatorTreeId}`);
|
||||
}
|
||||
@ -252,7 +255,7 @@ workerHelper.createTask(self, "getImmediatelyDominated", request => {
|
||||
maxRetainingPaths,
|
||||
} = request;
|
||||
|
||||
if (!(0 <= dominatorTreeId && dominatorTreeId < dominatorTrees.length)) {
|
||||
if (!(dominatorTreeId >= 0 && dominatorTreeId < dominatorTrees.length)) {
|
||||
throw new Error(
|
||||
`There does not exist a DominatorTree with the id ${dominatorTreeId}`);
|
||||
}
|
||||
|
@ -74,6 +74,7 @@ CensusTreeNodeCacheValue.prototype = null;
|
||||
* The unique string that can be used as a key in a CensusTreeNodeCache.
|
||||
*/
|
||||
CensusTreeNodeCache.hashFrame = function (frame) {
|
||||
// eslint-disable-next-line max-len
|
||||
return `FRAME,${frame.functionDisplayName},${frame.source},${frame.line},${frame.column},${frame.asyncCause}`;
|
||||
};
|
||||
|
||||
|
@ -48,6 +48,7 @@ exports.deduplicatePaths = function (target, paths) {
|
||||
nameSet.add(name);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-labels
|
||||
outer: for (let path of paths) {
|
||||
const pathLength = path.length;
|
||||
|
||||
@ -57,6 +58,7 @@ exports.deduplicatePaths = function (target, paths) {
|
||||
predecessorsSeen.add(target);
|
||||
for (let i = 0; i < pathLength; i++) {
|
||||
if (predecessorsSeen.has(path[i].predecessor)) {
|
||||
// eslint-disable-next-line no-labels
|
||||
continue outer;
|
||||
}
|
||||
predecessorsSeen.add(path[i].predecessor);
|
||||
|
10
devtools/shared/heapsnapshot/tests/mochitest/.eslintrc.js
Normal file
10
devtools/shared/heapsnapshot/tests/mochitest/.eslintrc.js
Normal file
@ -0,0 +1,10 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = {
|
||||
// Extend from the shared list of defined globals for mochitests.
|
||||
"extends": "../../../../.eslintrc.mochitests.js",
|
||||
"globals": {
|
||||
"ChromeUtils": true,
|
||||
"sendAsyncMessage": true,
|
||||
}
|
||||
};
|
@ -12,8 +12,11 @@ Sanity test that we can compute dominator trees from a heap snapshot in a web wi
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script>
|
||||
"use strict";
|
||||
/* global window, ChromeUtils, DominatorTree */
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
window.onload = function() {
|
||||
window.onload = function () {
|
||||
const path = ChromeUtils.saveHeapSnapshot({ runtime: true });
|
||||
const snapshot = ChromeUtils.readHeapSnapshot(path);
|
||||
|
||||
|
@ -12,8 +12,10 @@ Bug 1024774 - Sanity test that we can take a heap snapshot in a web window.
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
window.onload = function() {
|
||||
window.onload = function () {
|
||||
ok(ChromeUtils, "The ChromeUtils interface should be exposed in chrome windows.");
|
||||
ChromeUtils.saveHeapSnapshot({ runtime: true });
|
||||
ok(true, "Should save a heap snapshot and shouldn't throw.");
|
||||
|
@ -12,70 +12,70 @@ Bug 1201597 - Sanity test that we can take a heap snapshot in an e10s child proc
|
||||
</head>
|
||||
<body>
|
||||
<script type="application/javascript">
|
||||
window.onerror = function (msg, url, line, col, err) {
|
||||
ok(false, "@" + url + ":" + line + ":" + col + ": " + msg + "\n" + err.stack);
|
||||
};
|
||||
"use strict";
|
||||
window.onerror = function (msg, url, line, col, err) {
|
||||
ok(false, "@" + url + ":" + line + ":" + col + ": " + msg + "\n" + err.stack);
|
||||
};
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
var childFrameURL = "data:text/html,<!DOCTYPE HTML><html><body></body></html>";
|
||||
var childFrameURL = "data:text/html,<!DOCTYPE HTML><html><body></body></html>";
|
||||
|
||||
// This function is stringified and loaded in the child process as a frame
|
||||
// script.
|
||||
function childFrameScript() {
|
||||
try {
|
||||
ChromeUtils.saveHeapSnapshot({ runtime: true });
|
||||
} catch (err) {
|
||||
sendAsyncMessage("testSaveHeapSnapshot:error",
|
||||
{ error: err.toString() });
|
||||
return;
|
||||
}
|
||||
// This function is stringified and loaded in the child process as a frame
|
||||
// script.
|
||||
function childFrameScript() {
|
||||
try {
|
||||
ChromeUtils.saveHeapSnapshot({ runtime: true });
|
||||
} catch (err) {
|
||||
sendAsyncMessage("testSaveHeapSnapshot:error",
|
||||
{ error: err.toString() });
|
||||
return;
|
||||
}
|
||||
|
||||
sendAsyncMessage("testSaveHeapSnapshot:done", {});
|
||||
}
|
||||
sendAsyncMessage("testSaveHeapSnapshot:done", {});
|
||||
}
|
||||
|
||||
// Kick everything off on load.
|
||||
window.onload = function () {
|
||||
info("window.onload fired");
|
||||
SpecialPowers.addPermission("browser", true, document);
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": [
|
||||
["dom.ipc.browser_frames.oop_by_default", true],
|
||||
["dom.mozBrowserFramesEnabled", true],
|
||||
["browser.pagethumbnails.capturing_disabled", true]
|
||||
]
|
||||
}, function () {
|
||||
var iframe = document.createElement("iframe");
|
||||
SpecialPowers.wrap(iframe).mozbrowser = true;
|
||||
iframe.id = "iframe";
|
||||
iframe.src = childFrameURL;
|
||||
// Kick everything off on load.
|
||||
window.onload = function () {
|
||||
info("window.onload fired");
|
||||
SpecialPowers.addPermission("browser", true, document);
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": [
|
||||
["dom.ipc.browser_frames.oop_by_default", true],
|
||||
["dom.mozBrowserFramesEnabled", true],
|
||||
["browser.pagethumbnails.capturing_disabled", true]
|
||||
]
|
||||
}, function () {
|
||||
let iframe = document.createElement("iframe");
|
||||
SpecialPowers.wrap(iframe).mozbrowser = true;
|
||||
iframe.id = "iframe";
|
||||
iframe.src = childFrameURL;
|
||||
|
||||
iframe.addEventListener("mozbrowserloadend", function () {
|
||||
info("iframe done loading");
|
||||
|
||||
iframe.addEventListener("mozbrowserloadend", function () {
|
||||
info("iframe done loading");
|
||||
let mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
|
||||
|
||||
var mm = SpecialPowers.getBrowserFrameMessageManager(iframe);
|
||||
function onError(e) {
|
||||
ok(false, e.data.error);
|
||||
}
|
||||
mm.addMessageListener("testSaveHeapSnapshot:error", onError);
|
||||
|
||||
function onError(e) {
|
||||
ok(false, e.data.error);
|
||||
}
|
||||
mm.addMessageListener("testSaveHeapSnapshot:error", onError);
|
||||
mm.addMessageListener("testSaveHeapSnapshot:done", function onMsg() {
|
||||
mm.removeMessageListener("testSaveHeapSnapshot:done", onMsg);
|
||||
mm.removeMessageListener("testSaveHeapSnapshot:error", onError);
|
||||
ok(true, "Saved heap snapshot in child process");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
mm.addMessageListener("testSaveHeapSnapshot:done", function onMsg() {
|
||||
mm.removeMessageListener("testSaveHeapSnapshot:done", onMsg);
|
||||
mm.removeMessageListener("testSaveHeapSnapshot:error", onError);
|
||||
ok(true, "Saved heap snapshot in child process");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
info("Loading frame script to save heap snapshot");
|
||||
mm.loadFrameScript("data:,(" + encodeURI(childFrameScript.toString()) + ")();",
|
||||
false);
|
||||
}, {once: true});
|
||||
|
||||
info("Loading frame script to save heap snapshot");
|
||||
mm.loadFrameScript("data:,(" + encodeURI(childFrameScript.toString()) + ")();",
|
||||
false);
|
||||
}, {once: true});
|
||||
|
||||
info("Loading iframe");
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
info("Loading iframe");
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
</window>
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Debugger.Memory.prototype.takeCensus and
|
||||
// HeapSnapshot.prototype.takeCensus. Adapted from js/src/jit-test/lib/census.js.
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Census"];
|
||||
|
||||
this.Census = (function () {
|
||||
@ -62,7 +64,11 @@ this.Census = (function () {
|
||||
Census.assertAllZeros = {
|
||||
enter: () => Census.assertAllZeros,
|
||||
done: () => undefined,
|
||||
check: elt => { if (elt !== 0) throw new Error("Census mismatch: expected zero, found " + elt); }
|
||||
check: elt => {
|
||||
if (elt !== 0) {
|
||||
throw new Error("Census mismatch: expected zero, found " + elt);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function expectedObject() {
|
||||
@ -89,27 +95,27 @@ this.Census = (function () {
|
||||
function makeBasisChecker({compare, missing, extra}) {
|
||||
return function makeWalker(basis) {
|
||||
if (typeof basis === "object") {
|
||||
var unvisited = new Set(Object.getOwnPropertyNames(basis));
|
||||
let unvisited = new Set(Object.getOwnPropertyNames(basis));
|
||||
return {
|
||||
enter: prop => {
|
||||
unvisited.delete(prop);
|
||||
if (prop in basis) {
|
||||
return makeWalker(basis[prop]);
|
||||
} else {
|
||||
return extra(prop);
|
||||
}
|
||||
|
||||
return extra(prop);
|
||||
},
|
||||
|
||||
done: () => unvisited.forEach(prop => missing(prop, basis[prop])),
|
||||
check: expectedObject
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
enter: expectedLeaf,
|
||||
done: expectedLeaf,
|
||||
check: elt => compare(elt, basis)
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
enter: expectedLeaf,
|
||||
done: expectedLeaf,
|
||||
check: elt => compare(elt, basis)
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@ -118,13 +124,18 @@ this.Census = (function () {
|
||||
}
|
||||
|
||||
function extraProp(prop) {
|
||||
throw new Error("Census mismatch: subject has property not present in basis: " + prop);
|
||||
throw new Error("Census mismatch: subject has property not present in basis: "
|
||||
+ prop);
|
||||
}
|
||||
|
||||
// Return a walker that checks that the subject census has counts all equal to
|
||||
// |basis|.
|
||||
Census.assertAllEqual = makeBasisChecker({
|
||||
compare: (a, b) => { if (a !== b) throw new Error("Census mismatch: expected " + a + " got " + b);},
|
||||
compare: (a, b) => {
|
||||
if (a !== b) {
|
||||
throw new Error("Census mismatch: expected " + a + " got " + b);
|
||||
}
|
||||
},
|
||||
missing: missingProp,
|
||||
extra: extraProp
|
||||
});
|
||||
@ -155,7 +166,7 @@ this.Census = (function () {
|
||||
// items of each category of the count in |basis|.
|
||||
Census.assertAllWithin = function (fudge, basis) {
|
||||
return makeBasisChecker({
|
||||
compare: (subject, basis) => ok(Math.abs(subject - basis) <= fudge),
|
||||
compare: (subject, base) => ok(Math.abs(subject - base) <= fudge),
|
||||
missing: missingProp,
|
||||
extra: () => Census.walkAnything
|
||||
})(basis);
|
||||
|
@ -3,188 +3,212 @@
|
||||
// Ported from js/src/tests/js1_8_5/reflect-parse/Match.js for use with devtools
|
||||
// server xpcshell tests.
|
||||
|
||||
"use strict";
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["Match"];
|
||||
|
||||
this.Match = (function() {
|
||||
|
||||
function Pattern(template) {
|
||||
// act like a constructor even as a function
|
||||
if (!(this instanceof Pattern))
|
||||
return new Pattern(template);
|
||||
|
||||
this.template = template;
|
||||
this.Match = (function () {
|
||||
function Pattern(template) {
|
||||
// act like a constructor even as a function
|
||||
if (!(this instanceof Pattern)) {
|
||||
return new Pattern(template);
|
||||
}
|
||||
|
||||
Pattern.prototype = {
|
||||
match: function(act) {
|
||||
return match(act, this.template);
|
||||
},
|
||||
this.template = template;
|
||||
}
|
||||
|
||||
matches: function(act) {
|
||||
try {
|
||||
return this.match(act);
|
||||
}
|
||||
catch (e if e instanceof MatchError) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
Pattern.prototype = {
|
||||
match: function (act) {
|
||||
return match(act, this.template);
|
||||
},
|
||||
|
||||
assert: function(act, message) {
|
||||
try {
|
||||
return this.match(act);
|
||||
}
|
||||
catch (e if e instanceof MatchError) {
|
||||
throw new Error((message || "failed match") + ": " + e.message);
|
||||
}
|
||||
},
|
||||
|
||||
toString: () => "[object Pattern]"
|
||||
};
|
||||
|
||||
Pattern.ANY = new Pattern;
|
||||
Pattern.ANY.template = Pattern.ANY;
|
||||
|
||||
Pattern.NUMBER = new Pattern;
|
||||
Pattern.NUMBER.match = function (act) {
|
||||
if (typeof act !== 'number') {
|
||||
throw new MatchError("Expected number, got: " + quote(act));
|
||||
matches: function (act) {
|
||||
try {
|
||||
return this.match(act);
|
||||
} catch (e) {
|
||||
if (e instanceof MatchError) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
Pattern.NATURAL = new Pattern
|
||||
Pattern.NATURAL.match = function (act) {
|
||||
if (typeof act !== 'number' || act !== Math.floor(act) || act < 0) {
|
||||
throw new MatchError("Expected natural number, got: " + quote(act));
|
||||
assert: function (act, message) {
|
||||
try {
|
||||
return this.match(act);
|
||||
} catch (e) {
|
||||
if (e instanceof MatchError) {
|
||||
throw new Error((message || "failed match") + ": " + e.message);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
toString: () => "[object Pattern]"
|
||||
};
|
||||
|
||||
Pattern.ANY = new Pattern();
|
||||
Pattern.ANY.template = Pattern.ANY;
|
||||
|
||||
Pattern.NUMBER = new Pattern();
|
||||
Pattern.NUMBER.match = function (act) {
|
||||
if (typeof act !== "number") {
|
||||
throw new MatchError("Expected number, got: " + quote(act));
|
||||
}
|
||||
};
|
||||
|
||||
Pattern.NATURAL = new Pattern();
|
||||
Pattern.NATURAL.match = function (act) {
|
||||
if (typeof act !== "number" || act !== Math.floor(act) || act < 0) {
|
||||
throw new MatchError("Expected natural number, got: " + quote(act));
|
||||
}
|
||||
};
|
||||
|
||||
let quote = uneval;
|
||||
|
||||
function MatchError(msg) {
|
||||
this.message = msg;
|
||||
}
|
||||
|
||||
MatchError.prototype = {
|
||||
toString: function () {
|
||||
return "match error: " + this.message;
|
||||
}
|
||||
};
|
||||
|
||||
function isAtom(x) {
|
||||
return (typeof x === "number") ||
|
||||
(typeof x === "string") ||
|
||||
(typeof x === "boolean") ||
|
||||
(x === null) ||
|
||||
(typeof x === "object" && x instanceof RegExp);
|
||||
}
|
||||
|
||||
function isObject(x) {
|
||||
return (x !== null) && (typeof x === "object");
|
||||
}
|
||||
|
||||
function isFunction(x) {
|
||||
return typeof x === "function";
|
||||
}
|
||||
|
||||
function isArrayLike(x) {
|
||||
return isObject(x) && ("length" in x);
|
||||
}
|
||||
|
||||
function matchAtom(act, exp) {
|
||||
if ((typeof exp) === "number" && isNaN(exp)) {
|
||||
if ((typeof act) !== "number" || !isNaN(act)) {
|
||||
throw new MatchError("expected NaN, got: " + quote(act));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
var quote = uneval;
|
||||
|
||||
function MatchError(msg) {
|
||||
this.message = msg;
|
||||
if (exp === null) {
|
||||
if (act !== null) {
|
||||
throw new MatchError("expected null, got: " + quote(act));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
MatchError.prototype = {
|
||||
toString: function() {
|
||||
return "match error: " + this.message;
|
||||
if (exp instanceof RegExp) {
|
||||
if (!(act instanceof RegExp) || exp.source !== act.source) {
|
||||
throw new MatchError("expected " + quote(exp) + ", got: " + quote(act));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (typeof exp) {
|
||||
case "string":
|
||||
if (act !== exp) {
|
||||
throw new MatchError("expected " + quote(exp) + ", got " + quote(act));
|
||||
}
|
||||
};
|
||||
|
||||
function isAtom(x) {
|
||||
return (typeof x === "number") ||
|
||||
(typeof x === "string") ||
|
||||
(typeof x === "boolean") ||
|
||||
(x === null) ||
|
||||
(typeof x === "object" && x instanceof RegExp);
|
||||
}
|
||||
|
||||
function isObject(x) {
|
||||
return (x !== null) && (typeof x === "object");
|
||||
}
|
||||
|
||||
function isFunction(x) {
|
||||
return typeof x === "function";
|
||||
}
|
||||
|
||||
function isArrayLike(x) {
|
||||
return isObject(x) && ("length" in x);
|
||||
}
|
||||
|
||||
function matchAtom(act, exp) {
|
||||
if ((typeof exp) === "number" && isNaN(exp)) {
|
||||
if ((typeof act) !== "number" || !isNaN(act))
|
||||
throw new MatchError("expected NaN, got: " + quote(act));
|
||||
return true;
|
||||
return true;
|
||||
case "boolean":
|
||||
case "number":
|
||||
if (exp !== act) {
|
||||
throw new MatchError("expected " + exp + ", got " + quote(act));
|
||||
}
|
||||
|
||||
if (exp === null) {
|
||||
if (act !== null)
|
||||
throw new MatchError("expected null, got: " + quote(act));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (exp instanceof RegExp) {
|
||||
if (!(act instanceof RegExp) || exp.source !== act.source)
|
||||
throw new MatchError("expected " + quote(exp) + ", got: " + quote(act));
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (typeof exp) {
|
||||
case "string":
|
||||
if (act !== exp)
|
||||
throw new MatchError("expected " + quote(exp) + ", got " + quote(act));
|
||||
return true;
|
||||
case "boolean":
|
||||
case "number":
|
||||
if (exp !== act)
|
||||
throw new MatchError("expected " + exp + ", got " + quote(act));
|
||||
return true;
|
||||
}
|
||||
|
||||
throw new Error("bad pattern: " + exp.toSource());
|
||||
}
|
||||
|
||||
function matchObject(act, exp) {
|
||||
if (!isObject(act))
|
||||
throw new MatchError("expected object, got " + quote(act));
|
||||
|
||||
for (var key in exp) {
|
||||
if (!(key in act))
|
||||
throw new MatchError("expected property " + quote(key) + " not found in " + quote(act));
|
||||
match(act[key], exp[key]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function matchFunction(act, exp) {
|
||||
if (!isFunction(act))
|
||||
throw new MatchError("expected function, got " + quote(act));
|
||||
throw new Error("bad pattern: " + exp.toSource());
|
||||
}
|
||||
|
||||
if (act !== exp)
|
||||
throw new MatchError("expected function: " + exp +
|
||||
"\nbut got different function: " + act);
|
||||
function matchObject(act, exp) {
|
||||
if (!isObject(act)) {
|
||||
throw new MatchError("expected object, got " + quote(act));
|
||||
}
|
||||
|
||||
function matchArray(act, exp) {
|
||||
if (!isObject(act) || !("length" in act))
|
||||
throw new MatchError("expected array-like object, got " + quote(act));
|
||||
for (let key in exp) {
|
||||
if (!(key in act)) {
|
||||
throw new MatchError("expected property " + quote(key)
|
||||
+ " not found in " + quote(act));
|
||||
}
|
||||
match(act[key], exp[key]);
|
||||
}
|
||||
|
||||
var length = exp.length;
|
||||
if (act.length !== exp.length)
|
||||
throw new MatchError("expected array-like object of length " + length + ", got " + quote(act));
|
||||
return true;
|
||||
}
|
||||
|
||||
for (var i = 0; i < length; i++) {
|
||||
if (i in exp) {
|
||||
if (!(i in act))
|
||||
throw new MatchError("expected array property " + i + " not found in " + quote(act));
|
||||
match(act[i], exp[i]);
|
||||
}
|
||||
function matchFunction(act, exp) {
|
||||
if (!isFunction(act)) {
|
||||
throw new MatchError("expected function, got " + quote(act));
|
||||
}
|
||||
|
||||
if (act !== exp) {
|
||||
throw new MatchError("expected function: " + exp +
|
||||
"\nbut got different function: " + act);
|
||||
}
|
||||
}
|
||||
|
||||
function matchArray(act, exp) {
|
||||
if (!isObject(act) || !("length" in act)) {
|
||||
throw new MatchError("expected array-like object, got " + quote(act));
|
||||
}
|
||||
|
||||
let length = exp.length;
|
||||
if (act.length !== exp.length) {
|
||||
throw new MatchError("expected array-like object of length "
|
||||
+ length + ", got " + quote(act));
|
||||
}
|
||||
|
||||
for (let i = 0; i < length; i++) {
|
||||
if (i in exp) {
|
||||
if (!(i in act)) {
|
||||
throw new MatchError("expected array property " + i + " not found in "
|
||||
+ quote(act));
|
||||
}
|
||||
|
||||
return true;
|
||||
match(act[i], exp[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function match(act, exp) {
|
||||
if (exp === Pattern.ANY)
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (exp instanceof Pattern)
|
||||
return exp.match(act);
|
||||
|
||||
if (isAtom(exp))
|
||||
return matchAtom(act, exp);
|
||||
|
||||
if (isArrayLike(exp))
|
||||
return matchArray(act, exp);
|
||||
|
||||
if (isFunction(exp))
|
||||
return matchFunction(act, exp);
|
||||
|
||||
return matchObject(act, exp);
|
||||
function match(act, exp) {
|
||||
if (exp === Pattern.ANY) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return { Pattern: Pattern,
|
||||
MatchError: MatchError };
|
||||
if (exp instanceof Pattern) {
|
||||
return exp.match(act);
|
||||
}
|
||||
|
||||
if (isAtom(exp)) {
|
||||
return matchAtom(act, exp);
|
||||
}
|
||||
|
||||
if (isArrayLike(exp)) {
|
||||
return matchArray(act, exp);
|
||||
}
|
||||
|
||||
if (isFunction(exp)) {
|
||||
return matchFunction(act, exp);
|
||||
}
|
||||
|
||||
return matchObject(act, exp);
|
||||
}
|
||||
|
||||
return { Pattern, MatchError };
|
||||
})();
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
console.log("Initializing worker.");
|
||||
|
||||
self.onmessage = e => {
|
||||
@ -16,12 +18,12 @@ self.onmessage = e => {
|
||||
let threw = false;
|
||||
try {
|
||||
new DominatorTree();
|
||||
} catch (e) {
|
||||
} catch (excp) {
|
||||
threw = true;
|
||||
}
|
||||
ok(threw, "Constructor shouldn't be usable");
|
||||
} catch (e) {
|
||||
ok(false, "Unexpected error inside worker:\n" + e.toString() + "\n" + e.stack);
|
||||
} catch (ex) {
|
||||
ok(false, "Unexpected error inside worker:\n" + ex.toString() + "\n" + ex.stack);
|
||||
} finally {
|
||||
done();
|
||||
}
|
||||
|
@ -2,6 +2,12 @@
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
/* exported Cr, CC, Match, Census, Task, DevToolsUtils, HeapAnalysesClient,
|
||||
assertThrows, getFilePath, saveHeapSnapshotAndTakeCensus,
|
||||
saveHeapSnapshotAndComputeDominatorTree, compareCensusViewData, assertDiff,
|
||||
assertLabelAndShallowSize, makeTestDominatorTreeNode,
|
||||
assertDominatorTreeNodeInsertion, assertDeduplicatedPaths,
|
||||
assertCountToBucketBreakdown, pathEntry */
|
||||
|
||||
var Cc = Components.classes;
|
||||
var Ci = Components.interfaces;
|
||||
@ -14,7 +20,6 @@ const { Match } = Cu.import("resource://test/Match.jsm", {});
|
||||
const { Census } = Cu.import("resource://test/Census.jsm", {});
|
||||
const { addDebuggerToGlobal } =
|
||||
Cu.import("resource://gre/modules/jsdebugger.jsm", {});
|
||||
const { Task } = require("devtools/shared/task");
|
||||
|
||||
const DevToolsUtils = require("devtools/shared/DevToolsUtils");
|
||||
const flags = require("devtools/shared/flags");
|
||||
@ -27,7 +32,6 @@ const DominatorTreeNode = require("devtools/shared/heapsnapshot/DominatorTreeNod
|
||||
const { deduplicatePaths } = require("devtools/shared/heapsnapshot/shortest-paths");
|
||||
const { LabelAndShallowSizeVisitor } = DominatorTreeNode;
|
||||
|
||||
|
||||
// Always log packets when running tests. runxpcshelltests.py will throw
|
||||
// the output away anyway, unless you give it the --verbose flag.
|
||||
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_DEFAULT) {
|
||||
@ -75,19 +79,24 @@ function newGlobal() {
|
||||
return global;
|
||||
}
|
||||
|
||||
function assertThrowsValue(f, val, msg) {
|
||||
var fullmsg;
|
||||
function assertThrows(f, val, msg) {
|
||||
let fullmsg;
|
||||
try {
|
||||
f();
|
||||
} catch (exc) {
|
||||
if ((exc === val) === (val === val) && (val !== 0 || 1 / exc === 1 / val))
|
||||
if ((exc === val) && (val !== 0 || 1 / exc === 1 / val)) {
|
||||
return;
|
||||
} else if (exc instanceof Error && exc.message === val) {
|
||||
return;
|
||||
}
|
||||
fullmsg = "Assertion failed: expected exception " + val + ", got " + exc;
|
||||
}
|
||||
if (fullmsg === undefined)
|
||||
if (fullmsg === undefined) {
|
||||
fullmsg = "Assertion failed: expected exception " + val + ", no exception thrown";
|
||||
if (msg !== undefined)
|
||||
}
|
||||
if (msg !== undefined) {
|
||||
fullmsg += " - " + msg;
|
||||
}
|
||||
throw new Error(fullmsg);
|
||||
}
|
||||
|
||||
@ -95,9 +104,8 @@ function assertThrowsValue(f, val, msg) {
|
||||
* Returns the full path of the file with the specified name in a
|
||||
* platform-independent and URL-like form.
|
||||
*/
|
||||
function getFilePath(aName, aAllowMissing = false, aUsePlatformPathSeparator = false)
|
||||
{
|
||||
let file = do_get_file(aName, aAllowMissing);
|
||||
function getFilePath(name, allowMissing = false, usePlatformPathSeparator = false) {
|
||||
let file = do_get_file(name, allowMissing);
|
||||
let path = Services.io.newFileURI(file).spec;
|
||||
let filePrePath = "file://";
|
||||
if ("nsILocalFileWin" in Ci &&
|
||||
@ -107,7 +115,7 @@ function getFilePath(aName, aAllowMissing = false, aUsePlatformPathSeparator = f
|
||||
|
||||
path = path.slice(filePrePath.length);
|
||||
|
||||
if (aUsePlatformPathSeparator && path.match(/^\w:/)) {
|
||||
if (sePlatformPathSeparator && path.match(/^\w:/)) {
|
||||
path = path.replace(/\//g, "\\");
|
||||
}
|
||||
|
||||
@ -152,7 +160,8 @@ function saveHeapSnapshotAndTakeCensus(dbg = null, censusOptions = undefined) {
|
||||
const filePath = saveNewHeapSnapshot(snapshotOptions);
|
||||
const snapshot = readHeapSnapshot(filePath);
|
||||
|
||||
equal(typeof snapshot.takeCensus, "function", "snapshot should have a takeCensus method");
|
||||
equal(typeof snapshot.takeCensus, "function",
|
||||
"snapshot should have a takeCensus method");
|
||||
|
||||
return snapshot.takeCensus(censusOptions);
|
||||
}
|
||||
@ -190,9 +199,8 @@ function isSavedFrame(obj) {
|
||||
function savedFrameReplacer(key, val) {
|
||||
if (isSavedFrame(val)) {
|
||||
return `<SavedFrame '${val.toString().split(/\n/g).shift()}'>`;
|
||||
} else {
|
||||
return val;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -244,7 +252,7 @@ function assertStructurallyEquivalent(actual, expected, path = "root") {
|
||||
|
||||
for (let key of actual.keys()) {
|
||||
ok(expectedKeys.has(key),
|
||||
`${path}: every key in actual should exist in expected: ${String(key).slice(0, 10)}`);
|
||||
`${path}: every key in actual is expected: ${String(key).slice(0, 10)}`);
|
||||
expectedKeys.delete(key);
|
||||
|
||||
assertStructurallyEquivalent(actual.get(key), expected.get(key),
|
||||
@ -252,7 +260,8 @@ function assertStructurallyEquivalent(actual, expected, path = "root") {
|
||||
}
|
||||
|
||||
equal(expectedKeys.size, 0,
|
||||
`${path}: every key in expected should also exist in actual, did not see ${[...expectedKeys]}`);
|
||||
`${path}: every key in expected should also exist in actual,\
|
||||
did not see ${[...expectedKeys]}`);
|
||||
} else if (actualProtoString === "[object Set]") {
|
||||
const expectedItems = new Set([...expected]);
|
||||
|
||||
@ -263,7 +272,8 @@ function assertStructurallyEquivalent(actual, expected, path = "root") {
|
||||
}
|
||||
|
||||
equal(expectedItems.size, 0,
|
||||
`${path}: every set item in expected should also exist in actual, did not see ${[...expectedItems]}`);
|
||||
`${path}: every set item in expected should also exist in actual,\
|
||||
did not see ${[...expectedItems]}`);
|
||||
} else {
|
||||
const expectedKeys = new Set(Object.keys(expected));
|
||||
|
||||
@ -276,7 +286,8 @@ function assertStructurallyEquivalent(actual, expected, path = "root") {
|
||||
}
|
||||
|
||||
equal(expectedKeys.size, 0,
|
||||
`${path}: every key in expected should also exist in actual, did not see ${[...expectedKeys]}`);
|
||||
`${path}: every key in expected should also exist in actual,\
|
||||
did not see ${[...expectedKeys]}`);
|
||||
}
|
||||
} else {
|
||||
equal(actual, expected, `${path}: primitives should be equal`);
|
||||
@ -321,7 +332,8 @@ function assertDiff(breakdown, first, second, expected) {
|
||||
* @param {Number} expectedShallowSize
|
||||
* @param {Object} expectedLabel
|
||||
*/
|
||||
function assertLabelAndShallowSize(breakdown, givenDescription, expectedShallowSize, expectedLabel) {
|
||||
function assertLabelAndShallowSize(breakdown, givenDescription,
|
||||
expectedShallowSize, expectedLabel) {
|
||||
dumpn("Computing label and shallow size from node description:");
|
||||
dumpn("Breakdown: " + JSON.stringify(breakdown, null, 4));
|
||||
dumpn("Given description: " + JSON.stringify(givenDescription, null, 4));
|
||||
@ -364,7 +376,7 @@ function makeTestDominatorTreeNode(opts, children) {
|
||||
}, opts);
|
||||
|
||||
if (children && children.length) {
|
||||
children.map(c => c.parentId = node.nodeId);
|
||||
children.map(c => (c.parentId = node.nodeId));
|
||||
}
|
||||
|
||||
return node;
|
||||
@ -375,7 +387,8 @@ function makeTestDominatorTreeNode(opts, children) {
|
||||
* `path` from the root to the node the `newChildren` should be inserted
|
||||
* beneath. Assert that the resulting tree matches `expected`.
|
||||
*/
|
||||
function assertDominatorTreeNodeInsertion(tree, path, newChildren, moreChildrenAvailable, expected) {
|
||||
function assertDominatorTreeNodeInsertion(tree, path, newChildren,
|
||||
moreChildrenAvailable, expected) {
|
||||
dumpn("Inserting new children into a dominator tree:");
|
||||
dumpn("Dominator tree: " + JSON.stringify(tree, null, 2));
|
||||
dumpn("Path: " + JSON.stringify(path, null, 2));
|
||||
@ -425,7 +438,8 @@ function assertDeduplicatedPaths({ target, paths, expectedNodes, expectedEdges }
|
||||
}
|
||||
}
|
||||
equal(count, 1,
|
||||
"should have exactly one matching edge for the expected edge = " + JSON.stringify(edge));
|
||||
"should have exactly one matching edge for the expected edge = "
|
||||
+ JSON.stringify(edge));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +1,11 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
console.log("Initializing worker.");
|
||||
|
||||
self.onmessage = e => {
|
||||
self.onmessage = ex => {
|
||||
console.log("Starting test.");
|
||||
try {
|
||||
ok(typeof ChromeUtils === "undefined",
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that we can generate label structures from node description reports.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that we can generate label structures from node description reports.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that we can generate label structures from node description reports.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that we can generate label structures from node description reports.
|
||||
|
||||
|
@ -69,7 +69,8 @@ const expected = [
|
||||
}
|
||||
}),
|
||||
|
||||
makeTestDominatorTreeNode({ nodeId: 3000,
|
||||
makeTestDominatorTreeNode({
|
||||
nodeId: 3000,
|
||||
shortestPaths: {
|
||||
nodes: [
|
||||
{ id: 3000, label: ["SomeType-3000"] },
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that we can find the node with the given id along the specified path.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that we can insert new children into an existing DominatorTreeNode tree.
|
||||
|
||||
@ -108,5 +109,6 @@ const expected = {
|
||||
};
|
||||
|
||||
function run_test() {
|
||||
assertDominatorTreeNodeInsertion(tree, path, newChildren, moreChildrenAvailable, expected);
|
||||
assertDominatorTreeNodeInsertion(tree, path, newChildren,
|
||||
moreChildrenAvailable, expected);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test attempting to insert new children into an existing DominatorTreeNode
|
||||
// tree with a bad path.
|
||||
@ -26,5 +27,6 @@ const moreChildrenAvailable = false;
|
||||
const expected = tree;
|
||||
|
||||
function run_test() {
|
||||
assertDominatorTreeNodeInsertion(tree, path, newChildren, moreChildrenAvailable, expected);
|
||||
assertDominatorTreeNodeInsertion(tree, path, newChildren,
|
||||
moreChildrenAvailable, expected);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test inserting new children into an existing DominatorTreeNode at the root.
|
||||
|
||||
@ -113,5 +114,6 @@ const expected = {
|
||||
};
|
||||
|
||||
function run_test() {
|
||||
assertDominatorTreeNodeInsertion(tree, path, newChildren, moreChildrenAvailable, expected);
|
||||
assertDominatorTreeNodeInsertion(tree, path, newChildren,
|
||||
moreChildrenAvailable, expected);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that we correctly set `moreChildrenAvailable` when doing a partial
|
||||
// traversal of a dominator tree to create the initial incrementally loaded
|
||||
@ -154,8 +155,10 @@ function run_test() {
|
||||
const actual = DominatorTreeNode.partialTraversal(mockDominatorTree,
|
||||
mockSnapshot,
|
||||
breakdown,
|
||||
/* maxDepth = */ 4,
|
||||
/* siblings = */ 2);
|
||||
// maxDepth
|
||||
4,
|
||||
// siblings
|
||||
2);
|
||||
|
||||
dumpn("Expected = " + JSON.stringify(expected, null, 2));
|
||||
dumpn("Actual = " + JSON.stringify(actual, null, 2));
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Sanity test that we can compute dominator trees.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that we can compute dominator trees from a snapshot in a worker.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that we can get the root of dominator trees.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that we can get the retained sizes of dominator trees.
|
||||
|
||||
|
@ -1,11 +1,12 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that we can get the set of immediately dominated nodes for any given
|
||||
// node and that this forms a tree.
|
||||
|
||||
function run_test() {
|
||||
var dominatorTree = saveHeapSnapshotAndComputeDominatorTree();
|
||||
let dominatorTree = saveHeapSnapshotAndComputeDominatorTree();
|
||||
equal(typeof dominatorTree.getImmediatelyDominated, "function",
|
||||
"getImmediatelyDominated should be a function");
|
||||
|
||||
@ -16,33 +17,33 @@ function run_test() {
|
||||
// every one. This test would constantly time out and assertion messages would
|
||||
// overflow the log size.
|
||||
|
||||
var root = dominatorTree.root;
|
||||
let root = dominatorTree.root;
|
||||
equal(dominatorTree.getImmediateDominator(root), null,
|
||||
"The root should not have a parent");
|
||||
|
||||
var seen = new Set();
|
||||
var stack = [root];
|
||||
let seen = new Set();
|
||||
let stack = [root];
|
||||
while (stack.length > 0) {
|
||||
var top = stack.pop();
|
||||
let top = stack.pop();
|
||||
|
||||
if (seen.has(top)) {
|
||||
ok(false,
|
||||
"This is a tree, not a graph: we shouldn't have multiple edges to the same node");
|
||||
ok(false, "This is a tree, not a graph: we shouldn't have "
|
||||
+ "multiple edges to the same node");
|
||||
}
|
||||
seen.add(top);
|
||||
if (seen.size % 1000 === 0) {
|
||||
dumpn("Progress update: seen size = " + seen.size);
|
||||
}
|
||||
|
||||
var newNodes = dominatorTree.getImmediatelyDominated(top);
|
||||
let newNodes = dominatorTree.getImmediatelyDominated(top);
|
||||
if (Object.prototype.toString.call(newNodes) !== "[object Array]") {
|
||||
ok(false, "getImmediatelyDominated should return an array for known node ids");
|
||||
}
|
||||
|
||||
var topSize = dominatorTree.getRetainedSize(top);
|
||||
let topSize = dominatorTree.getRetainedSize(top);
|
||||
|
||||
var lastSize = Infinity;
|
||||
for (var i = 0; i < newNodes.length; i++) {
|
||||
let lastSize = Infinity;
|
||||
for (let i = 0; i < newNodes.length; i++) {
|
||||
if (typeof newNodes[i] !== "number") {
|
||||
ok(false, "Every dominated id should be a number");
|
||||
}
|
||||
@ -51,10 +52,11 @@ function run_test() {
|
||||
ok(false, "child's parent should be the expected parent");
|
||||
}
|
||||
|
||||
var thisSize = dominatorTree.getRetainedSize(newNodes[i]);
|
||||
let thisSize = dominatorTree.getRetainedSize(newNodes[i]);
|
||||
|
||||
if (thisSize >= topSize) {
|
||||
ok(false, "the size of children in the dominator tree should always be less than that of their parent");
|
||||
ok(false, "the size of children in the dominator tree should"
|
||||
+ " always be less than that of their parent");
|
||||
}
|
||||
|
||||
if (thisSize > lastSize) {
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the retained size of a node is the sum of its children retained
|
||||
// sizes plus its shallow size.
|
||||
@ -14,31 +15,31 @@ function fastAssert(cond, msg) {
|
||||
}
|
||||
}
|
||||
|
||||
var COUNT = { by: "count", count: false, bytes: true };
|
||||
let COUNT = { by: "count", count: false, bytes: true };
|
||||
|
||||
function run_test() {
|
||||
var path = saveNewHeapSnapshot();
|
||||
var snapshot = ChromeUtils.readHeapSnapshot(path);
|
||||
var dominatorTree = snapshot.computeDominatorTree();
|
||||
let path = saveNewHeapSnapshot();
|
||||
let snapshot = ChromeUtils.readHeapSnapshot(path);
|
||||
let dominatorTree = snapshot.computeDominatorTree();
|
||||
|
||||
// Do a traversal of the dominator tree and assert the relationship between
|
||||
// retained size, shallow size, and children's retained sizes.
|
||||
|
||||
var root = dominatorTree.root;
|
||||
var stack = [root];
|
||||
let root = dominatorTree.root;
|
||||
let stack = [root];
|
||||
while (stack.length > 0) {
|
||||
var top = stack.pop();
|
||||
let top = stack.pop();
|
||||
|
||||
var children = dominatorTree.getImmediatelyDominated(top);
|
||||
let children = dominatorTree.getImmediatelyDominated(top);
|
||||
|
||||
var topRetainedSize = dominatorTree.getRetainedSize(top);
|
||||
var topShallowSize = snapshot.describeNode(COUNT, top).bytes;
|
||||
let topRetainedSize = dominatorTree.getRetainedSize(top);
|
||||
let topShallowSize = snapshot.describeNode(COUNT, top).bytes;
|
||||
fastAssert(topShallowSize <= topRetainedSize,
|
||||
"The shallow size should be less than or equal to the " +
|
||||
"retained size");
|
||||
|
||||
var sumOfChildrensRetainedSizes = 0;
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
let sumOfChildrensRetainedSizes = 0;
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
sumOfChildrensRetainedSizes += dominatorTree.getRetainedSize(children[i]);
|
||||
stack.push(children[i]);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test the HeapAnalyses{Client,Worker} "computeDominatorTree" request.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test the HeapAnalyses{Client,Worker} "computeDominatorTree" request with bad
|
||||
// file paths.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the HeapAnalyses{Client,Worker} can delete heap snapshots.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test deleteHeapSnapshot is a noop if the provided path matches no snapshot
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test other dominatorTrees can still be retrieved after deleting a snapshot
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the HeapAnalyses{Client,Worker} can get census individuals.
|
||||
|
||||
|
@ -1,12 +1,15 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the HeapAnalyses{Client,Worker} can get a HeapSnapshot's
|
||||
// creation time.
|
||||
|
||||
function waitForThirtyMilliseconds() {
|
||||
const start = Date.now();
|
||||
while (Date.now() - start < 30) ;
|
||||
while (Date.now() - start < 30) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test the HeapAnalyses{Client,Worker} "getDominatorTree" request.
|
||||
|
||||
@ -47,7 +48,8 @@ add_task(function* () {
|
||||
"each node should have a retained size");
|
||||
|
||||
ok(node.children === undefined || Array.isArray(node.children),
|
||||
"each node either has a list of children, or undefined meaning no children loaded");
|
||||
"each node either has a list of children, "
|
||||
+ "or undefined meaning no children loaded");
|
||||
equal(typeof node.moreChildrenAvailable, "boolean",
|
||||
"each node should indicate if there are more children available or not");
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test the HeapAnalyses{Client,Worker} "getDominatorTree" request with bad
|
||||
// dominator tree ids.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test the HeapAnalyses{Client,Worker} "getImmediatelyDominated" request.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the HeapAnalyses{Client,Worker} can read heap snapshots.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the HeapAnalyses{Client,Worker} can take diffs between censuses.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the HeapAnalyses{Client,Worker} can take diffs between censuses as
|
||||
// inverted trees.
|
||||
@ -43,10 +44,11 @@ add_task(function* () {
|
||||
secondSnapshotFilePath,
|
||||
{ breakdown: BREAKDOWN });
|
||||
|
||||
const { delta: deltaTreeNode } = yield client.takeCensusDiff(firstSnapshotFilePath,
|
||||
secondSnapshotFilePath,
|
||||
{ breakdown: BREAKDOWN },
|
||||
{ asInvertedTreeNode: true });
|
||||
const { delta: deltaTreeNode }
|
||||
= yield client.takeCensusDiff(firstSnapshotFilePath,
|
||||
secondSnapshotFilePath,
|
||||
{ breakdown: BREAKDOWN },
|
||||
{ asInvertedTreeNode: true });
|
||||
|
||||
// Have to manually set these because symbol properties aren't structured
|
||||
// cloned.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the HeapAnalyses{Client,Worker} can take censuses.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the HeapAnalyses{Client,Worker} can take censuses with breakdown
|
||||
// options.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the HeapAnalyses{Client,Worker} bubbles errors properly when things
|
||||
// go wrong.
|
||||
@ -27,7 +28,8 @@ add_task(function* () {
|
||||
} catch (e) {
|
||||
failed = true;
|
||||
}
|
||||
ok(failed, "should not be able to read a file that is not a heap snapshot as a heap snapshot");
|
||||
ok(failed, "should not be able to read a file "
|
||||
+ "that is not a heap snapshot as a heap snapshot");
|
||||
|
||||
const snapshotFilePath = saveNewHeapSnapshot();
|
||||
yield client.readHeapSnapshot(snapshotFilePath);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the HeapAnalyses{Client,Worker} can send SavedFrame stacks from
|
||||
// by-allocation-stack reports from the worker.
|
||||
@ -20,7 +21,7 @@ add_task(function* test() {
|
||||
function f() { this.log.push(allocationMarker()); } // 3
|
||||
function g() { this.log.push(allocationMarker()); } // 4
|
||||
function h() { this.log.push(allocationMarker()); } // 5
|
||||
`); // 6
|
||||
`);
|
||||
|
||||
// Create one allocationMarker with tracking turned off,
|
||||
// so it will have no associated stack.
|
||||
@ -49,20 +50,26 @@ add_task(function* test() {
|
||||
// Run a census broken down by class name -> allocation stack so we can grab
|
||||
// only the AllocationMarker objects we have complete control over.
|
||||
|
||||
const { report } = yield client.takeCensus(snapshotFilePath, {
|
||||
breakdown: { by: "objectClass",
|
||||
then: { by: "allocationStack",
|
||||
then: { by: "count",
|
||||
bytes: true,
|
||||
count: true
|
||||
},
|
||||
noStack: { by: "count",
|
||||
bytes: true,
|
||||
count: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
const { report } = yield client.takeCensus(
|
||||
snapshotFilePath,
|
||||
{
|
||||
breakdown: {
|
||||
by: "objectClass",
|
||||
then: {
|
||||
by: "allocationStack",
|
||||
then: {
|
||||
by: "count",
|
||||
bytes: true,
|
||||
count: true
|
||||
},
|
||||
noStack: {
|
||||
by: "count",
|
||||
bytes: true,
|
||||
count: true
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Test the generated report.
|
||||
|
||||
@ -72,7 +79,7 @@ add_task(function* test() {
|
||||
ok(map, "Should get AllocationMarkers in the report.");
|
||||
// From a module with a different global, and therefore a different Map
|
||||
// constructor, so we can't use instanceof.
|
||||
equal(map.__proto__.constructor.name, "Map");
|
||||
equal(Object.getPrototypeOf(map).constructor.name, "Map");
|
||||
|
||||
equal(map.size, 4, "Should have 4 allocation stacks (including the lack of a stack)");
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the HeapAnalyses{Client,Worker} can take censuses and return
|
||||
// a CensusTreeNode.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the HeapAnalyses{Client,Worker} can take censuses by
|
||||
// "allocationStack" and return a CensusTreeNode.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that the HeapAnalyses{Client,Worker} can take censuses and return
|
||||
// an inverted CensusTreeNode.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Sanity test that we can compute shortest paths.
|
||||
//
|
||||
@ -21,7 +22,8 @@ function run_test() {
|
||||
|
||||
const targetSet = new Set(dominatedByRoot);
|
||||
|
||||
const shortestPaths = snapshot.computeShortestPaths(dominatorTree.root, dominatedByRoot, 2);
|
||||
const shortestPaths
|
||||
= snapshot.computeShortestPaths(dominatorTree.root, dominatedByRoot, 2);
|
||||
ok(shortestPaths);
|
||||
ok(shortestPaths instanceof Map);
|
||||
ok(shortestPaths.size === targetSet.size);
|
||||
@ -38,21 +40,21 @@ function run_test() {
|
||||
|
||||
dumpn("---------------------");
|
||||
dumpn("Shortest paths for 0x" + target.toString(16) + ":");
|
||||
for (let path of paths) {
|
||||
for (let pth of paths) {
|
||||
dumpn(" path =");
|
||||
for (let part of path) {
|
||||
for (let part of pth) {
|
||||
dumpn(" predecessor: 0x" + part.predecessor.toString(16) +
|
||||
"; edge: " + part.edge);
|
||||
}
|
||||
}
|
||||
dumpn("---------------------");
|
||||
|
||||
for (let path of paths) {
|
||||
ok(path.length > 0, "Cannot have zero length paths");
|
||||
ok(path[0].predecessor === dominatorTree.root,
|
||||
for (let path2 of paths) {
|
||||
ok(path2.length > 0, "Cannot have zero length paths");
|
||||
ok(path2[0].predecessor === dominatorTree.root,
|
||||
"The first predecessor is always our start node");
|
||||
|
||||
for (let part of path) {
|
||||
for (let part of path2) {
|
||||
ok(part.predecessor, "Each part of a path has a predecessor");
|
||||
ok(!!snapshot.describeNode({ by: "count", count: true, bytes: true},
|
||||
part.predecessor),
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test computing shortest paths with invalid arguments.
|
||||
|
||||
|
@ -1,11 +1,14 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// HeapSnapshot.prototype.creationTime returns the expected time.
|
||||
|
||||
function waitForThirtyMilliseconds() {
|
||||
const start = Date.now();
|
||||
while (Date.now() - start < 30) ;
|
||||
while (Date.now() - start < 30) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that we can save a core dump with very deep allocation stacks and read
|
||||
// it back into a HeapSnapshot.
|
||||
@ -20,8 +21,9 @@ function run_test() {
|
||||
debuggee.eval("this.objects = []");
|
||||
debuggee.eval(
|
||||
(function recursiveAllocate(n) {
|
||||
if (n <= 0)
|
||||
if (n <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure to recurse before pushing the object so that when TCO is
|
||||
// implemented sometime in the future, it doesn't invalidate this test.
|
||||
@ -46,7 +48,7 @@ function run_test() {
|
||||
breakdown: { by: "allocationStack",
|
||||
then: { by: "count", bytes: true, count: true },
|
||||
noStack: { by: "count", bytes: true, count: true }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Keep this synchronized with `HeapSnapshot::MAX_STACK_DEPTH`!
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that we can describe nodes with a breakdown.
|
||||
|
||||
|
@ -1,29 +1,31 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// HeapSnapshot.prototype.takeCensus returns a value of an appropriate
|
||||
// shape. Ported from js/src/jit-tests/debug/Memory-takeCensus-01.js
|
||||
|
||||
function run_test() {
|
||||
var dbg = new Debugger;
|
||||
let dbg = new Debugger();
|
||||
|
||||
function checkProperties(census) {
|
||||
equal(typeof census, "object");
|
||||
for (prop of Object.getOwnPropertyNames(census)) {
|
||||
var desc = Object.getOwnPropertyDescriptor(census, prop);
|
||||
for (let prop of Object.getOwnPropertyNames(census)) {
|
||||
let desc = Object.getOwnPropertyDescriptor(census, prop);
|
||||
equal(desc.enumerable, true);
|
||||
equal(desc.configurable, true);
|
||||
equal(desc.writable, true);
|
||||
if (typeof desc.value === "object")
|
||||
if (typeof desc.value === "object") {
|
||||
checkProperties(desc.value);
|
||||
else
|
||||
} else {
|
||||
equal(typeof desc.value, "number");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
checkProperties(saveHeapSnapshotAndTakeCensus(dbg));
|
||||
|
||||
var g = newGlobal();
|
||||
let g = newGlobal();
|
||||
dbg.addDebuggee(g);
|
||||
checkProperties(saveHeapSnapshotAndTakeCensus(dbg));
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// HeapSnapshot.prototype.takeCensus behaves plausibly as we allocate objects.
|
||||
//
|
||||
@ -15,12 +16,12 @@
|
||||
|
||||
function run_test() {
|
||||
// A Debugger with no debuggees had better not find anything.
|
||||
var dbg = new Debugger;
|
||||
var census0 = saveHeapSnapshotAndTakeCensus(dbg);
|
||||
let dbg = new Debugger();
|
||||
let census0 = saveHeapSnapshotAndTakeCensus(dbg);
|
||||
Census.walkCensus(census0, "census0", Census.assertAllZeros);
|
||||
|
||||
function newGlobalWithDefs() {
|
||||
var g = newGlobal();
|
||||
let g = newGlobal();
|
||||
g.eval(`
|
||||
function times(n, fn) {
|
||||
var a=[];
|
||||
@ -34,7 +35,7 @@ function run_test() {
|
||||
|
||||
// Allocate a large number of various types of objects, and check that census
|
||||
// finds them.
|
||||
var g = newGlobalWithDefs();
|
||||
let g = newGlobalWithDefs();
|
||||
dbg.addDebuggee(g);
|
||||
|
||||
g.eval("var objs = times(100, () => ({}));");
|
||||
@ -42,16 +43,16 @@ function run_test() {
|
||||
g.eval("var ars = times(400, () => []);");
|
||||
g.eval("var fns = times(800, () => () => {});");
|
||||
|
||||
var census1 = dbg.memory.takeCensus(dbg);
|
||||
let census1 = dbg.memory.takeCensus(dbg);
|
||||
Census.walkCensus(census1, "census1",
|
||||
Census.assertAllNotLessThan(
|
||||
{ "objects":
|
||||
{ "Object": { count: 100 },
|
||||
"RegExp": { count: 200 },
|
||||
"Array": { count: 400 },
|
||||
"Function": { count: 800 }
|
||||
}
|
||||
}));
|
||||
Census.assertAllNotLessThan({
|
||||
"objects": {
|
||||
"Object": { count: 100 },
|
||||
"RegExp": { count: 200 },
|
||||
"Array": { count: 400 },
|
||||
"Function": { count: 800 }
|
||||
}
|
||||
}));
|
||||
|
||||
do_test_finished();
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// HeapSnapshot.prototype.takeCensus behaves plausibly as we add and remove
|
||||
// debuggees.
|
||||
@ -7,27 +8,27 @@
|
||||
// Ported from js/src/jit-test/tests/debug/Memory-takeCensus-03.js
|
||||
|
||||
function run_test() {
|
||||
var dbg = new Debugger;
|
||||
let dbg = new Debugger();
|
||||
|
||||
var census0 = saveHeapSnapshotAndTakeCensus(dbg);
|
||||
let census0 = saveHeapSnapshotAndTakeCensus(dbg);
|
||||
Census.walkCensus(census0, "census0", Census.assertAllZeros);
|
||||
|
||||
var g1 = newGlobal();
|
||||
let g1 = newGlobal();
|
||||
dbg.addDebuggee(g1);
|
||||
var census1 = saveHeapSnapshotAndTakeCensus(dbg);
|
||||
let census1 = saveHeapSnapshotAndTakeCensus(dbg);
|
||||
Census.walkCensus(census1, "census1", Census.assertAllNotLessThan(census0));
|
||||
|
||||
var g2 = newGlobal();
|
||||
let g2 = newGlobal();
|
||||
dbg.addDebuggee(g2);
|
||||
var census2 = saveHeapSnapshotAndTakeCensus(dbg);
|
||||
let census2 = saveHeapSnapshotAndTakeCensus(dbg);
|
||||
Census.walkCensus(census2, "census2", Census.assertAllNotLessThan(census1));
|
||||
|
||||
dbg.removeDebuggee(g2);
|
||||
var census3 = saveHeapSnapshotAndTakeCensus(dbg);
|
||||
let census3 = saveHeapSnapshotAndTakeCensus(dbg);
|
||||
Census.walkCensus(census3, "census3", Census.assertAllEqual(census1));
|
||||
|
||||
dbg.removeDebuggee(g1);
|
||||
var census4 = saveHeapSnapshotAndTakeCensus(dbg);
|
||||
let census4 = saveHeapSnapshotAndTakeCensus(dbg);
|
||||
Census.walkCensus(census4, "census4", Census.assertAllEqual(census0));
|
||||
|
||||
do_test_finished();
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that HeapSnapshot.prototype.takeCensus finds GC roots that are on the
|
||||
// stack.
|
||||
@ -7,8 +8,8 @@
|
||||
// Ported from js/src/jit-test/tests/debug/Memory-takeCensus-04.js
|
||||
|
||||
function run_test() {
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
let g = newGlobal();
|
||||
let dbg = new Debugger(g);
|
||||
|
||||
g.eval(`
|
||||
function withAllocationMarkerOnStack(f) {
|
||||
@ -22,7 +23,7 @@ function withAllocationMarkerOnStack(f) {
|
||||
equal("AllocationMarker" in saveHeapSnapshotAndTakeCensus(dbg).objects, false,
|
||||
"There shouldn't exist any allocation markers in the census.");
|
||||
|
||||
var allocationMarkerCount;
|
||||
let allocationMarkerCount;
|
||||
g.withAllocationMarkerOnStack(() => {
|
||||
const census = saveHeapSnapshotAndTakeCensus(dbg);
|
||||
allocationMarkerCount = census.objects.AllocationMarker.count;
|
||||
|
@ -6,9 +6,10 @@
|
||||
//
|
||||
// Ported from js/src/jit-test/tests/debug/Memory-takeCensus-05.js
|
||||
|
||||
/* eslint-disable strict */
|
||||
function run_test() {
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
let g = newGlobal();
|
||||
let dbg = new Debugger(g);
|
||||
|
||||
equal("AllocationMarker" in saveHeapSnapshotAndTakeCensus(dbg).objects, false,
|
||||
"No allocation markers should exist in the census.");
|
||||
|
@ -1,88 +1,91 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Check HeapSnapshot.prototype.takeCensus handling of 'breakdown' argument.
|
||||
//
|
||||
// Ported from js/src/jit-test/tests/debug/Memory-takeCensus-06.js
|
||||
|
||||
function run_test() {
|
||||
var Pattern = Match.Pattern;
|
||||
let Pattern = Match.Pattern;
|
||||
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
let g = newGlobal();
|
||||
let dbg = new Debugger(g);
|
||||
|
||||
Pattern({ count: Pattern.NATURAL,
|
||||
bytes: Pattern.NATURAL })
|
||||
.assert(saveHeapSnapshotAndTakeCensus(dbg, { breakdown: { by: "count" } }));
|
||||
|
||||
let census = saveHeapSnapshotAndTakeCensus(dbg, { breakdown: { by: "count", count: false, bytes: false } });
|
||||
let census = saveHeapSnapshotAndTakeCensus(dbg,
|
||||
{ breakdown: { by: "count", count: false, bytes: false } });
|
||||
equal("count" in census, false);
|
||||
equal("bytes" in census, false);
|
||||
|
||||
census = saveHeapSnapshotAndTakeCensus(dbg, { breakdown: { by: "count", count: true, bytes: false } });
|
||||
census = saveHeapSnapshotAndTakeCensus(dbg,
|
||||
{ breakdown: { by: "count", count: true, bytes: false } });
|
||||
equal("count" in census, true);
|
||||
equal("bytes" in census, false);
|
||||
|
||||
census = saveHeapSnapshotAndTakeCensus(dbg, { breakdown: { by: "count", count: false, bytes: true } });
|
||||
census = saveHeapSnapshotAndTakeCensus(dbg,
|
||||
{ breakdown: { by: "count", count: false, bytes: true } });
|
||||
equal("count" in census, false);
|
||||
equal("bytes" in census, true);
|
||||
|
||||
census = saveHeapSnapshotAndTakeCensus(dbg, { breakdown: { by: "count", count: true, bytes: true } });
|
||||
census = saveHeapSnapshotAndTakeCensus(dbg,
|
||||
{ breakdown: { by: "count", count: true, bytes: true } });
|
||||
equal("count" in census, true);
|
||||
equal("bytes" in census, true);
|
||||
|
||||
|
||||
// Pattern doesn't mind objects with extra properties, so we'll restrict this
|
||||
// list to the object classes we're pretty sure are going to stick around for
|
||||
// the forseeable future.
|
||||
Pattern({
|
||||
Function: { count: Pattern.NATURAL },
|
||||
Object: { count: Pattern.NATURAL },
|
||||
Debugger: { count: Pattern.NATURAL },
|
||||
Sandbox: { count: Pattern.NATURAL },
|
||||
Function: { count: Pattern.NATURAL },
|
||||
Object: { count: Pattern.NATURAL },
|
||||
Debugger: { count: Pattern.NATURAL },
|
||||
Sandbox: { count: Pattern.NATURAL },
|
||||
|
||||
// The below are all Debugger prototype objects.
|
||||
Source: { count: Pattern.NATURAL },
|
||||
Environment: { count: Pattern.NATURAL },
|
||||
Script: { count: Pattern.NATURAL },
|
||||
Memory: { count: Pattern.NATURAL },
|
||||
Frame: { count: Pattern.NATURAL }
|
||||
Source: { count: Pattern.NATURAL },
|
||||
Environment: { count: Pattern.NATURAL },
|
||||
Script: { count: Pattern.NATURAL },
|
||||
Memory: { count: Pattern.NATURAL },
|
||||
Frame: { count: Pattern.NATURAL }
|
||||
})
|
||||
.assert(saveHeapSnapshotAndTakeCensus(dbg, { breakdown: { by: "objectClass" } }));
|
||||
|
||||
Pattern({
|
||||
objects: { count: Pattern.NATURAL },
|
||||
scripts: { count: Pattern.NATURAL },
|
||||
strings: { count: Pattern.NATURAL },
|
||||
other: { count: Pattern.NATURAL }
|
||||
objects: { count: Pattern.NATURAL },
|
||||
scripts: { count: Pattern.NATURAL },
|
||||
strings: { count: Pattern.NATURAL },
|
||||
other: { count: Pattern.NATURAL }
|
||||
})
|
||||
.assert(saveHeapSnapshotAndTakeCensus(dbg, { breakdown: { by: "coarseType" } }));
|
||||
|
||||
// As for { by: 'objectClass' }, restrict our pattern to the types
|
||||
// we predict will stick around for a long time.
|
||||
Pattern({
|
||||
JSString: { count: Pattern.NATURAL },
|
||||
"js::Shape": { count: Pattern.NATURAL },
|
||||
JSObject: { count: Pattern.NATURAL },
|
||||
JSScript: { count: Pattern.NATURAL }
|
||||
JSString: { count: Pattern.NATURAL },
|
||||
"js::Shape": { count: Pattern.NATURAL },
|
||||
JSObject: { count: Pattern.NATURAL },
|
||||
JSScript: { count: Pattern.NATURAL }
|
||||
})
|
||||
.assert(saveHeapSnapshotAndTakeCensus(dbg, { breakdown: { by: "internalType" } }));
|
||||
|
||||
|
||||
// Nested breakdowns.
|
||||
|
||||
let coarseTypePattern = {
|
||||
objects: { count: Pattern.NATURAL },
|
||||
scripts: { count: Pattern.NATURAL },
|
||||
strings: { count: Pattern.NATURAL },
|
||||
other: { count: Pattern.NATURAL }
|
||||
objects: { count: Pattern.NATURAL },
|
||||
scripts: { count: Pattern.NATURAL },
|
||||
strings: { count: Pattern.NATURAL },
|
||||
other: { count: Pattern.NATURAL }
|
||||
};
|
||||
|
||||
Pattern({
|
||||
JSString: coarseTypePattern,
|
||||
JSString: coarseTypePattern,
|
||||
"js::Shape": coarseTypePattern,
|
||||
JSObject: coarseTypePattern,
|
||||
JSScript: coarseTypePattern,
|
||||
JSObject: coarseTypePattern,
|
||||
JSScript: coarseTypePattern,
|
||||
})
|
||||
.assert(saveHeapSnapshotAndTakeCensus(dbg, {
|
||||
breakdown: { by: "internalType",
|
||||
@ -91,16 +94,16 @@ function run_test() {
|
||||
}));
|
||||
|
||||
Pattern({
|
||||
Function: { count: Pattern.NATURAL },
|
||||
Object: { count: Pattern.NATURAL },
|
||||
Debugger: { count: Pattern.NATURAL },
|
||||
Sandbox: { count: Pattern.NATURAL },
|
||||
other: coarseTypePattern
|
||||
Function: { count: Pattern.NATURAL },
|
||||
Object: { count: Pattern.NATURAL },
|
||||
Debugger: { count: Pattern.NATURAL },
|
||||
Sandbox: { count: Pattern.NATURAL },
|
||||
other: coarseTypePattern
|
||||
})
|
||||
.assert(saveHeapSnapshotAndTakeCensus(dbg, {
|
||||
breakdown: {
|
||||
by: "objectClass",
|
||||
then: { by: "count" },
|
||||
then: { by: "count" },
|
||||
other: { by: "coarseType" }
|
||||
}
|
||||
}));
|
||||
@ -109,7 +112,7 @@ function run_test() {
|
||||
objects: { count: Pattern.NATURAL, label: "object" },
|
||||
scripts: { count: Pattern.NATURAL, label: "scripts" },
|
||||
strings: { count: Pattern.NATURAL, label: "strings" },
|
||||
other: { count: Pattern.NATURAL, label: "other" }
|
||||
other: { count: Pattern.NATURAL, label: "other" }
|
||||
})
|
||||
.assert(saveHeapSnapshotAndTakeCensus(dbg, {
|
||||
breakdown: {
|
||||
@ -117,7 +120,7 @@ function run_test() {
|
||||
objects: { by: "count", label: "object" },
|
||||
scripts: { by: "count", label: "scripts" },
|
||||
strings: { by: "count", label: "strings" },
|
||||
other: { by: "count", label: "other" }
|
||||
other: { by: "count", label: "other" }
|
||||
}
|
||||
}));
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// HeapSnapshot.prototype.takeCensus breakdown: check error handling on property
|
||||
// gets.
|
||||
@ -7,74 +8,86 @@
|
||||
// Ported from js/src/jit-test/tests/debug/Memory-takeCensus-07.js
|
||||
|
||||
function run_test() {
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
let g = newGlobal();
|
||||
let dbg = new Debugger(g);
|
||||
|
||||
assertThrowsValue(() => {
|
||||
assertThrows(() => {
|
||||
saveHeapSnapshotAndTakeCensus(dbg, {
|
||||
breakdown: { get by() { throw "ಠ_ಠ"; } }
|
||||
breakdown: { get by() {
|
||||
throw Error("ಠ_ಠ");
|
||||
} }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
|
||||
|
||||
assertThrowsValue(() => {
|
||||
assertThrows(() => {
|
||||
saveHeapSnapshotAndTakeCensus(dbg, {
|
||||
breakdown: { by: "count", get count() { throw "ಠ_ಠ"; } }
|
||||
breakdown: { by: "count", get count() {
|
||||
throw Error("ಠ_ಠ");
|
||||
} }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
assertThrowsValue(() => {
|
||||
assertThrows(() => {
|
||||
saveHeapSnapshotAndTakeCensus(dbg, {
|
||||
breakdown: { by: "count", get bytes() { throw "ಠ_ಠ"; } }
|
||||
breakdown: { by: "count", get bytes() {
|
||||
throw Error("ಠ_ಠ");
|
||||
} }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
|
||||
|
||||
assertThrowsValue(() => {
|
||||
assertThrows(() => {
|
||||
saveHeapSnapshotAndTakeCensus(dbg, {
|
||||
breakdown: { by: "objectClass", get then() { throw "ಠ_ಠ"; } }
|
||||
breakdown: { by: "objectClass", get then() {
|
||||
throw Error("ಠ_ಠ");
|
||||
} }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
assertThrowsValue(() => {
|
||||
assertThrows(() => {
|
||||
saveHeapSnapshotAndTakeCensus(dbg, {
|
||||
breakdown: { by: "objectClass", get other() { throw "ಠ_ಠ"; } }
|
||||
breakdown: { by: "objectClass", get other() {
|
||||
throw Error("ಠ_ಠ");
|
||||
} }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
|
||||
|
||||
assertThrowsValue(() => {
|
||||
assertThrows(() => {
|
||||
saveHeapSnapshotAndTakeCensus(dbg, {
|
||||
breakdown: { by: "coarseType", get objects() { throw "ಠ_ಠ"; } }
|
||||
breakdown: { by: "coarseType", get objects() {
|
||||
throw Error("ಠ_ಠ");
|
||||
} }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
assertThrowsValue(() => {
|
||||
assertThrows(() => {
|
||||
saveHeapSnapshotAndTakeCensus(dbg, {
|
||||
breakdown: { by: "coarseType", get scripts() { throw "ಠ_ಠ"; } }
|
||||
breakdown: { by: "coarseType", get scripts() {
|
||||
throw Error("ಠ_ಠ");
|
||||
} }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
assertThrowsValue(() => {
|
||||
assertThrows(() => {
|
||||
saveHeapSnapshotAndTakeCensus(dbg, {
|
||||
breakdown: { by: "coarseType", get strings() { throw "ಠ_ಠ"; } }
|
||||
breakdown: { by: "coarseType", get strings() {
|
||||
throw Error("ಠ_ಠ");
|
||||
} }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
assertThrowsValue(() => {
|
||||
assertThrows(() => {
|
||||
saveHeapSnapshotAndTakeCensus(dbg, {
|
||||
breakdown: { by: "coarseType", get other() { throw "ಠ_ಠ"; } }
|
||||
breakdown: { by: "coarseType", get other() {
|
||||
throw Error("ಠ_ಠ");
|
||||
} }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
|
||||
|
||||
assertThrowsValue(() => {
|
||||
assertThrows(() => {
|
||||
saveHeapSnapshotAndTakeCensus(dbg, {
|
||||
breakdown: { by: "internalType", get then() { throw "ಠ_ಠ"; } }
|
||||
breakdown: { by: "internalType", get then() {
|
||||
throw Error("ಠ_ಠ");
|
||||
} }
|
||||
});
|
||||
}, "ಠ_ಠ");
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// HeapSnapshot.prototype.takeCensus: test by: 'count' breakdown
|
||||
//
|
||||
|
@ -1,20 +1,21 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// HeapSnapshot.prototype.takeCensus: by: allocationStack breakdown
|
||||
//
|
||||
// Ported from js/src/jit-test/tests/debug/Memory-takeCensus-09.js
|
||||
|
||||
function run_test() {
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
let g = newGlobal();
|
||||
let dbg = new Debugger(g);
|
||||
|
||||
g.eval(` // 1
|
||||
var log = []; // 2
|
||||
function f() { log.push(allocationMarker()); } // 3
|
||||
function g() { f(); } // 4
|
||||
function h() { f(); } // 5
|
||||
`); // 6
|
||||
`);
|
||||
|
||||
// Create one allocationMarker with tracking turned off,
|
||||
// so it will have no associated stack.
|
||||
@ -22,7 +23,7 @@ function run_test() {
|
||||
|
||||
dbg.memory.allocationSamplingProbability = 1;
|
||||
|
||||
for ([func, n] of [[g.f, 20], [g.g, 10], [g.h, 5]]) {
|
||||
for (let [func, n] of [[g.f, 20], [g.g, 10], [g.h, 5]]) {
|
||||
for (let i = 0; i < n; i++) {
|
||||
dbg.memory.trackingAllocationSites = true;
|
||||
// All allocations of allocationMarker occur with this line as the oldest
|
||||
@ -32,17 +33,19 @@ function run_test() {
|
||||
}
|
||||
}
|
||||
|
||||
let census = saveHeapSnapshotAndTakeCensus(dbg, { breakdown: { by: "objectClass",
|
||||
then: { by: "allocationStack",
|
||||
then: { by: "count",
|
||||
label: "haz stack"
|
||||
},
|
||||
noStack: { by: "count",
|
||||
label: "no haz stack"
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
let census = saveHeapSnapshotAndTakeCensus(
|
||||
dbg, { breakdown: {
|
||||
by: "objectClass",
|
||||
then: {
|
||||
by: "allocationStack",
|
||||
then: { by: "count", label: "haz stack"},
|
||||
noStack: {
|
||||
by: "count",
|
||||
label: "no haz stack"
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let map = census.AllocationMarker;
|
||||
ok(map instanceof Map, "Should be a Map instance");
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Check byte counts produced by takeCensus.
|
||||
//
|
||||
@ -25,7 +26,7 @@ function run_test() {
|
||||
for (let i = 0; i < 10; i++) // 5
|
||||
objs.push(allocationMarker()); // 6
|
||||
} // 7
|
||||
`); // 8
|
||||
`);
|
||||
|
||||
dbg.memory.allocationSamplingProbability = 1;
|
||||
dbg.memory.trackingAllocationSites = true;
|
||||
@ -35,7 +36,7 @@ function run_test() {
|
||||
census = saveHeapSnapshotAndTakeCensus(dbg, {
|
||||
breakdown: { by: "objectClass",
|
||||
then: { by: "allocationStack" }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let seen = 0;
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that Debugger.Memory.prototype.takeCensus and
|
||||
// HeapSnapshot.prototype.takeCensus return the same data for the same heap
|
||||
@ -14,7 +15,7 @@ function doLiveAndOfflineCensus(g, dbg, opts) {
|
||||
this.markers.push(allocationMarker()); // 4
|
||||
} // 5
|
||||
}()); // 6
|
||||
`); // 7
|
||||
`);
|
||||
dbg.memory.trackingAllocationSites = false;
|
||||
|
||||
return {
|
||||
@ -24,8 +25,8 @@ function doLiveAndOfflineCensus(g, dbg, opts) {
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
var g = newGlobal();
|
||||
var dbg = new Debugger(g);
|
||||
let g = newGlobal();
|
||||
let dbg = new Debugger(g);
|
||||
|
||||
g.eval("this.markers = []");
|
||||
const markerSize = byteSize(allocationMarker());
|
||||
@ -36,7 +37,7 @@ function run_test() {
|
||||
let prevCount = 0;
|
||||
let prevBytes = 0;
|
||||
|
||||
for (var i = 0; i < 10; i++) {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const { live, offline } = doLiveAndOfflineCensus(g, dbg, {
|
||||
breakdown: { by: "objectClass",
|
||||
then: { by: "count"} }
|
||||
@ -96,9 +97,8 @@ function run_test() {
|
||||
return -1;
|
||||
} else if (a[0] > b[0]) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
liveEntries.sort(sortEntries);
|
||||
offlineEntries.sort(sortEntries);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that when we take a census and get a bucket list of ids that matched the
|
||||
// given category, that the returned ids are all in the snapshot and their
|
||||
|
@ -2,7 +2,7 @@
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that we can read core dumps into HeapSnapshot instances.
|
||||
|
||||
/* eslint-disable strict */
|
||||
if (typeof Debugger != "function") {
|
||||
const { addDebuggerToGlobal } = Cu.import("resource://gre/modules/jsdebugger.jsm", {});
|
||||
addDebuggerToGlobal(this);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that we can save a core dump with allocation stacks and read it back
|
||||
// into a HeapSnapshot.
|
||||
|
@ -2,7 +2,7 @@
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test that we can read core dumps into HeapSnapshot instances in a worker.
|
||||
|
||||
// eslint-disable-next-line
|
||||
add_task(function* () {
|
||||
const worker = new ChromeWorker("resource://test/heap-snapshot-worker.js");
|
||||
worker.postMessage({});
|
||||
|
@ -2,7 +2,7 @@
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Test the ChromeUtils interface.
|
||||
|
||||
// eslint-disable-next-line
|
||||
if (typeof Debugger != "function") {
|
||||
const { addDebuggerToGlobal } = Cu.import("resource://gre/modules/jsdebugger.jsm", {});
|
||||
addDebuggerToGlobal(this);
|
||||
@ -49,8 +49,9 @@ function testBadParameters() {
|
||||
throws(() => ChromeUtils.saveHeapSnapshot({ debugger: Debugger.prototype }),
|
||||
"Should throw if debugger is the Debugger.prototype object.");
|
||||
|
||||
throws(() => ChromeUtils.saveHeapSnapshot({ get globals() { return [this]; } }),
|
||||
"Should throw if boundaries property is a getter.");
|
||||
throws(() => ChromeUtils.saveHeapSnapshot({ get globals() {
|
||||
return [this];
|
||||
} }), "Should throw if boundaries property is a getter.");
|
||||
}
|
||||
|
||||
const makeNewSandbox = () =>
|
||||
@ -63,14 +64,14 @@ function testGoodParameters() {
|
||||
ChromeUtils.saveHeapSnapshot({ debugger: dbg });
|
||||
ok(true, "Should be able to save a snapshot for a debuggee global.");
|
||||
|
||||
dbg = new Debugger;
|
||||
dbg = new Debugger();
|
||||
let sandboxes = Array(10).fill(null).map(makeNewSandbox);
|
||||
sandboxes.forEach(sb => dbg.addDebuggee(sb));
|
||||
|
||||
ChromeUtils.saveHeapSnapshot({ debugger: dbg });
|
||||
ok(true, "Should be able to save a snapshot for many debuggee globals.");
|
||||
|
||||
dbg = new Debugger;
|
||||
dbg = new Debugger();
|
||||
ChromeUtils.saveHeapSnapshot({ debugger: dbg });
|
||||
ok(true, "Should be able to save a snapshot with no debuggee globals.");
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Tests CensusTreeNode with `internalType` breakdown.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Tests CensusTreeNode with `coarseType` breakdown.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Tests CensusTreeNode with `objectClass` breakdown.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Tests CensusTreeNode with `allocationStack` breakdown.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Tests CensusTreeNode with `allocationStack` => `objectClass` breakdown.
|
||||
@ -29,11 +30,11 @@ function run_test() {
|
||||
}());
|
||||
|
||||
const REPORT = new Map([
|
||||
[stack, { Foo: { bytes: 10, count: 1 },
|
||||
Bar: { bytes: 20, count: 2 },
|
||||
Baz: { bytes: 30, count: 3 },
|
||||
other: { bytes: 40, count: 4 }
|
||||
}],
|
||||
[stack, { Foo: { bytes: 10, count: 1 },
|
||||
Bar: { bytes: 20, count: 2 },
|
||||
Baz: { bytes: 30, count: 3 },
|
||||
other: { bytes: 40, count: 4 }
|
||||
}],
|
||||
["noStack", { bytes: 50, count: 5 }],
|
||||
]);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Test inverting CensusTreeNode with a by alloaction stack breakdown.
|
||||
@ -12,8 +13,6 @@ function run_test() {
|
||||
noStack: { by: "count", count: true, bytes: true },
|
||||
};
|
||||
|
||||
let stack1, stack2, stack3, stack4;
|
||||
|
||||
function a(n) {
|
||||
return b(n);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Test inverting CensusTreeNode with a non-allocation stack breakdown.
|
||||
@ -21,7 +22,7 @@ function run_test() {
|
||||
by: "internalType",
|
||||
then: { by: "count", count: true, bytes: true },
|
||||
},
|
||||
other:{
|
||||
other: {
|
||||
by: "internalType",
|
||||
then: { by: "count", count: true, bytes: true },
|
||||
},
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Test inverting CensusTreeNode with a non-allocation stack breakdown.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test diffing census reports of breakdown by "internalType".
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test diffing census reports of breakdown by "count".
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test diffing census reports of breakdown by "coarseType".
|
||||
|
||||
@ -8,7 +9,7 @@ const BREAKDOWN = {
|
||||
objects: { by: "count", count: true, bytes: true },
|
||||
scripts: { by: "count", count: true, bytes: true },
|
||||
strings: { by: "count", count: true, bytes: true },
|
||||
other: { by: "count", count: true, bytes: true },
|
||||
other: { by: "count", count: true, bytes: true },
|
||||
};
|
||||
|
||||
const REPORT1 = {
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test diffing census reports of breakdown by "objectClass".
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test diffing census reports of breakdown by "allocationStack".
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test diffing census reports of a "complex" and "realistic" breakdown.
|
||||
|
||||
@ -41,11 +42,11 @@ const REPORT1 = {
|
||||
[stack1, { Function: { bytes: 1 },
|
||||
Object: { bytes: 2 },
|
||||
other: { bytes: 0 },
|
||||
}],
|
||||
}],
|
||||
[stack2, { Array: { bytes: 3 },
|
||||
Date: { bytes: 4 },
|
||||
other: { bytes: 0 },
|
||||
}],
|
||||
}],
|
||||
["noStack", { Object: { bytes: 3 }}],
|
||||
]),
|
||||
strings: {
|
||||
@ -66,11 +67,11 @@ const REPORT2 = {
|
||||
[stack2, { Array: { bytes: 1 },
|
||||
Date: { bytes: 2 },
|
||||
other: { bytes: 3 },
|
||||
}],
|
||||
}],
|
||||
[stack3, { Function: { bytes: 1 },
|
||||
Object: { bytes: 2 },
|
||||
other: { bytes: 0 },
|
||||
}],
|
||||
}],
|
||||
["noStack", { Object: { bytes: 3 }}],
|
||||
]),
|
||||
strings: {
|
||||
@ -92,15 +93,15 @@ const EXPECTED = {
|
||||
[stack1, { Function: { bytes: -1 },
|
||||
Object: { bytes: -2 },
|
||||
other: { bytes: 0 },
|
||||
}],
|
||||
}],
|
||||
[stack2, { Array: { bytes: -2 },
|
||||
Date: { bytes: -2 },
|
||||
other: { bytes: 3 },
|
||||
}],
|
||||
}],
|
||||
[stack3, { Function: { bytes: 1 },
|
||||
Object: { bytes: 2 },
|
||||
other: { bytes: 0 },
|
||||
}],
|
||||
}],
|
||||
["noStack", { Object: { bytes: 0 }}],
|
||||
]),
|
||||
"scripts": {
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test filtering basic CensusTreeNode trees.
|
||||
|
||||
@ -19,7 +20,7 @@ function run_test() {
|
||||
by: "internalType",
|
||||
then: { by: "count", count: true, bytes: true },
|
||||
},
|
||||
other:{
|
||||
other: {
|
||||
by: "internalType",
|
||||
then: { by: "count", count: true, bytes: true },
|
||||
},
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test filtering CensusTreeNode trees with an `allocationStack` breakdown.
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test filtering with no matches.
|
||||
|
||||
@ -19,7 +20,7 @@ function run_test() {
|
||||
by: "internalType",
|
||||
then: { by: "count", count: true, bytes: true },
|
||||
},
|
||||
other:{
|
||||
other: {
|
||||
by: "internalType",
|
||||
then: { by: "count", count: true, bytes: true },
|
||||
},
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test the filtered nodes' counts and bytes are the same as they were when
|
||||
// unfiltered.
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test that filtered and inverted allocation stack census trees are sorted
|
||||
// properly.
|
||||
|
@ -1,6 +1,7 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
// eslint-disable no-inline-comments
|
||||
|
||||
// Test basic functionality of `CensusUtils.getCensusIndividuals`.
|
||||
|
||||
@ -24,6 +25,7 @@ function run_test() {
|
||||
breakdown,
|
||||
CensusUtils.countToBucketBreakdown(BREAKDOWN));
|
||||
|
||||
/* eslint-disable */
|
||||
// DFS Index
|
||||
return new Map([ // 0
|
||||
[stack1, { // 1
|
||||
@ -43,6 +45,7 @@ function run_test() {
|
||||
JSString: [411, 412, 413], // 12
|
||||
}],
|
||||
]);
|
||||
/* eslint-enable */
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -63,7 +63,8 @@ function run_test() {
|
||||
const [ leaf ] = CensusUtils.getReportLeaves(new Set([node.reportLeafIndex]),
|
||||
BREAKDOWN,
|
||||
REPORT);
|
||||
ok(leaf, "Should be able to find leaf for a node with a reportLeafIndex = " + node.reportLeafIndex);
|
||||
ok(leaf, "Should be able to find leaf "
|
||||
+ "for a node with a reportLeafIndex = " + node.reportLeafIndex);
|
||||
}
|
||||
|
||||
if (node.children) {
|
||||
@ -88,6 +89,8 @@ function run_test() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const arrayNode = find("Array", root);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
"use strict";
|
||||
|
||||
// Test saving a heap snapshot in the sandboxed e10s child process.
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user