diff --git a/tests/closures.rs b/tests/closures.rs index 9be2b82c..32d4b795 100644 --- a/tests/closures.rs +++ b/tests/closures.rs @@ -375,3 +375,62 @@ fn test_closures_external() -> Result<(), Box> { Ok(()) } + +#[test] +#[cfg(not(feature = "no_closure"))] +fn test_closures_callback() -> Result<(), Box> { + use std::cell::RefCell; + use std::rc::Rc; + + type SingleNode = Rc; + + trait Node { + fn run(&self, x: INT) -> INT; + } + + struct PhaserNode { + func: Box INT>, + } + + impl Node for PhaserNode { + fn run(&self, x: INT) -> INT { + (self.func)(x) + } + } + + fn phaser(callback: impl Fn(INT) -> INT + 'static) -> impl Node { + PhaserNode { + func: Box::new(callback), + } + } + + let mut engine = Engine::new(); + + let ast = Rc::new(engine.compile( + " + const FACTOR = 2; + phaser(|x| x * FACTOR) + ", + )?); + + let shared_engine = Rc::new(RefCell::new(Engine::new_raw())); + let engine2 = shared_engine.clone(); + let ast2 = ast.clone(); + + engine.register_fn("phaser", move |fp: FnPtr| { + let engine = engine2.clone(); + let ast = ast2.clone(); + + let callback = Box::new(move |x: INT| fp.call(&engine.borrow(), &ast, (x,)).unwrap()); + + Rc::new(phaser(callback)) as SingleNode + }); + + *shared_engine.borrow_mut() = engine; + + let cb = shared_engine.borrow().eval_ast::(&ast)?; + + assert_eq!(cb.run(21), 42); + + Ok(()) +}