1use crate::BaseDocument;
8use bliss_traits::events::DomEvent;
9
10#[derive(Debug, Clone)]
12pub enum ScriptValue {
13 Null,
14 Bool(bool),
15 Number(f64),
16 String(String),
17 Object(Vec<(String, ScriptValue)>),
18 Promise(u64), }
20
21#[derive(Debug, Clone)]
23pub enum ScriptError {
24 ParseError(String),
25 RuntimeError(String),
26 CapabilityDenied { operation: String, reason: String },
27 Timeout,
28 MemoryLimitExceeded,
29 UnsupportedLanguage(String),
30}
31
32pub enum EventHandled {
34 Handled, Propagate, }
37
38#[derive(Debug, Clone, Copy, PartialEq)]
40pub enum ScriptLanguage {
41 JavaScript,
42 TypeScript,
43 Lua,
44 Python,
45 Casm, }
47
48impl std::fmt::Display for ScriptLanguage {
49 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50 match self {
51 ScriptLanguage::JavaScript => write!(f, "javascript"),
52 ScriptLanguage::TypeScript => write!(f, "typescript"),
53 ScriptLanguage::Lua => write!(f, "lua"),
54 ScriptLanguage::Python => write!(f, "python"),
55 ScriptLanguage::Casm => write!(f, "casm"),
56 }
57 }
58}
59
60#[derive(Debug, Clone)]
62pub struct ExecutionContext {
63 pub source_url: Option<String>,
64 pub line_number: u32,
65 pub is_module: bool,
66}
67
68impl Default for ExecutionContext {
69 fn default() -> Self {
70 Self {
71 source_url: None,
72 line_number: 1,
73 is_module: false,
74 }
75 }
76}
77
78pub type ScriptErrorCallback = Box<dyn Fn(&ScriptError) + Send + Sync>;
80
81pub trait ScriptEngine: Send {
83 fn init(&mut self, document: &mut BaseDocument);
85
86 fn execute(
88 &mut self,
89 code: &str,
90 language: ScriptLanguage,
91 context: &ExecutionContext,
92 ) -> Result<ScriptValue, ScriptError>;
93
94 fn handle_event(&mut self, event: &DomEvent) -> EventHandled;
97
98 fn tick(&mut self) -> Result<bool, ScriptError>;
101
102 fn set_error_handler(&mut self, callback: Option<ScriptErrorCallback>);
104}
105
106pub struct NoopScriptEngine;
108
109impl ScriptEngine for NoopScriptEngine {
110 fn init(&mut self, _document: &mut BaseDocument) {}
111
112 fn execute(
113 &mut self,
114 _code: &str,
115 language: ScriptLanguage,
116 _context: &ExecutionContext,
117 ) -> Result<ScriptValue, ScriptError> {
118 Err(ScriptError::UnsupportedLanguage(language.to_string()))
119 }
120
121 fn handle_event(&mut self, _event: &DomEvent) -> EventHandled {
122 EventHandled::Propagate
123 }
124
125 fn tick(&mut self) -> Result<bool, ScriptError> {
126 Ok(false)
127 }
128
129 fn set_error_handler(&mut self, _callback: Option<ScriptErrorCallback>) {}
130}
131
132pub type BoxedScriptEngine = Box<dyn ScriptEngine>;