diff --git a/.changes/menu-command-panic-on-wrong-input.md b/.changes/menu-command-panic-on-wrong-input.md new file mode 100644 index 000000000000..5b65a1b7ab88 --- /dev/null +++ b/.changes/menu-command-panic-on-wrong-input.md @@ -0,0 +1,9 @@ +--- +tauri: minor:bug +tauri-macros: minor:bug +--- + +Fix menu related commands can panic if called with invalid menu types through `invoke` directly. + +- The internal `do_menu_item!` macro now returns `Err(crate::Error::UnexpectedMenuKind)` instead of `unreachable!()` +- Added a new error type `tauri::Error::UnexpectedMenuKind` diff --git a/crates/tauri-macros/src/lib.rs b/crates/tauri-macros/src/lib.rs index 034f991447ab..7b2328edbcd4 100644 --- a/crates/tauri-macros/src/lib.rs +++ b/crates/tauri-macros/src/lib.rs @@ -3,6 +3,8 @@ // SPDX-License-Identifier: MIT //! Create macros for `tauri::Context`, invoke handler and commands leveraging the `tauri-codegen` crate. +//! +//! Don't depend on this crate directly, use the re-exported types from tauri instead. #![doc( html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/.github/icon.png", @@ -117,7 +119,7 @@ pub fn default_runtime(attributes: TokenStream, input: TokenStream) -> TokenStre /// do_menu_item!(resources_table, rid, kind, |i| i.set_text(text), !Check | Submenu); /// ``` /// -/// #### Example +/// ## Examples /// /// ```ignore /// let rid = 23; @@ -151,9 +153,10 @@ pub fn default_runtime(attributes: TokenStream, input: TokenStream) -> TokenStre /// let i = resources_table.get::>(rid)?; /// i.set_text(text) /// } -/// _ => unreachable!(), +/// _ => return Err(crate::Error::UnexpectedMenuKind), /// } /// ``` +#[doc(hidden)] #[proc_macro] pub fn do_menu_item(input: TokenStream) -> TokenStream { let tokens = parse_macro_input!(input as menu::DoMenuItemInput); diff --git a/crates/tauri-macros/src/menu.rs b/crates/tauri-macros/src/menu.rs index 1e230d152324..8ab2b9b92723 100644 --- a/crates/tauri-macros/src/menu.rs +++ b/crates/tauri-macros/src/menu.rs @@ -130,7 +130,7 @@ pub fn do_menu_item(input: DoMenuItemInput) -> TokenStream { #expr } )* - _ => unreachable!(), + _ => return Err(crate::Error::UnexpectedMenuKind), } } } diff --git a/crates/tauri/src/error.rs b/crates/tauri/src/error.rs index 405a9b48dd1e..2f86acc1ffd5 100644 --- a/crates/tauri/src/error.rs +++ b/crates/tauri/src/error.rs @@ -166,6 +166,9 @@ pub enum Error { /// tokio oneshot channel failed to receive message #[error(transparent)] TokioOneshotRecv(#[from] tokio::sync::oneshot::error::RecvError), + /// Unexpected menu kind passed to menu/tray plugin command + #[error("Unexpected menu kind")] + UnexpectedMenuKind, } impl From for Error { diff --git a/crates/tauri/src/menu/plugin.rs b/crates/tauri/src/menu/plugin.rs index 13b2bc76e27e..8c3c031f3ea6 100644 --- a/crates/tauri/src/menu/plugin.rs +++ b/crates/tauri/src/menu/plugin.rs @@ -486,7 +486,7 @@ fn append( item.with_item(&webview, &resources_table, |i| submenu.append(i))?; } } - _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + _ => return Err(crate::Error::UnexpectedMenuKind), }; Ok(()) @@ -513,7 +513,7 @@ fn prepend( item.with_item(&webview, &resources_table, |i| submenu.prepend(i))?; } } - _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + _ => return Err(crate::Error::UnexpectedMenuKind), }; Ok(()) @@ -543,7 +543,7 @@ fn insert( position += 1 } } - _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + _ => return Err(crate::Error::UnexpectedMenuKind), }; Ok(()) @@ -568,7 +568,7 @@ fn remove( do_menu_item!(resources_table, item_rid, item_kind, |i| submenu .remove(&*i))?; } - _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + _ => return Err(crate::Error::UnexpectedMenuKind), }; Ok(()) @@ -609,7 +609,7 @@ fn remove_at( return Ok(Some(make_item_resource!(resources_table, item))); } } - _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + _ => return Err(crate::Error::UnexpectedMenuKind), }; Ok(None) @@ -625,7 +625,7 @@ fn items( let items = match kind { ItemKind::Menu => resources_table.get::>(rid)?.items()?, ItemKind::Submenu => resources_table.get::>(rid)?.items()?, - _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + _ => return Err(crate::Error::UnexpectedMenuKind), }; Ok( @@ -657,7 +657,7 @@ fn get( return Ok(Some(make_item_resource!(resources_table, item))); } } - _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + _ => return Err(crate::Error::UnexpectedMenuKind), }; Ok(None) @@ -687,7 +687,7 @@ async fn popup( let submenu = resources_table.get::>(rid)?; submenu.popup_inner(window, at)?; } - _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + _ => return Err(crate::Error::UnexpectedMenuKind), }; } diff --git a/crates/tauri/src/tray/plugin.rs b/crates/tauri/src/tray/plugin.rs index f2d74ca5adda..25ecc4501046 100644 --- a/crates/tauri/src/tray/plugin.rs +++ b/crates/tauri/src/tray/plugin.rs @@ -62,7 +62,7 @@ fn new( let submenu = resources_table.get::>(rid)?; builder = builder.menu(&*submenu); } - _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + _ => return Err(crate::Error::UnexpectedMenuKind), }; } if let Some(icon) = options.icon { @@ -144,7 +144,7 @@ fn set_menu( let submenu = webview_resources_table.get::>(rid)?; tray.set_menu(Some((*submenu).clone()))?; } - _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()), + _ => return Err(crate::Error::UnexpectedMenuKind), }; } else { tray.set_menu(None::>)?;