use quickjs_rusty::Context; use quickjs_rusty::ContextError; use quickjs_rusty::ExecutionError; use quickjs_rusty::OwnedJsValue as JsValue; #[derive(thiserror::Error, Debug)] pub enum ScriptError { #[error("error context: {0:?}")] ContextError(#[from] ContextError), #[error("error running: {0:?}")] ExecutionError(#[from] ExecutionError), } pub type ScriptResult = Result; // TODO: remove this function since it is suitable only for early development #[allow(clippy::print_stdout)] fn print(s: String) { println!("{s}"); } pub struct Runner { context: Context, } impl Runner { pub fn init() -> ScriptResult { let context = Context::new(None)?; context.add_callback("print", |a: String| { print(a); None:: })?; Ok(Runner { context }) } pub fn run_script(&self, content: &str) -> ScriptResult { let ctx = &self.context; let val = ctx.eval(content, false)?; Ok(val) } } #[cfg(test)] // allowing this since it is better for debugging tests) #[allow(clippy::unwrap_used)] #[allow(clippy::print_stdout)] mod tests { use super::*; #[test] fn test_run_script_valid() { let runner = Runner::init().unwrap(); let val = runner.run_script(r#"print"#).unwrap(); println!("Val: {:?}", val); let val = runner.run_script(r#"print('Hello from JS!');"#).unwrap(); println!("Val: {:?}", val); assert!(val.is_null()); let val = runner.run_script(r#"const a = 1+2; a"#).unwrap(); println!("Val: {:?}", val); assert_eq!(val.to_int(), Ok(3)); let val = runner.run_script(r#"a + 39"#).unwrap(); println!("Val: {:?}", val); assert_eq!(val.to_int(), Ok(42)); } #[test] fn test_run_script_file_main() { let runner = Runner::init().unwrap(); let val = runner.run_script(include_str!("../mainbot.js")).unwrap(); println!("config: {:?}", val); let val = runner.run_script("start_buttons()").unwrap(); println!("Val: {:?}", val.to_string()); } #[test] fn test_run_script_invalid() { let runner = Runner::init().unwrap(); let result = runner.run_script(r#"invalid_script();"#); assert!(result.is_err()); let errstr = if let Err(ScriptError::ExecutionError(ExecutionError::Exception(errstr))) = result { errstr.to_string().unwrap() } else { panic!("test returned wrong error!, {result:?}"); }; if errstr != "ReferenceError: invalid_script is not defined" { panic!("test returned an error, but the wrong one, {errstr}") } } }