diff --git a/Cargo.lock b/Cargo.lock index 73327c3d2b2..b8703ce5106 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -39,9 +39,9 @@ dependencies = [ [[package]] name = "android_system_properties" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7ed72e1635e121ca3e79420540282af22da58be50de153d36f81ddc6b83aa9e" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" dependencies = [ "libc", ] @@ -57,15 +57,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1485d4d2cc45e7b201ee3767015c96faa5904387c9d87c6efdd0fb511f12d305" +checksum = "a26fa4d7e3f2eebadf743988fc8aec9fa9a9e82611acafd77c1462ed6262440a" [[package]] name = "arbitrary" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a7924531f38b1970ff630f03eb20a2fde69db5c590c93b0f3482e95dcc5fd60" +checksum = "8931eb436ab9bf1980c6cb2b9d1ba5390cd6793b2c6e2d2ea8147da3570c2a2e" dependencies = [ "derive_arbitrary", ] @@ -279,7 +279,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6358dedf60f4d9b8db43ad187391afe959746101346fe51bb978126bec61dfb" dependencies = [ - "clap 3.2.17", + "clap 3.2.20", "heck", "indexmap", "log", @@ -297,6 +297,9 @@ name = "cc" version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +dependencies = [ + "jobserver", +] [[package]] name = "cexpr" @@ -361,9 +364,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.17" +version = "3.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29e724a68d9319343bb3328c9cc2dfde263f4b3142ee1059a9980580171c954b" +checksum = "23b71c3ce99b7611011217b366d923f1d0a7e07a92bb2dbf1e84508c673ca3bd" dependencies = [ "atty", "bitflags", @@ -378,9 +381,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.2.17" +version = "3.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13547f7012c01ab4a0e8f8967730ada8f9fdf419e8b6c792788f39cf4e46eefa" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ "heck", "proc-macro-error", @@ -756,9 +759,9 @@ dependencies = [ [[package]] name = "derive_arbitrary" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9a577516173adb681466d517d39bd468293bc2c2a16439375ef0f35bba45f3d" +checksum = "d749b611838b7e92cba33b8552187059f2dc32f91d4d66bdc4fe5da9526b4e07" dependencies = [ "proc-macro2", "quote", @@ -941,9 +944,9 @@ dependencies = [ [[package]] name = "erased-serde" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003000e712ad0f95857bd4d2ef8d1890069e06554101697d12050668b2f6f020" +checksum = "54558e0ba96fbe24280072642eceb9d7d442e32c7ec0ea9e7ecd7b4ea2cf4e11" dependencies = [ "serde", ] @@ -1174,13 +1177,14 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "iana-time-zone" -version = "0.1.46" +version = "0.1.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad2bfd338099682614d3ee3fe0cd72e0b6a41ca6a87f6a74a3bd593c91650501" +checksum = "4c495f162af0bf17656d0014a0eded5f3cd2f365fdd204548c2869db89359dc7" dependencies = [ "android_system_properties", "core-foundation-sys", "js-sys", + "once_cell", "wasm-bindgen", "winapi", ] @@ -1296,6 +1300,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +[[package]] +name = "jobserver" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af25a77299a7f711a01975c35a6a424eb6862092cc2d6c72c4ed6cbc56dfc1fa" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" version = "0.3.59" @@ -1331,9 +1344,9 @@ checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" [[package]] name = "libfuzzer-sys" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "336244aaeab6a12df46480dc585802aa743a72d66b11937844c61bbca84c991d" +checksum = "ae185684fe19814afd066da15a7cc41e126886c21282934225d9fc847582da58" dependencies = [ "arbitrary", "cc", @@ -1365,9 +1378,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53" +checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390" dependencies = [ "autocfg", "scopeguard", @@ -1391,6 +1404,16 @@ dependencies = [ "libc", ] +[[package]] +name = "macro-wasmer-universal-test" +version = "0.1.0" +dependencies = [ + "proc-macro2", + "proc-quote", + "quote", + "syn", +] + [[package]] name = "matchers" version = "0.1.0" @@ -1631,9 +1654,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9423e2b32f7a043629287a536f21951e8c6a82482d0acb1eeebfc90bc2225b22" +checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" [[package]] name = "peeking_take_while" @@ -1729,14 +1752,14 @@ dependencies = [ [[package]] name = "pretty_assertions" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89f989ac94207d048d92db058e4f6ec7342b0971fc58d1271ca148b799b3563" +checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" dependencies = [ - "ansi_term", "ctor", "diff", "output_vt100", + "yansi", ] [[package]] @@ -1778,6 +1801,30 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proc-quote" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e84ab161de78c915302ca325a19bee6df272800e2ae1a43fe3ef430bab2a100" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "proc-quote-impl", + "quote", + "syn", +] + +[[package]] +name = "proc-quote-impl" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fb3ec628b063cdbcf316e06a8b8c1a541d28fa6c0a8eacd2bfb2b7f49e88aa0" +dependencies = [ + "proc-macro-hack", + "proc-macro2", + "quote", +] + [[package]] name = "ptr_meta" version = "0.1.4" @@ -2233,9 +2280,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.83" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "itoa 1.0.3", "ryu", @@ -2515,18 +2562,18 @@ checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" [[package]] name = "thiserror" -version = "1.0.32" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994" +checksum = "3d0a539a918745651435ac7db7a18761589a94cd7e94cd56999f828bf73c8a57" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.32" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21" +checksum = "c251e90f708e16c49a16f4917dc2131e75222b72edfa9cb7f7c58ae56aae0c09" dependencies = [ "proc-macro2", "quote", @@ -2928,6 +2975,7 @@ dependencies = [ "hashbrown 0.11.2", "indexmap", "js-sys", + "macro-wasmer-universal-test", "more-asserts", "target-lexicon 0.12.4", "tempfile", @@ -3010,7 +3058,7 @@ dependencies = [ "atty", "bytesize", "cfg-if 1.0.0", - "clap 3.2.17", + "clap 3.2.20", "colored 2.0.0", "dirs", "distance", @@ -3071,7 +3119,7 @@ dependencies = [ "atty", "bytesize", "cfg-if 1.0.0", - "clap 3.2.17", + "clap 3.2.20", "colored 2.0.0", "distance", "fern", @@ -3713,3 +3761,9 @@ name = "xml-rs" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" + +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" diff --git a/lib/api/Cargo.toml b/lib/api/Cargo.toml index 9bcb2c9b0a1..d3373036c2a 100644 --- a/lib/api/Cargo.toml +++ b/lib/api/Cargo.toml @@ -55,6 +55,7 @@ winapi = "0.3" wat = "1.0" tempfile = "3.1" anyhow = "1.0" +macro-wasmer-universal-test = { version = "0.1.0", path = "./macro-wasmer-universal-test" } # Dependencies and Develoment Dependencies for `js`. [target.'cfg(target_arch = "wasm32")'.dependencies] @@ -72,6 +73,7 @@ hashbrown = { version = "0.11", optional = true } wat = "1.0" anyhow = "1.0" wasm-bindgen-test = "0.3.0" +macro-wasmer-universal-test = { version = "0.1.0", path = "./macro-wasmer-universal-test" } # Specific to `js`. # diff --git a/lib/api/macro-wasmer-universal-test/Cargo.toml b/lib/api/macro-wasmer-universal-test/Cargo.toml new file mode 100644 index 00000000000..f6f401ad4b1 --- /dev/null +++ b/lib/api/macro-wasmer-universal-test/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "macro-wasmer-universal-test" +version = "0.1.0" +edition = "2021" +license = "MIT" +description = "Universal test macro for wasmer-test" + +[lib] +proc-macro = true + +[dependencies] +proc-quote = "0.4.0" +proc-macro2 = "1.0.43" +syn = { version = "1.0.99", features = ["full"] } +quote = "*" \ No newline at end of file diff --git a/lib/api/macro-wasmer-universal-test/src/lib.rs b/lib/api/macro-wasmer-universal-test/src/lib.rs new file mode 100644 index 00000000000..48838c0e7f8 --- /dev/null +++ b/lib/api/macro-wasmer-universal-test/src/lib.rs @@ -0,0 +1,36 @@ +extern crate proc_macro; + +use proc_macro::TokenStream; +use proc_macro2::{Ident, Span}; + +#[proc_macro_attribute] +pub fn universal_test(_attr: TokenStream, item: TokenStream) -> TokenStream { + let item_clone = item.clone(); + let mut iter = item_clone.into_iter(); + let _ = iter.next().unwrap(); // fn + let item_tree: proc_macro::TokenTree = iter.next().unwrap(); // fn ... + let n = match &item_tree { + proc_macro::TokenTree::Ident(i) => i.to_string(), + _ => panic!("expected fn ...() -> Result<(), String>"), + }; + + let function_name_normal = Ident::new(&n, Span::call_site()); + let function_name_js = Ident::new(&format!("{}_js", n), Span::call_site()); + let parsed = match syn::parse::(item) { + Ok(o) => o, + Err(e) => { + return proc_macro::TokenStream::from(e.to_compile_error()); + } + }; + + let tokens = quote::quote! { + #[cfg(feature = "js")] + #[cfg_attr(feature = "js", wasm_bindgen_test)] + fn #function_name_js() { #function_name_normal().unwrap(); } + + #[cfg_attr(feature = "sys", test)] + #parsed + }; + + proc_macro::TokenStream::from(tokens) +} diff --git a/lib/api/tests/externals.rs b/lib/api/tests/externals.rs new file mode 100644 index 00000000000..5c17579a4ab --- /dev/null +++ b/lib/api/tests/externals.rs @@ -0,0 +1,408 @@ +use macro_wasmer_universal_test::universal_test; +#[cfg(feature = "js")] +use wasm_bindgen_test::*; + +use wasmer::*; + +#[universal_test] +fn global_new() -> Result<(), String> { + let mut store = Store::default(); + let global = Global::new(&mut store, Value::I32(10)); + assert_eq!( + global.ty(&mut store), + GlobalType { + ty: Type::I32, + mutability: Mutability::Const + } + ); + + let global_mut = Global::new_mut(&mut store, Value::I32(10)); + assert_eq!( + global_mut.ty(&mut store), + GlobalType { + ty: Type::I32, + mutability: Mutability::Var + } + ); + + Ok(()) +} + +#[universal_test] +fn global_get() -> Result<(), String> { + let mut store = Store::default(); + + let global_i32 = Global::new(&mut store, Value::I32(10)); + assert_eq!(global_i32.get(&mut store), Value::I32(10)); + + // 64-bit values are not yet fully supported in some versions of Node + #[cfg(feature = "sys")] + { + let global_i64 = Global::new(&mut store, Value::I64(20)); + assert_eq!(global_i64.get(&mut store), Value::I64(20)); + } + + let global_f32 = Global::new(&mut store, Value::F32(10.0)); + assert_eq!(global_f32.get(&mut store), Value::F32(10.0)); + + // 64-bit values are not yet fully supported in some versions of Node + #[cfg(feature = "sys")] + { + let global_f64 = Global::new(&mut store, Value::F64(20.0)); + assert_eq!(global_f64.get(&mut store), Value::F64(20.0)); + } + + Ok(()) +} + +#[universal_test] +fn global_set() -> Result<(), String> { + let mut store = Store::default(); + let global_i32 = Global::new(&mut store, Value::I32(10)); + // Set on a constant should error + assert!(global_i32.set(&mut store, Value::I32(20)).is_err()); + + let global_i32_mut = Global::new_mut(&mut store, Value::I32(10)); + // Set on different type should error + assert!(global_i32_mut.set(&mut store, Value::I64(20)).is_err()); + + // Set on same type should succeed + global_i32_mut + .set(&mut store, Value::I32(20)) + .map_err(|e| format!("{e:?}"))?; + assert_eq!(global_i32_mut.get(&mut store), Value::I32(20)); + + Ok(()) +} + +#[universal_test] +fn table_new() -> Result<(), String> { + let mut store = Store::default(); + let table_type = TableType { + ty: Type::FuncRef, + minimum: 0, + maximum: None, + }; + let f = Function::new_typed(&mut store, || {}); + let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f))) + .map_err(|e| format!("{e:?}"))?; + assert_eq!(table.ty(&mut store), table_type); + + // Anyrefs not yet supported + // let table_type = TableType { + // ty: Type::ExternRef, + // minimum: 0, + // maximum: None, + // }; + // let table = Table::new(&store, table_type, Value::ExternRef(ExternRef::Null)).map_err(|e| format!("{e:?}"))?; + // assert_eq!(*table.ty(), table_type); + + Ok(()) +} + +#[universal_test] +fn table_get() -> Result<(), String> { + // Tables are not yet fully supported in Wasm + // This test was marked as #[ignore] on -sys, which is why it is commented out. + + // let mut store = Store::default(); + // let table_type = TableType { + // ty: Type::FuncRef, + // minimum: 0, + // maximum: Some(1), + // }; + // let f = Function::new_typed(&mut store, |num: i32| num + 1); + // let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f))) + // .map_err(|e| format!("{e:?}"))?; + // assert_eq!(table.ty(&mut store), table_type); + // let _elem = table.get(&mut store, 0).unwrap(); + // assert_eq!(elem.funcref().unwrap(), f); + + Ok(()) +} + +#[universal_test] +fn table_set() -> Result<(), String> { + // Table set not yet tested + Ok(()) +} + +#[universal_test] +fn table_grow() -> Result<(), String> { + // Tables are not yet fully supported in Wasm + #[cfg(feature = "sys")] + { + let mut store = Store::default(); + let table_type = TableType { + ty: Type::FuncRef, + minimum: 0, + maximum: Some(10), + }; + let f = Function::new_typed(&mut store, |num: i32| num + 1); + let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f.clone()))) + .map_err(|e| format!("{e:?}"))?; + // Growing to a bigger maximum should return None + let old_len = table.grow(&mut store, 12, Value::FuncRef(Some(f.clone()))); + assert!(old_len.is_err()); + + // Growing to a bigger maximum should return None + let old_len = table + .grow(&mut store, 5, Value::FuncRef(Some(f))) + .map_err(|e| format!("{e:?}"))?; + assert_eq!(old_len, 0); + } + + Ok(()) +} + +#[universal_test] +fn table_copy() -> Result<(), String> { + // TODO: table copy test not yet implemented + Ok(()) +} + +#[universal_test] +fn memory_new() -> Result<(), String> { + let mut store = Store::default(); + let memory_type = MemoryType { + shared: false, + minimum: Pages(0), + maximum: Some(Pages(10)), + }; + let memory = Memory::new(&mut store, memory_type).map_err(|e| format!("{e:?}"))?; + assert_eq!(memory.view(&mut store).size(), Pages(0)); + assert_eq!(memory.ty(&mut store), memory_type); + Ok(()) +} + +#[universal_test] +fn memory_grow() -> Result<(), String> { + let mut store = Store::default(); + let desc = MemoryType::new(Pages(10), Some(Pages(16)), false); + let memory = Memory::new(&mut store, desc).map_err(|e| format!("{e:?}"))?; + assert_eq!(memory.view(&mut store).size(), Pages(10)); + + let result = memory.grow(&mut store, Pages(2)).unwrap(); + assert_eq!(result, Pages(10)); + assert_eq!(memory.view(&mut store).size(), Pages(12)); + + let result = memory.grow(&mut store, Pages(10)); + assert_eq!( + result, + Err(MemoryError::CouldNotGrow { + current: 12.into(), + attempted_delta: 10.into() + }) + ); + + // JS will never give BadMemory unless V8 is broken somehow + #[cfg(feature = "sys")] + { + let bad_desc = MemoryType::new(Pages(15), Some(Pages(10)), false); + let bad_result = Memory::new(&mut store, bad_desc); + assert!(matches!(bad_result, Err(MemoryError::InvalidMemory { .. }))); + } + + Ok(()) +} + +#[universal_test] +fn function_new() -> Result<(), String> { + let mut store = Store::default(); + let function = Function::new_typed(&mut store, || {}); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![], vec![]) + ); + let function = Function::new_typed(&mut store, |_a: i32| {}); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![Type::I32], vec![]) + ); + let function = Function::new_typed(&mut store, |_a: i32, _b: i64, _c: f32, _d: f64| {}); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) + ); + let function = Function::new_typed(&mut store, || -> i32 { 1 }); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![], vec![Type::I32]) + ); + let function = Function::new_typed(&mut store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) + ); + Ok(()) +} + +#[universal_test] +fn function_new_env() -> Result<(), String> { + let mut store = Store::default(); + #[derive(Clone)] + struct MyEnv {} + + let my_env = MyEnv {}; + let env = FunctionEnv::new(&mut store, my_env); + let function = Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut| {}); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![], vec![]) + ); + let function = + Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut, _a: i32| {}); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![Type::I32], vec![]) + ); + let function = Function::new_typed_with_env( + &mut store, + &env, + |_env: FunctionEnvMut, _a: i32, _b: i64, _c: f32, _d: f64| {}, + ); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) + ); + let function = + Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut| -> i32 { 1 }); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![], vec![Type::I32]) + ); + let function = Function::new_typed_with_env( + &mut store, + &env, + |_env: FunctionEnvMut| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, + ); + assert_eq!( + function.ty(&mut store).clone(), + FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) + ); + Ok(()) +} + +#[universal_test] +fn function_new_dynamic() -> Result<(), String> { + let mut store = Store::default(); + + // Using &FunctionType signature + let function_type = FunctionType::new(vec![], vec![]); + let function = Function::new( + &mut store, + &function_type, + |_values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + let function_type = FunctionType::new(vec![Type::I32], vec![]); + let function = Function::new( + &mut store, + &function_type, + |_values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); + let function = Function::new( + &mut store, + &function_type, + |_values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + let function_type = FunctionType::new(vec![], vec![Type::I32]); + let function = Function::new( + &mut store, + &function_type, + |_values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); + let function = Function::new( + &mut store, + &function_type, + |_values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + + // Using array signature + let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); + let function = Function::new( + &mut store, + function_type, + |_values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).params(), [Type::V128]); + assert_eq!( + function.ty(&mut store).results(), + [Type::I32, Type::F32, Type::F64] + ); + + Ok(()) +} + +#[universal_test] +fn function_new_dynamic_env() -> Result<(), String> { + let mut store = Store::default(); + #[derive(Clone)] + struct MyEnv {} + let my_env = MyEnv {}; + let env = FunctionEnv::new(&mut store, my_env); + + // Using &FunctionType signature + let function_type = FunctionType::new(vec![], vec![]); + let function = Function::new_with_env( + &mut store, + &env, + &function_type, + |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + let function_type = FunctionType::new(vec![Type::I32], vec![]); + let function = Function::new_with_env( + &mut store, + &env, + &function_type, + |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); + let function = Function::new_with_env( + &mut store, + &env, + &function_type, + |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + let function_type = FunctionType::new(vec![], vec![Type::I32]); + let function = Function::new_with_env( + &mut store, + &env, + &function_type, + |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); + let function = Function::new_with_env( + &mut store, + &env, + &function_type, + |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).clone(), function_type); + + // Using array signature + let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); + let function = Function::new_with_env( + &mut store, + &env, + function_type, + |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), + ); + assert_eq!(function.ty(&mut store).params(), [Type::V128]); + assert_eq!( + function.ty(&mut store).results(), + [Type::I32, Type::F32, Type::F64] + ); + + Ok(()) +} diff --git a/lib/api/tests/instance.rs b/lib/api/tests/instance.rs new file mode 100644 index 00000000000..bffdfd81250 --- /dev/null +++ b/lib/api/tests/instance.rs @@ -0,0 +1,80 @@ +use macro_wasmer_universal_test::universal_test; +#[cfg(feature = "js")] +use wasm_bindgen_test::*; + +use wasmer::*; + +#[universal_test] +fn exports_work_after_multiple_instances_have_been_freed() -> Result<(), String> { + let mut store = Store::default(); + let module = Module::new( + &store, + " +(module + (type $sum_t (func (param i32 i32) (result i32))) + (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) + local.get $x + local.get $y + i32.add) + (export \"sum\" (func $sum_f))) +", + ) + .map_err(|e| format!("{e:?}"))?; + + let imports = Imports::new(); + let instance = Instance::new(&mut store, &module, &imports).map_err(|e| format!("{e:?}"))?; + let instance2 = instance.clone(); + let instance3 = instance.clone(); + + // The function is cloned to “break” the connection with `instance`. + let sum = instance + .exports + .get_function("sum") + .map_err(|e| format!("{e:?}"))? + .clone(); + + drop(instance); + drop(instance2); + drop(instance3); + + // All instances have been dropped, but `sum` continues to work! + assert_eq!( + sum.call(&mut store, &[Value::I32(1), Value::I32(2)]) + .map_err(|e| format!("{e:?}"))? + .into_vec(), + vec![Value::I32(3)], + ); + + Ok(()) +} + +#[universal_test] +fn unit_native_function_env() -> Result<(), String> { + let mut store = Store::default(); + + #[derive(Clone)] + struct Env { + multiplier: u32, + } + + fn imported_fn(env: FunctionEnvMut, args: &[Value]) -> Result, RuntimeError> { + let value = env.data().multiplier * args[0].unwrap_i32() as u32; + Ok(vec![Value::I32(value as _)]) + } + + // We create the environment + let env = Env { multiplier: 3 }; + // We move the environment to the store, so it can be used by the `Function` + let env = FunctionEnv::new(&mut store, env); + + let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); + let imported = Function::new_with_env(&mut store, &env, imported_signature, imported_fn); + + let expected = vec![Value::I32(12)].into_boxed_slice(); + let result = imported + .call(&mut store, &[Value::I32(4)]) + .map_err(|e| format!("{e:?}"))?; + assert_eq!(result, expected); + + Ok(()) +} diff --git a/lib/api/tests/js_externals.rs b/lib/api/tests/js_externals.rs deleted file mode 100644 index 90a181ec874..00000000000 --- a/lib/api/tests/js_externals.rs +++ /dev/null @@ -1,445 +0,0 @@ -#[cfg(feature = "js")] -mod js { - use wasm_bindgen_test::*; - use wasmer::*; - - #[wasm_bindgen_test] - fn global_new() { - let mut store = Store::default(); - let global = Global::new(&mut store, Value::I32(10)); - assert_eq!( - global.ty(&store), - GlobalType { - ty: Type::I32, - mutability: Mutability::Const - } - ); - - let global_mut = Global::new_mut(&mut store, Value::I32(10)); - assert_eq!( - global_mut.ty(&store), - GlobalType { - ty: Type::I32, - mutability: Mutability::Var - } - ); - } - - #[wasm_bindgen_test] - fn global_get() { - let mut store = Store::default(); - let global_i32 = Global::new(&mut store, Value::I32(10)); - assert_eq!(global_i32.get(&mut store), Value::I32(10)); - // 64-bit values are not yet fully supported in some versions of Node - // Commenting this tests for now: - - // let global_i64 = Global::new(&store, Value::I64(20)); - // assert_eq!(global_i64.get(), Value::I64(20)); - let global_f32 = Global::new(&mut store, Value::F32(10.0)); - assert_eq!(global_f32.get(&store), Value::F32(10.0)); - // let global_f64 = Global::new(&store, Value::F64(20.0)); - // assert_eq!(global_f64.get(), Value::F64(20.0)); - } - - #[wasm_bindgen_test] - fn global_set() { - let mut store = Store::default(); - let global_i32 = Global::new(&mut store, Value::I32(10)); - // Set on a constant should error - assert!(global_i32.set(&mut store, Value::I32(20)).is_err()); - - let global_i32_mut = Global::new_mut(&mut store, Value::I32(10)); - // Set on different type should error - assert!(global_i32_mut.set(&mut store, Value::I64(20)).is_err()); - - // Set on same type should succeed - global_i32_mut.set(&mut store, Value::I32(20)).unwrap(); - assert_eq!(global_i32_mut.get(&store), Value::I32(20)); - } - - #[wasm_bindgen_test] - fn table_new() { - let mut store = Store::default(); - let table_type = TableType { - ty: Type::FuncRef, - minimum: 0, - maximum: None, - }; - let f = Function::new_typed(&mut store, || {}); - let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f))).unwrap(); - assert_eq!(table.ty(&store), table_type); - - // table.get() - // Anyrefs not yet supported - // let table_type = TableType { - // ty: Type::ExternRef, - // minimum: 0, - // maximum: None, - // }; - // let table = Table::new(&store, table_type, Value::ExternRef(ExternRef::Null))?; - // assert_eq!(*table.ty(&store), table_type); - } - - // Tables are not yet fully supported in Wasm - // Commenting this tests for now - - // #[test] - // #[ignore] - // fn table_get() -> Result<()> { - // let mut store = Store::default(); - // let mut env = FunctionEnv::new(&mut store, ()); - // let table_type = TableType { - // ty: Type::FuncRef, - // minimum: 0, - // maximum: Some(1), - // }; - // let f = Function::new(&mut store, |num: i32| num + 1); - // let table = Table::new(&store, table_type, Value::FuncRef(Some(f.clone())))?; - // assert_eq!(*table.ty(&store), table_type); - // let _elem = table.get(0).unwrap(); - // // assert_eq!(elem.funcref().unwrap(), f); - // Ok(()) - // } - - // #[test] - // #[ignore] - // fn table_set() -> Result<()> { - // // Table set not yet tested - // Ok(()) - // } - - // #[test] - // fn table_grow() -> Result<()> { - // let mut store = Store::default(); - // let mut env = FunctionEnv::new(&mut store, ()); - // let table_type = TableType { - // ty: Type::FuncRef, - // minimum: 0, - // maximum: Some(10), - // }; - // let f = Function::new(&mut store, &env, |num: i32| num + 1); - // let table = Table::new(&store, table_type, Value::FuncRef(Some(f.clone())))?; - // // Growing to a bigger maximum should return None - // let old_len = table.grow(12, Value::FuncRef(Some(f.clone()))); - // assert!(old_len.is_err()); - - // // Growing to a bigger maximum should return None - // let old_len = table.grow(5, Value::FuncRef(Some(f.clone())))?; - // assert_eq!(old_len, 0); - - // Ok(()) - // } - - // #[test] - // #[ignore] - // fn table_copy() -> Result<()> { - // // TODO: table copy test not yet implemented - // Ok(()) - // } - - #[wasm_bindgen_test] - fn memory_new() { - let mut store = Store::default(); - let memory_type = MemoryType { - shared: false, - minimum: Pages(0), - maximum: Some(Pages(10)), - }; - let memory = Memory::new(&mut store, memory_type).unwrap(); - assert_eq!(memory.view(&store).size(), Pages(0)); - assert_eq!(memory.ty(&store), memory_type); - } - - #[wasm_bindgen_test] - fn memory_grow() { - let mut store = Store::default(); - - let desc = MemoryType::new(Pages(10), Some(Pages(16)), false); - let memory = Memory::new(&mut store, desc).unwrap(); - assert_eq!(memory.view(&store).size(), Pages(10)); - - let result = memory.grow(&mut store, Pages(2)).unwrap(); - assert_eq!(result, Pages(10)); - assert_eq!(memory.view(&store).size(), Pages(12)); - - let result = memory.grow(&mut store, Pages(10)); - assert!(result.is_err()); - assert_eq!( - result, - Err(MemoryError::CouldNotGrow { - current: 12.into(), - attempted_delta: 10.into() - }) - ); - } - - #[wasm_bindgen_test] - fn function_new() { - let mut store = Store::default(); - let function = Function::new_typed(&mut store, || {}); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![], vec![]) - ); - let function = Function::new_typed(&mut store, |_a: i32| {}); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![Type::I32], vec![]) - ); - let function = Function::new_typed(&mut store, |_a: i32, _b: i64, _c: f32, _d: f64| {}); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) - ); - let function = Function::new_typed(&mut store, || -> i32 { 1 }); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![], vec![Type::I32]) - ); - let function = - Function::new_typed(&mut store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) - ); - } - - #[wasm_bindgen_test] - fn function_new_env() { - let mut store = Store::default(); - #[derive(Clone)] - struct MyEnv {} - - let my_env = MyEnv {}; - let env = FunctionEnv::new(&mut store, my_env); - - let function = - Function::new_typed_with_env(&mut store, &env, |_: FunctionEnvMut<'_, MyEnv>| {}); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![], vec![]) - ); - let function = Function::new_typed_with_env( - &mut store, - &env, - |_: FunctionEnvMut<'_, MyEnv>, _a: i32| {}, - ); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![Type::I32], vec![]) - ); - let function = Function::new_typed_with_env( - &mut store, - &env, - |_: FunctionEnvMut<'_, MyEnv>, _a: i32, _b: i64, _c: f32, _d: f64| {}, - ); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) - ); - let function = - Function::new_typed_with_env(&mut store, &env, |_: FunctionEnvMut<'_, MyEnv>| -> i32 { - 1 - }); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![], vec![Type::I32]) - ); - let function = Function::new_typed_with_env( - &mut store, - &env, - |_: FunctionEnvMut<'_, MyEnv>| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, - ); - assert_eq!( - function.ty(&store).clone(), - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) - ); - } - - #[wasm_bindgen_test] - fn function_new_dynamic() { - let mut store = Store::default(); - - // Using &FunctionType signature - let function_type = FunctionType::new(vec![], vec![]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - let function_type = FunctionType::new(vec![Type::I32], vec![]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - let function_type = - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - let function_type = FunctionType::new(vec![], vec![Type::I32]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - let function_type = - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - - // Using array signature - let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); - let function = Function::new( - &mut store, - function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).params(), [Type::V128]); - assert_eq!( - function.ty(&store).results(), - [Type::I32, Type::F32, Type::F64] - ); - } - - #[wasm_bindgen_test] - fn function_new_dynamic_env() { - let mut store = Store::default(); - #[derive(Clone)] - struct MyEnv {} - - let my_env = MyEnv {}; - let env = FunctionEnv::new(&mut store, my_env); - - // Using &FunctionType signature - let function_type = FunctionType::new(vec![], vec![]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - let function_type = FunctionType::new(vec![Type::I32], vec![]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - let function_type = - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - let function_type = FunctionType::new(vec![], vec![Type::I32]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - let function_type = - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).clone(), function_type); - - // Using array signature - let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); - let function = Function::new_with_env( - &mut store, - &env, - function_type, - |_env: FunctionEnvMut<'_, MyEnv>, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&store).params(), [Type::V128]); - assert_eq!( - function.ty(&store).results(), - [Type::I32, Type::F32, Type::F64] - ); - } - - #[wasm_bindgen_test] - fn native_function_works() { - let mut store = Store::default(); - let function = Function::new_typed(&mut store, || {}); - let typed_function: TypedFunction<(), ()> = function.typed(&mut store).unwrap(); - let result = typed_function.call(&mut store); - assert!(result.is_ok()); - - let function = Function::new_typed(&mut store, |a: i32| -> i32 { a + 1 }); - let typed_function: TypedFunction = function.typed(&mut store).unwrap(); - assert_eq!(typed_function.call(&mut store, 3).unwrap(), 4); - - // fn rust_abi(a: i32, b: i64, c: f32, d: f64) -> u64 { - // (a as u64 * 1000) + (b as u64 * 100) + (c as u64 * 10) + (d as u64) - // } - // let function = Function::new(&mut store, &env, rust_abi); - // let typed_function: TypedFunction<(i32, i64, f32, f64), u64> = function.native(&mut store).unwrap(); - // assert_eq!(typed_function.call(8, 4, 1.5, 5.).unwrap(), 8415); - - let function = Function::new_typed(&mut store, || -> i32 { 1 }); - let typed_function: TypedFunction<(), i32> = function.typed(&mut store).unwrap(); - assert_eq!(typed_function.call(&mut store).unwrap(), 1); - - let function = Function::new_typed(&mut store, |_a: i32| {}); - let typed_function: TypedFunction = function.typed(&mut store).unwrap(); - assert!(typed_function.call(&mut store, 4).is_ok()); - - // let function = Function::new(&mut store, &env, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); - // let typed_function: TypedFunction<(), (i32, i64, f32, f64)> = function.native(&mut store).unwrap(); - // assert_eq!(typed_function.call().unwrap(), (1, 2, 3.0, 4.0)); - } - - #[wasm_bindgen_test] - fn function_outlives_instance() { - let mut store = Store::default(); - let wat = r#"(module - (type $sum_t (func (param i32 i32) (result i32))) - (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) - local.get $x - local.get $y - i32.add) - (export "sum" (func $sum_f))) - "#; - - let f = { - let module = Module::new(&store, wat).unwrap(); - let instance = Instance::new(&mut store, &module, &imports! {}).unwrap(); - let f = instance.exports.get_function("sum").unwrap(); - - assert_eq!( - f.call(&mut store, &[Val::I32(4), Val::I32(5)]).unwrap(), - vec![Val::I32(9)].into_boxed_slice() - ); - f.clone() - }; - - assert_eq!( - f.call(&mut store, &[Val::I32(4), Val::I32(5)]).unwrap(), - vec![Val::I32(9)].into_boxed_slice() - ); - } -} diff --git a/lib/api/tests/js_instance.rs b/lib/api/tests/js_instance.rs deleted file mode 100644 index 26e1054e62c..00000000000 --- a/lib/api/tests/js_instance.rs +++ /dev/null @@ -1,852 +0,0 @@ -#[cfg(feature = "js")] -mod js { - use anyhow::Result; - use wasm_bindgen_test::*; - use wasmer::*; - - /* - * For debugging, put web_sys in dev dependencies in Cargo.toml with the "console" feature - * on. - * - extern crate web_sys; - - // A macro to provide `println!(..)`-style syntax for `console.log` logging. - macro_rules! log { - ( $( $t:tt )* ) => { - web_sys::console::log_1(&format!( $( $t )* ).into()); - } - } - */ - macro_rules! log { - ( $( $t:tt )* ) => {}; - } - - #[wasm_bindgen_test] - fn test_exported_memory() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (memory (export "mem") 1) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![], - exports: vec![ExternType::Memory(MemoryType::new(Pages(1), None, false))], - }) - .unwrap(); - - let import_object = imports! {}; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let memory = instance.exports.get_memory("mem").unwrap(); - assert!(memory.is_from_store(&store)); - assert_eq!(memory.ty(&store), MemoryType::new(Pages(1), None, false)); - assert_eq!(memory.view(&store).size(), Pages(1)); - assert_eq!(memory.view(&store).data_size(), 65536); - - memory.grow(&mut store, Pages(1)).unwrap(); - assert_eq!(memory.ty(&store), MemoryType::new(Pages(1), None, false)); - assert_eq!(memory.view(&store).size(), Pages(2)); - assert_eq!(memory.view(&store).data_size(), 65536 * 2); - } - - #[wasm_bindgen_test] - fn test_exported_function() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (func (export "get_magic") (result i32) - (i32.const 42) - ) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![], - exports: vec![ExternType::Function(FunctionType::new( - vec![], - vec![Type::I32], - ))], - }) - .unwrap(); - - let import_object = imports! {}; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let get_magic = instance.exports.get_function("get_magic").unwrap(); - assert_eq!( - get_magic.ty(&store).clone(), - FunctionType::new(vec![], vec![Type::I32]) - ); - - let expected = vec![Val::I32(42)].into_boxed_slice(); - assert_eq!(get_magic.call(&mut store, &[]).unwrap(), expected); - } - - #[wasm_bindgen_test] - fn test_imports_from_js_object() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) - ) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - exports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - }) - .unwrap(); - - let obj: js_sys::Object = js_sys::Function::new_with_args( - "", - "return { - \"env\": { - \"imported\": function(num) { - console.log(\"Calling `imported`...\"); - var result = num * 2; - console.log(\"Result of `imported`: \", result); - return result; - } - } - };", - ) - .call0(&wasm_bindgen::JsValue::UNDEFINED) - .unwrap() - .into(); - - let import_object = Imports::new_from_js_object(&mut store, &module, obj) - .expect("Can't get imports from js object"); - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let exported = instance.exports.get_function("exported").unwrap(); - - let expected = vec![Val::I32(6)].into_boxed_slice(); - assert_eq!(exported.call(&mut store, &[Val::I32(3)]).unwrap(), expected); - } - - #[wasm_bindgen_test] - fn test_imported_function_dynamic() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) - ) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - exports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - }) - .unwrap(); - - let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - - let imported = Function::new(&mut store, imported_signature, |args| { - log!("Calling `imported`..."); - let result = args[0].unwrap_i32() * 2; - log!("Result of `imported`: {:?}", result); - Ok(vec![Value::I32(result)]) - }); - - let import_object = imports! { - "env" => { - "imported" => imported, - } - }; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let exported = instance.exports.get_function("exported").unwrap(); - - let expected = vec![Val::I32(6)].into_boxed_slice(); - assert_eq!(exported.call(&mut store, &[Val::I32(3)]).unwrap(), expected); - } - - // We comment it for now because in old versions of Node, only single return values are supported - - // #[wasm_bindgen_test] - // fn test_imported_function_dynamic_multivalue() { - // let mut store = Store::default(); - // let mut module = Module::new( - // &store, - // br#" - // (module - // (func $multivalue (import "env" "multivalue") (param i32 i32) (result i32 i32)) - // (func (export "multivalue") (param i32 i32) (result i32 i32) - // (call $multivalue (local.get 0) (local.get 1)) - // ) - // ) - // "#, - // ) - // .unwrap(); - // module.set_type_hints(ModuleTypeHints { - // imports: vec![ - // ExternType::Function(FunctionType::new( - // vec![Type::I32, Type::I32], - // vec![Type::I32, Type::I32], - // )), - // ], - // exports: vec![ - // ExternType::Function(FunctionType::new( - // vec![Type::I32, Type::I32], - // vec![Type::I32, Type::I32], - // )), - // ], - // }); - - // let multivalue_signature = - // FunctionType::new(vec![Type::I32, Type::I32], vec![Type::I32, Type::I32]); - // let multivalue = Function::new(&store, &multivalue_signature, |args| { - // log!("Calling `imported`..."); - // // let result = args[0].unwrap_i32() * ; - // // log!("Result of `imported`: {:?}", result); - // Ok(vec![args[1].clone(), args[0].clone()]) - // }); - - // let import_object = imports! { - // "env" => { - // "multivalue" => multivalue, - // } - // }; - // let instance = Instance::new(&module, &import_object).unwrap(); - - // let exported_multivalue = instance - // .exports - // .get_function("multivalue") - // .unwrap(); - - // let expected = vec![Val::I32(2), Val::I32(3)].into_boxed_slice(); - // assert_eq!( - // exported_multivalue.call(&[Val::I32(3), Val::I32(2)]), - // Ok(expected) - // ); - // } - - #[wasm_bindgen_test] - fn test_imported_function_dynamic_with_env() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) - ) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - exports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - }) - .unwrap(); - - #[derive(Clone)] - struct Env { - multiplier: i32, - } - - let env = FunctionEnv::new(&mut store, Env { multiplier: 3 }); - - let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = - Function::new_with_env(&mut store, &env, &imported_signature, |env, args| { - log!("Calling `imported`..."); - let result = args[0].unwrap_i32() * env.data().multiplier; - log!("Result of `imported`: {:?}", result); - Ok(vec![Value::I32(result)]) - }); - - let import_object = imports! { - "env" => { - "imported" => imported, - } - }; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let exported = instance.exports.get_function("exported").unwrap(); - - let expected = vec![Val::I32(9)].into_boxed_slice(); - assert_eq!(exported.call(&mut store, &[Val::I32(3)]), Ok(expected)); - } - - #[wasm_bindgen_test] - fn test_imported_function_native() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) - ) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - exports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - }) - .unwrap(); - - fn imported_fn(arg: u32) -> u32 { - return arg + 1; - } - - let imported = Function::new_typed(&mut store, imported_fn); - - let import_object = imports! { - "env" => { - "imported" => imported, - } - }; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let exported = instance.exports.get_function("exported").unwrap(); - - let expected = vec![Val::I32(5)].into_boxed_slice(); - assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); - } - - #[wasm_bindgen_test] - fn test_imported_function_native_with_env() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) - ) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - exports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - }) - .unwrap(); - - #[derive(Clone, Debug)] - struct Env { - multiplier: u32, - } - - fn imported_fn(env: FunctionEnvMut<'_, Env>, arg: u32) -> u32 { - log!("inside imported_fn: env.data is {:?}", env.data()); - // log!("inside call id is {:?}", env.as_store_ref().objects().id); - return env.data().multiplier * arg; - } - - let env = FunctionEnv::new(&mut store, Env { multiplier: 3 }); - - let imported = Function::new_typed_with_env(&mut store, &env, imported_fn); - - let import_object = imports! { - "env" => { - "imported" => imported, - } - }; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let exported = instance.exports.get_function("exported").unwrap(); - - let expected = vec![Val::I32(12)].into_boxed_slice(); - env.as_mut(&mut store).multiplier = 3; - assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); - } - - #[wasm_bindgen_test] - fn test_imported_function_native_with_wasmer_env() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) - ) - (memory (export "memory") 1) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - exports: vec![ - ExternType::Function(FunctionType::new(vec![Type::I32], vec![Type::I32])), - ExternType::Memory(MemoryType::new(Pages(1), None, false)), - ], - }) - .unwrap(); - - #[derive(Clone, Debug)] - struct Env { - multiplier: u32, - memory: Option, - } - - fn imported_fn(env: FunctionEnvMut<'_, Env>, arg: u32) -> u32 { - let memory: &Memory = env.data().memory.as_ref().unwrap(); - let memory_val = memory.view(&env).read_u8(0).unwrap(); - return (memory_val as u32) * env.data().multiplier * arg; - } - - let env = FunctionEnv::new( - &mut store, - Env { - multiplier: 3, - memory: None, - }, - ); - let imported = Function::new_typed_with_env(&mut store, &env, imported_fn); - - let import_object = imports! { - "env" => { - "imported" => imported, - } - }; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let memory = instance.exports.get_memory("memory").unwrap(); - assert_eq!(memory.view(&store).data_size(), 65536); - let memory_val = memory.view(&store).read_u8(0).unwrap(); - assert_eq!(memory_val, 0); - - memory.view(&store).write_u8(0, 2).unwrap(); - let memory_val = memory.view(&store).read_u8(0).unwrap(); - assert_eq!(memory_val, 2); - - env.as_mut(&mut store).memory = Some(memory.clone()); - - let exported = instance.exports.get_function("exported").unwrap(); - - // It works with the provided memory - let expected = vec![Val::I32(24)].into_boxed_slice(); - assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); - - // It works if we update the memory - memory.view(&store).write_u8(0, 3).unwrap(); - let expected = vec![Val::I32(36)].into_boxed_slice(); - assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); - } - - #[wasm_bindgen_test] - fn test_unit_native_function_env() { - let mut store = Store::default(); - #[derive(Clone)] - struct Env { - multiplier: u32, - } - - let env = FunctionEnv::new(&mut store, Env { multiplier: 3 }); - - fn imported_fn(env: FunctionEnvMut, args: &[Val]) -> Result, RuntimeError> { - let value = env.data().multiplier * args[0].unwrap_i32() as u32; - return Ok(vec![Val::I32(value as _)]); - } - - let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = Function::new_with_env(&mut store, &env, imported_signature, imported_fn); - - let expected = vec![Val::I32(12)].into_boxed_slice(); - assert_eq!(imported.call(&mut store, &[Val::I32(4)]), Ok(expected)); - } - - #[wasm_bindgen_test] - fn test_imported_function_with_wasmer_env() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (func $imported (import "env" "imported") (param i32) (result i32)) - (func (export "exported") (param i32) (result i32) - (call $imported (local.get 0)) - ) - (memory (export "memory") 1) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![ExternType::Function(FunctionType::new( - vec![Type::I32], - vec![Type::I32], - ))], - exports: vec![ - ExternType::Function(FunctionType::new(vec![Type::I32], vec![Type::I32])), - ExternType::Memory(MemoryType::new(Pages(1), None, false)), - ], - }) - .unwrap(); - - #[derive(Clone, Debug)] - struct Env { - multiplier: u32, - memory: Option, - } - - fn imported_fn( - env: FunctionEnvMut<'_, Env>, - args: &[Val], - ) -> Result, RuntimeError> { - let memory: &Memory = env.data().memory.as_ref().unwrap(); - let memory_val = memory.view(&env).read_u8(0).unwrap(); - let value = (memory_val as u32) * env.data().multiplier * args[0].unwrap_i32() as u32; - return Ok(vec![Val::I32(value as _)]); - } - - let env = FunctionEnv::new( - &mut store, - Env { - multiplier: 3, - memory: None, - }, - ); - - let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = Function::new_with_env(&mut store, &env, imported_signature, imported_fn); - - let import_object = imports! { - "env" => { - "imported" => imported, - } - }; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let memory = instance.exports.get_memory("memory").unwrap(); - assert_eq!(memory.view(&store).data_size(), 65536); - let memory_val = memory.view(&store).read_u8(0).unwrap(); - assert_eq!(memory_val, 0); - - memory.view(&store).write_u8(0, 2).unwrap(); - let memory_val = memory.view(&store).read_u8(0).unwrap(); - assert_eq!(memory_val, 2); - - env.as_mut(&mut store).memory = Some(memory.clone()); - - let exported = instance.exports.get_function("exported").unwrap(); - - // It works with the provided memory - let expected = vec![Val::I32(24)].into_boxed_slice(); - assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); - - // It works if we update the memory - memory.view(&store).write_u8(0, 3).unwrap(); - let expected = vec![Val::I32(36)].into_boxed_slice(); - assert_eq!(exported.call(&mut store, &[Val::I32(4)]), Ok(expected)); - } - - #[wasm_bindgen_test] - fn test_imported_exported_global() { - let mut store = Store::default(); - let mut module = Module::new( - &store, - br#" - (module - (global $mut_i32_import (import "" "global") (mut i32)) - (func (export "getGlobal") (result i32) (global.get $mut_i32_import)) - (func (export "incGlobal") (global.set $mut_i32_import ( - i32.add (i32.const 1) (global.get $mut_i32_import) - ))) - ) - "#, - ) - .unwrap(); - module - .set_type_hints(ModuleTypeHints { - imports: vec![ExternType::Global(GlobalType::new( - ValType::I32, - Mutability::Var, - ))], - exports: vec![ - ExternType::Function(FunctionType::new(vec![], vec![Type::I32])), - ExternType::Function(FunctionType::new(vec![], vec![])), - ], - }) - .unwrap(); - let global = Global::new_mut(&mut store, Value::I32(0)); - let import_object = imports! { - "" => { - "global" => global.clone() - } - }; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let get_global = instance.exports.get_function("getGlobal").unwrap(); - assert_eq!( - get_global.call(&mut store, &[]), - Ok(vec![Val::I32(0)].into_boxed_slice()) - ); - - global.set(&mut store, Value::I32(42)).unwrap(); - assert_eq!( - get_global.call(&mut store, &[]), - Ok(vec![Val::I32(42)].into_boxed_slice()) - ); - - let inc_global = instance.exports.get_function("incGlobal").unwrap(); - inc_global.call(&mut store, &[]).unwrap(); - assert_eq!( - get_global.call(&mut store, &[]), - Ok(vec![Val::I32(43)].into_boxed_slice()) - ); - assert_eq!(global.get(&store), Val::I32(43)); - } - - #[wasm_bindgen_test] - fn test_native_function() { - let mut store = Store::default(); - let module = Module::new( - &store, - br#"(module - (func $add (import "env" "sum") (param i32 i32) (result i32)) - (func (export "add_one") (param i32) (result i32) - (call $add (local.get 0) (i32.const 1)) - ) - )"#, - ) - .unwrap(); - - fn sum(a: i32, b: i32) -> i32 { - a + b - } - - let import_object = imports! { - "env" => { - "sum" => Function::new_typed(&mut store, sum), - } - }; - - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let add_one: TypedFunction = instance - .exports - .get_typed_function(&mut store, "add_one") - .unwrap(); - assert_eq!(add_one.call(&mut store, 1), Ok(2)); - } - - #[wasm_bindgen_test] - fn test_panic() { - let mut store = Store::default(); - let module = Module::new( - &store, - br#" - (module - (type $run_t (func (param i32 i32) (result i32))) - (type $early_exit_t (func (param) (result))) - (import "env" "early_exit" (func $early_exit (type $early_exit_t))) - (func $run (type $run_t) (param $x i32) (param $y i32) (result i32) - (call $early_exit) - (i32.add - local.get $x - local.get $y)) - (export "run" (func $run))) - "#, - ) - .unwrap(); - - fn early_exit() { - panic!("Do panic") - } - - let import_object = imports! { - "env" => { - "early_exit" => Function::new_typed(&mut store, early_exit), - } - }; - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - let run_func: TypedFunction<(i32, i32), i32> = instance - .exports - .get_typed_function(&mut store, "run") - .unwrap(); - - assert!( - run_func.call(&mut store, 1, 7).is_err(), - "Expected early termination", - ); - let run_func = instance.exports.get_function("run").unwrap(); - - assert!( - run_func - .call(&mut store, &[Val::I32(1), Val::I32(7)]) - .is_err(), - "Expected early termination", - ); - } - - #[wasm_bindgen_test] - fn test_custom_error() { - let mut store = Store::default(); - let module = Module::new( - &store, - br#" - (module - (type $run_t (func (param i32 i32) (result i32))) - (type $early_exit_t (func (param) (result))) - (import "env" "early_exit" (func $early_exit (type $early_exit_t))) - (func $run (type $run_t) (param $x i32) (param $y i32) (result i32) - (call $early_exit) - (i32.add - local.get $x - local.get $y)) - (export "run" (func $run))) - "#, - ) - .unwrap(); - - use std::fmt; - - #[derive(Debug, Clone, Copy)] - struct ExitCode(u32); - - impl fmt::Display for ExitCode { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.0) - } - } - - impl std::error::Error for ExitCode {} - - fn early_exit() -> Result<(), ExitCode> { - Err(ExitCode(1)) - } - - let import_object = imports! { - "env" => { - "early_exit" => Function::new_typed(&mut store, early_exit), - } - }; - - let instance = Instance::new(&mut store, &module, &import_object).unwrap(); - - fn test_result(result: Result) { - match result { - Ok(result) => { - assert!( - false, - "Expected early termination with `ExitCode`, found: {:?}", - result - ); - } - Err(e) => { - match e.downcast::() { - // We found the exit code used to terminate execution. - Ok(exit_code) => { - assert_eq!(exit_code.0, 1); - } - Err(e) => { - assert!(false, "Unknown error `{:?}` found. expected `ErrorCode`", e); - } - } - } - } - } - - let run_func: TypedFunction<(i32, i32), i32> = instance - .exports - .get_typed_function(&mut store, "run") - .unwrap(); - test_result(run_func.call(&mut store, 1, 7)); - - let run_func = instance.exports.get_function("run").unwrap(); - test_result(run_func.call(&mut store, &[Val::I32(1), Val::I32(7)])); - } - - #[wasm_bindgen_test] - fn test_start_function_fails() { - let mut store = Store::default(); - let module = Module::new( - &store, - br#" - (module - (func $start_function - (i32.div_u - (i32.const 1) - (i32.const 0) - ) - drop - ) - (start $start_function) - ) - "#, - ) - .unwrap(); - - let import_object = imports! {}; - let result = Instance::new(&mut store, &module, &import_object); - let err = result.unwrap_err(); - assert!(format!("{:?}", err).contains("zero")) - } -} diff --git a/lib/api/tests/js_module.rs b/lib/api/tests/js_module.rs deleted file mode 100644 index 44b525f1ac4..00000000000 --- a/lib/api/tests/js_module.rs +++ /dev/null @@ -1,293 +0,0 @@ -#[cfg(feature = "js")] -mod js { - use js_sys::{Uint8Array, WebAssembly}; - use wasm_bindgen_test::*; - use wasmer::*; - - #[wasm_bindgen_test] - fn module_get_name() { - let store = Store::default(); - let wat = r#"(module)"#; - let module = Module::new(&store, wat).unwrap(); - assert_eq!(module.name(), None); - } - - #[wasm_bindgen_test] - fn module_set_name() { - let store = Store::default(); - let wat = r#"(module $name)"#; - let mut module = Module::new(&store, wat).unwrap(); - - #[cfg(feature = "wasm-types-polyfill")] - assert_eq!(module.name(), Some("name")); - - module.set_name("new_name"); - assert_eq!(module.name(), Some("new_name")); - } - - #[wasm_bindgen_test] - fn module_from_jsmodule() { - let wat = br#"(module $name)"#; - let binary = wat2wasm(wat).unwrap(); - let js_bytes = unsafe { Uint8Array::view(&binary) }; - let js_module = WebAssembly::Module::new(&js_bytes.into()).unwrap(); - let _module: Module = js_module.into(); - } - - #[wasm_bindgen_test] - fn imports() { - let store = Store::default(); - let wat = r#"(module - (import "host" "func" (func)) - (import "host" "memory" (memory 1)) - (import "host" "table" (table 1 anyfunc)) - (import "host" "global" (global i32)) -)"#; - let module = Module::new(&store, wat).unwrap(); - assert_eq!( - module.imports().collect::>(), - vec![ - ImportType::new( - "host", - "func", - ExternType::Function(FunctionType::new(vec![], vec![])) - ), - ImportType::new( - "host", - "memory", - ExternType::Memory(MemoryType::new(Pages(1), None, false)) - ), - ImportType::new( - "host", - "table", - ExternType::Table(TableType::new(Type::FuncRef, 1, None)) - ), - ImportType::new( - "host", - "global", - ExternType::Global(GlobalType::new(Type::I32, Mutability::Const)) - ) - ] - ); - - // Now we test the iterators - assert_eq!( - module.imports().functions().collect::>(), - vec![ImportType::new( - "host", - "func", - FunctionType::new(vec![], vec![]) - ),] - ); - assert_eq!( - module.imports().memories().collect::>(), - vec![ImportType::new( - "host", - "memory", - MemoryType::new(Pages(1), None, false) - ),] - ); - assert_eq!( - module.imports().tables().collect::>(), - vec![ImportType::new( - "host", - "table", - TableType::new(Type::FuncRef, 1, None) - ),] - ); - assert_eq!( - module.imports().globals().collect::>(), - vec![ImportType::new( - "host", - "global", - GlobalType::new(Type::I32, Mutability::Const) - ),] - ); - } - - #[wasm_bindgen_test] - fn exports() { - let store = Store::default(); - let wat = r#"(module - (func (export "func") nop) - (memory (export "memory") 2) - (table (export "table") 2 funcref) - (global (export "global") i32 (i32.const 0)) -)"#; - let mut module = Module::new(&store, wat).unwrap(); - module - .set_type_hints(ModuleTypeHints { - exports: vec![ - ExternType::Function(FunctionType::new(vec![], vec![])), - ExternType::Memory(MemoryType::new(Pages(2), None, false)), - ExternType::Table(TableType::new(Type::FuncRef, 2, None)), - ExternType::Global(GlobalType::new(Type::I32, Mutability::Const)), - ], - imports: vec![], - }) - .unwrap(); - assert_eq!( - module.exports().collect::>(), - vec![ - ExportType::new( - "func", - ExternType::Function(FunctionType::new(vec![], vec![])) - ), - ExportType::new( - "memory", - ExternType::Memory(MemoryType::new(Pages(2), None, false)) - ), - ExportType::new( - "table", - ExternType::Table(TableType::new(Type::FuncRef, 2, None)) - ), - ExportType::new( - "global", - ExternType::Global(GlobalType::new(Type::I32, Mutability::Const)) - ) - ] - ); - - // Now we test the iterators - assert_eq!( - module.exports().functions().collect::>(), - vec![ExportType::new("func", FunctionType::new(vec![], vec![])),] - ); - assert_eq!( - module.exports().memories().collect::>(), - vec![ExportType::new( - "memory", - MemoryType::new(Pages(2), None, false) - ),] - ); - assert_eq!( - module.exports().tables().collect::>(), - vec![ExportType::new( - "table", - TableType::new(Type::FuncRef, 2, None) - ),] - ); - assert_eq!( - module.exports().globals().collect::>(), - vec![ExportType::new( - "global", - GlobalType::new(Type::I32, Mutability::Const) - ),] - ); - } - - // Test commented because it doesn't work in old versions of Node - // which makes the CI to fail. - - // #[wasm_bindgen_test] - // fn calling_host_functions_with_negative_values_works() { - // let mut store = Store::default(); - // let wat = r#"(module - // (import "host" "host_func1" (func (param i64))) - // (import "host" "host_func2" (func (param i32))) - // (import "host" "host_func3" (func (param i64))) - // (import "host" "host_func4" (func (param i32))) - // (import "host" "host_func5" (func (param i32))) - // (import "host" "host_func6" (func (param i32))) - // (import "host" "host_func7" (func (param i32))) - // (import "host" "host_func8" (func (param i32))) - - // (func (export "call_host_func1") - // (call 0 (i64.const -1))) - // (func (export "call_host_func2") - // (call 1 (i32.const -1))) - // (func (export "call_host_func3") - // (call 2 (i64.const -1))) - // (func (export "call_host_func4") - // (call 3 (i32.const -1))) - // (func (export "call_host_func5") - // (call 4 (i32.const -1))) - // (func (export "call_host_func6") - // (call 5 (i32.const -1))) - // (func (export "call_host_func7") - // (call 6 (i32.const -1))) - // (func (export "call_host_func8") - // (call 7 (i32.const -1))) - // )"#; - // let module = Module::new(&store, wat).unwrap(); - // let imports = imports! { - // "host" => { - // "host_func1" => Function::new_typed(&store, |p: u64| { - // println!("host_func1: Found number {}", p); - // assert_eq!(p, u64::max_value()); - // }), - // "host_func2" => Function::new_typed(&store, |p: u32| { - // println!("host_func2: Found number {}", p); - // assert_eq!(p, u32::max_value()); - // }), - // "host_func3" => Function::new_typed(&store, |p: i64| { - // println!("host_func3: Found number {}", p); - // assert_eq!(p, -1); - // }), - // "host_func4" => Function::new_typed(&store, |p: i32| { - // println!("host_func4: Found number {}", p); - // assert_eq!(p, -1); - // }), - // "host_func5" => Function::new_typed(&store, |p: i16| { - // println!("host_func5: Found number {}", p); - // assert_eq!(p, -1); - // }), - // "host_func6" => Function::new_typed(&store, |p: u16| { - // println!("host_func6: Found number {}", p); - // assert_eq!(p, u16::max_value()); - // }), - // "host_func7" => Function::new_typed(&store, |p: i8| { - // println!("host_func7: Found number {}", p); - // assert_eq!(p, -1); - // }), - // "host_func8" => Function::new_typed(&store, |p: u8| { - // println!("host_func8: Found number {}", p); - // assert_eq!(p, u8::max_value()); - // }), - // } - // }; - // let instance = Instance::new(&module, &imports).unwrap(); - - // let f1: TypedFunction<(), ()> = instance - // .exports - // .get_typed_function("call_host_func1") - // .unwrap(); - // let f2: TypedFunction<(), ()> = instance - // .exports - // .get_typed_function("call_host_func2") - // .unwrap(); - // let f3: TypedFunction<(), ()> = instance - // .exports - // .get_typed_function("call_host_func3") - // .unwrap(); - // let f4: TypedFunction<(), ()> = instance - // .exports - // .get_typed_function("call_host_func4") - // .unwrap(); - // let f5: TypedFunction<(), ()> = instance - // .exports - // .get_typed_function("call_host_func5") - // .unwrap(); - // let f6: TypedFunction<(), ()> = instance - // .exports - // .get_typed_function("call_host_func6") - // .unwrap(); - // let f7: TypedFunction<(), ()> = instance - // .exports - // .get_typed_function("call_host_func7") - // .unwrap(); - // let f8: TypedFunction<(), ()> = instance - // .exports - // .get_typed_function("call_host_func8") - // .unwrap(); - - // f1.call().unwrap(); - // f2.call().unwrap(); - // f3.call().unwrap(); - // f4.call().unwrap(); - // f5.call().unwrap(); - // f6.call().unwrap(); - // f7.call().unwrap(); - // f8.call().unwrap(); - // } -} diff --git a/lib/api/tests/module.rs b/lib/api/tests/module.rs new file mode 100644 index 00000000000..13ccad34cbb --- /dev/null +++ b/lib/api/tests/module.rs @@ -0,0 +1,277 @@ +use macro_wasmer_universal_test::universal_test; +#[cfg(feature = "js")] +use wasm_bindgen_test::*; + +use wasmer::*; + +#[universal_test] +fn module_get_name() -> Result<(), String> { + let store = Store::default(); + let wat = r#"(module)"#; + let module = Module::new(&store, wat) + .map_err(|e| format!("{e:?}")) + .map_err(|e| format!("{e:?}"))?; + assert_eq!(module.name(), None); + + Ok(()) +} + +#[universal_test] +fn module_set_name() -> Result<(), String> { + let store = Store::default(); + let wat = r#"(module $name)"#; + let mut module = Module::new(&store, wat).map_err(|e| format!("{e:?}"))?; + assert_eq!(module.name(), Some("name")); + + module.set_name("new_name"); + assert_eq!(module.name(), Some("new_name")); + + Ok(()) +} + +#[universal_test] +fn imports() -> Result<(), String> { + let store = Store::default(); + let wat = r#"(module +(import "host" "func" (func)) +(import "host" "memory" (memory 1)) +(import "host" "table" (table 1 anyfunc)) +(import "host" "global" (global i32)) +)"#; + let module = Module::new(&store, wat).map_err(|e| format!("{e:?}"))?; + assert_eq!( + module.imports().collect::>(), + vec![ + ImportType::new( + "host", + "func", + ExternType::Function(FunctionType::new(vec![], vec![])) + ), + ImportType::new( + "host", + "memory", + ExternType::Memory(MemoryType::new(Pages(1), None, false)) + ), + ImportType::new( + "host", + "table", + ExternType::Table(TableType::new(Type::FuncRef, 1, None)) + ), + ImportType::new( + "host", + "global", + ExternType::Global(GlobalType::new(Type::I32, Mutability::Const)) + ) + ] + ); + + // Now we test the iterators + assert_eq!( + module.imports().functions().collect::>(), + vec![ImportType::new( + "host", + "func", + FunctionType::new(vec![], vec![]) + ),] + ); + assert_eq!( + module.imports().memories().collect::>(), + vec![ImportType::new( + "host", + "memory", + MemoryType::new(Pages(1), None, false) + ),] + ); + assert_eq!( + module.imports().tables().collect::>(), + vec![ImportType::new( + "host", + "table", + TableType::new(Type::FuncRef, 1, None) + ),] + ); + assert_eq!( + module.imports().globals().collect::>(), + vec![ImportType::new( + "host", + "global", + GlobalType::new(Type::I32, Mutability::Const) + ),] + ); + Ok(()) +} + +#[universal_test] +fn exports() -> Result<(), String> { + let store = Store::default(); + let wat = r#"(module +(func (export "func") nop) +(memory (export "memory") 1) +(table (export "table") 1 funcref) +(global (export "global") i32 (i32.const 0)) +)"#; + let module = Module::new(&store, wat).map_err(|e| format!("{e:?}"))?; + assert_eq!( + module.exports().collect::>(), + vec![ + ExportType::new( + "func", + ExternType::Function(FunctionType::new(vec![], vec![])) + ), + ExportType::new( + "memory", + ExternType::Memory(MemoryType::new(Pages(1), None, false)) + ), + ExportType::new( + "table", + ExternType::Table(TableType::new(Type::FuncRef, 1, None)) + ), + ExportType::new( + "global", + ExternType::Global(GlobalType::new(Type::I32, Mutability::Const)) + ) + ] + ); + + // Now we test the iterators + assert_eq!( + module.exports().functions().collect::>(), + vec![ExportType::new("func", FunctionType::new(vec![], vec![])),] + ); + assert_eq!( + module.exports().memories().collect::>(), + vec![ExportType::new( + "memory", + MemoryType::new(Pages(1), None, false) + ),] + ); + assert_eq!( + module.exports().tables().collect::>(), + vec![ExportType::new( + "table", + TableType::new(Type::FuncRef, 1, None) + ),] + ); + assert_eq!( + module.exports().globals().collect::>(), + vec![ExportType::new( + "global", + GlobalType::new(Type::I32, Mutability::Const) + ),] + ); + Ok(()) +} + +#[universal_test] +fn calling_host_functions_with_negative_values_works() -> Result<(), String> { + let mut store = Store::default(); + let wat = r#"(module +(import "host" "host_func1" (func (param i64))) +(import "host" "host_func2" (func (param i32))) +(import "host" "host_func3" (func (param i64))) +(import "host" "host_func4" (func (param i32))) +(import "host" "host_func5" (func (param i32))) +(import "host" "host_func6" (func (param i32))) +(import "host" "host_func7" (func (param i32))) +(import "host" "host_func8" (func (param i32))) + +(func (export "call_host_func1") + (call 0 (i64.const -1))) +(func (export "call_host_func2") + (call 1 (i32.const -1))) +(func (export "call_host_func3") + (call 2 (i64.const -1))) +(func (export "call_host_func4") + (call 3 (i32.const -1))) +(func (export "call_host_func5") + (call 4 (i32.const -1))) +(func (export "call_host_func6") + (call 5 (i32.const -1))) +(func (export "call_host_func7") + (call 6 (i32.const -1))) +(func (export "call_host_func8") + (call 7 (i32.const -1))) +)"#; + let module = Module::new(&store, wat).map_err(|e| format!("{e:?}"))?; + let imports = imports! { + "host" => { + "host_func1" => Function::new_typed(&mut store, |p: u64| { + println!("host_func1: Found number {}", p); + assert_eq!(p, u64::max_value()); + }), + "host_func2" => Function::new_typed(&mut store, |p: u32| { + println!("host_func2: Found number {}", p); + assert_eq!(p, u32::max_value()); + }), + "host_func3" => Function::new_typed(&mut store, |p: i64| { + println!("host_func3: Found number {}", p); + assert_eq!(p, -1); + }), + "host_func4" => Function::new_typed(&mut store, |p: i32| { + println!("host_func4: Found number {}", p); + assert_eq!(p, -1); + }), + "host_func5" => Function::new_typed(&mut store, |p: i16| { + println!("host_func5: Found number {}", p); + assert_eq!(p, -1); + }), + "host_func6" => Function::new_typed(&mut store, |p: u16| { + println!("host_func6: Found number {}", p); + assert_eq!(p, u16::max_value()); + }), + "host_func7" => Function::new_typed(&mut store, |p: i8| { + println!("host_func7: Found number {}", p); + assert_eq!(p, -1); + }), + "host_func8" => Function::new_typed(&mut store, |p: u8| { + println!("host_func8: Found number {}", p); + assert_eq!(p, u8::max_value()); + }), + } + }; + let instance = Instance::new(&mut store, &module, &imports).map_err(|e| format!("{e:?}"))?; + + let f1: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "call_host_func1") + .map_err(|e| format!("{e:?}"))?; + let f2: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "call_host_func2") + .map_err(|e| format!("{e:?}"))?; + let f3: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "call_host_func3") + .map_err(|e| format!("{e:?}"))?; + let f4: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "call_host_func4") + .map_err(|e| format!("{e:?}"))?; + let f5: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "call_host_func5") + .map_err(|e| format!("{e:?}"))?; + let f6: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "call_host_func6") + .map_err(|e| format!("{e:?}"))?; + let f7: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "call_host_func7") + .map_err(|e| format!("{e:?}"))?; + let f8: TypedFunction<(), ()> = instance + .exports + .get_typed_function(&mut store, "call_host_func8") + .map_err(|e| format!("{e:?}"))?; + + f1.call(&mut store).map_err(|e| format!("{e:?}"))?; + f2.call(&mut store).map_err(|e| format!("{e:?}"))?; + f3.call(&mut store).map_err(|e| format!("{e:?}"))?; + f4.call(&mut store).map_err(|e| format!("{e:?}"))?; + f5.call(&mut store).map_err(|e| format!("{e:?}"))?; + f6.call(&mut store).map_err(|e| format!("{e:?}"))?; + f7.call(&mut store).map_err(|e| format!("{e:?}"))?; + f8.call(&mut store).map_err(|e| format!("{e:?}"))?; + + Ok(()) +} diff --git a/lib/api/tests/sys_reference_types.rs b/lib/api/tests/reference_types.rs similarity index 77% rename from lib/api/tests/sys_reference_types.rs rename to lib/api/tests/reference_types.rs index b481a07d8f9..aecd46d48ec 100644 --- a/lib/api/tests/sys_reference_types.rs +++ b/lib/api/tests/reference_types.rs @@ -1,24 +1,27 @@ #[cfg(feature = "sys")] -mod sys { +pub mod reference_types { + use anyhow::Result; + use macro_wasmer_universal_test::universal_test; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; - use wasmer::FunctionEnv; + #[cfg(feature = "js")] + use wasm_bindgen_test::*; use wasmer::*; - #[test] + #[universal_test] fn func_ref_passed_and_returned() -> Result<()> { let mut store = Store::default(); let wat = r#"(module - (import "env" "func_ref_identity" (func (param funcref) (result funcref))) - (type $ret_i32_ty (func (result i32))) - (table $table (export "table") 2 2 funcref) - - (func (export "run") (param) (result funcref) - (call 0 (ref.null func))) - (func (export "call_set_value") (param $fr funcref) (result i32) - (table.set $table (i32.const 0) (local.get $fr)) - (call_indirect $table (type $ret_i32_ty) (i32.const 0))) +(import "env" "func_ref_identity" (func (param funcref) (result funcref))) +(type $ret_i32_ty (func (result i32))) +(table $table (export "table") 2 2 funcref) + +(func (export "run") (param) (result funcref) + (call 0 (ref.null func))) +(func (export "call_set_value") (param $fr funcref) (result i32) + (table.set $table (i32.const 0) (local.get $fr)) + (call_indirect $table (type $ret_i32_ty) (i32.const 0))) )"#; let module = Module::new(&store, wat)?; #[derive(Clone, Debug)] @@ -60,25 +63,25 @@ mod sys { Ok(()) } - #[test] + #[universal_test] fn func_ref_passed_and_called() -> Result<()> { let mut store = Store::default(); let wat = r#"(module - (func $func_ref_call (import "env" "func_ref_call") (param funcref) (result i32)) - (type $ret_i32_ty (func (result i32))) - (table $table (export "table") 2 2 funcref) - - (func $product (param $x i32) (param $y i32) (result i32) - (i32.mul (local.get $x) (local.get $y))) - ;; TODO: figure out exactly why this statement is needed - (elem declare func $product) - (func (export "call_set_value") (param $fr funcref) (result i32) - (table.set $table (i32.const 0) (local.get $fr)) - (call_indirect $table (type $ret_i32_ty) (i32.const 0))) - (func (export "call_func") (param $fr funcref) (result i32) - (call $func_ref_call (local.get $fr))) - (func (export "call_host_func_with_wasm_func") (result i32) - (call $func_ref_call (ref.func $product))) +(func $func_ref_call (import "env" "func_ref_call") (param funcref) (result i32)) +(type $ret_i32_ty (func (result i32))) +(table $table (export "table") 2 2 funcref) + +(func $product (param $x i32) (param $y i32) (result i32) + (i32.mul (local.get $x) (local.get $y))) +;; TODO: figure out exactly why this statement is needed +(elem declare func $product) +(func (export "call_set_value") (param $fr funcref) (result i32) + (table.set $table (i32.const 0) (local.get $fr)) + (call_indirect $table (type $ret_i32_ty) (i32.const 0))) +(func (export "call_func") (param $fr funcref) (result i32) + (call $func_ref_call (local.get $fr))) +(func (export "call_host_func_with_wasm_func") (result i32) + (call $func_ref_call (ref.func $product))) )"#; let module = Module::new(&store, wat)?; let env = FunctionEnv::new(&mut store, ()); @@ -130,25 +133,25 @@ mod sys { Ok(()) } - #[test] + #[macro_wasmer_universal_test::universal_test] fn extern_ref_passed_and_returned() -> Result<()> { use std::collections::HashMap; let mut store = Store::default(); let wat = r#"(module - (func $extern_ref_identity (import "env" "extern_ref_identity") (param externref) (result externref)) - (func $extern_ref_identity_native (import "env" "extern_ref_identity_native") (param externref) (result externref)) - (func $get_new_extern_ref (import "env" "get_new_extern_ref") (result externref)) - (func $get_new_extern_ref_native (import "env" "get_new_extern_ref_native") (result externref)) - - (func (export "run") (param) (result externref) - (call $extern_ref_identity (ref.null extern))) - (func (export "run_native") (param) (result externref) - (call $extern_ref_identity_native (ref.null extern))) - (func (export "get_hashmap") (param) (result externref) - (call $get_new_extern_ref)) - (func (export "get_hashmap_native") (param) (result externref) - (call $get_new_extern_ref_native)) - )"#; + (func $extern_ref_identity (import "env" "extern_ref_identity") (param externref) (result externref)) + (func $extern_ref_identity_native (import "env" "extern_ref_identity_native") (param externref) (result externref)) + (func $get_new_extern_ref (import "env" "get_new_extern_ref") (result externref)) + (func $get_new_extern_ref_native (import "env" "get_new_extern_ref_native") (result externref)) + + (func (export "run") (param) (result externref) + (call $extern_ref_identity (ref.null extern))) + (func (export "run_native") (param) (result externref) + (call $extern_ref_identity_native (ref.null extern))) + (func (export "get_hashmap") (param) (result externref) + (call $get_new_extern_ref)) + (func (export "get_hashmap_native") (param) (result externref) + (call $get_new_extern_ref_native)) +)"#; let module = Module::new(&store, wat)?; let env = FunctionEnv::new(&mut store, ()); let imports = imports! { @@ -221,13 +224,13 @@ mod sys { Ok(()) } - #[test] + #[universal_test] fn extern_ref_ref_counting_basic() -> Result<()> { let mut store = Store::default(); let wat = r#"(module - (func (export "drop") (param $er externref) (result) - (drop (local.get $er))) - )"#; + (func (export "drop") (param $er externref) (result) + (drop (local.get $er))) +)"#; let module = Module::new(&store, wat)?; let instance = Instance::new(&mut store, &module, &imports! {})?; let f: TypedFunction, ()> = @@ -242,16 +245,16 @@ mod sys { Ok(()) } - #[test] + #[universal_test] fn refs_in_globals() -> Result<()> { let mut store = Store::default(); let wat = r#"(module - (global $er_global (export "er_global") (mut externref) (ref.null extern)) - (global $fr_global (export "fr_global") (mut funcref) (ref.null func)) - (global $fr_immutable_global (export "fr_immutable_global") funcref (ref.func $hello)) - (func $hello (param) (result i32) - (i32.const 73)) - )"#; + (global $er_global (export "er_global") (mut externref) (ref.null extern)) + (global $fr_global (export "fr_global") (mut funcref) (ref.null func)) + (global $fr_immutable_global (export "fr_immutable_global") funcref (ref.func $hello)) + (func $hello (param) (result i32) + (i32.const 73)) +)"#; let module = Module::new(&store, wat)?; let instance = Instance::new(&mut store, &module, &imports! {})?; { @@ -307,20 +310,20 @@ mod sys { Ok(()) } - #[test] + #[universal_test] fn extern_ref_ref_counting_table_basic() -> Result<()> { let mut store = Store::default(); let wat = r#"(module - (global $global (export "global") (mut externref) (ref.null extern)) - (table $table (export "table") 4 4 externref) - (func $insert (param $er externref) (param $idx i32) - (table.set $table (local.get $idx) (local.get $er))) - (func $intermediate (param $er externref) (param $idx i32) - (call $insert (local.get $er) (local.get $idx))) - (func $insert_into_table (export "insert_into_table") (param $er externref) (param $idx i32) (result externref) - (call $intermediate (local.get $er) (local.get $idx)) - (local.get $er)) - )"#; + (global $global (export "global") (mut externref) (ref.null extern)) + (table $table (export "table") 4 4 externref) + (func $insert (param $er externref) (param $idx i32) + (table.set $table (local.get $idx) (local.get $er))) + (func $intermediate (param $er externref) (param $idx i32) + (call $insert (local.get $er) (local.get $idx))) + (func $insert_into_table (export "insert_into_table") (param $er externref) (param $idx i32) (result externref) + (call $intermediate (local.get $er) (local.get $idx)) + (local.get $er)) +)"#; let module = Module::new(&store, wat)?; let instance = Instance::new(&mut store, &module, &imports! {})?; @@ -349,15 +352,15 @@ mod sys { Ok(()) } - #[test] + #[universal_test] fn extern_ref_ref_counting_global_basic() -> Result<()> { let mut store = Store::default(); let wat = r#"(module - (global $global (export "global") (mut externref) (ref.null extern)) - (func $get_from_global (export "get_from_global") (result externref) - (drop (global.get $global)) - (global.get $global)) - )"#; + (global $global (export "global") (mut externref) (ref.null extern)) + (func $get_from_global (export "get_from_global") (result externref) + (drop (global.get $global)) + (global.get $global)) +)"#; let module = Module::new(&store, wat)?; let instance = Instance::new(&mut store, &module, &imports! {})?; @@ -378,14 +381,14 @@ mod sys { Ok(()) } - #[test] + #[universal_test] fn extern_ref_ref_counting_traps() -> Result<()> { let mut store = Store::default(); let wat = r#"(module - (func $pass_er (export "pass_extern_ref") (param externref) - (local.get 0) - (unreachable)) - )"#; + (func $pass_er (export "pass_extern_ref") (param externref) + (local.get 0) + (unreachable)) +)"#; let module = Module::new(&store, wat)?; let instance = Instance::new(&mut store, &module, &imports! {})?; @@ -401,19 +404,19 @@ mod sys { Ok(()) } - #[test] + #[universal_test] fn extern_ref_ref_counting_table_instructions() -> Result<()> { let mut store = Store::default(); let wat = r#"(module - (table $table1 (export "table1") 2 12 externref) - (table $table2 (export "table2") 6 12 externref) - (func $grow_table_with_ref (export "grow_table_with_ref") (param $er externref) (param $size i32) (result i32) - (table.grow $table1 (local.get $er) (local.get $size))) - (func $fill_table_with_ref (export "fill_table_with_ref") (param $er externref) (param $start i32) (param $end i32) - (table.fill $table1 (local.get $start) (local.get $er) (local.get $end))) - (func $copy_into_table2 (export "copy_into_table2") - (table.copy $table2 $table1 (i32.const 0) (i32.const 0) (i32.const 4))) - )"#; + (table $table1 (export "table1") 2 12 externref) + (table $table2 (export "table2") 6 12 externref) + (func $grow_table_with_ref (export "grow_table_with_ref") (param $er externref) (param $size i32) (result i32) + (table.grow $table1 (local.get $er) (local.get $size))) + (func $fill_table_with_ref (export "fill_table_with_ref") (param $er externref) (param $start i32) (param $end i32) + (table.fill $table1 (local.get $start) (local.get $er) (local.get $end))) + (func $copy_into_table2 (export "copy_into_table2") + (table.copy $table2 $table1 (i32.const 0) (i32.const 0) (i32.const 4))) +)"#; let module = Module::new(&store, wat)?; let instance = Instance::new(&mut store, &module, &imports! {})?; diff --git a/lib/api/tests/sys_externals.rs b/lib/api/tests/sys_externals.rs deleted file mode 100644 index 5899ee3ab26..00000000000 --- a/lib/api/tests/sys_externals.rs +++ /dev/null @@ -1,519 +0,0 @@ -#[cfg(feature = "sys")] -mod sys { - use anyhow::Result; - use wasmer::FunctionEnv; - use wasmer::*; - - #[test] - fn global_new() -> Result<()> { - let mut store = Store::default(); - let global = Global::new(&mut store, Value::I32(10)); - assert_eq!( - global.ty(&mut store), - GlobalType { - ty: Type::I32, - mutability: Mutability::Const - } - ); - - let global_mut = Global::new_mut(&mut store, Value::I32(10)); - assert_eq!( - global_mut.ty(&mut store), - GlobalType { - ty: Type::I32, - mutability: Mutability::Var - } - ); - - Ok(()) - } - - #[test] - fn global_get() -> Result<()> { - let mut store = Store::default(); - let global_i32 = Global::new(&mut store, Value::I32(10)); - assert_eq!(global_i32.get(&mut store), Value::I32(10)); - let global_i64 = Global::new(&mut store, Value::I64(20)); - assert_eq!(global_i64.get(&mut store), Value::I64(20)); - let global_f32 = Global::new(&mut store, Value::F32(10.0)); - assert_eq!(global_f32.get(&mut store), Value::F32(10.0)); - let global_f64 = Global::new(&mut store, Value::F64(20.0)); - assert_eq!(global_f64.get(&mut store), Value::F64(20.0)); - - Ok(()) - } - - #[test] - fn global_set() -> Result<()> { - let mut store = Store::default(); - let global_i32 = Global::new(&mut store, Value::I32(10)); - // Set on a constant should error - assert!(global_i32.set(&mut store, Value::I32(20)).is_err()); - - let global_i32_mut = Global::new_mut(&mut store, Value::I32(10)); - // Set on different type should error - assert!(global_i32_mut.set(&mut store, Value::I64(20)).is_err()); - - // Set on same type should succeed - global_i32_mut.set(&mut store, Value::I32(20))?; - assert_eq!(global_i32_mut.get(&mut store), Value::I32(20)); - - Ok(()) - } - - #[test] - fn table_new() -> Result<()> { - let mut store = Store::default(); - let table_type = TableType { - ty: Type::FuncRef, - minimum: 0, - maximum: None, - }; - let f = Function::new_typed(&mut store, || {}); - let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f)))?; - assert_eq!(table.ty(&mut store), table_type); - - // Anyrefs not yet supported - // let table_type = TableType { - // ty: Type::ExternRef, - // minimum: 0, - // maximum: None, - // }; - // let table = Table::new(&store, table_type, Value::ExternRef(ExternRef::Null))?; - // assert_eq!(*table.ty(), table_type); - - Ok(()) - } - - #[test] - #[ignore] - fn table_get() -> Result<()> { - let mut store = Store::default(); - let table_type = TableType { - ty: Type::FuncRef, - minimum: 0, - maximum: Some(1), - }; - let f = Function::new_typed(&mut store, |num: i32| num + 1); - let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f)))?; - assert_eq!(table.ty(&mut store), table_type); - let _elem = table.get(&mut store, 0).unwrap(); - // assert_eq!(elem.funcref().unwrap(), f); - Ok(()) - } - - #[test] - #[ignore] - fn table_set() -> Result<()> { - // Table set not yet tested - Ok(()) - } - - #[test] - fn table_grow() -> Result<()> { - let mut store = Store::default(); - let table_type = TableType { - ty: Type::FuncRef, - minimum: 0, - maximum: Some(10), - }; - let f = Function::new_typed(&mut store, |num: i32| num + 1); - let table = Table::new(&mut store, table_type, Value::FuncRef(Some(f.clone())))?; - // Growing to a bigger maximum should return None - let old_len = table.grow(&mut store, 12, Value::FuncRef(Some(f.clone()))); - assert!(old_len.is_err()); - - // Growing to a bigger maximum should return None - let old_len = table.grow(&mut store, 5, Value::FuncRef(Some(f)))?; - assert_eq!(old_len, 0); - - Ok(()) - } - - #[test] - #[ignore] - fn table_copy() -> Result<()> { - // TODO: table copy test not yet implemented - Ok(()) - } - - #[test] - fn memory_new() -> Result<()> { - let mut store = Store::default(); - let memory_type = MemoryType { - shared: false, - minimum: Pages(0), - maximum: Some(Pages(10)), - }; - let memory = Memory::new(&mut store, memory_type)?; - assert_eq!(memory.view(&mut store).size(), Pages(0)); - assert_eq!(memory.ty(&mut store), memory_type); - Ok(()) - } - - #[test] - fn memory_grow() -> Result<()> { - let mut store = Store::default(); - let desc = MemoryType::new(Pages(10), Some(Pages(16)), false); - let memory = Memory::new(&mut store, desc)?; - assert_eq!(memory.view(&mut store).size(), Pages(10)); - - let result = memory.grow(&mut store, Pages(2)).unwrap(); - assert_eq!(result, Pages(10)); - assert_eq!(memory.view(&mut store).size(), Pages(12)); - - let result = memory.grow(&mut store, Pages(10)); - assert_eq!( - result, - Err(MemoryError::CouldNotGrow { - current: 12.into(), - attempted_delta: 10.into() - }) - ); - - let bad_desc = MemoryType::new(Pages(15), Some(Pages(10)), false); - let bad_result = Memory::new(&mut store, bad_desc); - - assert!(matches!(bad_result, Err(MemoryError::InvalidMemory { .. }))); - - Ok(()) - } - - #[test] - fn function_new() -> Result<()> { - let mut store = Store::default(); - let function = Function::new_typed(&mut store, || {}); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![], vec![]) - ); - let function = Function::new_typed(&mut store, |_a: i32| {}); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![Type::I32], vec![]) - ); - let function = Function::new_typed(&mut store, |_a: i32, _b: i64, _c: f32, _d: f64| {}); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) - ); - let function = Function::new_typed(&mut store, || -> i32 { 1 }); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![], vec![Type::I32]) - ); - let function = - Function::new_typed(&mut store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) - ); - Ok(()) - } - - #[test] - fn function_new_env() -> Result<()> { - let mut store = Store::default(); - #[derive(Clone)] - struct MyEnv {} - - let my_env = MyEnv {}; - let env = FunctionEnv::new(&mut store, my_env); - let function = - Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut| {}); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![], vec![]) - ); - let function = Function::new_typed_with_env( - &mut store, - &env, - |_env: FunctionEnvMut, _a: i32| {}, - ); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![Type::I32], vec![]) - ); - let function = Function::new_typed_with_env( - &mut store, - &env, - |_env: FunctionEnvMut, _a: i32, _b: i64, _c: f32, _d: f64| {}, - ); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]) - ); - let function = - Function::new_typed_with_env(&mut store, &env, |_env: FunctionEnvMut| -> i32 { - 1 - }); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![], vec![Type::I32]) - ); - let function = Function::new_typed_with_env( - &mut store, - &env, - |_env: FunctionEnvMut| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) }, - ); - assert_eq!( - function.ty(&mut store).clone(), - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]) - ); - Ok(()) - } - - #[test] - fn function_new_dynamic() -> Result<()> { - let mut store = Store::default(); - - // Using &FunctionType signature - let function_type = FunctionType::new(vec![], vec![]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = FunctionType::new(vec![Type::I32], vec![]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = FunctionType::new(vec![], vec![Type::I32]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); - let function = Function::new( - &mut store, - &function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - - // Using array signature - let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); - let function = Function::new( - &mut store, - function_type, - |_values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).params(), [Type::V128]); - assert_eq!( - function.ty(&mut store).results(), - [Type::I32, Type::F32, Type::F64] - ); - - Ok(()) - } - - #[test] - fn function_new_dynamic_env() -> Result<()> { - let mut store = Store::default(); - #[derive(Clone)] - struct MyEnv {} - let my_env = MyEnv {}; - let env = FunctionEnv::new(&mut store, my_env); - - // Using &FunctionType signature - let function_type = FunctionType::new(vec![], vec![]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = FunctionType::new(vec![Type::I32], vec![]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = - FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = FunctionType::new(vec![], vec![Type::I32]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - let function_type = - FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]); - let function = Function::new_with_env( - &mut store, - &env, - &function_type, - |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).clone(), function_type); - - // Using array signature - let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]); - let function = Function::new_with_env( - &mut store, - &env, - function_type, - |_env: FunctionEnvMut, _values: &[Value]| unimplemented!(), - ); - assert_eq!(function.ty(&mut store).params(), [Type::V128]); - assert_eq!( - function.ty(&mut store).results(), - [Type::I32, Type::F32, Type::F64] - ); - - Ok(()) - } - - // #[test] - // fn native_function_works() -> Result<()> { - // let mut store = Store::default(); - // let function = Function::new_typed(&mut store, || {}); - // let typed_function: TypedFunction<(), ()> = function.typed(&mut store).unwrap(); - // let result = typed_function.call(&mut store); - // assert!(result.is_ok()); - - // let function = - // Function::new_typed(&mut store, |a: i32| -> i32 { a + 1 }); - // let typed_function: TypedFunction = function.typed(&mut store).unwrap(); - // assert_eq!(typed_function.call(&mut store, 3).unwrap(), 4); - - // fn rust_abi(a: i32, b: i64, c: f32, d: f64) -> u64 { - // (a as u64 * 1000) + (b as u64 * 100) + (c as u64 * 10) + (d as u64) - // } - // let function = Function::new_typed(&mut store, rust_abi); - // let typed_function: TypedFunction<(i32, i64, f32, f64), u64> = - // function.typed(&mut store).unwrap(); - // assert_eq!(typed_function.call(&mut store, 8, 4, 1.5, 5.).unwrap(), 8415); - - // let function = Function::new_typed(&mut store, || -> i32 { 1 }); - // let typed_function: TypedFunction<(), i32> = function.typed(&mut store).unwrap(); - // assert_eq!(typed_function.call(&mut store).unwrap(), 1); - - // let function = Function::new_typed(&mut store, |_a: i32| {}); - // let typed_function: TypedFunction = function.typed(&mut store).unwrap(); - // assert!(typed_function.call(&mut store, 4).is_ok()); - - // let function = - // Function::new_typed(&mut store, || -> (i32, i64, f32, f64) { - // (1, 2, 3.0, 4.0) - // }); - // let typed_function: TypedFunction<(), (i32, i64, f32, f64)> = - // function.typed(&mut store).unwrap(); - // assert_eq!(typed_function.call(&mut store).unwrap(), (1, 2, 3.0, 4.0)); - - // Ok(()) - // } - - // #[test] - // fn function_outlives_instance() -> Result<()> { - // let mut store = Store::default(); - // let wat = r#"(module - // (type $sum_t (func (param i32 i32) (result i32))) - // (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) - // local.get $x - // local.get $y - // i32.add) - // (export "sum" (func $sum_f))) - // "#; - - // let f = { - // let module = Module::new(&store, wat)?; - // let instance = Instance::new(&mut store, &module, &imports! {})?; - // let f: TypedFunction<(i32, i32), i32> = - // instance.exports.get_typed_function(&mut store, "sum")?; - - // assert_eq!(f.call(&mut store, 4, 5)?, 9); - // f - // }; - - // assert_eq!(f.call(&mut store, 4, 5)?, 9); - - // Ok(()) - // } - // /* - // #[test] - // fn weak_instance_ref_externs_after_instance() -> Result<()> { - // let mut store = Store::default(); - // let wat = r#"(module - // (memory (export "mem") 1) - // (type $sum_t (func (param i32 i32) (result i32))) - // (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) - // local.get $x - // local.get $y - // i32.add) - // (export "sum" (func $sum_f))) - // "#; - - // let f = { - // let module = Module::new(&store, wat)?; - // let instance = Instance::new(&mut store, &module, &imports! {})?; - // let f: TypedFunction<(i32, i32), i32> = - // instance.exports.get("sum")?; - - // assert_eq!(f.call(&mut store, 4, 5)?, 9); - // f - // }; - - // assert_eq!(f.call(&mut store, 4, 5)?, 9); - - // Ok(()) - // } - // */ - // #[test] - // fn manually_generate_wasmer_env() -> Result<()> { - // let mut store = Store::default(); - // #[derive(Clone)] - // struct MyEnv { - // val: u32, - // memory: Option, - // } - - // fn host_function(env: FunctionEnvMut, arg1: u32, arg2: u32) -> u32 { - // env.data().val + arg1 + arg2 - // } - - // let mut env = MyEnv { - // val: 5, - // memory: None, - // }; - // let env = FunctionEnv::new(&mut store, env); - - // let result = host_function(ctx.as_context_mut(), 7, 9); - // assert_eq!(result, 21); - - // let memory = Memory::new(&mut store, MemoryType::new(0, None, false))?; - // ctx.as_mut(&mut store).memory = Some(memory); - - // let result = host_function(ctx.as_context_mut(), 1, 2); - // assert_eq!(result, 8); - - // Ok(()) - // } -} diff --git a/lib/api/tests/sys_instance.rs b/lib/api/tests/sys_instance.rs deleted file mode 100644 index c1f51ed65b8..00000000000 --- a/lib/api/tests/sys_instance.rs +++ /dev/null @@ -1,76 +0,0 @@ -#[cfg(feature = "sys")] -mod sys { - use anyhow::Result; - use wasmer::FunctionEnv; - use wasmer::*; - - #[test] - fn exports_work_after_multiple_instances_have_been_freed() -> Result<()> { - let mut store = Store::default(); - let module = Module::new( - &store, - " - (module - (type $sum_t (func (param i32 i32) (result i32))) - (func $sum_f (type $sum_t) (param $x i32) (param $y i32) (result i32) - local.get $x - local.get $y - i32.add) - (export \"sum\" (func $sum_f))) -", - )?; - - let imports = Imports::new(); - let instance = Instance::new(&mut store, &module, &imports)?; - let instance2 = instance.clone(); - let instance3 = instance.clone(); - - // The function is cloned to “break” the connection with `instance`. - let sum = instance.exports.get_function("sum")?.clone(); - - drop(instance); - drop(instance2); - drop(instance3); - - // All instances have been dropped, but `sum` continues to work! - assert_eq!( - sum.call(&mut store, &[Value::I32(1), Value::I32(2)])? - .into_vec(), - vec![Value::I32(3)], - ); - - Ok(()) - } - - #[test] - fn unit_native_function_env() -> Result<()> { - let mut store = Store::default(); - - #[derive(Clone)] - struct Env { - multiplier: u32, - } - - fn imported_fn( - env: FunctionEnvMut, - args: &[Value], - ) -> Result, RuntimeError> { - let value = env.data().multiplier * args[0].unwrap_i32() as u32; - Ok(vec![Value::I32(value as _)]) - } - - // We create the environment - let env = Env { multiplier: 3 }; - // We move the environment to the store, so it can be used by the `Function` - let env = FunctionEnv::new(&mut store, env); - - let imported_signature = FunctionType::new(vec![Type::I32], vec![Type::I32]); - let imported = Function::new_with_env(&mut store, &env, imported_signature, imported_fn); - - let expected = vec![Value::I32(12)].into_boxed_slice(); - let result = imported.call(&mut store, &[Value::I32(4)])?; - assert_eq!(result, expected); - - Ok(()) - } -} diff --git a/lib/api/tests/sys_module.rs b/lib/api/tests/sys_module.rs deleted file mode 100644 index 633fa7a477e..00000000000 --- a/lib/api/tests/sys_module.rs +++ /dev/null @@ -1,267 +0,0 @@ -#[cfg(feature = "sys")] -mod sys { - use anyhow::Result; - use wasmer::*; - - #[test] - fn module_get_name() -> Result<()> { - let store = Store::default(); - let wat = r#"(module)"#; - let module = Module::new(&store, wat)?; - assert_eq!(module.name(), None); - - Ok(()) - } - - #[test] - fn module_set_name() -> Result<()> { - let store = Store::default(); - let wat = r#"(module $name)"#; - let mut module = Module::new(&store, wat)?; - assert_eq!(module.name(), Some("name")); - - module.set_name("new_name"); - assert_eq!(module.name(), Some("new_name")); - - Ok(()) - } - - #[test] - fn imports() -> Result<()> { - let store = Store::default(); - let wat = r#"(module - (import "host" "func" (func)) - (import "host" "memory" (memory 1)) - (import "host" "table" (table 1 anyfunc)) - (import "host" "global" (global i32)) -)"#; - let module = Module::new(&store, wat)?; - assert_eq!( - module.imports().collect::>(), - vec![ - ImportType::new( - "host", - "func", - ExternType::Function(FunctionType::new(vec![], vec![])) - ), - ImportType::new( - "host", - "memory", - ExternType::Memory(MemoryType::new(Pages(1), None, false)) - ), - ImportType::new( - "host", - "table", - ExternType::Table(TableType::new(Type::FuncRef, 1, None)) - ), - ImportType::new( - "host", - "global", - ExternType::Global(GlobalType::new(Type::I32, Mutability::Const)) - ) - ] - ); - - // Now we test the iterators - assert_eq!( - module.imports().functions().collect::>(), - vec![ImportType::new( - "host", - "func", - FunctionType::new(vec![], vec![]) - ),] - ); - assert_eq!( - module.imports().memories().collect::>(), - vec![ImportType::new( - "host", - "memory", - MemoryType::new(Pages(1), None, false) - ),] - ); - assert_eq!( - module.imports().tables().collect::>(), - vec![ImportType::new( - "host", - "table", - TableType::new(Type::FuncRef, 1, None) - ),] - ); - assert_eq!( - module.imports().globals().collect::>(), - vec![ImportType::new( - "host", - "global", - GlobalType::new(Type::I32, Mutability::Const) - ),] - ); - Ok(()) - } - - #[test] - fn exports() -> Result<()> { - let store = Store::default(); - let wat = r#"(module - (func (export "func") nop) - (memory (export "memory") 1) - (table (export "table") 1 funcref) - (global (export "global") i32 (i32.const 0)) -)"#; - let module = Module::new(&store, wat)?; - assert_eq!( - module.exports().collect::>(), - vec![ - ExportType::new( - "func", - ExternType::Function(FunctionType::new(vec![], vec![])) - ), - ExportType::new( - "memory", - ExternType::Memory(MemoryType::new(Pages(1), None, false)) - ), - ExportType::new( - "table", - ExternType::Table(TableType::new(Type::FuncRef, 1, None)) - ), - ExportType::new( - "global", - ExternType::Global(GlobalType::new(Type::I32, Mutability::Const)) - ) - ] - ); - - // Now we test the iterators - assert_eq!( - module.exports().functions().collect::>(), - vec![ExportType::new("func", FunctionType::new(vec![], vec![])),] - ); - assert_eq!( - module.exports().memories().collect::>(), - vec![ExportType::new( - "memory", - MemoryType::new(Pages(1), None, false) - ),] - ); - assert_eq!( - module.exports().tables().collect::>(), - vec![ExportType::new( - "table", - TableType::new(Type::FuncRef, 1, None) - ),] - ); - assert_eq!( - module.exports().globals().collect::>(), - vec![ExportType::new( - "global", - GlobalType::new(Type::I32, Mutability::Const) - ),] - ); - Ok(()) - } - - #[test] - fn calling_host_functions_with_negative_values_works() -> Result<()> { - let mut store = Store::default(); - let wat = r#"(module - (import "host" "host_func1" (func (param i64))) - (import "host" "host_func2" (func (param i32))) - (import "host" "host_func3" (func (param i64))) - (import "host" "host_func4" (func (param i32))) - (import "host" "host_func5" (func (param i32))) - (import "host" "host_func6" (func (param i32))) - (import "host" "host_func7" (func (param i32))) - (import "host" "host_func8" (func (param i32))) - - (func (export "call_host_func1") - (call 0 (i64.const -1))) - (func (export "call_host_func2") - (call 1 (i32.const -1))) - (func (export "call_host_func3") - (call 2 (i64.const -1))) - (func (export "call_host_func4") - (call 3 (i32.const -1))) - (func (export "call_host_func5") - (call 4 (i32.const -1))) - (func (export "call_host_func6") - (call 5 (i32.const -1))) - (func (export "call_host_func7") - (call 6 (i32.const -1))) - (func (export "call_host_func8") - (call 7 (i32.const -1))) -)"#; - let module = Module::new(&store, wat)?; - let imports = imports! { - "host" => { - "host_func1" => Function::new_typed(&mut store, |p: u64| { - println!("host_func1: Found number {}", p); - assert_eq!(p, u64::max_value()); - }), - "host_func2" => Function::new_typed(&mut store, |p: u32| { - println!("host_func2: Found number {}", p); - assert_eq!(p, u32::max_value()); - }), - "host_func3" => Function::new_typed(&mut store, |p: i64| { - println!("host_func3: Found number {}", p); - assert_eq!(p, -1); - }), - "host_func4" => Function::new_typed(&mut store, |p: i32| { - println!("host_func4: Found number {}", p); - assert_eq!(p, -1); - }), - "host_func5" => Function::new_typed(&mut store, |p: i16| { - println!("host_func5: Found number {}", p); - assert_eq!(p, -1); - }), - "host_func6" => Function::new_typed(&mut store, |p: u16| { - println!("host_func6: Found number {}", p); - assert_eq!(p, u16::max_value()); - }), - "host_func7" => Function::new_typed(&mut store, |p: i8| { - println!("host_func7: Found number {}", p); - assert_eq!(p, -1); - }), - "host_func8" => Function::new_typed(&mut store, |p: u8| { - println!("host_func8: Found number {}", p); - assert_eq!(p, u8::max_value()); - }), - } - }; - let instance = Instance::new(&mut store, &module, &imports)?; - - let f1: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "call_host_func1")?; - let f2: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "call_host_func2")?; - let f3: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "call_host_func3")?; - let f4: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "call_host_func4")?; - let f5: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "call_host_func5")?; - let f6: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "call_host_func6")?; - let f7: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "call_host_func7")?; - let f8: TypedFunction<(), ()> = instance - .exports - .get_typed_function(&mut store, "call_host_func8")?; - - f1.call(&mut store)?; - f2.call(&mut store)?; - f3.call(&mut store)?; - f4.call(&mut store)?; - f5.call(&mut store)?; - f6.call(&mut store)?; - f7.call(&mut store)?; - f8.call(&mut store)?; - - Ok(()) - } -}