use anyhow::{Context, Result};
use crate::{RuntimeLite, debugger};
use crate::debugger::cli::DebugConsole;
use std::collections::{BTreeMap, HashMap};
use std::sync::{Arc, Mutex};
use std::path::PathBuf;
use std::io::Read;
pub struct DebugSession {
runtime: RuntimeLite,
debugger: Arc<Mutex<DebuggerEngine>>,
event_listener: Arc<SimpleEventListener>,
script_path: Option<PathBuf>,
debug_port: u16,
web_ui: bool,
}
impl DebugSession {
pub fn new(
runtime: RuntimeLite,
cmd: crate::cli::commands::SubCommand,
) -> Result<Self> {
let (script_path, debug_port, web_ui) = match cmd {
crate::cli::commands::SubCommand::Debug { file, port, web, .. } => {
(file, port, web)
},
_ => return Err(anyhow::anyhow!("Invalid debug command")),
};
let config: _ = DebugConfig::default();
let debugger: _ = Arc::new(Mutex::new(DebuggerEngine::new(config)));
let event_listener: _ = Arc::new(Mutex::new(SimpleEventListener::new()));
Ok(Self {
runtime,
debugger,
event_listener,
script_path,
debug_port,
web_ui,
})
}
pub fn initialize(&self) -> Result<()> {
println!("🔧 Initializing debug session...");
println!(" Debug port: {}", self.debug_port);
if let Some(ref script) = self.script_path {
println!(" Script: {}", script.display());
}
Ok(())
}
pub async fn start(&mut self) -> Result<()> {
self.initialize()?;
println!("🚀 Starting debug session on port {}", self.debug_port);
if self.web_ui {
println!("🌐 Web UI mode enabled");
println!(" Open http://localhost:{} in your browser", self.debug_port);
println!(" ⚠️ Web UI not yet implemented");
} else {
println!("💻 CLI debug mode");
}
if let Some(ref script_path) = self.script_path {
println!("\n📄 Loading script: {}", script_path.display());
let _code: _ = std::fs::read_to_string(script_path)
.context("Failed to read script file")?;
self.start_interactive_cli().await?;
} else {
println!("\n📋 Debug session ready!");
println!(" Status: Waiting for connection");
println!(" Debug port: {}", self.debug_port);
println!(" ⚠️ Chrome DevTools protocol not yet implemented");
}
Ok(())
}
async fn start_interactive_cli(&mut self) -> Result<()> {
println!("\n🐛 Starting interactive debug console...");
println!(" Type 'help' for available commands\n");
let mut console = DebugConsole::new(
Arc::clone(&self.debugger),
Arc::new(Mutex::new(self.runtime.clone())),
);
console.run().await?;
Ok(())
}
pub fn port(&self) -> u16 {
self.debug_port
}
pub fn web_ui_enabled(&self) -> bool {
self.web_ui
}
pub fn script_path(&self) -> Option<&PathBuf> {
self.script_path.as_ref()
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_debug_session_creation() {
let runtime: _ = RuntimeLite::new(false).unwrap();
let cmd: _ = SubCommand::Debug {
file: Some(PathBuf::from("test.js")),
break_at: None,
port: 9229,
web: false,
pid: None,
};
let session: _ = DebugSession::new(runtime, cmd).unwrap();
assert_eq!(session.port(), 9229);
assert!(!session.web_ui_enabled());
assert_eq!(session.script_path().unwrap().to_str(), Some("test.js"));
}
#[test]
fn test_debug_session_attach() {
let runtime: _ = RuntimeLite::new(false).unwrap();
let cmd: _ = SubCommand::Debug {
file: None,
break_at: None,
port: 9229,
web: false,
pid: Some(1234),
};
let session: _ = DebugSession::new(runtime, cmd).unwrap();
assert_eq!(session.port(), 9229);
assert!(session.script_path().is_none());
}
#[test]
fn test_debug_session_inspect() {
let runtime: _ = RuntimeLite::new(false).unwrap();
let cmd: _ = SubCommand::Debug {
file: None,
break_at: None,
port: 8080,
web: true,
pid: None,
};
let session: _ = DebugSession::new(runtime, cmd).unwrap();
assert_eq!(session.port(), 8080);
assert!(session.web_ui_enabled());
assert!(session.script_path().is_none());
}
}