use std::collections::HashMap;
use rusty_v8 as v8;
use crate::debugger::{DebugResult, config::DebugConfig};
use std::collections::{BTreeMap};
use std::hash::Hash;
use std::task::Context;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ScopeType {
Global, Local, Closure, Catch, With, Eval, Module, Script, }
#[derive(Debug, Clone)]
pub struct VariableInfo {
pub name: String,
pub value: String,
pub type_name: String,
pub preview: String,
pub properties: Option<Vec<VariableInfo>>,
pub length: Option<usize>,
pub scope_type: ScopeType,
}
#[derive(Debug, Clone)]
pub struct VariableScope {
pub scope_type: ScopeType,
pub object: v8::Global<v8::Object>,
pub scope_chain_position: usize,
}
pub struct VariableInspector {
config: DebugConfig,
}
impl VariableInspector {
pub fn new(config: DebugConfig) -> Self {
Self { config }
}
pub fn get_scope_variables(
&self,
scope: &VariableScope,
) -> DebugResult<Vec<VariableInfo>> {
let variables: _ = Vec::new();
DebugResult::ok(variables)
}
pub fn get_all_scope_variables(
&self,
scopes: &[VariableScope],
) -> DebugResult<HashMap<ScopeType, Vec<VariableInfo>>> {
let mut all_vars = HashMap::new();
for scope in scopes {
match self.get_scope_variables(scope) {
DebugResult { success: true, data: Some(vars), .. } => {
all_vars.insert(scope.scope_type.clone(), vars);
}
DebugResult { success: false, error: Some(e), .. } => {
return DebugResult::err(e);
}
_ => return DebugResult::err("Unknown error".to_string()),
}
}
DebugResult::ok(all_vars)
}
pub fn evaluate_expression(
&self,
context: &v8::Global<v8::Context>,
expression: &str,
) -> DebugResult<VariableInfo> {
let info: _ = VariableInfo {
name: expression.to_string(),
value: "undefined".to_string(),
type_name: "unknown".to_string(),
preview: "undefined".to_string(),
properties: None,
length: None,
scope_type: ScopeType::Local,
};
DebugResult::ok(info)
}
pub fn get_global_variables(
&self,
_context: &v8::Global<v8::Context>,
) -> DebugResult<Vec<VariableInfo>> {
DebugResult::ok(Vec::new())
}
fn object_to_variables(
&self,
_scope: &mut v8::PinScope,
_object: v8::Global<v8::Object>,
_name: String,
) -> DebugResult<Vec<VariableInfo>> {
DebugResult::ok(Vec::new())
}
pub fn get_object_properties(
&self,
_context: &v8::Global<v8::Context>,
_object: &v8::Global<v8::Object>,
max_depth: usize,
) -> DebugResult<Vec<VariableInfo>> {
if max_depth == 0 {
return DebugResult::ok(Vec::new());
}
DebugResult::ok(Vec::new())
}
pub fn find_variable(
&self,
scopes: &[VariableScope],
var_name: &str,
) -> Option<(ScopeType, VariableInfo)> {
for scope in scopes {
let variables_result: _ = self.get_scope_variables(scope);
if !variables_result.success {
continue;
}
let variables: _ = variables_result.data.unwrap_or_default();
if let Some(var) = variables.iter().find(|v| v.name == var_name) {
return Some((scope.scope_type.clone(), var.clone()));
}
}
None
}
pub fn get_variable_from_scope(
&self,
scope: &VariableScope,
var_name: &str,
) -> DebugResult<Option<VariableInfo>> {
let variables_result: _ = self.get_scope_variables(scope);
if variables_result.success {
if let Some(variables) = variables_result.data {
let found: _ = variables.into_iter().find(|v| v.name == var_name);
DebugResult::ok(found)
} else {
DebugResult::ok(None)
}
} else {
DebugResult::err(variables_result.error.unwrap_or_else(|| "Unknown error".to_string()))
}
}
pub fn format_variable(&self, var: &VariableInfo, max_length: usize) -> String {
let mut result = format!("{}: {}", var.name, var.value);
if result.len() > max_length {
result.truncate(max_length);
result.push_str("...");
}
result
}
pub fn format_variables(
&self,
variables: &[VariableInfo],
max_length: usize,
) -> Vec<String> {
variables
.iter()
.map(|v| self.format_variable(v, max_length))
.collect()
}
}
pub struct ScopeUtils;
impl ScopeUtils {
pub fn create_global_scope(
_context: &v8::Global<v8::Context>,
) -> DebugResult<VariableScope> {
DebugResult::ok(VariableScope {
scope_type: ScopeType::Global,
object: unsafe { std::mem::zeroed() },
scope_chain_position: 0,
})
}
pub fn parse_scope_type(s: &str) -> Option<ScopeType> {
match s.to_lowercase().as_str() {
"global" => Some(ScopeType::Global),
"local" => Some(ScopeType::Local),
"closure" => Some(ScopeType::Closure),
"catch" => Some(ScopeType::Catch),
"with" => Some(ScopeType::With),
"eval" => Some(ScopeType::Eval),
"module" => Some(ScopeType::Module),
"script" => Some(ScopeType::Script),
_ => None,
}
}
pub fn scope_type_name(scope_type: &ScopeType) -> &'static str {
match scope_type {
ScopeType::Global => "Global",
ScopeType::Local => "Local",
ScopeType::Closure => "Closure",
ScopeType::Catch => "Catch",
ScopeType::With => "With",
ScopeType::Eval => "Eval",
ScopeType::Module => "Module",
ScopeType::Script => "Script",
}
}
}