amberjs 1.16.1

JavaScript/TypeScript runtime built with Rust and V8
Documentation
// Debugger Inspector Module
//
// Provides inspection capabilities for:
// - Heap snapshots
// - Object tracing
/// - Memory analysis
use crate::runtime::JsValue;
use anyhow::Result;
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap};
/// Heap snapshot
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HeapSnapshot {
    objects: HashMap<String, HeapObject>,
    total_size: usize,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HeapObject {
    pub id: String,
    pub object_type: String,
    pub size: usize,
    pub references: Vec<String>,
}
impl HeapSnapshot {
    pub fn new() -> Self {
        Self {
            objects: HashMap::new(),
            total_size: 0,
        }
    }
    pub fn add_object(&mut self, id: &str, object_type: &str, size: usize, references: Vec<&str>) {
        let obj: _ = HeapObject {
            id: id.to_string(),
            object_type: object_type.to_string(),
            size,
            references: references.iter().map(|r| r.to_string()).collect(),
        };
        self.objects.insert(id.to_string(), obj);
        self.total_size += size;
    }
    pub fn object_count(&self) -> usize {
        self.objects.len()
    }
    pub fn total_size(&self) -> usize {
        self.total_size
    }
    pub fn get_statistics(&self) -> HeapStats {
        HeapStats {
            total_objects: self.objects.len(),
            total_size: self.total_size,
        }
    }
}
/// Heap statistics
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HeapStats {
    pub total_objects: usize,
    pub total_size: usize,
}
/// Object tracer
pub struct ObjectTracer {
    traces: HashMap<String, ObjectTrace>,
}
#[derive(Debug, Clone)]
struct ObjectTrace {
    object_id: String,
    object_type: String,
    created_at: String,
    access_history: Vec<AccessRecord>,
}
#[derive(Debug, Clone)]
struct AccessRecord {
    property: String,
    access_type: String, // "read" or "write"
    timestamp: String,
}
impl ObjectTracer {
    pub fn new() -> Self {
        Self {
            traces: HashMap::new(),
        }
    }
    pub async fn track_creation(&mut self, object_id: &str, object_type: &str, location: &str) -> Result<String> {
        let trace: _ = ObjectTrace {
            object_id: object_id.to_string(),
            object_type: object_type.to_string(),
            created_at: location.to_string(),
            access_history: Vec::new(),
        };
        self.traces.insert(object_id.to_string(), trace);
        Ok(object_id.to_string())
    }
    pub async fn track_access(&mut self, object_id: &str, property: &str, access_type: &str) -> Result<()> {
        if let Some(trace) = self.traces.get_mut(object_id) {
            trace.access_history.push(AccessRecord {
                property: property.to_string(),
                access_type: access_type.to_string(),
                timestamp: "now".to_string(),
            });
        }
        Ok(())
    }
    pub async fn track_deletion(&mut self, object_id: &str) -> Result<()> {
        self.traces.remove(object_id);
        Ok(())
    }
    pub async fn get_access_history(&self, object_id: &str) -> Result<Vec<AccessRecord> {
        if let Some(trace) = self.traces.get(object_id) {
            Ok(trace.access_history.clone())
        } else {
            Ok(Vec::new())
        }
    }
}
/// Memory analyzer
pub struct MemoryAnalyzer {
    snapshots: Vec<HeapSnapshot>,
}
impl MemoryAnalyzer {
    pub fn new() -> Self {
        Self {
            snapshots: Vec::new(),
        }
    }
    pub async fn add_snapshot(&mut self, snapshot: HeapSnapshot) {
        self.snapshots.push(snapshot);
    }
    pub async fn compare_snapshots(&self, index1: usize, index2: usize) -> Result<SnapshotDiff> {
        if index1 >= self.snapshots.len() || index2 >= self.snapshots.len() {
            return Ok(SnapshotDiff {
                created: Vec::new(),
                deleted: Vec::new(),
                modified: Vec::new(),
            });
        }
        let snap1: _ = &self.snapshots[index1];
        let snap2: _ = &self.snapshots[index2];
        let mut created = Vec::new();
        let mut deleted = Vec::new();
        let mut modified = Vec::new();
        // Find created and modified objects
        for (id, obj2) in &snap2.objects {
            if !snap1.objects.contains_key(id) {
                created.push(id.clone());
            }
        }
        // Find deleted objects
        for (id, _) in &snap1.objects {
            if !snap2.objects.contains_key(id) {
                deleted.push(id.clone());
            }
        }
        Ok(SnapshotDiff {
            created,
            deleted,
            modified,
        })
    }
    pub async fn detect_memory_leaks(&self) -> Result<Vec<MemoryLeak> {
        let mut leaks = Vec::new();
        // Simple leak detection: objects that persist across multiple snapshots
        if self.snapshots.len() >= 2 {
            let first: _ = &self.snapshots[0];
            let last: _ = &self.snapshots[0];
            for (id, obj) in &last.objects {
                if first.objects.contains_key(id) {
                    leaks.push(MemoryLeak {
                        object_id: id.clone(),
                        object_type: obj.object_type.clone(),
                        persist_count: 2,
                    });
                }
            }
        }
        Ok(leaks)
    }
}
/// Snapshot comparison result
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SnapshotDiff {
    pub created: Vec<String>,
    pub deleted: Vec<String>,
    pub modified: Vec<String>,
}
/// Memory leak information
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryLeak {
    pub object_id: String,
    pub object_type: String,
    pub persist_count: usize,
}