quickjs_runtime/quickjs_utils/
interrupthandler.rs1use crate::quickjsruntimeadapter::QuickJsRuntimeAdapter;
2use libquickjs_sys as q;
3use std::ffi::c_void;
4use std::os::raw::c_int;
5
6pub unsafe fn set_interrupt_handler(runtime: *mut q::JSRuntime, handler: q::JSInterruptHandler) {
12 q::JS_SetInterruptHandler(runtime, handler, std::ptr::null_mut());
13}
14
15pub(crate) fn init(q_js_rt: &QuickJsRuntimeAdapter) {
16 unsafe { set_interrupt_handler(q_js_rt.runtime, Some(interrupt_handler)) };
17}
18
19unsafe extern "C" fn interrupt_handler(_rt: *mut q::JSRuntime, _opaque: *mut c_void) -> c_int {
20 QuickJsRuntimeAdapter::do_with(|q_js_rt| {
21 let handler = q_js_rt.interrupt_handler.as_ref().unwrap();
22 i32::from(handler(q_js_rt))
23 })
24}
25
26#[cfg(test)]
27pub mod tests {
28 use crate::builder::QuickJsRuntimeBuilder;
29 use crate::jsutils::Script;
30 use crate::quickjs_utils::get_script_or_module_name_q;
31
32 use std::cell::RefCell;
33 use std::panic;
34 use std::sync::{Arc, Mutex};
35
36 #[test]
37 fn test_interrupt_handler() {
38 log::info!("interrupt_handler test");
39
40 let called = Arc::new(Mutex::new(RefCell::new(false)));
41 let called2 = called.clone();
42
43 let rt = QuickJsRuntimeBuilder::new()
57 .set_interrupt_handler(move |qjs_rt| {
58 log::debug!("interrupt_handler called / 1");
59 let script_name = get_script_or_module_name_q(qjs_rt.get_main_realm());
60 match script_name {
61 Ok(script_name) => {
62 log::debug!("interrupt_handler called: {}", script_name);
63 }
64 Err(_) => {
65 log::debug!("interrupt_handler called");
66 }
67 }
68 let lck = called2.lock().unwrap();
69 *lck.borrow_mut() = true;
70 false
71 })
72 .build();
73
74 match rt.eval_sync(
75 None,
76 Script::new(
77 "test_interrupt.es",
78 "for (let x = 0; x < 10000; x++) {console.log('x' + x);}",
79 ),
80 ) {
81 Ok(_) => {}
82 Err(err) => {
83 panic!("err: {}", err);
84 }
85 }
86
87 rt.create_context("newctx").expect("ctx crea failed");
88 rt.exe_rt_task_in_event_loop(|q_js_rt| {
89 let ctx = q_js_rt.get_context("newctx");
90 match ctx.eval(Script::new(
91 "test_interrupt.es",
92 "for (let x = 0; x < 10000; x++) {console.log('x' + x);}",
93 )) {
94 Ok(_) => {}
95 Err(err) => {
96 panic!("err: {}", err);
97 }
98 }
99 });
100
101 let lck = called.lock().unwrap();
102 assert!(*lck.borrow());
103 }
104}