Commit eb7f0a2
Refactor
Changed files (1)
Diff
@@ -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(®ister_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)]"))+ }+ }+}