1use js_sys::{Array, Function, JsString, Object};
2use std::sync::atomic::{AtomicBool, Ordering};
3use wasm_bindgen::prelude::*;
4
5#[doc(hidden)]
6pub mod __macrodeps {
7 pub use gensym::gensym;
8 pub use std::{concat, stringify};
9}
10
11static INIT_DONE: AtomicBool = AtomicBool::new(false);
12
13#[cfg(feature = "auto-init")]
14#[wasm_bindgen(start)]
15fn main() {
16 wasm_init();
17}
18
19#[wasm_bindgen]
29pub fn wasm_init() {
30 if INIT_DONE.swap(true, Ordering::Relaxed) {
31 return;
32 };
33
34 let exports: Object = wasm_bindgen::exports().into();
35 let entries = Object::entries(&exports);
36 for entry in entries {
37 let entry = Array::from(&entry);
38 let name: JsString = entry.get(0).into();
39 let func: Function = entry.get(1).into();
40
41 if name.starts_with("__wasm_init", 0) {
42 func.apply(&JsValue::undefined(), &Array::new())
43 .expect("func invocation failed");
44 }
45 }
46}
47
48#[doc(hidden)]
49#[macro_export]
50macro_rules! __wasm_init_impl {
51 ($gensym:ident, $($input:tt)*) => {
52 const _: () = {
53 #[export_name = $crate::__macrodeps::concat!(
54 "__wasm_init",
55 $crate::__macrodeps::stringify!($gensym)
56 )]
57 pub extern "C" fn init() {
58 $($input)*
59 }
60 };
61 };
62}
63
64#[macro_export]
93macro_rules! wasm_init {
94 ($($input:tt)*) => {
95 $crate::__macrodeps::gensym! { $crate::__wasm_init_impl! { $($input)* } }
96 };
97}