Files
wasmer/lib/api/tests/js_externals.rs
Syrus Akbary a419ccdf52 Move Webassembly objects to Store and remove Context
Co-authored-by: ptitSeb <sebastien.chev@gmail.com>
Co-authored-by: Manos Pitsidianakis <manos@wasmer.io>
2022-07-19 15:31:51 +03:00

475 lines
17 KiB
Rust

#[cfg(feature = "js")]
mod js {
use wasm_bindgen_test::*;
use wasmer::*;
#[wasm_bindgen_test]
fn global_new() {
let mut store = Store::default();
let mut env = FunctionEnv::new(&mut store, ());
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 mut env = FunctionEnv::new(&mut store, ());
let global_i32 = Global::new(&mut store, Value::I32(10));
assert_eq!(global_i32.get(&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 mut env = FunctionEnv::new(&mut store, ());
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 mut env = FunctionEnv::new(&mut store, ());
let table_type = TableType {
ty: Type::FuncRef,
minimum: 0,
maximum: None,
};
let f = Function::new_native(&mut store, &env, |_: FunctionEnvMut<'_, ()>| {});
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, &env, |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 mut env = FunctionEnv::new(&mut store, ());
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.size(&store), Pages(0));
assert_eq!(memory.ty(&store), memory_type);
}
#[wasm_bindgen_test]
fn memory_grow() {
let mut store = Store::default();
let mut env = FunctionEnv::new(&mut store, ());
let desc = MemoryType::new(Pages(10), Some(Pages(16)), false);
let memory = Memory::new(&mut store, desc).unwrap();
assert_eq!(memory.size(&store), Pages(10));
let result = memory.grow(&mut store, Pages(2)).unwrap();
assert_eq!(result, Pages(10));
assert_eq!(memory.size(&store), 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 mut env = FunctionEnv::new(&mut store, ());
let function = Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<'_, ()>| {});
assert_eq!(
function.ty(&store).clone(),
FunctionType::new(vec![], vec![])
);
let function =
Function::new_native(&mut store, &env, |_ctx: FunctionEnvMut<'_, ()>, _a: i32| {});
assert_eq!(
function.ty(&store).clone(),
FunctionType::new(vec![Type::I32], vec![])
);
let function = Function::new_native(
&mut store,
&env,
|_ctx: FunctionEnvMut<'_, ()>, _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_native(&mut store, &env, |_ctx: FunctionEnvMut<'_, ()>| -> i32 {
1
});
assert_eq!(
function.ty(&store).clone(),
FunctionType::new(vec![], vec![Type::I32])
);
let function = Function::new_native(
&mut store,
&env,
|_ctx: FunctionEnvMut<'_, ()>| -> (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 mut env = FunctionEnv::new(&mut store, my_env);
let function = Function::new_native(&mut store, &env, |_: FunctionEnvMut<'_, MyEnv>| {});
assert_eq!(
function.ty(&store).clone(),
FunctionType::new(vec![], vec![])
);
let function =
Function::new_native(&mut store, &env, |_: FunctionEnvMut<'_, MyEnv>, _a: i32| {});
assert_eq!(
function.ty(&store).clone(),
FunctionType::new(vec![Type::I32], vec![])
);
let function = Function::new_native(
&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_native(&mut store, &env, |_: FunctionEnvMut<'_, MyEnv>| -> i32 {
1
});
assert_eq!(
function.ty(&store).clone(),
FunctionType::new(vec![], vec![Type::I32])
);
let function = Function::new_native(
&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();
let mut env = FunctionEnv::new(&mut store, ());
// Using &FunctionType signature
let function_type = FunctionType::new(vec![], vec![]);
let function = Function::new(
&mut store,
&env,
&function_type,
|_ctx: FunctionEnvMut<'_, ()>, _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,
&env,
&function_type,
|_ctx: FunctionEnvMut<'_, ()>, _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,
&env,
&function_type,
|_ctx: FunctionEnvMut<'_, ()>, _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,
&env,
&function_type,
|_ctx: FunctionEnvMut<'_, ()>, _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,
&env,
&function_type,
|_ctx: FunctionEnvMut<'_, ()>, _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,
&env,
function_type,
|_ctx: FunctionEnvMut<'_, ()>, _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 mut env = FunctionEnv::new(&mut store, my_env);
// Using &FunctionType signature
let function_type = FunctionType::new(vec![], vec![]);
let function = Function::new(
&mut store,
&env,
&function_type,
|_ctx: 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(
&mut store,
&env,
&function_type,
|_ctx: 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(
&mut store,
&env,
&function_type,
|_ctx: 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(
&mut store,
&env,
&function_type,
|_ctx: 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(
&mut store,
&env,
&function_type,
|_ctx: 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(
&mut store,
&env,
function_type,
|_ctx: 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 mut env = FunctionEnv::new(&mut store, ());
let function = Function::new_native(&mut store, &env, |_: FunctionEnvMut<'_, ()>| {});
let typed_function: TypedFunction<(), ()> = function.native(&mut store).unwrap();
let result = typed_function.call(&mut store);
assert!(result.is_ok());
let function = Function::new_native(
&mut store,
&env,
|_: FunctionEnvMut<'_, ()>, a: i32| -> i32 { a + 1 },
);
let typed_function: TypedFunction<i32, i32> = function.native(&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_native(&mut store, &env, |_: FunctionEnvMut<'_, ()>| -> i32 { 1 });
let typed_function: TypedFunction<(), i32> = function.native(&mut store).unwrap();
assert_eq!(typed_function.call(&mut store).unwrap(), 1);
let function =
Function::new_native(&mut store, &env, |_: FunctionEnvMut<'_, ()>, _a: i32| {});
let typed_function: TypedFunction<i32, ()> = function.native(&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 mut env = FunctionEnv::new(&mut store, ());
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()
);
}
}