Clone in a terminal:
Commit 0f73065
Johan Mattsson - 2026-06-01T17:59:06+00:00
0f7306506b1b70a900652350f582568f5e606ad1johan.mattsson.m@gmail.com

Fix type issue

Changed files (1)

Diff

diff --git a/src/lib.rs b/src/lib.rsindex 7b6a076..1fd1a89 100644--- a/src/lib.rs+++ b/src/lib.rs@@ -81,11 +81,140 @@ fn generate_callback_closure(     use proc_macro2::Span;     use quote::quote; -    if inputs.iter().len() == 3 {+    let mut js_value_types: Vec<proc_macro2::TokenStream> = Vec::new(); // array of wasm_bindgen::JsValue,+    let mut js_arg_idents: Vec<syn::Ident> = Vec::new(); // val0, val1, ... lambda arguments+    let mut rust_arg_types: Vec<syn::Type> = Vec::new(); // extracted types form the annotated rust function+    let mut rs_arg_idents: Vec<syn::Ident> = Vec::new(); // arg0, arg1, ... converted from val0, val1,+    let mut temp_result_idents: Vec<syn::Ident> = Vec::new(); // res0, res1, ... result for serde parser++    for (i, arg) in inputs.iter().enumerate() {+        let span = Span::call_site();++        let js_value_type = quote! { wasm_bindgen::JsValue };+        js_value_types.push(js_value_type);++        let val_ident = syn::Ident::new(&format!("val{}", i), span);+        js_arg_idents.push(val_ident);++        let rs_ident = syn::Ident::new(&format!("arg{}", i), span);+        rs_arg_idents.push(rs_ident);++        let res_ident = syn::Ident::new(&format!("res{}", i), span);+        temp_result_idents.push(res_ident);++        match arg {+            FnArg::Typed(pat_type) => {+                rust_arg_types.push((*pat_type.ty).clone());+            }+            _ => panic!("expected typed argument"),+        }+    }++    if inputs.len() == 3 {+        let mut conversions = Vec::new();+        for ((res_ident, rs_ident), (val_ident, ty)) in temp_result_idents+            .iter()+            .zip(rs_arg_idents.iter())+            .zip(js_arg_idents.iter().zip(rust_arg_types.iter()))+        {+            // attempt simple conversions for common primitive types to avoid requiring+            // serde_wasm_bindgen in the consumer crate. Fall back to serde for other types.+            let conv = if let syn::Type::Path(type_path) = ty {+                if let Some(seg) = type_path.path.segments.last() {+                    let ident_str = seg.ident.to_string();+                    match ident_str.as_str() {+                        "u32" | "i32" | "usize" | "f64" => {+                            quote! {+                                let #res_ident: Option<#ty> = #val_ident.as_f64().map(|v| v as #ty);+                                if #res_ident.is_none() {+                                    gloo::console::log!(+                                        concat!("Callback error: ", stringify!(#fn_name), ". Wrong argument")+                                    );+                                    return;+                                }+                                let #rs_ident = #res_ident.unwrap();+                            }+                        }+                        "bool" => {+                            quote! {+                                let #res_ident: Option<#ty> = #val_ident.as_bool();+                                if #res_ident.is_none() {+                                    gloo::console::log!(+                                        concat!("Callback error: ", stringify!(#fn_name), ". Wrong argument")+                                    );+                                    return;+                                }+                                let #rs_ident = #res_ident.unwrap();+                            }+                        }+                        "String" => {+                            quote! {+                                let #res_ident: Option<#ty> = #val_ident.as_string();+                                if #res_ident.is_none() {+                                    gloo::console::log!(+                                        concat!("Callback error: ", stringify!(#fn_name), ". Wrong argument")+                                    );+                                    return;+                                }+                                let #rs_ident = #res_ident.unwrap();+                            }+                        }+                        _ => {+                            quote! {+                                let #res_ident = serde_wasm_bindgen::from_value::<#ty>(#val_ident.clone());+                                if #res_ident.is_err() {+                                    gloo::console::log!(+                                        concat!("Callback error: ", stringify!(#fn_name), ". Wrong argument"),+                                        #res_ident.err().unwrap()+                                    );+                                    return;+                                }+                                let #rs_ident = #res_ident.unwrap();+                            }+                        }+                    }+                } else {+                    // fallback+                    quote! {+                        let #res_ident = serde_wasm_bindgen::from_value::<#ty>(#val_ident.clone());+                        if #res_ident.is_err() {+                            gloo::console::log!(+                                concat!("Callback error: ", stringify!(#fn_name), ". Wrong argument"),+                                #res_ident.err().unwrap()+                            );+                            return;+                        }+                        let #rs_ident = #res_ident.unwrap();+                    }+                }+            } else {+                // not a path type; fallback to serde+                quote! {+                    let #res_ident = serde_wasm_bindgen::from_value::<#ty>(#val_ident.clone());+                    if #res_ident.is_err() {+                        gloo::console::log!(+                            concat!("Callback error: ", stringify!(#fn_name), ". Wrong argument"),+                            #res_ident.err().unwrap()+                        );+                        return;+                    }+                    let #rs_ident = #res_ident.unwrap();+                }+            };++            conversions.push(conv);+        }++        // build a token-list of wasm_bindgen::JsValue types for the trait object+        let js_types: Vec<proc_macro2::TokenStream> = (0..js_arg_idents.len())+            .map(|_| quote! { wasm_bindgen::JsValue })+            .collect();+         let expanded = quote! {-            let cb = Closure::<dyn FnMut(wasm_bindgen::JsValue, wasm_bindgen::JsValue, wasm_bindgen::JsValue)>::new(|val, val2, val3| {-                #fn_name(1, 2, 3);-            });+            let cb = Closure::wrap(Box::new(move | #( #js_arg_idents : #js_types ),* | {+                #(#conversions)*+                #fn_name( #(#rs_arg_idents),* );+            }) as Box<dyn FnMut( #(#js_types),* ) + 'static>);         };          return expanded;@@ -93,7 +222,9 @@ fn generate_callback_closure(      if inputs.iter().len() == 2 {         let expanded = quote! {-            let cb = Closure::<dyn FnMut(wasm_bindgen::JsValue, wasm_bindgen::JsValue)>::new(|val, val2| {+            let cb = Closure::<dyn FnMut(#(#js_value_types),*)>::new(+                |val0, val1| {+                 let event = Test1Data {                     test_parameter: "test".to_string(),                 };@@ -109,7 +240,8 @@ fn generate_callback_closure(      if inputs.iter().len() == 1 {         let expanded = quote! {-            let cb = Closure::<dyn FnMut(wasm_bindgen::JsValue)>::new(|val| {+            let cb = Closure::<dyn FnMut(#(#js_value_types),*)>::new(+                |val0| {                 let event = Test1Data {                     test_parameter: "test".to_string(),                 };@@ -122,7 +254,8 @@ fn generate_callback_closure(     }      let expanded = quote! {-        let cb = Closure::<dyn FnMut()>::new(|| {+        let cb = Closure::<dyn FnMut(#(#js_value_types),*)>::new(+            || {             #fn_name();         });     };

Contact

Email: johan.mattsson.m@gmail.com
Mastodon: typo.social/@birdfont
GitHub: johanmattssonm
LinkedIn: johan-mattsson-2ab324112