tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit d60c7c078bfee64add1dd4b025632db20eb0f477
parent a0b750c5fc0df2f7ab481542365d24cc42645465
Author: Lorenz A <me@lorenzackermann.xyz>
Date:   Tue, 16 Dec 2025 13:52:42 +0000

Bug 2004238 - [devtools] Turn devtools/shared/heapsnapshot/CensusUtils.js into an ES class. r=devtools-reviewers,nchevobbe

Differential Revision: https://phabricator.services.mozilla.com/D276560

Diffstat:
Mdevtools/shared/heapsnapshot/CensusUtils.js | 409+++++++++++++++++++++++++++++++++++++++----------------------------------------
1 file changed, 203 insertions(+), 206 deletions(-)

diff --git a/devtools/shared/heapsnapshot/CensusUtils.js b/devtools/shared/heapsnapshot/CensusUtils.js @@ -13,55 +13,53 @@ const { * A Visitor visits each node and edge of a census report tree as the census * report is being traversed by `walk`. */ -function Visitor() {} +class Visitor { + /** + * The `enter` method is called when a new sub-report is entered in traversal. + * + * @param {object} breakdown + * The breakdown for the sub-report that is being entered by traversal. + * + * @param {object} report + * The report generated by the given breakdown. + * + * @param {any} edge + * The edge leading to this sub-report. The edge is null if (but not iff! + * eg, null allocation stack edges) we are entering the root report. + */ + enter() {} + /** + * The `exit` method is called when traversal of a sub-report has finished. + * + * @param {object} breakdown + * The breakdown for the sub-report whose traversal has finished. + * + * @param {object} report + * The report generated by the given breakdown. + * + * @param {any} edge + * The edge leading to this sub-report. The edge is null if (but not iff! + * eg, null allocation stack edges) we are entering the root report. + */ + exit() {} + /** + * The `count` method is called when leaf nodes (reports whose breakdown is + * by: "count") in the report tree are encountered. + * + * @param {object} breakdown + * The count breakdown for this report. + * + * @param {object} report + * The report generated by a breakdown by "count". + * + * @param {any|null} edge + * The edge leading to this count report. The edge is null if we are + * entering the root report. + */ + count() {} +} exports.Visitor = Visitor; -/** - * The `enter` method is called when a new sub-report is entered in traversal. - * - * @param {object} breakdown - * The breakdown for the sub-report that is being entered by traversal. - * - * @param {object} report - * The report generated by the given breakdown. - * - * @param {any} edge - * The edge leading to this sub-report. The edge is null if (but not iff! - * eg, null allocation stack edges) we are entering the root report. - */ -Visitor.prototype.enter = function () {}; - -/** - * The `exit` method is called when traversal of a sub-report has finished. - * - * @param {object} breakdown - * The breakdown for the sub-report whose traversal has finished. - * - * @param {object} report - * The report generated by the given breakdown. - * - * @param {any} edge - * The edge leading to this sub-report. The edge is null if (but not iff! - * eg, null allocation stack edges) we are entering the root report. - */ -Visitor.prototype.exit = function () {}; - -/** - * The `count` method is called when leaf nodes (reports whose breakdown is - * by: "count") in the report tree are encountered. - * - * @param {object} breakdown - * The count breakdown for this report. - * - * @param {object} report - * The report generated by a breakdown by "count". - * - * @param {any|null} edge - * The edge leading to this count report. The edge is null if we are - * entering the root report. - */ -Visitor.prototype.count = function () {}; - /*** getReportEdges *********************************************************/ const EDGES = Object.create(null); @@ -193,165 +191,164 @@ function isMap(obj) { return Object.prototype.toString.call(obj) === "[object Map]"; } +const basisTotalBytes = (exports.basisTotalBytes = Symbol("basisTotalBytes")); +const basisTotalCount = (exports.basisTotalCount = Symbol("basisTotalCount")); + /** * A Visitor for computing the difference between the census report being * traversed and the given other census. - * - * @param {object} otherCensus - * The other census report. */ -function DiffVisitor(otherCensus) { - // The other census we are comparing against. - this._otherCensus = otherCensus; - - // The total bytes and count of the basis census we are traversing. - this._totalBytes = 0; - this._totalCount = 0; - - // Stack maintaining the current corresponding sub-report for the other - // census we are comparing against. - this._otherCensusStack = []; - - // Stack maintaining the set of edges visited at each sub-report. - this._edgesVisited = [new Set()]; - - // The final delta census. Valid only after traversal. - this._results = null; - - // Stack maintaining the results corresponding to each sub-report we are - // currently traversing. - this._resultsStack = []; -} - -DiffVisitor.prototype = Object.create(Visitor.prototype); - -/** - * Given a report and an outgoing edge, get the edge's referent. - */ -DiffVisitor.prototype._get = function (report, edge) { - if (!report) { - return undefined; +class DiffVisitor extends Visitor { + /** + * @param {object} otherCensus + * The other census report. + */ + constructor(otherCensus) { + super(); + + // The other census we are comparing against. + this._otherCensus = otherCensus; + + // The total bytes and count of the basis census we are traversing. + this._totalBytes = 0; + this._totalCount = 0; + + // Stack maintaining the current corresponding sub-report for the other + // census we are comparing against. + this._otherCensusStack = []; + + // Stack maintaining the set of edges visited at each sub-report. + this._edgesVisited = [new Set()]; + + // The final delta census. Valid only after traversal. + this._results = null; + + // Stack maintaining the results corresponding to each sub-report we are + // currently traversing. + this._resultsStack = []; } - return isMap(report) ? report.get(edge) : report[edge]; -}; - -/** - * Given a report, an outgoing edge, and a value, set the edge's referent to - * the given value. - */ -DiffVisitor.prototype._set = function (report, edge, val) { - if (isMap(report)) { - report.set(edge, val); - } else { - report[edge] = val; + /** + * Given a report and an outgoing edge, get the edge's referent. + */ + _get(report, edge) { + if (!report) { + return undefined; + } + return isMap(report) ? report.get(edge) : report[edge]; } -}; - -/** - * @overrides Visitor.prototype.enter - */ -DiffVisitor.prototype.enter = function (breakdown, report, edge) { - const newResults = breakdown.by === "allocationStack" ? new Map() : {}; - let newOther; - - if (!this._results) { - // This is the first time we have entered a sub-report. - this._results = newResults; - newOther = this._otherCensus; - } else { - const topResults = this._resultsStack[this._resultsStack.length - 1]; - this._set(topResults, edge, newResults); - - const topOther = this._otherCensusStack[this._otherCensusStack.length - 1]; - newOther = this._get(topOther, edge); + /** + * Given a report, an outgoing edge, and a value, set the edge's referent to + * the given value. + */ + _set(report, edge, val) { + if (isMap(report)) { + report.set(edge, val); + } else { + report[edge] = val; + } } + /** + * @override + */ + enter(breakdown, report, edge) { + const newResults = breakdown.by === "allocationStack" ? new Map() : {}; + let newOther; + + if (!this._results) { + // This is the first time we have entered a sub-report. + this._results = newResults; + newOther = this._otherCensus; + } else { + const topResults = this._resultsStack[this._resultsStack.length - 1]; + this._set(topResults, edge, newResults); + + const topOther = + this._otherCensusStack[this._otherCensusStack.length - 1]; + newOther = this._get(topOther, edge); + } - this._resultsStack.push(newResults); - this._otherCensusStack.push(newOther); + this._resultsStack.push(newResults); + this._otherCensusStack.push(newOther); - const visited = this._edgesVisited[this._edgesVisited.length - 1]; - visited.add(edge); - this._edgesVisited.push(new Set()); -}; - -/** - * @overrides Visitor.prototype.exit - */ -DiffVisitor.prototype.exit = function (breakdown) { - // Find all the edges in the other census report that were not traversed and - // add them to the results directly. - const other = this._otherCensusStack[this._otherCensusStack.length - 1]; - if (other) { const visited = this._edgesVisited[this._edgesVisited.length - 1]; - const unvisited = getReportEdges(breakdown, other) - .map(e => e.edge) - .filter(e => !visited.has(e)); - const results = this._resultsStack[this._resultsStack.length - 1]; - for (const edg of unvisited) { - this._set(results, edg, this._get(other, edg)); - } + visited.add(edge); + this._edgesVisited.push(new Set()); } + /** + * @override + */ + exit(breakdown) { + // Find all the edges in the other census report that were not traversed and + // add them to the results directly. + const other = this._otherCensusStack[this._otherCensusStack.length - 1]; + if (other) { + const visited = this._edgesVisited[this._edgesVisited.length - 1]; + const unvisited = getReportEdges(breakdown, other) + .map(e => e.edge) + .filter(e => !visited.has(e)); + const results = this._resultsStack[this._resultsStack.length - 1]; + for (const edg of unvisited) { + this._set(results, edg, this._get(other, edg)); + } + } - this._otherCensusStack.pop(); - this._resultsStack.pop(); - this._edgesVisited.pop(); -}; - -/** - * @overrides Visitor.prototype.count - */ -DiffVisitor.prototype.count = function (breakdown, report) { - const other = this._otherCensusStack[this._otherCensusStack.length - 1]; - const results = this._resultsStack[this._resultsStack.length - 1]; - - if (breakdown.count) { - this._totalCount += report.count; - } - if (breakdown.bytes) { - this._totalBytes += report.bytes; + this._otherCensusStack.pop(); + this._resultsStack.pop(); + this._edgesVisited.pop(); } + /** + * @override + */ + count(breakdown, report) { + const other = this._otherCensusStack[this._otherCensusStack.length - 1]; + const results = this._resultsStack[this._resultsStack.length - 1]; - if (other) { if (breakdown.count) { - results.count = other.count - report.count; + this._totalCount += report.count; } if (breakdown.bytes) { - results.bytes = other.bytes - report.bytes; - } - } else { - if (breakdown.count) { - results.count = -report.count; + this._totalBytes += report.bytes; } - if (breakdown.bytes) { - results.bytes = -report.bytes; + + if (other) { + if (breakdown.count) { + results.count = other.count - report.count; + } + if (breakdown.bytes) { + results.bytes = other.bytes - report.bytes; + } + } else { + if (breakdown.count) { + results.count = -report.count; + } + if (breakdown.bytes) { + results.bytes = -report.bytes; + } } } -}; - -const basisTotalBytes = (exports.basisTotalBytes = Symbol("basisTotalBytes")); -const basisTotalCount = (exports.basisTotalCount = Symbol("basisTotalCount")); -/** - * Get the resulting report of the difference between the traversed census - * report and the other census report. - * - * @returns {object} - * The delta census report. - */ -DiffVisitor.prototype.results = function () { - if (!this._results) { - throw new Error("Attempt to get results before computing diff!"); - } + /** + * Get the resulting report of the difference between the traversed census + * report and the other census report. + * + * @returns {object} + * The delta census report. + */ + results() { + if (!this._results) { + throw new Error("Attempt to get results before computing diff!"); + } - if (this._resultsStack.length) { - throw new Error("Attempt to get results while still computing diff!"); - } + if (this._resultsStack.length) { + throw new Error("Attempt to get results while still computing diff!"); + } - this._results[basisTotalBytes] = this._totalBytes; - this._results[basisTotalCount] = this._totalCount; + this._results[basisTotalBytes] = this._totalBytes; + this._results[basisTotalCount] = this._totalCount; - return this._results; -}; + return this._results; + } +} /** * Take the difference between two censuses. The resulting delta report @@ -436,33 +433,33 @@ exports.countToBucketBreakdown = function (breakdown) { /** * A Visitor for finding report leaves by their DFS index. */ -function GetLeavesVisitor(targetIndices) { - this._index = -1; - this._targetIndices = targetIndices; - this._leaves = []; -} +class GetLeavesVisitor extends Visitor { + constructor(targetIndices) { + super(); -GetLeavesVisitor.prototype = Object.create(Visitor.prototype); - -/** - * @overrides Visitor.prototype.enter - */ -GetLeavesVisitor.prototype.enter = function (breakdown, report) { - this._index++; - if (this._targetIndices.has(this._index)) { - this._leaves.push(report); + this._index = -1; + this._targetIndices = targetIndices; + this._leaves = []; } -}; - -/** - * Get the accumulated report leaves after traversal. - */ -GetLeavesVisitor.prototype.leaves = function () { - if (this._index === -1) { - throw new Error("Attempt to call `leaves` before traversing report!"); + /** + * @override + */ + enter(breakdown, report) { + this._index++; + if (this._targetIndices.has(this._index)) { + this._leaves.push(report); + } } - return this._leaves; -}; + /** + * Get the accumulated report leaves after traversal. + */ + leaves() { + if (this._index === -1) { + throw new Error("Attempt to call `leaves` before traversing report!"); + } + return this._leaves; + } +} /** * Given a set of indices of leaves in a pre-order depth-first traversal of the