Clone in a terminal:
Commit eb7f0a2
Johan Mattsson - 2026-06-01T10:49:09+00:00
eb7f0a26486bacfb02b7b08aa2a4fa118ac7af05johan.mattsson.m@gmail.com

Refactor

Changed files (1)

Diff

diff --git a/src/lib.rs b/src/lib.rsindex f869585..b983bcd 100644--- a/src/lib.rs+++ b/src/lib.rs@@ -26,32 +26,6 @@ use syn::{parse_macro_input, ItemFn, LitStr}; /// ``` #[proc_macro_attribute] pub fn callback(attr: TokenStream, item: TokenStream) -> TokenStream {-    // parse attribute as either a string literal `"name"` or an identifier `name`-    struct CallbackArg {-        name: String,-        span: proc_macro2::Span,-    }--    impl syn::parse::Parse for CallbackArg {-        fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {-            if input.peek(LitStr) {-                let s: LitStr = input.parse()?;-                Ok(CallbackArg {-                    name: s.value(),-                    span: s.span(),-                })-            } else if input.peek(syn::Ident) {-                let id: syn::Ident = input.parse()?;-                Ok(CallbackArg {-                    name: id.to_string(),-                    span: id.span(),-                })-            } else {-                Err(input.error("expected string literal or identifier, e.g. #[callback(\"name\")] or #[callback(name)]"))-            }-        }-    }-     let callback_arg = parse_macro_input!(attr as CallbackArg);     let js_name_lit = LitStr::new(&callback_arg.name, callback_arg.span);     let input_fn = parse_macro_input!(item as ItemFn);@@ -63,48 +37,69 @@ pub fn callback(attr: TokenStream, item: TokenStream) -> TokenStream {     let register_fn_name = syn::Ident::new(&format!("{}_register", fn_name), fn_name.span());     let register_fn_name_lit = LitStr::new(&register_fn_name.to_string(), register_fn_name.span()); -    let expanded = match input_fn.sig.inputs.len() {-        0 => {-            // No argument: ignore the JsValue passed from JS and call the function directly.-            quote! {-                #vis #sig #fn_block+    let expanded = {+        let inputs = &input_fn.sig.inputs;+        let inputs_len = inputs.len(); -                #[wasm_bindgen]-                pub fn #register_fn_name() {-                    use wasm_bindgen::closure::Closure;-                    use wasm_bindgen::JsCast;-                    use js_sys::{Array, Object, Reflect};-                    use wasm_bindgen::JsValue;+        // No argument: ignore the JsValue passed from JS and call the function directly.+        quote! {+            #vis #sig #fn_block -                    if let Some(window) = web_sys::window() {-                        let cb = Closure::<dyn FnMut(wasm_bindgen::JsValue)>::new(|_val| {-                            #fn_name();-                        });+            #[wasm_bindgen]+            pub fn #register_fn_name() {+                use wasm_bindgen::closure::Closure;+                use wasm_bindgen::JsCast;+                use js_sys::{Array, Object, Reflect};+                use wasm_bindgen::JsValue; -                        let _ = Reflect::set(-                            window.as_ref(),-                            &JsValue::from_str(#register_fn_name_lit),-                            cb.as_ref().unchecked_ref(),-                        );+                if let Some(window) = web_sys::window() {+                    let cb = Closure::<dyn FnMut(wasm_bindgen::JsValue)>::new(|_val| {+                        #fn_name();+                    }); -                        let key = JsValue::from_str(#js_name_lit);-                        let _ = Reflect::set(window.as_ref(), &key, cb.as_ref().unchecked_ref());-                        cb.forget();-                    }-                }+                    let _ = Reflect::set(+                        window.as_ref(),+                        &JsValue::from_str(#register_fn_name_lit),+                        cb.as_ref().unchecked_ref(),+                    ); -                ::inventory::submit! {-                    InitFn(#register_fn_name)+                    let key = JsValue::from_str(#js_name_lit);+                    let _ = Reflect::set(window.as_ref(), &key, cb.as_ref().unchecked_ref());+                    cb.forget();                 }             }-        }-        _ => {-            // More than one argument is not supported by this macro.-            return TokenStream::from(quote! {-                compile_error!("#[callback(...)] only supports functions with 0 arguments");-            });++            ::inventory::submit! {+                InitFn(#register_fn_name)+            }         }     };      TokenStream::from(expanded) }++struct CallbackArg {+    name: String,+    span: proc_macro2::Span,+}++// remoce quote if present+impl syn::parse::Parse for CallbackArg {+    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {+        if input.peek(LitStr) {+            let s: LitStr = input.parse()?;+            Ok(CallbackArg {+                name: s.value(),+                span: s.span(),+            })+        } else if input.peek(syn::Ident) {+            let id: syn::Ident = input.parse()?;+            Ok(CallbackArg {+                name: id.to_string(),+                span: id.span(),+            })+        } else {+            Err(input.error("expected string literal or identifier, e.g. #[callback(\"name\")] or #[callback(name)]"))+        }+    }+}

Contact

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