wasm_bridge_js/
helpers.rs

1use std::fmt::Debug;
2
3use js_sys::Function;
4use wasm_bindgen::JsValue;
5
6use crate::Error;
7
8#[allow(unused)]
9pub(crate) fn warn(msg: &str) {
10    let console_warn: Function = js_sys::eval("console.warn").unwrap().into();
11
12    console_warn
13        .call1(&JsValue::UNDEFINED, &msg.into())
14        .unwrap();
15}
16
17#[allow(unused)]
18pub(crate) fn log_js_value(name: &str, value: &JsValue) {
19    let console_log: Function = js_sys::eval("console.log").unwrap().into();
20
21    console_log
22        .call3(&JsValue::UNDEFINED, &name.into(), &value.js_typeof(), value)
23        .unwrap();
24}
25
26#[allow(unused)]
27pub(crate) fn log_js_value_error(name: &str, value: &JsValue) {
28    let console_error: Function = js_sys::eval("console.error").unwrap().into();
29
30    console_error
31        .call2(&JsValue::UNDEFINED, &name.into(), value)
32        .unwrap();
33}
34
35#[allow(unused)]
36pub fn console_log(value: impl Debug) {
37    let console_log: Function = js_sys::eval("console.log").unwrap().into();
38
39    console_log
40        .call1(&JsValue::UNDEFINED, &format!("{value:?}").into())
41        .unwrap();
42}
43
44pub fn map_js_error<T: Debug + AsRef<JsValue>>(hint: &'static str) -> impl Fn(T) -> Error {
45    move |value: T| {
46        if cfg!(feature = "error-logging") {
47            log_js_value(hint, value.as_ref());
48            anyhow::anyhow!(
49                "{}, error value: {:?}, see console.error log for detail.",
50                hint,
51                value
52            )
53        } else {
54            anyhow::anyhow!(
55                "{}, error value: {:?}, enable 'error-logging' feature to log value to console.error.",
56                hint,
57                value
58            )
59        }
60    }
61}
62
63pub fn static_str_to_js(s: &'static str) -> &'static JsValue {
64    use std::cell::RefCell;
65    use std::collections::HashMap;
66
67    thread_local! {
68        // Since we're mainly optimizing for converting the exact same string literal over and over again,
69        // which will always have the same pointer, we can speed things up by indexing by the string's pointer
70        // instead of its value.
71        static CACHE: RefCell<HashMap<(*const u8, usize), &'static JsValue>> = Default::default();
72    }
73
74    let key = (s.as_ptr(), s.len());
75
76    CACHE.with(|cache| {
77        let mut cache = cache.borrow_mut();
78        let reference = cache.entry(key).or_insert_with(|| {
79            let js_val: JsValue = s.into();
80            let boxed = Box::new(js_val);
81            let leaked = Box::leak(boxed);
82            leaked as &'static JsValue
83        });
84        *reference
85        // .clone()
86        // .clone()
87        //let val = cache.borrow_mut().entry(key).or_insert_with(|| s.into());
88        // unsafe { &*(val as *const JsString) }
89        //val.clone()
90        //val as &'static JsString
91    })
92}