UNPKG

libxml2-wasm

Version:

WebAssembly-based libxml2 javascript wrapper

114 lines 3.57 kB
const noopTracker = { trackAllocate() { }, trackDeallocate() { }, report() { }, }; function callstack(numSkip) { const { stack } = new Error(); if (!stack) return undefined; let pos = 0; // each line is one function call // remove two extract lines, error message and call to this function for (let i = numSkip + 2; i > 0; i -= 1) { pos = stack.indexOf('\n', pos) + 1; } return stack.substring(pos); } class MemTrackerImpl { constructor(callerDetail, callerStats) { this.callerDetail = callerDetail; this.callerStats = callerStats; this.idCounter = 0; this.disposableId = new WeakMap(); this.disposableInfo = new Map(); } trackAllocate(obj) { this.idCounter += 1; this.disposableId.set(obj, this.idCounter); const info = { object: new WeakRef(obj), classname: obj.constructor.name, }; if (this.callerDetail || this.callerStats) { info.callstack = callstack(2); } this.disposableInfo.set(this.idCounter, info); } trackDeallocate(obj) { const id = this.disposableId.get(obj); if (id) { // the object may be created before the diagnosis enabled this.disposableInfo.delete(id); this.disposableId.delete(obj); } } report() { const memReport = {}; this.disposableInfo.forEach((info) => { // eslint-disable-next-line no-multi-assign const classReport = memReport[info.classname] ||= { garbageCollected: 0, totalInstances: 0, instances: [], }; classReport.totalInstances += 1; const obj = info.object.deref(); if (obj != null) { const instanceInfo = { instance: obj }; if (this.callerDetail) { instanceInfo.caller = info.callstack; } classReport.instances.push(instanceInfo); } else { classReport.garbageCollected += 1; } if (this.callerStats) { const callers = (classReport.callers ||= {}); // eslint-disable-line no-multi-assign callers[info.callstack] = (callers[info.callstack] || 0) + 1; } }); return memReport; } } /** * Set up memory diagnostic helpers. * * When enabled, * these helpers will record allocated {@link disposable.XmlDisposable} objects * (and their subclass objects) * and track whether the {@link disposable.XmlDisposable#dispose} method is called. * * Note that the allocation of these objects will not be monitored * before memory diagnostics is enabled. * * @param options * @see {@link report} */ export function configure(options) { if (options.enabled) { memTracker = new MemTrackerImpl(options.callerDetail === true, options.callerStats === true); } else { memTracker = noopTracker; } } /** * Obtain the report containing information about un-disposed objects. * @returns The report (in JSON format) whose format may vary according to the settings, * and is subject to change. * If memory diagnostic is not enabled, the report will be undefined. * @see {@link configure} */ export function report() { return memTracker.report(); } let memTracker = noopTracker; /** @internal */ export function tracker() { return memTracker; } //# sourceMappingURL=diag.mjs.map