diff --git a/lib/api/src/sys/externals/function.rs b/lib/api/src/sys/externals/function.rs index babb2311a37..773faacd4ef 100644 --- a/lib/api/src/sys/externals/function.rs +++ b/lib/api/src/sys/externals/function.rs @@ -522,13 +522,26 @@ impl Function { /// assert_eq!(sum.call(&[Value::I32(1), Value::I32(2)]).unwrap().to_vec(), vec![Value::I32(3)]); /// ``` pub fn call(&self, params: &[Val]) -> Result, RuntimeError> { + // If it's a function defined in the Wasm, it will always have a call_trampoline if let Some(trampoline) = self.exported.vm_function.call_trampoline { let mut results = vec![Val::null(); self.result_arity()]; self.call_wasm(trampoline, params, &mut results)?; return Ok(results.into_boxed_slice()); } - unimplemented!("The function definition isn't supported for the moment"); + // If it's a function defined in the host + match self.exported.vm_function.kind { + VMFunctionKind::Dynamic => unsafe { + type VMContextWithEnv = VMDynamicFunctionContext>; + let ctx = self.exported.vm_function.vmctx.host_env as *mut VMContextWithEnv; + Ok((*ctx).ctx.call(¶ms)?.into_boxed_slice()) + }, + VMFunctionKind::Static => { + unimplemented!( + "Native function definitions can't be directly called from the host yet" + ); + } + } } pub(crate) fn from_vm_export(store: &Store, wasmer_export: ExportFunction) -> Self { diff --git a/lib/api/tests/js_instance.rs b/lib/api/tests/js_instance.rs index 374f0094140..ba9a4b07fe5 100644 --- a/lib/api/tests/js_instance.rs +++ b/lib/api/tests/js_instance.rs @@ -420,6 +420,31 @@ mod js { assert_eq!(exported.call(&[Val::I32(4)]), Ok(expected)); } + #[wasm_bindgen_test] + fn test_unit_native_function_env() { + let store = Store::default(); + #[derive(WasmerEnv, Clone)] + struct Env { + multiplier: u32, + } + + fn imported_fn(env: &Env, args: &[Val]) -> Result, RuntimeError> { + let value = env.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( + &store, + imported_signature, + Env { multiplier: 3 }, + imported_fn, + ); + + let expected = vec![Val::I32(12)].into_boxed_slice(); + assert_eq!(imported.call(&[Val::I32(4)]), Ok(expected)); + } + #[wasm_bindgen_test] fn test_imported_function_with_wasmer_env() { let store = Store::default(); diff --git a/lib/api/tests/sys/export.rs b/lib/api/tests/sys_export.rs similarity index 100% rename from lib/api/tests/sys/export.rs rename to lib/api/tests/sys_export.rs diff --git a/lib/api/tests/sys/externals.rs b/lib/api/tests/sys_externals.rs similarity index 100% rename from lib/api/tests/sys/externals.rs rename to lib/api/tests/sys_externals.rs diff --git a/lib/api/tests/sys/instance.rs b/lib/api/tests/sys_instance.rs similarity index 58% rename from lib/api/tests/sys/instance.rs rename to lib/api/tests/sys_instance.rs index 4afbba187e2..b4d8f33fa74 100644 --- a/lib/api/tests/sys/instance.rs +++ b/lib/api/tests/sys_instance.rs @@ -39,4 +39,32 @@ mod sys { Ok(()) } + + #[test] + fn unit_native_function_env() -> Result<()> { + let store = Store::default(); + #[derive(WasmerEnv, Clone)] + struct Env { + multiplier: u32, + } + + fn imported_fn(env: &Env, args: &[Val]) -> Result, RuntimeError> { + let value = env.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( + &store, + imported_signature, + Env { multiplier: 3 }, + imported_fn, + ); + + let expected = vec![Val::I32(12)].into_boxed_slice(); + let result = imported.call(&[Val::I32(4)])?; + assert_eq!(result, expected); + + Ok(()) + } } diff --git a/lib/api/tests/sys/module.rs b/lib/api/tests/sys_module.rs similarity index 100% rename from lib/api/tests/sys/module.rs rename to lib/api/tests/sys_module.rs diff --git a/lib/api/tests/sys/reference_types.rs b/lib/api/tests/sys_reference_types.rs similarity index 100% rename from lib/api/tests/sys/reference_types.rs rename to lib/api/tests/sys_reference_types.rs