From 3319e0f893ccbd24ab8ac0ea1a029febba8ec287 Mon Sep 17 00:00:00 2001 From: Syrus Akbary Date: Tue, 10 Aug 2021 11:07:32 -0700 Subject: [PATCH] Added support for calling dynamic functions defined on the host --- lib/api/src/sys/externals/function.rs | 15 +++++++++- lib/api/tests/js_instance.rs | 25 +++++++++++++++++ .../tests/{sys/export.rs => sys_export.rs} | 0 .../{sys/externals.rs => sys_externals.rs} | 0 .../{sys/instance.rs => sys_instance.rs} | 28 +++++++++++++++++++ .../tests/{sys/module.rs => sys_module.rs} | 0 ...erence_types.rs => sys_reference_types.rs} | 0 7 files changed, 67 insertions(+), 1 deletion(-) rename lib/api/tests/{sys/export.rs => sys_export.rs} (100%) rename lib/api/tests/{sys/externals.rs => sys_externals.rs} (100%) rename lib/api/tests/{sys/instance.rs => sys_instance.rs} (58%) rename lib/api/tests/{sys/module.rs => sys_module.rs} (100%) rename lib/api/tests/{sys/reference_types.rs => sys_reference_types.rs} (100%) 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