use anyhow::{Context as _, Result}; use wasmtime::{Config, Engine, Instance, Linker, Module, Store}; test_helpers::runtime_tests_wasmtime!(); 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.wasm_backtrace_details(wasmtime::WasmBacktraceDetails::Enable); Ok(config) } fn default_wasi() -> wasmtime_wasi::WasiCtx { wasmtime_wasi::sync::WasiCtxBuilder::new() .inherit_stdio() .build() } struct Context { wasi: wasmtime_wasi::WasiCtx, 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)?; wasmtime_wasi::add_to_linker(&mut linker, |cx| &mut cx.wasi)?; let mut store = Store::new( &engine, Context { wasi: default_wasi(), imports: I::default(), exports: E::default(), }, ); let (exports, _instance) = mk_exports(&mut store, &module, &mut linker)?; Ok((exports, store)) } // TODO: This function needs to be updated to use the component model once it's ready. See // https://github.com/bytecodealliance/wit-bindgen/issues/259 for details. // // Also, rename the ignore_host.rs files under the tests/runtime/smw_{functions|lists|strings} to host.rs and // remove the leading underscore from this function's name to re-enable the Spidermonkey tests. fn _instantiate_smw( 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 mut config = default_config()?; config.wasm_multi_memory(true); let engine = Engine::new(&config)?; println!("reading wasms..."); let wasm = std::fs::read(wasm).context(format!("failed to read {}", wasm))?; let smw = std::fs::read("../gen-spidermonkey/spidermonkey-wasm/spidermonkey.wasm") .context("failed to read `spidermonkey.wasm`")?; println!("compiling input wasm..."); let module = Module::new(&engine, &wasm)?; println!("compiling spidermonkey.wasm..."); let smw = Module::new(&engine, &smw)?; let mut linker = Linker::new(&engine); add_imports(&mut linker)?; wasmtime_wasi::add_to_linker(&mut linker, |cx| &mut cx.wasi)?; let mut store = Store::new( &engine, Context { wasi: default_wasi(), imports: I::default(), exports: E::default(), }, ); println!("instantiating spidermonkey.wasm..."); let _smw_instance = linker .instantiate(&mut store, &smw) .context("failed to instantiate `spidermonkey.wasm`")?; // TODO: replace this with a component model equivalent: // linker.define_name("spidermonkey", smw_instance)?; println!("instantiating input wasm..."); let (exports, instance) = mk_exports(&mut store, &module, &mut linker)?; println!("running wizer.initialize"); let init = instance.get_typed_func::<(), (), _>(&mut store, "wizer.initialize")?; init.call(&mut store, ()) .context("failed to call wizer.initialize")?; Ok((exports, store)) }