UNPKG

js-memory-leak-detector

Version:

A comprehensive memory leak detector for web applications with Redux Toolkit support

80 lines 2.71 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.DOMTracker = void 0; class DOMTracker { constructor() { this.observer = null; this.detachedNodes = new Set(); this.nodeCount = 0; this.setupMutationObserver(); } setupMutationObserver() { if (typeof MutationObserver === 'undefined') { return; // Not available in this environment } this.observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { // Track added nodes mutation.addedNodes.forEach((node) => { this.nodeCount++; }); // Track removed nodes that might become detached mutation.removedNodes.forEach((node) => { this.checkForDetachedNode(node); }); }); }); this.observer.observe(document.body, { childList: true, subtree: true }); } checkForDetachedNode(node) { // Check if node is completely detached from DOM if (node.nodeType === Node.ELEMENT_NODE) { const element = node; if (!document.contains(element) && element.parentNode === null) { this.detachedNodes.add(node); } } } getDOMNodeCount() { return document.querySelectorAll('*').length; } getDetachedNodeCount() { return this.detachedNodes.size; } detectLeaks() { const suspects = []; const currentNodeCount = this.getDOMNodeCount(); const detachedCount = this.getDetachedNodeCount(); // Check for excessive DOM nodes if (currentNodeCount > 10000) { suspects.push({ type: 'dom-reference', severity: currentNodeCount > 50000 ? 'critical' : 'high', description: `${currentNodeCount} DOM nodes detected (potential DOM bloat)`, count: currentNodeCount }); } // Check for detached DOM nodes if (detachedCount > 100) { suspects.push({ type: 'detached-dom', severity: detachedCount > 1000 ? 'critical' : 'medium', description: `${detachedCount} detached DOM nodes found in memory`, count: detachedCount }); } return suspects; } cleanup() { if (this.observer) { this.observer.disconnect(); this.observer = null; } this.detachedNodes.clear(); } } exports.DOMTracker = DOMTracker; //# sourceMappingURL=dom-tracker.js.map