web/
window.rs

1use js::*;
2use std::collections::HashMap;
3use std::sync::Mutex;
4
5use crate::{get_property_f64, get_property_i64};
6
7pub type TimerHandle = f64;
8
9static ANIMATION_FRAME_EVENT_HANDLERS: Mutex<
10    Option<HashMap<i64, Box<dyn FnMut() + Send + 'static>>>,
11> = Mutex::new(None);
12
13#[no_mangle]
14pub extern "C" fn web_one_time_empty_handler(id: i64) {
15    let mut c = None;
16    {
17        let mut handlers = ANIMATION_FRAME_EVENT_HANDLERS.lock().unwrap();
18        if let Some(h) = handlers.as_mut() {
19            // remove
20            if let Some(handler) = h.remove(&id) {
21                c = Some(handler);
22            }
23        }
24    }
25    if let Some(mut c) = c {
26        c();
27    }
28}
29
30pub fn request_animation_frame(handler: impl FnMut() + Send + Sync + 'static) {
31    let function_handle = js!(r#"
32        function(){
33            const handler = () => {
34                this.module.instance.exports.web_one_time_empty_handler(id);
35                this.releaseObject(id);
36            };
37            const id = this.storeObject(handler);
38            requestAnimationFrame(handler);
39            return id;
40        }"#)
41    .invoke_and_return_bigint(&[]);
42    let mut h = ANIMATION_FRAME_EVENT_HANDLERS.lock().unwrap();
43    if h.is_none() {
44        *h = Some(HashMap::new());
45    }
46    h.as_mut()
47        .unwrap()
48        .insert(function_handle, Box::new(handler));
49}
50
51pub fn set_timeout(
52    handler: impl FnMut() + 'static + Send + Sync,
53    ms: impl Into<f64>,
54) -> TimerHandle {
55    let obj_handle = js!(r#"
56        function(ms){
57            const handler = () => {
58                this.module.instance.exports.web_one_time_empty_handler(id);
59                this.releaseObject(id);
60            };
61            const id = this.storeObject(handler);
62            const handle = window.setTimeout(handler, ms);
63            return {id,handle};
64        }"#)
65    .invoke_and_return_object(&[ms.into().into()]);
66    let function_handle = get_property_i64(&obj_handle, "id");
67    let timer_handle = get_property_f64(&obj_handle, "handle");
68    let mut h = ANIMATION_FRAME_EVENT_HANDLERS.lock().unwrap();
69    if h.is_none() {
70        *h = Some(HashMap::new());
71    }
72    h.as_mut()
73        .unwrap()
74        .insert(function_handle, Box::new(handler));
75    timer_handle
76}
77
78pub fn clear_timeout(interval_id: impl Into<f64>) {
79    let clear_interval = js!(r#"
80        function(interval_id){
81            window.clearTimeout(interval_id);
82        }"#);
83    clear_interval.invoke(&[interval_id.into().into()]);
84}