extern crate core; use anyhow::Result; use serde_json::Value; use wasmtime::{Config, Engine, Instance, Linker, Module, Store}; use crate::fn_common::FnResult; mod fn_common; mod fn_fetch; wit_bindgen_wasmtime::export!("../container.wit"); #[derive(Default)] pub struct MyContainer { fetch_invoked_count: u32, } impl container::Container for MyContainer { fn fetch(&mut self, params: &str) -> String { if self.fetch_invoked_count > 10 { return FnResult::fail("Fetch invoke count cannot more than 10").to_json(); } self.fetch_invoked_count += 1; fn_fetch::do_fetch(params).to_json() } } wit_bindgen_wasmtime::import!("../exports.wit"); fn main() -> Result<()> { use exports::*; let wasm = "../engine/target/wasm32-unknown-unknown/debug/engine.wasm"; let (exports, mut store) = instantiate( wasm, |linker| container::add_to_linker(linker, |cx| -> &mut MyContainer { &mut cx.imports }), |store, module, linker| Exports::instantiate(store, module, linker, |cx| &mut cx.exports), )?; let a = exports.eval_javascript(&mut store, r##" function hi(name) { return "hi: " + name; } let a = []; a.push(fetch('https://hatter.ink/util/print_request.action')); a.push(fetch('https://hatter.ink/ip.action')); a.push(fetch('https://hatter.ink/ip/ip.jsonp')); a.push(fetch('https://hatter.ink/ip2.action')); a.push({ userId: 'id001', name: 'Test', }); JSON.stringify(a) // a "##); let a = a.expect("error"); let a: Value = match serde_json::from_str(&a) { Ok(a) => a, Err(e) => panic!("ERROR: {}", e), }; let a = match a { Value::String(a) => a, _ => panic!("error: {}", a), }; let v: Value = match serde_json::from_str(&a) { Ok(v) => v, Err(e) => panic!("Parse json1 failed: {}, raw json:\n - {}", e, a), }; let p = serde_json::to_string_pretty(&v).expect("error"); // println!("------- {}", v); println!("{}", p); Ok(()) } struct Context { imports: I, exports: E, } fn instantiate( wasm: &str, add_imports: impl FnOnce(&mut Linker>) -> Result<()>, mk_exports: impl FnOnce( &mut Store>, &Module, &mut Linker>, ) -> Result<(T, Instance)>, ) -> Result<(T, Store>)> { let engine = Engine::new(&default_config()?)?; let module = Module::from_file(&engine, wasm)?; let mut linker = Linker::new(&engine); add_imports(&mut linker)?; let mut store = Store::new( &engine, Context { imports: I::default(), exports: E::default(), }, ); let (exports, _instance) = mk_exports(&mut store, &module, &mut linker)?; Ok((exports, store)) } fn default_config() -> Result { // Create an engine with caching enabled to assist with iteration in this project. let mut config = Config::new(); config.cache_config_load_default()?; // config.debug_info(true); config.wasm_backtrace_details(wasmtime::WasmBacktraceDetails::Enable); Ok(config) }