@@ -6,7 +6,7 @@ use alloc::vec::Vec;
66use core:: fmt:: Debug ;
77
88use crate :: func:: { FromWasmValueTuple , IntoWasmValueTuple , ValTypesFromTuple } ;
9- use crate :: { log, LinkingError , MemoryRef , MemoryRefMut , Result } ;
9+ use crate :: { cold , log, Error , LinkingError , MemoryRef , MemoryRefMut , Result } ;
1010use tinywasm_types:: * ;
1111
1212/// The internal representation of a function
@@ -42,11 +42,12 @@ impl HostFunction {
4242
4343 /// Call the function
4444 pub fn call ( & self , ctx : FuncContext < ' _ > , args : & [ WasmValue ] ) -> Result < Vec < WasmValue > > {
45- ( self . func ) ( ctx, args)
45+ ( self . func ) ( ctx, args, & self . ty . results )
4646 }
4747}
4848
49- pub ( crate ) type HostFuncInner = Box < dyn Fn ( FuncContext < ' _ > , & [ WasmValue ] ) -> Result < Vec < WasmValue > > > ;
49+ // third argument - expected return types, for validation
50+ pub ( crate ) type HostFuncInner = Box < dyn Fn ( FuncContext < ' _ > , & [ WasmValue ] , & [ ValType ] ) -> Result < Vec < WasmValue > > > ;
5051
5152/// The context of a host-function call
5253#[ derive( Debug ) ]
@@ -139,7 +140,19 @@ impl Extern {
139140 ty : & tinywasm_types:: FuncType ,
140141 func : impl Fn ( FuncContext < ' _ > , & [ WasmValue ] ) -> Result < Vec < WasmValue > > + ' static ,
141142 ) -> Self {
142- Self :: Function ( Function :: Host ( Rc :: new ( HostFunction { func : Box :: new ( func) , ty : ty. clone ( ) } ) ) )
143+ let wrapper = move |ctx : FuncContext < ' _ > , params : & [ WasmValue ] , res_ty : & [ ValType ] | {
144+ let ret = func ( ctx, params) ?;
145+ let types_match = res_ty. iter ( ) . cloned ( ) . eq ( ret. iter ( ) . map ( WasmValue :: val_type) ) ;
146+ if types_match {
147+ Ok ( ret)
148+ } else {
149+ cold ( ) ;
150+ let got_types = ret. iter ( ) . map ( WasmValue :: val_type) . collect :: < Box < [ _ ] > > ( ) ;
151+ log:: error!( "Return from host function type mismatch: expected {:?}, got {:?}" , res_ty, got_types) ;
152+ Err ( Error :: InvalidHostFnReturn )
153+ }
154+ } ;
155+ Self :: Function ( Function :: Host ( Rc :: new ( HostFunction { func : Box :: new ( wrapper) , ty : ty. clone ( ) } ) ) )
143156 }
144157
145158 /// Create a new typed function import
@@ -148,7 +161,7 @@ impl Extern {
148161 P : FromWasmValueTuple + ValTypesFromTuple ,
149162 R : IntoWasmValueTuple + ValTypesFromTuple + Debug ,
150163 {
151- let inner_func = move |ctx : FuncContext < ' _ > , args : & [ WasmValue ] | -> Result < Vec < WasmValue > > {
164+ let inner_func = move |ctx : FuncContext < ' _ > , args : & [ WasmValue ] , _ : & [ ValType ] | -> Result < Vec < WasmValue > > {
152165 let args = P :: from_wasm_value_tuple ( args) ?;
153166 let result = func ( ctx, args) ?;
154167 Ok ( result. into_wasm_value_tuple ( ) . to_vec ( ) )
0 commit comments