From 3778469de96bd7174e815348768d20a901848104 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kav=C3=ADk?= Date: Tue, 25 Jun 2024 18:29:33 +0200 Subject: [PATCH] component_manager, strict_eval.js --- frontend/src/header_panel.rs | 6 ++- frontend/src/platform.rs | 6 +++ frontend/src/platform/browser.rs | 10 +++- frontend/src/platform/tauri.rs | 12 +++++ frontend/src/script_bridge.rs | 16 +++--- frontend/src/waveform_panel.rs | 4 +- frontend/typescript/bundles/strict_eval.js | 5 ++ frontend/typescript/bundles/tauri_glue.js | 4 ++ frontend/typescript/tauri_glue/tauri_glue.ts | 6 +++ src-tauri/src/component_manager.rs | 54 ++++++++++++++++++++ src-tauri/src/lib.rs | 10 ++++ 11 files changed, 119 insertions(+), 14 deletions(-) create mode 100644 frontend/typescript/bundles/strict_eval.js create mode 100644 src-tauri/src/component_manager.rs diff --git a/frontend/src/header_panel.rs b/frontend/src/header_panel.rs index 72e5c25..3becd90 100644 --- a/frontend/src/header_panel.rs +++ b/frontend/src/header_panel.rs @@ -241,8 +241,10 @@ impl HeaderPanel { if raw_event.shift_key() { // @TODO move `prevent_default` to MZ API (next to the `pass_to_parent` method?) raw_event.prevent_default(); - let result = script_bridge::strict_eval(&script.lock_ref()); - command_result.set(Some(result)); + Task::start(clone!((script, command_result) async move { + let result = script_bridge::strict_eval(&script.lock_ref()).await; + command_result.set(Some(result)); + })); } } }) diff --git a/frontend/src/platform.rs b/frontend/src/platform.rs index e152433..4f1cad4 100644 --- a/frontend/src/platform.rs +++ b/frontend/src/platform.rs @@ -15,6 +15,8 @@ use browser as platform; type Filename = String; type JavascriptCode = String; +type AddedDecodersCount = usize; +type DecoderPath = String; pub async fn show_window() { platform::show_window().await @@ -58,3 +60,7 @@ pub async fn load_signal_and_get_timeline( pub async fn unload_signal(signal_ref: wellen::SignalRef) { platform::unload_signal(signal_ref).await } + +pub async fn add_decoders(decoder_paths: Vec) -> AddedDecodersCount { + platform::add_decoders(decoder_paths).await +} diff --git a/frontend/src/platform/browser.rs b/frontend/src/platform/browser.rs index 363a5c2..22c0ca1 100644 --- a/frontend/src/platform/browser.rs +++ b/frontend/src/platform/browser.rs @@ -1,7 +1,7 @@ use shared::wellen_helpers; use std::sync::Mutex; use wellen::simple::Waveform; -use zoon::*; +use zoon::{*, eprintln}; #[derive(Default)] struct BrowserPlatformStore { @@ -120,3 +120,11 @@ pub(super) async fn unload_signal(signal_ref: wellen::SignalRef) { let waveform = waveform_lock.as_mut().unwrap_throw(); waveform.unload_signals(&[signal_ref]); } + +pub(super) async fn add_decoders( + _decoder_paths: Vec, +) -> super::AddedDecodersCount { + // @TODO error message for user + eprintln!("Adding decoders is not supported in the browser."); + 0 +} diff --git a/frontend/src/platform/tauri.rs b/frontend/src/platform/tauri.rs index aea34b6..4e65e4b 100644 --- a/frontend/src/platform/tauri.rs +++ b/frontend/src/platform/tauri.rs @@ -56,6 +56,13 @@ pub(super) async fn unload_signal(signal_ref: wellen::SignalRef) { .unwrap_throw() } +pub(super) async fn add_decoders( + decoder_paths: Vec, +) -> super::AddedDecodersCount { + serde_wasm_bindgen::from_value(tauri_glue::add_decoders(decoder_paths).await.unwrap_throw()) + .unwrap_throw() +} + mod tauri_glue { use zoon::*; @@ -86,5 +93,10 @@ mod tauri_glue { #[wasm_bindgen(catch)] pub async fn unload_signal(signal_ref_index: usize) -> Result<(), JsValue>; + + #[wasm_bindgen(catch)] + pub async fn add_decoders( + decoder_paths: Vec, + ) -> Result; } } diff --git a/frontend/src/script_bridge.rs b/frontend/src/script_bridge.rs index 392ab13..2e57894 100644 --- a/frontend/src/script_bridge.rs +++ b/frontend/src/script_bridge.rs @@ -1,16 +1,15 @@ -use crate::STORE; +use crate::{platform, STORE}; use wellen::GetItem; use zoon::*; type FullVarName = String; +type AddedDecodersCount = usize; type DecoderPath = String; -#[wasm_bindgen( - inline_js = r#"export function strict_eval(code) { "use strict"; return eval?.(`${code}`) }"# -)] +#[wasm_bindgen(module = "/typescript/bundles/strict_eval.js")] extern "C" { #[wasm_bindgen(catch)] - pub fn strict_eval(code: &str) -> Result; + pub async fn strict_eval(code: &str) -> Result; } #[wasm_bindgen] @@ -70,8 +69,7 @@ impl FW { } /// JS: `FW.add_decoders(["test_files/components/rust_decoder/rust_decoder.wasm"])` -> `1` - pub fn add_decoders(decoder_paths: Vec) -> usize { - zoon::println!("decoders: {decoder_paths:#?}"); - 0 - } + pub async fn add_decoders(decoder_paths: Vec) -> AddedDecodersCount { + platform::add_decoders(decoder_paths).await + } } diff --git a/frontend/src/waveform_panel.rs b/frontend/src/waveform_panel.rs index f9f42e6..ee6eb83 100644 --- a/frontend/src/waveform_panel.rs +++ b/frontend/src/waveform_panel.rs @@ -96,7 +96,7 @@ impl WaveformPanel { if let Some(javascript_code) = platform::load_file_with_selected_vars(None).await { - match script_bridge::strict_eval(&javascript_code) { + match script_bridge::strict_eval(&javascript_code).await { Ok(js_value) => { zoon::println!("File with selected vars loaded: {js_value:?}") } @@ -153,7 +153,7 @@ impl WaveformPanel { if let Some(javascript_code) = platform::load_file_with_selected_vars(Some(file)).await { - match script_bridge::strict_eval(&javascript_code) { + match script_bridge::strict_eval(&javascript_code).await { Ok(js_value) => zoon::println!( "File with selected vars loaded: {js_value:?}" ), diff --git a/frontend/typescript/bundles/strict_eval.js b/frontend/typescript/bundles/strict_eval.js new file mode 100644 index 0000000..ffcdd89 --- /dev/null +++ b/frontend/typescript/bundles/strict_eval.js @@ -0,0 +1,5 @@ +"use strict"; + +export async function strict_eval(code) { + return await eval(code) +} diff --git a/frontend/typescript/bundles/tauri_glue.js b/frontend/typescript/bundles/tauri_glue.js index 026793f..34be301 100644 --- a/frontend/typescript/bundles/tauri_glue.js +++ b/frontend/typescript/bundles/tauri_glue.js @@ -2536,7 +2536,11 @@ async function load_signal_and_get_timeline(signal_ref_index, timeline_zoom, tim async function unload_signal(signal_ref_index) { return await invoke2("unload_signal", { signal_ref_index }); } +async function add_decoders(decoder_paths) { + return await invoke2("add_decoders", { decoder_paths }); +} export { + add_decoders, get_hierarchy, load_file_with_selected_vars, load_signal_and_get_timeline, diff --git a/frontend/typescript/tauri_glue/tauri_glue.ts b/frontend/typescript/tauri_glue/tauri_glue.ts index a4be66c..9856a6f 100644 --- a/frontend/typescript/tauri_glue/tauri_glue.ts +++ b/frontend/typescript/tauri_glue/tauri_glue.ts @@ -9,6 +9,8 @@ type JavascriptCode = string; type WellenHierarchy = unknown; type Timeline = unknown; type VarFormat = unknown; +type AddedDecodersCount = number; +type DecoderPath = string; export async function show_window(): Promise { return await invoke("show_window"); @@ -47,3 +49,7 @@ export async function load_signal_and_get_timeline( export async function unload_signal(signal_ref_index: number): Promise { return await invoke("unload_signal", { signal_ref_index }); } + +export async function add_decoders(decoder_paths: Array): Promise { + return await invoke("add_decoders", { decoder_paths }); +} diff --git a/src-tauri/src/component_manager.rs b/src-tauri/src/component_manager.rs new file mode 100644 index 0000000..6d4ec6a --- /dev/null +++ b/src-tauri/src/component_manager.rs @@ -0,0 +1,54 @@ +use crate::{AddedDecodersCount, DecoderPath}; +use wasmtime::*; + +pub fn add_decoders(decoder_paths: Vec) -> AddedDecodersCount { + println!("decoders in Tauri: {decoder_paths:#?}"); + + wasmtime_test().unwrap(); + + decoder_paths.len() +} + +fn wasmtime_test() -> wasmtime::Result<()> { + let engine = Engine::default(); + + // Modules can be compiled through either the text or binary format + let wat = r#" + (module + (import "host" "host_func" (func $host_hello (param i32))) + + (func (export "hello") + i32.const 3 + call $host_hello) + ) + "#; + let module = Module::new(&engine, wat)?; + + // Host functionality can be arbitrary Rust functions and is provided + // to guests through a `Linker`. + let mut linker = Linker::new(&engine); + linker.func_wrap( + "host", + "host_func", + |caller: Caller<'_, u32>, param: i32| { + println!("Got {} from WebAssembly", param); + println!("my host state is: {}", caller.data()); + }, + )?; + + // All wasm objects operate within the context of a "store". Each + // `Store` has a type parameter to store host-specific data, which in + // this case we're using `4` for. + let mut store: Store = Store::new(&engine, 4); + + // Instantiation of a module requires specifying its imports and then + // afterwards we can fetch exports by name, as well as asserting the + // type signature of the function with `get_typed_func`. + let instance = linker.instantiate(&mut store, &module)?; + let hello = instance.get_typed_func::<(), ()>(&mut store, "hello")?; + + // And finally we can call the wasm! + hello.call(&mut store, ())?; + + Ok(()) +} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index c8752db..fa2bda8 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -5,6 +5,10 @@ use wellen::simple::Waveform; type Filename = String; type JavascriptCode = String; +type AddedDecodersCount = usize; +type DecoderPath = String; + +mod component_manager; #[derive(Default)] struct Store { @@ -91,6 +95,11 @@ async fn unload_signal(signal_ref_index: usize, store: tauri::State<'_, Store>) Ok(()) } +#[tauri::command(rename_all = "snake_case")] +async fn add_decoders(decoder_paths: Vec) -> Result { + Ok(component_manager::add_decoders(decoder_paths)) +} + #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { // https://github.com/tauri-apps/tauri/issues/8462 @@ -109,6 +118,7 @@ pub fn run() { get_hierarchy, load_signal_and_get_timeline, unload_signal, + add_decoders, ]) .run(tauri::generate_context!()) .expect("error while running tauri application");