amberjs 1.16.1

JavaScript/TypeScript runtime built with Rust and V8
Documentation
// Amber 高级调试器
// Stage 80 Phase 3 - 开发者工具链
// 支持多线程调试、实时变量监控、断点管理

use std::collections::{BTreeMap, HashMap};
use std::sync::{Arc, Mutex, RwLock};
use std::time::{Duration, Instant};
use std::hash::Hash;

/// 线程 ID
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ThreadId(pub u64);
/// 断点 ID
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BreakpointId(pub Uuid);
/// 源码位置
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct SourceLocation {
    pub file_path: String,
    pub line: u32,
    pub column: u32,
}
/// 断点信息
#[derive(Debug, Clone)]
pub struct Breakpoint {
    pub id: BreakpointId,
    pub location: SourceLocation,
    pub enabled: bool,
    pub hit_count: u64,
    pub created_at: Instant,
}
/// 断点映射
pub type BreakpointMap = HashMap<BreakpointId, Breakpoint>;
/// 线程检查器
#[derive(Debug, Clone)]
pub struct ThreadInspector {
    pub thread_id: ThreadId,
    pub status: ThreadStatus,
    pub current_location: Option<SourceLocation>,
    pub variables: HashMap<String, VariableValue>,
}
/// 线程状态
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ThreadStatus {
    Running,
    Paused,
    Stopped,
    Terminated,
}
/// 变量值
#[derive(Debug, Clone, PartialEq)]
pub enum VariableValue {
    Undefined,
    Null,
    Boolean(bool),
    Number(f64),
    String(String),
    Object(HashMap<String, VariableValue>),
    Array(Vec<VariableValue>),
}
/// 线程检查器集合
pub type ThreadInspectors = HashMap<ThreadId, ThreadInspector>;
/// 高级调试器
#[derive(Debug)]
pub struct Debugger {
    /// 断点映射
    pub breakpoints: Arc<RwLock<BreakpointMap>>,
    /// 线程检查器
    pub inspectors: Arc<RwLock<ThreadInspectors>>,
}
impl Debugger {
    /// 创建新的调试器
    pub fn new() -> Self {
        Self {
            breakpoints: Arc::new(Mutex::new(HashMap::new()))
            inspectors: Arc::new(Mutex::new(HashMap::new()))
        }
    }
    /// 设置断点
    pub async fn set_breakpoint(
        &self,
        location: &SourceLocation,
    ) -> Result<BreakpointId, Box<dyn std::error::Error + Send + Sync>> {
        let breakpoint_id: _ = BreakpointId(Uuid::new_v4());
        let breakpoint: _ = Breakpoint {
            id: breakpoint_id,
            location: location.clone(),
            enabled: true,
            hit_count: 0,
            created_at: Instant::now(),
        };
        let mut breakpoints = self.breakpoints.write().map_err(|_| "Failed to acquire write lock")?;
        breakpoints.insert(breakpoint_id, breakpoint);
        Ok(breakpoint_id)
    }
    /// 移除断点
    pub async fn remove_breakpoint(
        &self,
        breakpoint_id: &BreakpointId,
    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        let mut breakpoints = self.breakpoints.write().map_err(|_| "Failed to acquire write lock")?;
        breakpoints.remove(breakpoint_id);
        Ok(())
    }
    /// 启用/禁用断点
    pub async fn toggle_breakpoint(
        &self,
        breakpoint_id: &BreakpointId,
    ) -> Result<bool, Box<dyn std::error::Error + Send + Sync>> {
        let mut breakpoints = self.breakpoints.write().map_err(|_| "Failed to acquire write lock")?;
        if let Some(breakpoint) = breakpoints.get_mut(breakpoint_id) {
            breakpoint.enabled = !breakpoint.enabled;
            Ok(breakpoint.enabled)
        } else {
            Err("Breakpoint not found".into())
        }
    }
    /// 获取所有断点
    pub async fn get_breakpoints(
        &self,
    ) -> Result<Vec<Breakpoint>, Box<dyn std::error::Error + Send + Sync>> {
        let breakpoints: _ = self.breakpoints.read().map_err(|_| "Failed to acquire read lock")?;
        Ok(breakpoints.values().cloned().collect())
    }
    /// 检查线程状态
    pub async fn inspect_thread(
        &self,
        thread_id: ThreadId,
    ) -> Result<ThreadState, Box<dyn std::error::Error + Send + Sync>> {
        let inspectors: _ = self.inspectors.read().map_err(|_| "Failed to acquire read lock")?;
        if let Some(inspector) = inspectors.get(&thread_id) {
            Ok(ThreadState {
                thread_id,
                status: inspector.status.clone(),
                current_location: inspector.current_location.clone(),
                variables: inspector.variables.clone(),
            })
        } else {
            Err("Thread not found".into())
        }
    }
    /// 注册线程
    pub async fn register_thread(
        &self,
        thread_id: ThreadId,
    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        let mut inspectors = self.inspectors.write().map_err(|_| "Failed to acquire write lock")?;
        if !inspectors.contains_key(&thread_id) {
            let inspector: _ = ThreadInspector {
                thread_id,
                status: ThreadStatus::Running,
                current_location: None,
                variables: HashMap::new(),
            };
            inspectors.insert(thread_id, inspector);
        }
        Ok(())
    }
    /// 暂停线程
    pub async fn pause_thread(
        &self,
        thread_id: ThreadId,
    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        let mut inspectors = self.inspectors.write().map_err(|_| "Failed to acquire write lock")?;
        if let Some(inspector) = inspectors.get_mut(&thread_id) {
            inspector.status = ThreadStatus::Paused;
            Ok(())
        } else {
            Err("Thread not found".into())
        }
    }
    /// 恢复线程
    pub async fn resume_thread(
        &self,
        thread_id: ThreadId,
    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        let mut inspectors = self.inspectors.write().map_err(|_| "Failed to acquire write lock")?;
        if let Some(inspector) = inspectors.get_mut(&thread_id) {
            inspector.status = ThreadStatus::Running;
            Ok(())
        } else {
            Err("Thread not found".into())
        }
    }
    /// 更新线程状态
    pub async fn update_thread_state(
        &self,
        thread_id: ThreadId,
        location: Option<SourceLocation>,
        variables: HashMap<String, VariableValue>,
    ) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
        let mut inspectors = self.inspectors.write().map_err(|_| "Failed to acquire write lock")?;
        if let Some(inspector) = inspectors.get_mut(&thread_id) {
            inspector.current_location = location;
            inspector.variables = variables;
            Ok(())
        } else {
            Err("Thread not found".into())
        }
    }
    /// 获取所有线程状态
    pub async fn get_all_threads(
        &self,
    ) -> Result<Vec<ThreadState>, Box<dyn std::error::Error + Send + Sync>> {
        let inspectors: _ = self.inspectors.read().map_err(|_| "Failed to acquire read lock")?;
        Ok(inspectors
            .values()
            .map(|inspector| ThreadState {
                thread_id: inspector.thread_id,
                status: inspector.status.clone(),
                current_location: inspector.current_location.clone(),
                variables: inspector.variables.clone(),
            })
            .collect())
    }
}
/// 线程状态信息
#[derive(Debug, Clone)]
pub struct ThreadState {
    pub thread_id: ThreadId,
    pub status: ThreadStatus,
    pub current_location: Option<SourceLocation>,
    pub variables: HashMap<String, VariableValue>,
}
impl Default for Debugger {
    fn default() -> Self {
        Self::new()
    }
}
#[cfg(test)]
mod tests {
    #[tokio::test]
    async fn test_breakpoint_management() {
        let debugger: _ = Debugger::new();
        let location: _ = SourceLocation {
            file_path: "test.js".to_string(),
            line: 10,
            column: 5,
        };
        // 设置断点
        let breakpoint_id: _ = debugger.set_breakpoint(&location).await.unwrap();
        // 获取断点列表
        let breakpoints: _ = debugger.get_breakpoints().await.unwrap();
        assert_eq!(breakpoints.len(), 1);
        assert_eq!(breakpoints[0].id, breakpoint_id);
        assert_eq!(breakpoints[0].location, location);
        assert!(breakpoints[0].enabled);
        // 切换断点状态
        let enabled: _ = debugger.toggle_breakpoint(&breakpoint_id).await.unwrap();
        assert!(!enabled);
        // 移除断点
        debugger.remove_breakpoint(&breakpoint_id).await.unwrap();
        let breakpoints: _ = debugger.get_breakpoints().await.unwrap();
        assert_eq!(breakpoints.len(), 0);
    }
    #[tokio::test]
    async fn test_multithread_debugging() {
        let debugger: _ = Debugger::new();
        // 注册线程
        let thread_id: _ = ThreadId(1);
        debugger.register_thread(thread_id).await.unwrap();
        // 检查线程状态
        let thread_state: _ = debugger.inspect_thread(thread_id).await.unwrap();
        assert_eq!(thread_state.thread_id, thread_id);
        assert_eq!(thread_state.status, ThreadStatus::Running);
        // 暂停线程
        debugger.pause_thread(thread_id).await.unwrap();
        let thread_state: _ = debugger.inspect_thread(thread_id).await.unwrap();
        assert_eq!(thread_state.status, ThreadStatus::Paused);
        // 恢复线程
        debugger.resume_thread(thread_id).await.unwrap();
        let thread_state: _ = debugger.inspect_thread(thread_id).await.unwrap();
        assert_eq!(thread_state.status, ThreadStatus::Running);
        // 更新线程状态
        let location: _ = SourceLocation {
            file_path: "test.js".to_string(),
            line: 20,
            column: 10,
        };
        let mut variables = HashMap::new();
        variables.insert(
            "x".to_string(),
            VariableValue::Number(42.0),
        );
        debugger
            .update_thread_state(thread_id, Some(location.clone()), variables)
            .await
            .unwrap();
        let thread_state: _ = debugger.inspect_thread(thread_id).await.unwrap();
        assert_eq!(thread_state.current_location, Some(location));
        assert_eq!(
            thread_state.variables.get("x"),
            Some(&VariableValue::Number(42.0));
    }
    #[tokio::test]
    async fn test_get_all_threads() {
        let debugger: _ = Debugger::new();
        // 注册多个线程
        debugger.register_thread(ThreadId(1)).await.unwrap();
        debugger.register_thread(ThreadId(2)).await.unwrap();
        debugger.register_thread(ThreadId(3)).await.unwrap();
        // 获取所有线程
        let threads: _ = debugger.get_all_threads().await.unwrap();
        assert_eq!(threads.len(), 3);
        let thread_ids: Vec<ThreadId> = threads.iter().map(|t| t.thread_id).collect();
        assert!(thread_ids.contains(&ThreadId(1));
        assert!(thread_ids.contains(&ThreadId(2));
        assert!(thread_ids.contains(&ThreadId(3));
    }
}