mirror of
https://github.com/mii443/wasmer.git
synced 2025-12-12 05:18:43 +00:00
Added basic example of Wasmer-js
This commit is contained in:
334
lib/js-api/tests/export.rs
Normal file
334
lib/js-api/tests/export.rs
Normal file
@@ -0,0 +1,334 @@
|
||||
// use anyhow::Result;
|
||||
// use wasmer::*;
|
||||
// use wasmer_vm::WeakOrStrongInstanceRef;
|
||||
|
||||
// const MEM_WAT: &str = "
|
||||
// (module
|
||||
// (func $host_fn (import \"env\" \"host_fn\") (param) (result))
|
||||
// (func (export \"call_host_fn\") (param) (result)
|
||||
// (call $host_fn))
|
||||
|
||||
// (memory $mem 0)
|
||||
// (export \"memory\" (memory $mem))
|
||||
// )
|
||||
// ";
|
||||
|
||||
// const GLOBAL_WAT: &str = "
|
||||
// (module
|
||||
// (func $host_fn (import \"env\" \"host_fn\") (param) (result))
|
||||
// (func (export \"call_host_fn\") (param) (result)
|
||||
// (call $host_fn))
|
||||
|
||||
// (global $global i32 (i32.const 11))
|
||||
// (export \"global\" (global $global))
|
||||
// )
|
||||
// ";
|
||||
|
||||
// const TABLE_WAT: &str = "
|
||||
// (module
|
||||
// (func $host_fn (import \"env\" \"host_fn\") (param) (result))
|
||||
// (func (export \"call_host_fn\") (param) (result)
|
||||
// (call $host_fn))
|
||||
|
||||
// (table $table 4 4 funcref)
|
||||
// (export \"table\" (table $table))
|
||||
// )
|
||||
// ";
|
||||
|
||||
// const FUNCTION_WAT: &str = "
|
||||
// (module
|
||||
// (func $host_fn (import \"env\" \"host_fn\") (param) (result))
|
||||
// (func (export \"call_host_fn\") (param) (result)
|
||||
// (call $host_fn))
|
||||
// )
|
||||
// ";
|
||||
|
||||
// fn is_memory_instance_ref_strong(memory: &Memory) -> Option<bool> {
|
||||
// // This is safe because we're calling it from a test to test the internals
|
||||
// unsafe {
|
||||
// memory
|
||||
// .get_vm_memory()
|
||||
// .instance_ref
|
||||
// .as_ref()
|
||||
// .map(|v| matches!(v, WeakOrStrongInstanceRef::Strong(_)))
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn is_table_instance_ref_strong(table: &Table) -> Option<bool> {
|
||||
// // This is safe because we're calling it from a test to test the internals
|
||||
// unsafe {
|
||||
// table
|
||||
// .get_vm_table()
|
||||
// .instance_ref
|
||||
// .as_ref()
|
||||
// .map(|v| matches!(v, WeakOrStrongInstanceRef::Strong(_)))
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn is_global_instance_ref_strong(global: &Global) -> Option<bool> {
|
||||
// // This is safe because we're calling it from a test to test the internals
|
||||
// unsafe {
|
||||
// global
|
||||
// .get_vm_global()
|
||||
// .instance_ref
|
||||
// .as_ref()
|
||||
// .map(|v| matches!(v, WeakOrStrongInstanceRef::Strong(_)))
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn is_function_instance_ref_strong(f: &Function) -> Option<bool> {
|
||||
// // This is safe because we're calling it from a test to test the internals
|
||||
// unsafe {
|
||||
// f.get_vm_function()
|
||||
// .instance_ref
|
||||
// .as_ref()
|
||||
// .map(|v| matches!(v, WeakOrStrongInstanceRef::Strong(_)))
|
||||
// }
|
||||
// }
|
||||
|
||||
// fn is_native_function_instance_ref_strong<Args, Rets>(f: &NativeFunc<Args, Rets>) -> Option<bool>
|
||||
// where
|
||||
// Args: WasmTypeList,
|
||||
// Rets: WasmTypeList,
|
||||
// {
|
||||
// // This is safe because we're calling it from a test to test the internals
|
||||
// unsafe {
|
||||
// f.get_vm_function()
|
||||
// .instance_ref
|
||||
// .as_ref()
|
||||
// .map(|v| matches!(v, WeakOrStrongInstanceRef::Strong(_)))
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn strong_weak_behavior_works_memory() -> Result<()> {
|
||||
// #[derive(Clone, Debug, WasmerEnv, Default)]
|
||||
// struct MemEnv {
|
||||
// #[wasmer(export)]
|
||||
// memory: LazyInit<Memory>,
|
||||
// }
|
||||
|
||||
// let host_fn = |env: &MemEnv| {
|
||||
// let mem = env.memory_ref().unwrap();
|
||||
// assert_eq!(is_memory_instance_ref_strong(&mem), Some(false));
|
||||
// let mem_clone = mem.clone();
|
||||
// assert_eq!(is_memory_instance_ref_strong(&mem_clone), Some(true));
|
||||
// assert_eq!(is_memory_instance_ref_strong(&mem), Some(false));
|
||||
// };
|
||||
|
||||
// let f: NativeFunc<(), ()> = {
|
||||
// let store = Store::default();
|
||||
// let module = Module::new(&store, MEM_WAT)?;
|
||||
// let env = MemEnv::default();
|
||||
|
||||
// let instance = Instance::new(
|
||||
// &module,
|
||||
// &imports! {
|
||||
// "env" => {
|
||||
// "host_fn" => Function::new_native_with_env(&store, env, host_fn)
|
||||
// }
|
||||
// },
|
||||
// )?;
|
||||
|
||||
// {
|
||||
// let mem = instance.exports.get_memory("memory")?;
|
||||
// assert_eq!(is_memory_instance_ref_strong(&mem), Some(true));
|
||||
// }
|
||||
|
||||
// let f: NativeFunc<(), ()> = instance.exports.get_native_function("call_host_fn")?;
|
||||
// f.call()?;
|
||||
// f
|
||||
// };
|
||||
// f.call()?;
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn strong_weak_behavior_works_global() -> Result<()> {
|
||||
// #[derive(Clone, Debug, WasmerEnv, Default)]
|
||||
// struct GlobalEnv {
|
||||
// #[wasmer(export)]
|
||||
// global: LazyInit<Global>,
|
||||
// }
|
||||
|
||||
// let host_fn = |env: &GlobalEnv| {
|
||||
// let global = env.global_ref().unwrap();
|
||||
// assert_eq!(is_global_instance_ref_strong(&global), Some(false));
|
||||
// let global_clone = global.clone();
|
||||
// assert_eq!(is_global_instance_ref_strong(&global_clone), Some(true));
|
||||
// assert_eq!(is_global_instance_ref_strong(&global), Some(false));
|
||||
// };
|
||||
|
||||
// let f: NativeFunc<(), ()> = {
|
||||
// let store = Store::default();
|
||||
// let module = Module::new(&store, GLOBAL_WAT)?;
|
||||
// let env = GlobalEnv::default();
|
||||
|
||||
// let instance = Instance::new(
|
||||
// &module,
|
||||
// &imports! {
|
||||
// "env" => {
|
||||
// "host_fn" => Function::new_native_with_env(&store, env, host_fn)
|
||||
// }
|
||||
// },
|
||||
// )?;
|
||||
|
||||
// {
|
||||
// let global = instance.exports.get_global("global")?;
|
||||
// assert_eq!(is_global_instance_ref_strong(&global), Some(true));
|
||||
// }
|
||||
|
||||
// let f: NativeFunc<(), ()> = instance.exports.get_native_function("call_host_fn")?;
|
||||
// f.call()?;
|
||||
// f
|
||||
// };
|
||||
// f.call()?;
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn strong_weak_behavior_works_table() -> Result<()> {
|
||||
// #[derive(Clone, WasmerEnv, Default)]
|
||||
// struct TableEnv {
|
||||
// #[wasmer(export)]
|
||||
// table: LazyInit<Table>,
|
||||
// }
|
||||
|
||||
// let host_fn = |env: &TableEnv| {
|
||||
// let table = env.table_ref().unwrap();
|
||||
// assert_eq!(is_table_instance_ref_strong(&table), Some(false));
|
||||
// let table_clone = table.clone();
|
||||
// assert_eq!(is_table_instance_ref_strong(&table_clone), Some(true));
|
||||
// assert_eq!(is_table_instance_ref_strong(&table), Some(false));
|
||||
// };
|
||||
|
||||
// let f: NativeFunc<(), ()> = {
|
||||
// let store = Store::default();
|
||||
// let module = Module::new(&store, TABLE_WAT)?;
|
||||
// let env = TableEnv::default();
|
||||
|
||||
// let instance = Instance::new(
|
||||
// &module,
|
||||
// &imports! {
|
||||
// "env" => {
|
||||
// "host_fn" => Function::new_native_with_env(&store, env, host_fn)
|
||||
// }
|
||||
// },
|
||||
// )?;
|
||||
|
||||
// {
|
||||
// let table = instance.exports.get_table("table")?;
|
||||
// assert_eq!(is_table_instance_ref_strong(&table), Some(true));
|
||||
// }
|
||||
|
||||
// let f: NativeFunc<(), ()> = instance.exports.get_native_function("call_host_fn")?;
|
||||
// f.call()?;
|
||||
// f
|
||||
// };
|
||||
// f.call()?;
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn strong_weak_behavior_works_function() -> Result<()> {
|
||||
// #[derive(Clone, WasmerEnv, Default)]
|
||||
// struct FunctionEnv {
|
||||
// #[wasmer(export)]
|
||||
// call_host_fn: LazyInit<Function>,
|
||||
// }
|
||||
|
||||
// let host_fn = |env: &FunctionEnv| {
|
||||
// let function = env.call_host_fn_ref().unwrap();
|
||||
// assert_eq!(is_function_instance_ref_strong(&function), Some(false));
|
||||
// let function_clone = function.clone();
|
||||
// assert_eq!(is_function_instance_ref_strong(&function_clone), Some(true));
|
||||
// assert_eq!(is_function_instance_ref_strong(&function), Some(false));
|
||||
// };
|
||||
|
||||
// let f: NativeFunc<(), ()> = {
|
||||
// let store = Store::default();
|
||||
// let module = Module::new(&store, FUNCTION_WAT)?;
|
||||
// let env = FunctionEnv::default();
|
||||
|
||||
// let instance = Instance::new(
|
||||
// &module,
|
||||
// &imports! {
|
||||
// "env" => {
|
||||
// "host_fn" => Function::new_native_with_env(&store, env, host_fn)
|
||||
// }
|
||||
// },
|
||||
// )?;
|
||||
|
||||
// {
|
||||
// let function = instance.exports.get_function("call_host_fn")?;
|
||||
// assert_eq!(is_function_instance_ref_strong(&function), Some(true));
|
||||
// }
|
||||
|
||||
// let f: NativeFunc<(), ()> = instance.exports.get_native_function("call_host_fn")?;
|
||||
// f.call()?;
|
||||
// f
|
||||
// };
|
||||
// f.call()?;
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn strong_weak_behavior_works_native_function() -> Result<()> {
|
||||
// #[derive(Clone, WasmerEnv, Default)]
|
||||
// struct FunctionEnv {
|
||||
// #[wasmer(export)]
|
||||
// call_host_fn: LazyInit<NativeFunc<(), ()>>,
|
||||
// }
|
||||
|
||||
// let host_fn = |env: &FunctionEnv| {
|
||||
// let function = env.call_host_fn_ref().unwrap();
|
||||
// assert_eq!(
|
||||
// is_native_function_instance_ref_strong(&function),
|
||||
// Some(false)
|
||||
// );
|
||||
// let function_clone = function.clone();
|
||||
// assert_eq!(
|
||||
// is_native_function_instance_ref_strong(&function_clone),
|
||||
// Some(true)
|
||||
// );
|
||||
// assert_eq!(
|
||||
// is_native_function_instance_ref_strong(&function),
|
||||
// Some(false)
|
||||
// );
|
||||
// };
|
||||
|
||||
// let f: NativeFunc<(), ()> = {
|
||||
// let store = Store::default();
|
||||
// let module = Module::new(&store, FUNCTION_WAT)?;
|
||||
// let env = FunctionEnv::default();
|
||||
|
||||
// let instance = Instance::new(
|
||||
// &module,
|
||||
// &imports! {
|
||||
// "env" => {
|
||||
// "host_fn" => Function::new_native_with_env(&store, env, host_fn)
|
||||
// }
|
||||
// },
|
||||
// )?;
|
||||
|
||||
// {
|
||||
// let function: NativeFunc<(), ()> =
|
||||
// instance.exports.get_native_function("call_host_fn")?;
|
||||
// assert_eq!(
|
||||
// is_native_function_instance_ref_strong(&function),
|
||||
// Some(true)
|
||||
// );
|
||||
// }
|
||||
|
||||
// let f: NativeFunc<(), ()> = instance.exports.get_native_function("call_host_fn")?;
|
||||
// f.call()?;
|
||||
// f
|
||||
// };
|
||||
// f.call()?;
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
458
lib/js-api/tests/externals.rs
Normal file
458
lib/js-api/tests/externals.rs
Normal file
@@ -0,0 +1,458 @@
|
||||
use wasm_bindgen_test::*;
|
||||
// use anyhow::Result;
|
||||
use wasmer_js::*;
|
||||
|
||||
// #[test]
|
||||
// fn global_new() -> Result<()> {
|
||||
// let store = Store::default();
|
||||
// let global = Global::new(&store, Value::I32(10));
|
||||
// assert_eq!(
|
||||
// *global.ty(),
|
||||
// GlobalType {
|
||||
// ty: Type::I32,
|
||||
// mutability: Mutability::Const
|
||||
// }
|
||||
// );
|
||||
|
||||
// let global_mut = Global::new_mut(&store, Value::I32(10));
|
||||
// assert_eq!(
|
||||
// *global_mut.ty(),
|
||||
// GlobalType {
|
||||
// ty: Type::I32,
|
||||
// mutability: Mutability::Var
|
||||
// }
|
||||
// );
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn global_get() -> Result<()> {
|
||||
// let store = Store::default();
|
||||
// let global_i32 = Global::new(&store, Value::I32(10));
|
||||
// assert_eq!(global_i32.get(), Value::I32(10));
|
||||
// let global_i64 = Global::new(&store, Value::I64(20));
|
||||
// assert_eq!(global_i64.get(), Value::I64(20));
|
||||
// let global_f32 = Global::new(&store, Value::F32(10.0));
|
||||
// assert_eq!(global_f32.get(), Value::F32(10.0));
|
||||
// let global_f64 = Global::new(&store, Value::F64(20.0));
|
||||
// assert_eq!(global_f64.get(), Value::F64(20.0));
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn global_set() -> Result<()> {
|
||||
// let store = Store::default();
|
||||
// let global_i32 = Global::new(&store, Value::I32(10));
|
||||
// // Set on a constant should error
|
||||
// assert!(global_i32.set(Value::I32(20)).is_err());
|
||||
|
||||
// let global_i32_mut = Global::new_mut(&store, Value::I32(10));
|
||||
// // Set on different type should error
|
||||
// assert!(global_i32_mut.set(Value::I64(20)).is_err());
|
||||
|
||||
// // Set on same type should succeed
|
||||
// global_i32_mut.set(Value::I32(20))?;
|
||||
// assert_eq!(global_i32_mut.get(), Value::I32(20));
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn table_new() -> Result<()> {
|
||||
// let store = Store::default();
|
||||
// let table_type = TableType {
|
||||
// ty: Type::FuncRef,
|
||||
// minimum: 0,
|
||||
// maximum: None,
|
||||
// };
|
||||
// let f = Function::new_native(&store, || {});
|
||||
// let table = Table::new(&store, table_type, Value::FuncRef(Some(f)))?;
|
||||
// assert_eq!(*table.ty(), 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 store = Store::default();
|
||||
// let table_type = TableType {
|
||||
// ty: Type::FuncRef,
|
||||
// minimum: 0,
|
||||
// maximum: Some(1),
|
||||
// };
|
||||
// let f = Function::new_native(&store, |num: i32| num + 1);
|
||||
// let table = Table::new(&store, table_type, Value::FuncRef(Some(f.clone())))?;
|
||||
// assert_eq!(*table.ty(), 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 store = Store::default();
|
||||
// let table_type = TableType {
|
||||
// ty: Type::FuncRef,
|
||||
// minimum: 0,
|
||||
// maximum: Some(10),
|
||||
// };
|
||||
// let f = Function::new_native(&store, |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 store = Store::default();
|
||||
let memory_type = MemoryType {
|
||||
shared: false,
|
||||
minimum: Pages(0),
|
||||
maximum: Some(Pages(10)),
|
||||
};
|
||||
let memory = Memory::new(&store, memory_type).unwrap();
|
||||
assert_eq!(memory.size(), Pages(0));
|
||||
assert_eq!(memory.ty(), memory_type);
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn memory_grow() {
|
||||
let store = Store::default();
|
||||
|
||||
let desc = MemoryType::new(Pages(10), Some(Pages(16)), false);
|
||||
let memory = Memory::new(&store, desc).unwrap();
|
||||
assert_eq!(memory.size(), Pages(10));
|
||||
|
||||
let result = memory.grow(Pages(2)).unwrap();
|
||||
assert_eq!(result, Pages(10));
|
||||
assert_eq!(memory.size(), Pages(12));
|
||||
|
||||
// let result = memory.grow(Pages(10));
|
||||
// assert!(result.is_err());
|
||||
// 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(&store, bad_desc);
|
||||
|
||||
// // assert!(matches!(bad_result, Err(MemoryError::InvalidMemory { .. })));
|
||||
// assert!(bad_result.is_err());
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn function_new() -> Result<()> {
|
||||
// let store = Store::default();
|
||||
// let function = Function::new_native(&store, || {});
|
||||
// assert_eq!(function.ty().clone(), FunctionType::new(vec![], vec![]));
|
||||
// let function = Function::new_native(&store, |_a: i32| {});
|
||||
// assert_eq!(
|
||||
// function.ty().clone(),
|
||||
// FunctionType::new(vec![Type::I32], vec![])
|
||||
// );
|
||||
// let function = Function::new_native(&store, |_a: i32, _b: i64, _c: f32, _d: f64| {});
|
||||
// assert_eq!(
|
||||
// function.ty().clone(),
|
||||
// FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![])
|
||||
// );
|
||||
// let function = Function::new_native(&store, || -> i32 { 1 });
|
||||
// assert_eq!(
|
||||
// function.ty().clone(),
|
||||
// FunctionType::new(vec![], vec![Type::I32])
|
||||
// );
|
||||
// let function = Function::new_native(&store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) });
|
||||
// assert_eq!(
|
||||
// function.ty().clone(),
|
||||
// FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64])
|
||||
// );
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn function_new_env() -> Result<()> {
|
||||
// let store = Store::default();
|
||||
// #[derive(Clone, WasmerEnv)]
|
||||
// struct MyEnv {}
|
||||
|
||||
// let my_env = MyEnv {};
|
||||
// let function = Function::new_native_with_env(&store, my_env.clone(), |_env: &MyEnv| {});
|
||||
// assert_eq!(function.ty().clone(), FunctionType::new(vec![], vec![]));
|
||||
// let function =
|
||||
// Function::new_native_with_env(&store, my_env.clone(), |_env: &MyEnv, _a: i32| {});
|
||||
// assert_eq!(
|
||||
// function.ty().clone(),
|
||||
// FunctionType::new(vec![Type::I32], vec![])
|
||||
// );
|
||||
// let function = Function::new_native_with_env(
|
||||
// &store,
|
||||
// my_env.clone(),
|
||||
// |_env: &MyEnv, _a: i32, _b: i64, _c: f32, _d: f64| {},
|
||||
// );
|
||||
// assert_eq!(
|
||||
// function.ty().clone(),
|
||||
// FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![])
|
||||
// );
|
||||
// let function =
|
||||
// Function::new_native_with_env(&store, my_env.clone(), |_env: &MyEnv| -> i32 { 1 });
|
||||
// assert_eq!(
|
||||
// function.ty().clone(),
|
||||
// FunctionType::new(vec![], vec![Type::I32])
|
||||
// );
|
||||
// let function = Function::new_native_with_env(
|
||||
// &store,
|
||||
// my_env.clone(),
|
||||
// |_env: &MyEnv| -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) },
|
||||
// );
|
||||
// assert_eq!(
|
||||
// function.ty().clone(),
|
||||
// FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64])
|
||||
// );
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn function_new_dynamic() -> Result<()> {
|
||||
// let store = Store::default();
|
||||
|
||||
// // Using &FunctionType signature
|
||||
// let function_type = FunctionType::new(vec![], vec![]);
|
||||
// let function = Function::new(&store, &function_type, |_values: &[Value]| unimplemented!());
|
||||
// assert_eq!(function.ty().clone(), function_type);
|
||||
// let function_type = FunctionType::new(vec![Type::I32], vec![]);
|
||||
// let function = Function::new(&store, &function_type, |_values: &[Value]| unimplemented!());
|
||||
// assert_eq!(function.ty().clone(), function_type);
|
||||
// let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]);
|
||||
// let function = Function::new(&store, &function_type, |_values: &[Value]| unimplemented!());
|
||||
// assert_eq!(function.ty().clone(), function_type);
|
||||
// let function_type = FunctionType::new(vec![], vec![Type::I32]);
|
||||
// let function = Function::new(&store, &function_type, |_values: &[Value]| unimplemented!());
|
||||
// assert_eq!(function.ty().clone(), function_type);
|
||||
// let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]);
|
||||
// let function = Function::new(&store, &function_type, |_values: &[Value]| unimplemented!());
|
||||
// assert_eq!(function.ty().clone(), function_type);
|
||||
|
||||
// // Using array signature
|
||||
// let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]);
|
||||
// let function = Function::new(&store, function_type, |_values: &[Value]| unimplemented!());
|
||||
// assert_eq!(function.ty().params(), [Type::V128]);
|
||||
// assert_eq!(function.ty().results(), [Type::I32, Type::F32, Type::F64]);
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn function_new_dynamic_env() -> Result<()> {
|
||||
// let store = Store::default();
|
||||
// #[derive(Clone, WasmerEnv)]
|
||||
// struct MyEnv {}
|
||||
// let my_env = MyEnv {};
|
||||
|
||||
// // Using &FunctionType signature
|
||||
// let function_type = FunctionType::new(vec![], vec![]);
|
||||
// let function = Function::new_with_env(
|
||||
// &store,
|
||||
// &function_type,
|
||||
// my_env.clone(),
|
||||
// |_env: &MyEnv, _values: &[Value]| unimplemented!(),
|
||||
// );
|
||||
// assert_eq!(function.ty().clone(), function_type);
|
||||
// let function_type = FunctionType::new(vec![Type::I32], vec![]);
|
||||
// let function = Function::new_with_env(
|
||||
// &store,
|
||||
// &function_type,
|
||||
// my_env.clone(),
|
||||
// |_env: &MyEnv, _values: &[Value]| unimplemented!(),
|
||||
// );
|
||||
// assert_eq!(function.ty().clone(), function_type);
|
||||
// let function_type = FunctionType::new(vec![Type::I32, Type::I64, Type::F32, Type::F64], vec![]);
|
||||
// let function = Function::new_with_env(
|
||||
// &store,
|
||||
// &function_type,
|
||||
// my_env.clone(),
|
||||
// |_env: &MyEnv, _values: &[Value]| unimplemented!(),
|
||||
// );
|
||||
// assert_eq!(function.ty().clone(), function_type);
|
||||
// let function_type = FunctionType::new(vec![], vec![Type::I32]);
|
||||
// let function = Function::new_with_env(
|
||||
// &store,
|
||||
// &function_type,
|
||||
// my_env.clone(),
|
||||
// |_env: &MyEnv, _values: &[Value]| unimplemented!(),
|
||||
// );
|
||||
// assert_eq!(function.ty().clone(), function_type);
|
||||
// let function_type = FunctionType::new(vec![], vec![Type::I32, Type::I64, Type::F32, Type::F64]);
|
||||
// let function = Function::new_with_env(
|
||||
// &store,
|
||||
// &function_type,
|
||||
// my_env.clone(),
|
||||
// |_env: &MyEnv, _values: &[Value]| unimplemented!(),
|
||||
// );
|
||||
// assert_eq!(function.ty().clone(), function_type);
|
||||
|
||||
// // Using array signature
|
||||
// let function_type = ([Type::V128], [Type::I32, Type::F32, Type::F64]);
|
||||
// let function = Function::new_with_env(
|
||||
// &store,
|
||||
// function_type,
|
||||
// my_env.clone(),
|
||||
// |_env: &MyEnv, _values: &[Value]| unimplemented!(),
|
||||
// );
|
||||
// assert_eq!(function.ty().params(), [Type::V128]);
|
||||
// assert_eq!(function.ty().results(), [Type::I32, Type::F32, Type::F64]);
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn native_function_works() -> Result<()> {
|
||||
// let store = Store::default();
|
||||
// let function = Function::new_native(&store, || {});
|
||||
// let native_function: NativeFunc<(), ()> = function.native().unwrap();
|
||||
// let result = native_function.call();
|
||||
// assert!(result.is_ok());
|
||||
|
||||
// let function = Function::new_native(&store, |a: i32| -> i32 { a + 1 });
|
||||
// let native_function: NativeFunc<i32, i32> = function.native().unwrap();
|
||||
// assert_eq!(native_function.call(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_native(&store, rust_abi);
|
||||
// let native_function: NativeFunc<(i32, i64, f32, f64), u64> = function.native().unwrap();
|
||||
// assert_eq!(native_function.call(8, 4, 1.5, 5.).unwrap(), 8415);
|
||||
|
||||
// let function = Function::new_native(&store, || -> i32 { 1 });
|
||||
// let native_function: NativeFunc<(), i32> = function.native().unwrap();
|
||||
// assert_eq!(native_function.call().unwrap(), 1);
|
||||
|
||||
// let function = Function::new_native(&store, |_a: i32| {});
|
||||
// let native_function: NativeFunc<i32, ()> = function.native().unwrap();
|
||||
// assert!(native_function.call(4).is_ok());
|
||||
|
||||
// let function = Function::new_native(&store, || -> (i32, i64, f32, f64) { (1, 2, 3.0, 4.0) });
|
||||
// let native_function: NativeFunc<(), (i32, i64, f32, f64)> = function.native().unwrap();
|
||||
// assert_eq!(native_function.call().unwrap(), (1, 2, 3.0, 4.0));
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn function_outlives_instance() -> Result<()> {
|
||||
// let 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(&module, &imports! {})?;
|
||||
// let f: NativeFunc<(i32, i32), i32> = instance.exports.get_native_function("sum")?;
|
||||
|
||||
// assert_eq!(f.call(4, 5)?, 9);
|
||||
// f
|
||||
// };
|
||||
|
||||
// assert_eq!(f.call(4, 5)?, 9);
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn weak_instance_ref_externs_after_instance() -> Result<()> {
|
||||
// let 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(&module, &imports! {})?;
|
||||
// let f: NativeFunc<(i32, i32), i32> = instance.exports.get_with_generics_weak("sum")?;
|
||||
|
||||
// assert_eq!(f.call(4, 5)?, 9);
|
||||
// f
|
||||
// };
|
||||
|
||||
// assert_eq!(f.call(4, 5)?, 9);
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn manually_generate_wasmer_env() -> Result<()> {
|
||||
// let store = Store::default();
|
||||
// #[derive(WasmerEnv, Clone)]
|
||||
// struct MyEnv {
|
||||
// val: u32,
|
||||
// memory: LazyInit<Memory>,
|
||||
// }
|
||||
|
||||
// fn host_function(env: &mut MyEnv, arg1: u32, arg2: u32) -> u32 {
|
||||
// env.val + arg1 + arg2
|
||||
// }
|
||||
|
||||
// let mut env = MyEnv {
|
||||
// val: 5,
|
||||
// memory: LazyInit::new(),
|
||||
// };
|
||||
|
||||
// let result = host_function(&mut env, 7, 9);
|
||||
// assert_eq!(result, 21);
|
||||
|
||||
// let memory = Memory::new(&store, MemoryType::new(0, None, false))?;
|
||||
// env.memory.initialize(memory);
|
||||
|
||||
// let result = host_function(&mut env, 1, 2);
|
||||
// assert_eq!(result, 8);
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
87
lib/js-api/tests/instance.rs
Normal file
87
lib/js-api/tests/instance.rs
Normal file
@@ -0,0 +1,87 @@
|
||||
use anyhow::Result;
|
||||
use wasm_bindgen_test::*;
|
||||
use wasmer_js::*;
|
||||
|
||||
// #[test]
|
||||
// fn exports_work_after_multiple_instances_have_been_freed() -> Result<()> {
|
||||
// let 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 import_object = ImportObject::new();
|
||||
// let instance = Instance::new(&module, &import_object)?;
|
||||
// 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(&[Value::I32(1), Value::I32(2)])?.into_vec(),
|
||||
// vec![Value::I32(3)],
|
||||
// );
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn test_exported_memory() {
|
||||
// Let's declare the Wasm module with the text representation.
|
||||
let wasm_bytes = wat2wasm(
|
||||
br#"
|
||||
(module
|
||||
(memory (export "mem") 1)
|
||||
)
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// Create a Store.
|
||||
// Note that we don't need to specify the engine/compiler if we want to use
|
||||
// the default provided by Wasmer.
|
||||
// You can use `Store::default()` for that.
|
||||
let store = Store::default();
|
||||
|
||||
println!("Compiling module...");
|
||||
// Let's compile the Wasm module.
|
||||
let module = Module::new(&store, wasm_bytes).unwrap();
|
||||
|
||||
// Create an empty import object.
|
||||
let import_object = imports! {};
|
||||
|
||||
println!("Instantiating module...");
|
||||
// Let's instantiate the Wasm module.
|
||||
let instance = Instance::new(&module, &import_object).unwrap();
|
||||
|
||||
// let load = instance
|
||||
// .exports
|
||||
// .get_native_function::<(), (WasmPtr<u8, Array>, i32)>("load")?;
|
||||
|
||||
// Here we go.
|
||||
//
|
||||
// The Wasm module exports a memory under "mem". Let's get it.
|
||||
let memory = instance.exports.get_memory("mem").unwrap();
|
||||
|
||||
// Now that we have the exported memory, let's get some
|
||||
// information about it.
|
||||
//
|
||||
// The first thing we might be intersted in is the size of the memory.
|
||||
// Let's get it!
|
||||
println!("Memory size (pages) {:?}", memory.size());
|
||||
println!("Memory size (bytes) {:?}", memory.data_size());
|
||||
}
|
||||
248
lib/js-api/tests/module.rs
Normal file
248
lib/js-api/tests/module.rs
Normal file
@@ -0,0 +1,248 @@
|
||||
use anyhow::Result;
|
||||
use wasm_bindgen_test::*;
|
||||
use wasmer_js::*;
|
||||
|
||||
#[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();
|
||||
|
||||
// We explicitly don't test the wasm name from the name section
|
||||
// because it adds unnecessary overhead for really little gain.
|
||||
// assert_eq!(module.name(), Some("name"));
|
||||
|
||||
module.set_name("new_name");
|
||||
assert_eq!(module.name(), Some("new_name"));
|
||||
}
|
||||
|
||||
#[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<_>>(),
|
||||
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<_>>(),
|
||||
vec![ImportType::new(
|
||||
"host",
|
||||
"func",
|
||||
FunctionType::new(vec![], vec![])
|
||||
),]
|
||||
);
|
||||
assert_eq!(
|
||||
module.imports().memories().collect::<Vec<_>>(),
|
||||
vec![ImportType::new(
|
||||
"host",
|
||||
"memory",
|
||||
MemoryType::new(Pages(1), None, false)
|
||||
),]
|
||||
);
|
||||
assert_eq!(
|
||||
module.imports().tables().collect::<Vec<_>>(),
|
||||
vec![ImportType::new(
|
||||
"host",
|
||||
"table",
|
||||
TableType::new(Type::FuncRef, 1, None)
|
||||
),]
|
||||
);
|
||||
assert_eq!(
|
||||
module.imports().globals().collect::<Vec<_>>(),
|
||||
vec![ImportType::new(
|
||||
"host",
|
||||
"global",
|
||||
GlobalType::new(Type::I32, Mutability::Const)
|
||||
),]
|
||||
);
|
||||
// Ok(())
|
||||
}
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn exports() {
|
||||
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).unwrap();
|
||||
assert_eq!(
|
||||
module.exports().collect::<Vec<_>>(),
|
||||
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<_>>(),
|
||||
vec![ExportType::new("func", FunctionType::new(vec![], vec![])),]
|
||||
);
|
||||
assert_eq!(
|
||||
module.exports().memories().collect::<Vec<_>>(),
|
||||
vec![ExportType::new(
|
||||
"memory",
|
||||
MemoryType::new(Pages(1), None, false)
|
||||
),]
|
||||
);
|
||||
assert_eq!(
|
||||
module.exports().tables().collect::<Vec<_>>(),
|
||||
vec![ExportType::new(
|
||||
"table",
|
||||
TableType::new(Type::FuncRef, 1, None)
|
||||
),]
|
||||
);
|
||||
assert_eq!(
|
||||
module.exports().globals().collect::<Vec<_>>(),
|
||||
vec![ExportType::new(
|
||||
"global",
|
||||
GlobalType::new(Type::I32, Mutability::Const)
|
||||
),]
|
||||
);
|
||||
// Ok(())
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn calling_host_functions_with_negative_values_works() -> Result<()> {
|
||||
// let 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_native(&store, |p: u64| {
|
||||
// println!("host_func1: Found number {}", p);
|
||||
// assert_eq!(p, u64::max_value());
|
||||
// }),
|
||||
// "host_func2" => Function::new_native(&store, |p: u32| {
|
||||
// println!("host_func2: Found number {}", p);
|
||||
// assert_eq!(p, u32::max_value());
|
||||
// }),
|
||||
// "host_func3" => Function::new_native(&store, |p: i64| {
|
||||
// println!("host_func3: Found number {}", p);
|
||||
// assert_eq!(p, -1);
|
||||
// }),
|
||||
// "host_func4" => Function::new_native(&store, |p: i32| {
|
||||
// println!("host_func4: Found number {}", p);
|
||||
// assert_eq!(p, -1);
|
||||
// }),
|
||||
// "host_func5" => Function::new_native(&store, |p: i16| {
|
||||
// println!("host_func5: Found number {}", p);
|
||||
// assert_eq!(p, -1);
|
||||
// }),
|
||||
// "host_func6" => Function::new_native(&store, |p: u16| {
|
||||
// println!("host_func6: Found number {}", p);
|
||||
// assert_eq!(p, u16::max_value());
|
||||
// }),
|
||||
// "host_func7" => Function::new_native(&store, |p: i8| {
|
||||
// println!("host_func7: Found number {}", p);
|
||||
// assert_eq!(p, -1);
|
||||
// }),
|
||||
// "host_func8" => Function::new_native(&store, |p: u8| {
|
||||
// println!("host_func8: Found number {}", p);
|
||||
// assert_eq!(p, u8::max_value());
|
||||
// }),
|
||||
// }
|
||||
// };
|
||||
// let instance = Instance::new(&module, &imports)?;
|
||||
|
||||
// let f1: NativeFunc<(), ()> = instance.exports.get_native_function("call_host_func1")?;
|
||||
// let f2: NativeFunc<(), ()> = instance.exports.get_native_function("call_host_func2")?;
|
||||
// let f3: NativeFunc<(), ()> = instance.exports.get_native_function("call_host_func3")?;
|
||||
// let f4: NativeFunc<(), ()> = instance.exports.get_native_function("call_host_func4")?;
|
||||
// let f5: NativeFunc<(), ()> = instance.exports.get_native_function("call_host_func5")?;
|
||||
// let f6: NativeFunc<(), ()> = instance.exports.get_native_function("call_host_func6")?;
|
||||
// let f7: NativeFunc<(), ()> = instance.exports.get_native_function("call_host_func7")?;
|
||||
// let f8: NativeFunc<(), ()> = instance.exports.get_native_function("call_host_func8")?;
|
||||
|
||||
// f1.call()?;
|
||||
// f2.call()?;
|
||||
// f3.call()?;
|
||||
// f4.call()?;
|
||||
// f5.call()?;
|
||||
// f6.call()?;
|
||||
// f7.call()?;
|
||||
// f8.call()?;
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
497
lib/js-api/tests/reference_types.rs
Normal file
497
lib/js-api/tests/reference_types.rs
Normal file
@@ -0,0 +1,497 @@
|
||||
// use anyhow::Result;
|
||||
// use std::collections::HashMap;
|
||||
// use std::sync::atomic::{AtomicBool, Ordering};
|
||||
// use std::sync::Arc;
|
||||
// use wasmer::*;
|
||||
|
||||
// #[test]
|
||||
// fn func_ref_passed_and_returned() -> Result<()> {
|
||||
// let 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)))
|
||||
// )"#;
|
||||
// let module = Module::new(&store, wat)?;
|
||||
// let imports = imports! {
|
||||
// "env" => {
|
||||
// "func_ref_identity" => Function::new(&store, FunctionType::new([Type::FuncRef], [Type::FuncRef]), |values| -> Result<Vec<_>, _> {
|
||||
// Ok(vec![values[0].clone()])
|
||||
// })
|
||||
// },
|
||||
// };
|
||||
|
||||
// let instance = Instance::new(&module, &imports)?;
|
||||
|
||||
// let f: &Function = instance.exports.get_function("run")?;
|
||||
// let results = f.call(&[]).unwrap();
|
||||
// if let Value::FuncRef(fr) = &results[0] {
|
||||
// assert!(fr.is_none());
|
||||
// } else {
|
||||
// panic!("funcref not found!");
|
||||
// }
|
||||
|
||||
// #[derive(Clone, Debug, WasmerEnv)]
|
||||
// pub struct Env(Arc<AtomicBool>);
|
||||
// let env = Env(Arc::new(AtomicBool::new(false)));
|
||||
|
||||
// let func_to_call = Function::new_native_with_env(&store, env.clone(), |env: &Env| -> i32 {
|
||||
// env.0.store(true, Ordering::SeqCst);
|
||||
// 343
|
||||
// });
|
||||
// let call_set_value: &Function = instance.exports.get_function("call_set_value")?;
|
||||
// let results: Box<[Value]> = call_set_value.call(&[Value::FuncRef(Some(func_to_call))])?;
|
||||
// assert!(env.0.load(Ordering::SeqCst));
|
||||
// assert_eq!(&*results, &[Value::I32(343)]);
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn func_ref_passed_and_called() -> Result<()> {
|
||||
// let 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)))
|
||||
// )"#;
|
||||
// let module = Module::new(&store, wat)?;
|
||||
|
||||
// fn func_ref_call(values: &[Value]) -> Result<Vec<Value>, RuntimeError> {
|
||||
// // TODO: look into `Box<[Value]>` being returned breakage
|
||||
// let f = values[0].unwrap_funcref().as_ref().unwrap();
|
||||
// let f: NativeFunc<(i32, i32), i32> = f.native()?;
|
||||
// Ok(vec![Value::I32(f.call(7, 9)?)])
|
||||
// }
|
||||
|
||||
// let imports = imports! {
|
||||
// "env" => {
|
||||
// "func_ref_call" => Function::new(
|
||||
// &store,
|
||||
// FunctionType::new([Type::FuncRef], [Type::I32]),
|
||||
// func_ref_call
|
||||
// ),
|
||||
// // TODO(reftypes): this should work
|
||||
// /*
|
||||
// "func_ref_call_native" => Function::new_native(&store, |f: Function| -> Result<i32, RuntimeError> {
|
||||
// let f: NativeFunc::<(i32, i32), i32> = f.native()?;
|
||||
// f.call(7, 9)
|
||||
// })
|
||||
// */
|
||||
// },
|
||||
// };
|
||||
|
||||
// let instance = Instance::new(&module, &imports)?;
|
||||
// {
|
||||
// fn sum(a: i32, b: i32) -> i32 {
|
||||
// a + b
|
||||
// }
|
||||
// let sum_func = Function::new_native(&store, sum);
|
||||
|
||||
// let call_func: &Function = instance.exports.get_function("call_func")?;
|
||||
// let result = call_func.call(&[Value::FuncRef(Some(sum_func))])?;
|
||||
// assert_eq!(result[0].unwrap_i32(), 16);
|
||||
// }
|
||||
|
||||
// {
|
||||
// let f: NativeFunc<(), i32> = instance
|
||||
// .exports
|
||||
// .get_native_function("call_host_func_with_wasm_func")?;
|
||||
// let result = f.call()?;
|
||||
// assert_eq!(result, 63);
|
||||
// }
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "experimental-reference-types-extern-ref")]
|
||||
// #[test]
|
||||
// fn extern_ref_passed_and_returned() -> Result<()> {
|
||||
// let 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))
|
||||
// )"#;
|
||||
// let module = Module::new(&store, wat)?;
|
||||
// let imports = imports! {
|
||||
// "env" => {
|
||||
// "extern_ref_identity" => Function::new(&store, FunctionType::new([Type::ExternRef], [Type::ExternRef]), |values| -> Result<Vec<_>, _> {
|
||||
// Ok(vec![values[0].clone()])
|
||||
// }),
|
||||
// "extern_ref_identity_native" => Function::new_native(&store, |er: ExternRef| -> ExternRef {
|
||||
// er
|
||||
// }),
|
||||
// "get_new_extern_ref" => Function::new(&store, FunctionType::new([], [Type::ExternRef]), |_| -> Result<Vec<_>, _> {
|
||||
// let inner =
|
||||
// [("hello".to_string(), "world".to_string()),
|
||||
// ("color".to_string(), "orange".to_string())]
|
||||
// .iter()
|
||||
// .cloned()
|
||||
// .collect::<HashMap<String, String>>();
|
||||
// let new_extern_ref = ExternRef::new(inner);
|
||||
// Ok(vec![Value::ExternRef(new_extern_ref)])
|
||||
// }),
|
||||
// "get_new_extern_ref_native" => Function::new_native(&store, || -> ExternRef {
|
||||
// let inner =
|
||||
// [("hello".to_string(), "world".to_string()),
|
||||
// ("color".to_string(), "orange".to_string())]
|
||||
// .iter()
|
||||
// .cloned()
|
||||
// .collect::<HashMap<String, String>>();
|
||||
// ExternRef::new(inner)
|
||||
// })
|
||||
// },
|
||||
// };
|
||||
|
||||
// let instance = Instance::new(&module, &imports)?;
|
||||
// for run in &["run", "run_native"] {
|
||||
// let f: &Function = instance.exports.get_function(run)?;
|
||||
// let results = f.call(&[]).unwrap();
|
||||
// if let Value::ExternRef(er) = &results[0] {
|
||||
// assert!(er.is_null());
|
||||
// } else {
|
||||
// panic!("result is not an extern ref!");
|
||||
// }
|
||||
|
||||
// let f: NativeFunc<(), ExternRef> = instance.exports.get_native_function(run)?;
|
||||
// let result: ExternRef = f.call()?;
|
||||
// assert!(result.is_null());
|
||||
// }
|
||||
|
||||
// for get_hashmap in &["get_hashmap", "get_hashmap_native"] {
|
||||
// let f: &Function = instance.exports.get_function(get_hashmap)?;
|
||||
// let results = f.call(&[]).unwrap();
|
||||
// if let Value::ExternRef(er) = &results[0] {
|
||||
// let inner: &HashMap<String, String> = er.downcast().unwrap();
|
||||
// assert_eq!(inner["hello"], "world");
|
||||
// assert_eq!(inner["color"], "orange");
|
||||
// } else {
|
||||
// panic!("result is not an extern ref!");
|
||||
// }
|
||||
|
||||
// let f: NativeFunc<(), ExternRef> = instance.exports.get_native_function(get_hashmap)?;
|
||||
|
||||
// let result: ExternRef = f.call()?;
|
||||
// let inner: &HashMap<String, String> = result.downcast().unwrap();
|
||||
// assert_eq!(inner["hello"], "world");
|
||||
// assert_eq!(inner["color"], "orange");
|
||||
// }
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "experimental-reference-types-extern-ref")]
|
||||
// #[test]
|
||||
// // TODO(reftypes): reenable this test
|
||||
// #[ignore]
|
||||
// fn extern_ref_ref_counting_basic() -> Result<()> {
|
||||
// let store = Store::default();
|
||||
// let wat = r#"(module
|
||||
// (func (export "drop") (param $er externref) (result)
|
||||
// (drop (local.get $er)))
|
||||
// )"#;
|
||||
// let module = Module::new(&store, wat)?;
|
||||
// let instance = Instance::new(&module, &imports! {})?;
|
||||
// let f: NativeFunc<ExternRef, ()> = instance.exports.get_native_function("drop")?;
|
||||
|
||||
// let er = ExternRef::new(3u32);
|
||||
// f.call(er.clone())?;
|
||||
|
||||
// assert_eq!(er.downcast::<u32>().unwrap(), &3);
|
||||
// assert_eq!(er.strong_count(), 1);
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "experimental-reference-types-extern-ref")]
|
||||
// #[test]
|
||||
// fn refs_in_globals() -> Result<()> {
|
||||
// let 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))
|
||||
// )"#;
|
||||
// let module = Module::new(&store, wat)?;
|
||||
// let instance = Instance::new(&module, &imports! {})?;
|
||||
// {
|
||||
// let er_global: &Global = instance.exports.get_global("er_global")?;
|
||||
|
||||
// if let Value::ExternRef(er) = er_global.get() {
|
||||
// assert!(er.is_null());
|
||||
// } else {
|
||||
// panic!("Did not find extern ref in the global");
|
||||
// }
|
||||
|
||||
// er_global.set(Val::ExternRef(ExternRef::new(3u32)))?;
|
||||
|
||||
// if let Value::ExternRef(er) = er_global.get() {
|
||||
// assert_eq!(er.downcast::<u32>().unwrap(), &3);
|
||||
// assert_eq!(er.strong_count(), 1);
|
||||
// } else {
|
||||
// panic!("Did not find extern ref in the global");
|
||||
// }
|
||||
// }
|
||||
|
||||
// {
|
||||
// let fr_global: &Global = instance.exports.get_global("fr_immutable_global")?;
|
||||
|
||||
// if let Value::FuncRef(Some(f)) = fr_global.get() {
|
||||
// let native_func: NativeFunc<(), u32> = f.native()?;
|
||||
// assert_eq!(native_func.call()?, 73);
|
||||
// } else {
|
||||
// panic!("Did not find non-null func ref in the global");
|
||||
// }
|
||||
// }
|
||||
|
||||
// {
|
||||
// let fr_global: &Global = instance.exports.get_global("fr_global")?;
|
||||
|
||||
// if let Value::FuncRef(None) = fr_global.get() {
|
||||
// } else {
|
||||
// panic!("Did not find a null func ref in the global");
|
||||
// }
|
||||
|
||||
// let f = Function::new_native(&store, |arg1: i32, arg2: i32| -> i32 { arg1 + arg2 });
|
||||
|
||||
// fr_global.set(Val::FuncRef(Some(f)))?;
|
||||
|
||||
// if let Value::FuncRef(Some(f)) = fr_global.get() {
|
||||
// let native: NativeFunc<(i32, i32), i32> = f.native()?;
|
||||
// assert_eq!(native.call(5, 7)?, 12);
|
||||
// } else {
|
||||
// panic!("Did not find extern ref in the global");
|
||||
// }
|
||||
// }
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "experimental-reference-types-extern-ref")]
|
||||
// #[test]
|
||||
// fn extern_ref_ref_counting_table_basic() -> Result<()> {
|
||||
// let 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))
|
||||
// )"#;
|
||||
// let module = Module::new(&store, wat)?;
|
||||
// let instance = Instance::new(&module, &imports! {})?;
|
||||
|
||||
// let f: NativeFunc<(ExternRef, i32), ExternRef> =
|
||||
// instance.exports.get_native_function("insert_into_table")?;
|
||||
|
||||
// let er = ExternRef::new(3usize);
|
||||
|
||||
// let er = f.call(er, 1)?;
|
||||
// assert_eq!(er.strong_count(), 2);
|
||||
|
||||
// let table: &Table = instance.exports.get_table("table")?;
|
||||
|
||||
// {
|
||||
// let er2 = table.get(1).unwrap().externref().unwrap();
|
||||
// assert_eq!(er2.strong_count(), 3);
|
||||
// }
|
||||
|
||||
// assert_eq!(er.strong_count(), 2);
|
||||
// table.set(1, Val::ExternRef(ExternRef::null()))?;
|
||||
|
||||
// assert_eq!(er.strong_count(), 1);
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "experimental-reference-types-extern-ref")]
|
||||
// #[test]
|
||||
// // TODO(reftypes): reenable this test
|
||||
// #[ignore]
|
||||
// fn extern_ref_ref_counting_global_basic() -> Result<()> {
|
||||
// let 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))
|
||||
// )"#;
|
||||
// let module = Module::new(&store, wat)?;
|
||||
// let instance = Instance::new(&module, &imports! {})?;
|
||||
|
||||
// let global: &Global = instance.exports.get_global("global")?;
|
||||
// {
|
||||
// let er = ExternRef::new(3usize);
|
||||
// global.set(Val::ExternRef(er.clone()))?;
|
||||
// assert_eq!(er.strong_count(), 2);
|
||||
// }
|
||||
// let get_from_global: NativeFunc<(), ExternRef> =
|
||||
// instance.exports.get_native_function("get_from_global")?;
|
||||
|
||||
// let er = get_from_global.call()?;
|
||||
// assert_eq!(er.strong_count(), 2);
|
||||
// global.set(Val::ExternRef(ExternRef::null()))?;
|
||||
// assert_eq!(er.strong_count(), 1);
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "experimental-reference-types-extern-ref")]
|
||||
// #[test]
|
||||
// // TODO(reftypes): reenable this test
|
||||
// #[ignore]
|
||||
// fn extern_ref_ref_counting_traps() -> Result<()> {
|
||||
// let store = Store::default();
|
||||
// let wat = r#"(module
|
||||
// (func $pass_er (export "pass_extern_ref") (param externref)
|
||||
// (local.get 0)
|
||||
// (unreachable))
|
||||
// )"#;
|
||||
// let module = Module::new(&store, wat)?;
|
||||
// let instance = Instance::new(&module, &imports! {})?;
|
||||
|
||||
// let pass_extern_ref: NativeFunc<ExternRef, ()> =
|
||||
// instance.exports.get_native_function("pass_extern_ref")?;
|
||||
|
||||
// let er = ExternRef::new(3usize);
|
||||
// assert_eq!(er.strong_count(), 1);
|
||||
|
||||
// let result = pass_extern_ref.call(er.clone());
|
||||
// assert!(result.is_err());
|
||||
// assert_eq!(er.strong_count(), 1);
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
|
||||
// #[cfg(feature = "experimental-reference-types-extern-ref")]
|
||||
// #[test]
|
||||
// fn extern_ref_ref_counting_table_instructions() -> Result<()> {
|
||||
// let 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)))
|
||||
// )"#;
|
||||
// let module = Module::new(&store, wat)?;
|
||||
// let instance = Instance::new(&module, &imports! {})?;
|
||||
|
||||
// let grow_table_with_ref: NativeFunc<(ExternRef, i32), i32> = instance
|
||||
// .exports
|
||||
// .get_native_function("grow_table_with_ref")?;
|
||||
// let fill_table_with_ref: NativeFunc<(ExternRef, i32, i32), ()> = instance
|
||||
// .exports
|
||||
// .get_native_function("fill_table_with_ref")?;
|
||||
// let copy_into_table2: NativeFunc<(), ()> =
|
||||
// instance.exports.get_native_function("copy_into_table2")?;
|
||||
// let table1: &Table = instance.exports.get_table("table1")?;
|
||||
// let table2: &Table = instance.exports.get_table("table2")?;
|
||||
|
||||
// let er1 = ExternRef::new(3usize);
|
||||
// let er2 = ExternRef::new(5usize);
|
||||
// let er3 = ExternRef::new(7usize);
|
||||
// {
|
||||
// let result = grow_table_with_ref.call(er1.clone(), 0)?;
|
||||
// assert_eq!(result, 2);
|
||||
// assert_eq!(er1.strong_count(), 1);
|
||||
|
||||
// let result = grow_table_with_ref.call(er1.clone(), 10_000)?;
|
||||
// assert_eq!(result, -1);
|
||||
// assert_eq!(er1.strong_count(), 1);
|
||||
|
||||
// let result = grow_table_with_ref.call(er1.clone(), 8)?;
|
||||
// assert_eq!(result, 2);
|
||||
// assert_eq!(er1.strong_count(), 9);
|
||||
|
||||
// for i in 2..10 {
|
||||
// let e = table1.get(i).unwrap().unwrap_externref();
|
||||
// assert_eq!(*e.downcast::<usize>().unwrap(), 3);
|
||||
// assert_eq!(&e, &er1);
|
||||
// }
|
||||
// assert_eq!(er1.strong_count(), 9);
|
||||
// }
|
||||
|
||||
// {
|
||||
// fill_table_with_ref.call(er2.clone(), 0, 2)?;
|
||||
// assert_eq!(er2.strong_count(), 3);
|
||||
// }
|
||||
|
||||
// {
|
||||
// table2.set(0, Val::ExternRef(er3.clone()))?;
|
||||
// table2.set(1, Val::ExternRef(er3.clone()))?;
|
||||
// table2.set(2, Val::ExternRef(er3.clone()))?;
|
||||
// table2.set(3, Val::ExternRef(er3.clone()))?;
|
||||
// table2.set(4, Val::ExternRef(er3.clone()))?;
|
||||
// assert_eq!(er3.strong_count(), 6);
|
||||
// }
|
||||
|
||||
// {
|
||||
// copy_into_table2.call()?;
|
||||
// assert_eq!(er3.strong_count(), 2);
|
||||
// assert_eq!(er2.strong_count(), 5);
|
||||
// assert_eq!(er1.strong_count(), 11);
|
||||
// for i in 1..5 {
|
||||
// let e = table2.get(i).unwrap().unwrap_externref();
|
||||
// let value = e.downcast::<usize>().unwrap();
|
||||
// match i {
|
||||
// 0 | 1 => assert_eq!(*value, 5),
|
||||
// 4 => assert_eq!(*value, 7),
|
||||
// _ => assert_eq!(*value, 3),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// {
|
||||
// for i in 0..table1.size() {
|
||||
// table1.set(i, Val::ExternRef(ExternRef::null()))?;
|
||||
// }
|
||||
// for i in 0..table2.size() {
|
||||
// table2.set(i, Val::ExternRef(ExternRef::null()))?;
|
||||
// }
|
||||
// }
|
||||
|
||||
// assert_eq!(er1.strong_count(), 1);
|
||||
// assert_eq!(er2.strong_count(), 1);
|
||||
// assert_eq!(er3.strong_count(), 1);
|
||||
|
||||
// Ok(())
|
||||
// }
|
||||
Reference in New Issue
Block a user