use crate::id::MizeId; use crate::item::{Item, ItemData}; use crate::platform::js::js_sys::Function; use core::convert::From; use core::option::Option; use std::panic; use std::ptr::NonNull; use web_sys::js_sys::{self, eval, Promise}; use web_sys::Worker; use web_sys::{WorkerOptions, WorkerType}; use crate::core::item::IntoItemData; use crate::error::MizeResult; use crate::Mize; use crate::MizeError; use crate::mize_err; // console_log macro // that can be copied into other files for debugging purposes #[cfg(feature = "target-js")] use wasm_bindgen::prelude::*; #[cfg(feature = "target-js")] #[wasm_bindgen] extern "C" { #[wasm_bindgen(js_namespace = console)] fn log(s: &str); } #[cfg(feature = "target-js")] macro_rules! console_log { // Note that this is using the `log` function imported above during // `bare_bones` ($($t:tt)*) => (unsafe { log(&format_args!($($t)*).to_string())}) } #[cfg(not(feature = "target-js"))] macro_rules! console_log { // Note that this is using the `log` function imported above during // `bare_bones` ($($t:tt)*) => {}; } //end of console_log macro #[global_allocator] static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; pub fn wasm_instance_init(mize: &mut Mize) -> MizeResult<()> { console_log!("Hello world from wasm_instance_init!!!!!!!!!!"); #[cfg(feature = "target-obsidian")] { ////// populate values from $MIZE_CONFIG_FILES if let Ok(config_file_paths) = obsidian_get_env_var("MIZE_CONFIG_FILES") { for config_file_path in config_file_paths.split(":") { println!("reading config file: {config_file_path}"); let content = std::fs::read_to_string(config_file_path)?; let mut data = ItemData::from_toml(content.as_str())?; crate::core::item::set_config_from_data(mize, data)?; } } ////// load config from MIZE_CONFIG env var match std::env::var("MIZE_CONFIG") { Ok(config_string) => { let data = data_from_string(config_string)?; crate::core::item::set_config_from_data(mize, data)?; } Err(var_err) => match var_err { VarError::NotPresent => { debug!("env var MIZE_CONFIG NOT present") } VarError::NotUnicode(_) => { warn!("env var MIZE_CONFIG is not Unicode, so not reading it") } }, }; } Ok(()) } #[cfg(feature = "target-obsidian")] pub fn obsidian_get_env_var(name: &str) -> Option { use js_sys::{Reflect, Object}; // 1. Get the global `process` object let global = js_sys::global(); let process = Reflect::get(&global, &JsValue::from_str("process")).ok()?; if process.is_undefined() { return None; } // 2. Get the `env` object from `process` let env = Reflect::get(&process, &JsValue::from_str("env")).ok()?; if env.is_undefined() { return None; } // 3. Get the `MIZE_STORE` value from `env` let mize_store = Reflect::get(&env, &JsValue::from_str("MIZE_STORE")).ok()?; // 4. Convert the JsValue to a Rust String if it exists mize_store.as_string() } pub fn load_module(mize: &mut Mize, name: &str, path: Option) -> MizeResult<()> { console_log!("loading module NOT IMPLEMENTED: {}", name); //wasm_bindgen_futures::spawn_local(load_module_async(mize.clone(), name.to_owned(), path)); Ok(()) } /* async fn load_module_async(mut mize: Mize, name: String, path: Option) -> () { let name = name.as_str(); let module_url = fetch_module(&mut mize, name).unwrap(); let memory = wasm_bindgen::memory(); let mut empty_module: Box = Box::new(EmptyModule {}); let mut mize = mize.clone(); let empty_module_ptr = Box::into_raw(Box::new(empty_module)); let empty_module_usize = empty_module_ptr as usize; let mize_usize = Box::into_raw(Box::new(mize)) as usize; console_log!("testttttttttttttt in load_module_async..."); let function_str = format!( r#" const promise = new Promise((resolve, reject) => {{ import("{module_url}/mize_module_{name}.js").then( module => {{ const wasm_bindgen = module.get_wasm_bindgen(); const {{ wasm_get_mize_module_mme }} = wasm_bindgen; wasm_bindgen("{module_url}/mize_module_{name}_bg.wasm", memory).then( () => {{ console.log("empty_module_usize:", empty_module_usize) console.log("mize_usize:", mize_usize) //resolve() resolve(wasm_get_mize_module_mme(empty_module_usize, mize_usize)) }}) }}) }}) return promise; "# ); let function = Function::new_with_args("memory, empty_module_usize, mize_usize", &function_str); let ret_value: JsValue = match function.call3( &JsValue::null(), &memory, &empty_module_usize.into(), &mize_usize.into(), ) { Ok(val) => val, Err(err) => { console_log!("failed to load the wasm mize module...."); console_log!("{:?}", err); return; } }; console_log!("got ret_value: {:?}", ret_value); let ret_promise = Promise::from(ret_value); let ret_result = match wasm_bindgen_futures::JsFuture::from(ret_promise).await { Ok(val) => val, Err(err) => { console_log!("err awaiting ret_promise"); console_log!("{:?}", err); return; } }; let mut filled_module = unsafe { Box::from_raw(empty_module_ptr) }; console_log!("before...."); //let a = mize.get("0/config"); console_log!("after...."); //filled_module.init(&instance); /* console_log!("got ret_result: {:?}", ret_result); let ret_f64 = ret_result.as_f64().unwrap(); console_log!("got ret_f64: {:?}", ret_f64); let ret_usize = ret_f64.floor() as usize; let mut module: Box = Box::new(EmptyModule {}); unsafe { let get_mize_module_fn_ptr = ret_usize as *const fn(&mut Box, Instance) -> (); let get_mize_module_fn: fn(&mut Box, Instance) -> () = unsafe { std::mem::transmute(get_mize_module_fn_ptr) }; get_mize_module_fn(&mut module, instance.clone()); } */ } */ pub fn fetch_module(mize: &mut Mize, name: &str) -> MizeResult { let module_name_with_slashes = name.replace(".", "/"); if let Ok(module_path) = mize .get(format!( "self/config/module_dir/{}", module_name_with_slashes ))? .value_string() { return Ok(module_path); } else { let module_url = mize.get("self/config/module_url")?.value_string()?; return Ok(format!("{}/{}", module_url, module_name_with_slashes)); } } async fn download_module(mize: &mut Mize, name: &str) -> MizeResult { use wasm_bindgen_futures::JsFuture; use web_sys::{Request, RequestInit, RequestMode, Response}; let opts = RequestInit::new(); opts.set_method("GET"); opts.set_mode(RequestMode::Cors); let url = format!("{}/mize_module_{}_bg.wasm", fetch_module(mize, name)?, name); let request = Request::new_with_str_and_init(&url, &opts).unwrap(); let window = web_sys::window().unwrap(); let resp_value = JsFuture::from(window.fetch_with_request(&request)) .await .unwrap(); let resp: Response = resp_value.dyn_into().unwrap(); let wasm_bytes: js_sys::ArrayBuffer = JsFuture::from(resp.array_buffer().unwrap()) .await .unwrap() .dyn_into() .unwrap(); Ok(wasm_bytes) } #[wasm_bindgen] #[derive(Clone)] pub struct JsMize { inner: NonNull, } #[wasm_bindgen] pub struct JsItem { mize: NonNull, id: MizeId, } #[wasm_bindgen] pub async fn new_js_instance(config_json_str: String) -> JsMize { panic::set_hook(Box::new(console_error_panic_hook::hook)); let config = ItemData::from_json(config_json_str).expect("parsing of json config failed"); let mut mize = Mize::with_config(config).expect("Mize::new() failed"); let mut js_instance = JsMize { inner: NonNull::from(Box::leak(Box::new(mize))), }; return js_instance; } #[wasm_bindgen] impl JsMize { #[wasm_bindgen] pub unsafe fn init(&mut self) -> MizeResult<()> { self.inner.as_mut().init() } #[wasm_bindgen] pub unsafe fn set(&mut self, id: String, value: String) -> () { let data = value.into_item_data(); console_log!("data in set: {}", data); self.inner.as_mut().set(id, data); } #[wasm_bindgen] pub unsafe fn get_handle(&mut self, id: String) -> MizeResult { let item = self.inner.as_mut().get(id)?; Ok(JsItem { mize: self.inner, id: item.id(), }) } } impl JsMize { pub fn inner(&mut self) -> &mut Mize { unsafe { self.inner.as_mut() } } } #[wasm_bindgen] impl JsItem { #[wasm_bindgen] pub unsafe fn value_string(&mut self) -> MizeResult { let item = self.mize.as_mut().get(self.id.clone())?; let string = item.value_string()?; Ok(string) } #[wasm_bindgen] pub unsafe fn as_data_full(&mut self) -> MizeResult { let item = self.mize.as_mut().get(self.id.clone())?; let data_raw = item.as_data_full()?; let jsvalue = serde_wasm_bindgen::to_value(data_raw.cbor())?; Ok(jsvalue) } } impl From for JsValue { fn from(value: MizeError) -> Self { let string = format!("{:?}", value); string.into() } }