fortify2-js
Version:
MOST POWERFUL JavaScript Security Library! Military-grade cryptography + 19 enhanced object methods + quantum-resistant algorithms + perfect TypeScript support. More powerful than Lodash with built-in security.
729 lines (723 loc) • 24 kB
JavaScript
'use strict';
var global$1 = require('../../types/global.js');
var types = require('./types.js');
var eventManager = require('./event-manager.js');
var configManager = require('./config-manager.js');
var referenceTracker = require('./reference-tracker.js');
var memoryPool = require('./memory-pool.js');
/***************************************************************************
* FortifyJS - Secure Array Types
*
* This file contains type definitions for the SecureArray modular architecture
*
* @author Nehonix
*
* @license MIT
*
* Copyright (c) 2025 Nehonix. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
***************************************************************************** */
/**
* Advanced Memory Manager
*
* Main orchestrator for the memory management system with all components
*/
// Initialize polyfills for WeakRef and FinalizationRegistry
global$1.initializePolyfills();
/**
* Advanced Memory Manager with modular architecture
*/
class AdvancedMemoryManager {
constructor(config = {}) {
this.pools = new Map();
// Initialize state
this.state = {
isRunning: false,
lastGC: Date.now(),
nextScheduledGC: 0,
activeMonitors: 0,
errorCount: 0,
uptime: Date.now(),
};
// Initialize stats
this.stats = {
totalAllocated: 0,
totalFreed: 0,
currentUsage: 0,
peakUsage: 0,
gcCount: 0,
leakCount: 0,
pressure: 0,
poolStats: [],
trackedObjects: 0,
lastGC: Date.now(),
averageGCTime: 0,
};
// Initialize performance metrics
this.performanceMetrics = {
averageGCTime: 0,
gcFrequency: 0,
memoryEfficiency: 0,
poolHitRates: {},
leakDetectionAccuracy: 0,
systemLoad: 0,
};
// Initialize components in order
this.eventManager = new eventManager.MemoryEventManager(this.getDefaultConfig());
this.configManager = new configManager.ConfigurationManager(config, this.eventManager);
this.referenceTracker = new referenceTracker.AdvancedReferenceTracker(this.eventManager, this.configManager.getConfig());
// Start the memory manager
this.start();
}
/**
* Get singleton instance
*/
static getInstance(config) {
if (!AdvancedMemoryManager.instance) {
AdvancedMemoryManager.instance = new AdvancedMemoryManager(config);
}
return AdvancedMemoryManager.instance;
}
/**
* Get default configuration
*/
getDefaultConfig() {
return {
maxMemory: 100 * 1024 * 1024, // 100MB
gcThreshold: 0.8,
gcInterval: 30000, // 30 seconds
enableLeakDetection: true,
enablePerformanceMonitoring: true,
enableEventLogging: false,
autoCleanupInterval: 60000, // 1 minute
maxPoolAge: 300000, // 5 minutes
leakDetectionThreshold: 300000, // 5 minutes
maxEventHistory: 1000,
};
}
/**
* Start the memory manager
*/
start() {
if (this.state.isRunning) {
return;
}
this.state.isRunning = true;
this.state.uptime = Date.now();
const config = this.configManager.getConfig();
// Start garbage collection monitoring
this.startGCMonitoring();
// Start performance monitoring if enabled
if (config.enablePerformanceMonitoring) {
this.startPerformanceMonitoring();
}
// Start cleanup monitoring
this.startCleanupMonitoring();
this.eventManager.emit(types.MemoryEventType.CONFIG_UPDATED, {
action: "started",
config: config,
});
}
/**
* Start garbage collection monitoring
*/
startGCMonitoring() {
const config = this.configManager.getConfig();
if (this.gcInterval) {
clearInterval(this.gcInterval);
}
this.gcInterval = setInterval(() => {
this.checkMemoryPressure();
}, config.gcInterval);
this.state.nextScheduledGC = Date.now() + config.gcInterval;
}
/**
* Start performance monitoring
*/
startPerformanceMonitoring() {
if (this.monitoringInterval) {
clearInterval(this.monitoringInterval);
}
this.monitoringInterval = setInterval(() => {
this.updatePerformanceMetrics();
this.updateMemoryStats();
}, 5000); // Update every 5 seconds
this.state.activeMonitors++;
}
/**
* Start cleanup monitoring
*/
startCleanupMonitoring() {
const config = this.configManager.getConfig();
if (this.cleanupInterval) {
clearInterval(this.cleanupInterval);
}
this.cleanupInterval = setInterval(() => {
this.performCleanup();
}, config.autoCleanupInterval);
this.state.activeMonitors++;
}
/**
* Check memory pressure and trigger GC if needed
*/
checkMemoryPressure() {
try {
const usage = this.getCurrentMemoryUsage();
const config = this.configManager.getConfig();
this.stats.currentUsage = usage.estimatedSize;
this.stats.pressure = usage.estimatedSize / config.maxMemory;
const pressureInfo = this.getMemoryPressureInfo();
if (pressureInfo.shouldTriggerGC) {
this.triggerGarbageCollection();
}
// Emit memory pressure event if significant
if (pressureInfo.level !== types.MemoryPressureLevel.LOW) {
this.eventManager.emit(types.MemoryEventType.MEMORY_PRESSURE, pressureInfo);
}
}
catch (error) {
this.handleError("checkMemoryPressure", error);
}
}
/**
* Get current memory usage estimation
*/
getCurrentMemoryUsage() {
// Try Node.js process.memoryUsage first
if (typeof process !== "undefined" && process.memoryUsage) {
const usage = process.memoryUsage();
return {
estimatedSize: usage.heapUsed,
confidence: 0.95,
method: "node",
breakdown: {
heap: usage.heapUsed,
external: usage.external,
},
};
}
// Browser fallback - estimate based on tracked objects
const trackerStats = this.referenceTracker.getStats();
return {
estimatedSize: trackerStats.totalEstimatedSize || 0,
confidence: 0.6,
method: "browser",
breakdown: {
tracked: trackerStats.totalEstimatedSize || 0,
},
};
}
/**
* Get memory pressure information
*/
getMemoryPressureInfo() {
const config = this.configManager.getConfig();
const pressure = this.stats.pressure;
let level;
let recommendation;
let shouldTriggerGC;
if (pressure < 0.5) {
level = types.MemoryPressureLevel.LOW;
recommendation = "Memory usage is optimal";
shouldTriggerGC = false;
}
else if (pressure < config.gcThreshold) {
level = types.MemoryPressureLevel.MEDIUM;
recommendation = "Monitor memory usage";
shouldTriggerGC = false;
}
else if (pressure < 0.95) {
level = types.MemoryPressureLevel.HIGH;
recommendation = "Consider triggering garbage collection";
shouldTriggerGC = true;
}
else {
level = types.MemoryPressureLevel.CRITICAL;
recommendation = "Immediate garbage collection required";
shouldTriggerGC = true;
}
// Also check time since last GC
const timeSinceLastGC = Date.now() - this.state.lastGC;
if (timeSinceLastGC >= config.gcInterval) {
shouldTriggerGC = true;
}
return {
level,
pressure,
recommendation,
shouldTriggerGC,
};
}
/**
* Trigger garbage collection
*/
triggerGarbageCollection() {
const startTime = Date.now();
const beforeUsage = this.stats.currentUsage;
this.eventManager.emit(types.MemoryEventType.GC_TRIGGERED, {
beforeUsage,
pressure: this.stats.pressure,
trigger: "automatic",
});
try {
// Clean up dead references
this.referenceTracker.cleanup();
// Clean up memory pools
let poolsCleanedUp = 0;
for (const pool of this.pools.values()) {
// Remove old items from pools
const sizeBefore = pool.size;
// Pool cleanup is handled internally
if (pool.size < sizeBefore) {
poolsCleanedUp++;
}
}
// Force GC if available (Node.js)
if (typeof global !== "undefined" && global.gc) {
global.gc();
}
// Update stats
const afterUsage = this.getCurrentMemoryUsage().estimatedSize;
const duration = Date.now() - startTime;
const freedMemory = Math.max(0, beforeUsage - afterUsage);
this.stats.totalFreed += freedMemory;
this.stats.gcCount++;
this.stats.lastGC = Date.now();
this.state.lastGC = Date.now();
// Update average GC time
this.stats.averageGCTime =
(this.stats.averageGCTime * (this.stats.gcCount - 1) +
duration) /
this.stats.gcCount;
const result = {
beforeUsage,
afterUsage,
freedMemory,
duration,
objectsCollected: 0, // Would need more sophisticated tracking
poolsCleanedUp,
success: true,
};
this.eventManager.emit(types.MemoryEventType.GC_COMPLETED, result);
return result;
}
catch (error) {
const result = {
beforeUsage,
afterUsage: beforeUsage,
freedMemory: 0,
duration: Date.now() - startTime,
objectsCollected: 0,
poolsCleanedUp: 0,
success: false,
error: error instanceof Error ? error.message : String(error),
};
this.handleError("triggerGarbageCollection", error);
return result;
}
}
/**
* Perform routine cleanup
*/
performCleanup() {
try {
// Clean up reference tracker
this.referenceTracker.cleanup();
// Detect memory leaks if enabled
const config = this.configManager.getConfig();
if (config.enableLeakDetection) {
const leaks = this.referenceTracker.detectLeaks();
this.stats.leakCount = leaks.length;
}
// Update tracked objects count
this.stats.trackedObjects =
this.referenceTracker.getTrackedObjects().length;
}
catch (error) {
this.handleError("performCleanup", error);
}
}
/**
* Update performance metrics
*/
updatePerformanceMetrics() {
try {
// Update pool hit rates
const poolHitRates = {};
for (const [name, pool] of this.pools.entries()) {
const stats = pool.getStats();
poolHitRates[name] = stats.hitRate;
}
this.performanceMetrics.poolHitRates = poolHitRates;
// Calculate GC frequency (GCs per hour)
const uptime = Date.now() - this.state.uptime;
this.performanceMetrics.gcFrequency =
(this.stats.gcCount / uptime) * 3600000;
// Calculate memory efficiency
const config = this.configManager.getConfig();
this.performanceMetrics.memoryEfficiency =
1 - this.stats.currentUsage / config.maxMemory;
// Update average GC time
this.performanceMetrics.averageGCTime = this.stats.averageGCTime;
}
catch (error) {
this.handleError("updatePerformanceMetrics", error);
}
}
/**
* Update memory statistics
*/
updateMemoryStats() {
try {
const usage = this.getCurrentMemoryUsage();
this.stats.currentUsage = usage.estimatedSize;
this.stats.peakUsage = Math.max(this.stats.peakUsage, usage.estimatedSize);
const config = this.configManager.getConfig();
this.stats.pressure = usage.estimatedSize / config.maxMemory;
// Update pool stats
this.stats.poolStats = Array.from(this.pools.values()).map((pool) => pool.getStats());
}
catch (error) {
this.handleError("updateMemoryStats", error);
}
}
/**
* Handle errors with proper logging and recovery
*/
handleError(operation, error) {
this.state.errorCount++;
const errorMessage = error instanceof Error ? error.message : String(error);
console.error(`Memory Manager Error in ${operation}:`, errorMessage);
this.eventManager.emit(types.MemoryEventType.ERROR_OCCURRED, {
operation,
error: errorMessage,
timestamp: Date.now(),
errorCount: this.state.errorCount,
});
}
// Public API methods
/**
* Register an object for memory tracking
*/
registerObject(obj, id) {
try {
this.referenceTracker.addReference(obj, id);
this.stats.totalAllocated += this.estimateObjectSize(obj);
}
catch (error) {
this.handleError("registerObject", error);
}
}
/**
* Unregister an object from memory tracking
*/
unregisterObject(id) {
try {
this.referenceTracker.removeReference(id);
this.stats.trackedObjects = Math.max(0, this.stats.trackedObjects - 1);
}
catch (error) {
this.handleError("unregisterObject", error);
}
}
/**
* Add reference to an object
*/
addReference(id) {
try {
this.referenceTracker.addReference({}, id); // This needs to be fixed in the interface
}
catch (error) {
this.handleError("addReference", error);
}
}
/**
* Remove reference from an object
*/
removeReference(id) {
try {
this.referenceTracker.removeReference(id);
}
catch (error) {
this.handleError("removeReference", error);
}
}
/**
* Create a memory pool for object reuse
*/
createPool(config) {
try {
if (this.pools.has(config.name)) {
throw new Error(`Pool with name '${config.name}' already exists`);
}
const pool = new memoryPool.AdvancedMemoryPool(config, this.eventManager);
this.pools.set(config.name, pool);
return pool;
}
catch (error) {
this.handleError("createPool", error);
throw error;
}
}
/**
* Get memory pool by name
*/
getPool(name) {
return this.pools.get(name);
}
/**
* Remove a memory pool
*/
removePool(name) {
const pool = this.pools.get(name);
if (pool && "destroy" in pool && typeof pool.destroy === "function") {
pool.destroy();
}
return this.pools.delete(name);
}
/**
* Get current memory statistics
*/
getStats() {
this.updateMemoryStats();
return { ...this.stats };
}
/**
* Get performance metrics
*/
getPerformanceMetrics() {
this.updatePerformanceMetrics();
return { ...this.performanceMetrics };
}
/**
* Get memory manager state
*/
getState() {
return { ...this.state };
}
/**
* Set memory limits
*/
setLimits(maxMemory, gcThreshold = 0.8) {
try {
this.configManager.updateConfig({ maxMemory, gcThreshold });
// Restart monitoring with new configuration
this.startGCMonitoring();
}
catch (error) {
this.handleError("setLimits", error);
throw error;
}
}
/**
* Force garbage collection
*/
forceGC() {
this.eventManager.emit(types.MemoryEventType.GC_TRIGGERED, {
trigger: "manual",
timestamp: Date.now(),
});
return this.triggerGarbageCollection();
}
/**
* Estimate object size in bytes
*/
estimateObjectSize(obj) {
if (obj === null || obj === undefined)
return 0;
const type = typeof obj;
switch (type) {
case "boolean":
return 4;
case "number":
return 8;
case "string":
return obj.length * 2; // UTF-16
case "object":
if (obj instanceof ArrayBuffer)
return obj.byteLength;
if (obj instanceof Uint8Array)
return obj.byteLength;
if (Array.isArray(obj)) {
return obj.reduce((sum, item) => sum + this.estimateObjectSize(item), 0);
}
return Object.keys(obj).length * 64; // Rough estimate
default:
return 64; // Default estimate
}
}
/**
* Get memory usage report
*/
getMemoryReport() {
const stats = this.getStats();
const state = this.getState();
const config = this.configManager.getConfig();
return `
Memory Manager Report:
=====================
Current Usage: ${this.formatBytes(stats.currentUsage)}
Peak Usage: ${this.formatBytes(stats.peakUsage)}
Total Allocated: ${this.formatBytes(stats.totalAllocated)}
Total Freed: ${this.formatBytes(stats.totalFreed)}
Memory Pressure: ${(stats.pressure * 100).toFixed(1)}%
GC Count: ${stats.gcCount}
Average GC Time: ${stats.averageGCTime.toFixed(2)}ms
Tracked Objects: ${stats.trackedObjects}
Memory Pools: ${this.pools.size}
Leak Count: ${stats.leakCount}
Configuration:
- Max Memory: ${this.formatBytes(config.maxMemory)}
- GC Threshold: ${(config.gcThreshold * 100).toFixed(1)}%
- GC Interval: ${(config.gcInterval / 1000).toFixed(1)}s
- Leak Detection: ${config.enableLeakDetection ? "Enabled" : "Disabled"}
- Performance Monitoring: ${config.enablePerformanceMonitoring ? "Enabled" : "Disabled"}
State:
- Running: ${state.isRunning}
- Uptime: ${this.formatDuration(Date.now() - state.uptime)}
- Active Monitors: ${state.activeMonitors}
- Error Count: ${state.errorCount}
`.trim();
}
/**
* Format bytes for human-readable output
*/
formatBytes(bytes) {
const units = ["B", "KB", "MB", "GB"];
let size = bytes;
let unitIndex = 0;
while (size >= 1024 && unitIndex < units.length - 1) {
size /= 1024;
unitIndex++;
}
return `${size.toFixed(2)} ${units[unitIndex]}`;
}
/**
* Format duration for human-readable output
*/
formatDuration(ms) {
const seconds = Math.floor(ms / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);
if (days > 0)
return `${days}d ${hours % 24}h ${minutes % 60}m`;
if (hours > 0)
return `${hours}h ${minutes % 60}m ${seconds % 60}s`;
if (minutes > 0)
return `${minutes}m ${seconds % 60}s`;
return `${seconds}s`;
}
/**
* Update configuration
*/
updateConfig(updates) {
try {
this.configManager.updateConfig(updates);
// Update components with new configuration
const newConfig = this.configManager.getConfig();
this.referenceTracker.updateConfig(newConfig);
this.eventManager.updateConfig(newConfig);
// Restart monitoring if intervals changed
if (updates.gcInterval !== undefined) {
this.startGCMonitoring();
}
if (updates.autoCleanupInterval !== undefined) {
this.startCleanupMonitoring();
}
}
catch (error) {
this.handleError("updateConfig", error);
throw error;
}
}
/**
* Get configuration
*/
getConfig() {
return this.configManager.getConfig();
}
/**
* Add event listener
*/
on(type, listener) {
this.eventManager.on(type, listener);
}
/**
* Remove event listener
*/
off(type, listener) {
this.eventManager.off(type, listener);
}
/**
* Stop the memory manager
*/
stop() {
if (!this.state.isRunning) {
return;
}
this.state.isRunning = false;
// Clear all intervals
if (this.gcInterval) {
clearInterval(this.gcInterval);
this.gcInterval = undefined;
}
if (this.monitoringInterval) {
clearInterval(this.monitoringInterval);
this.monitoringInterval = undefined;
}
if (this.cleanupInterval) {
clearInterval(this.cleanupInterval);
this.cleanupInterval = undefined;
}
this.state.activeMonitors = 0;
this.eventManager.emit(types.MemoryEventType.CONFIG_UPDATED, {
action: "stopped",
timestamp: Date.now(),
});
}
/**
* Restart the memory manager
*/
restart() {
this.stop();
this.start();
}
/**
* Destroy the memory manager and clean up all resources
*/
destroy() {
this.stop();
// Destroy all pools
for (const [name, pool] of this.pools.entries()) {
if ("destroy" in pool && typeof pool.destroy === "function") {
pool.destroy();
}
}
this.pools.clear();
// Destroy components
this.referenceTracker.destroy();
this.eventManager.destroy();
// Reset singleton instance
AdvancedMemoryManager.instance = null;
}
}
exports.AdvancedMemoryManager = AdvancedMemoryManager;
//# sourceMappingURL=memory-manager.js.map