From 0fb3d761c9a5c5a2ea600a47aed896312c6d51d1 Mon Sep 17 00:00:00 2001 From: MrSaturn1 Date: Thu, 23 Apr 2026 13:08:48 -0400 Subject: [PATCH] fix(macos): handle nil NSOpenPanel in run_file_upload_panel NSOpenPanel::openPanel() can return nil in rare edge cases on macOS (code-signature mismatch after in-place update, system wake transient). The typed objc2 binding panics on nil, crashing the app. Use raw msg_send + Retained::retain to detect nil and gracefully cancel the file picker by calling the WebKit completion handler with null. Fixes tauri-apps/tauri#13047 --- .changes/fix-nil-open-panel.md | 5 +++++ src/wkwebview/class/wry_web_view_ui_delegate.rs | 14 +++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 .changes/fix-nil-open-panel.md diff --git a/.changes/fix-nil-open-panel.md b/.changes/fix-nil-open-panel.md new file mode 100644 index 000000000..4e88e2398 --- /dev/null +++ b/.changes/fix-nil-open-panel.md @@ -0,0 +1,5 @@ +--- +"wry": patch +--- + +Fix crash on macOS when `NSOpenPanel::openPanel()` returns nil in rare edge cases (e.g. code-signature mismatch after in-place update, system wake transient). Use raw `msg_send` + `Retained::retain` to detect nil and gracefully cancel the file picker. diff --git a/src/wkwebview/class/wry_web_view_ui_delegate.rs b/src/wkwebview/class/wry_web_view_ui_delegate.rs index 88349d736..4ac9870d6 100644 --- a/src/wkwebview/class/wry_web_view_ui_delegate.rs +++ b/src/wkwebview/class/wry_web_view_ui_delegate.rs @@ -8,7 +8,7 @@ use std::{cell::RefCell, ptr::null_mut, rc::Rc}; use block2::Block; #[cfg(target_os = "macos")] use objc2::DefinedClass; -use objc2::{define_class, msg_send, rc::Retained, runtime::NSObject, MainThreadOnly}; +use objc2::{define_class, msg_send, rc::Retained, runtime::NSObject, ClassType, MainThreadOnly}; #[cfg(target_os = "macos")] use objc2_app_kit::{NSModalResponse, NSModalResponseOK, NSOpenPanel, NSWindowDelegate}; use objc2_foundation::{MainThreadMarker, NSObjectProtocol}; @@ -106,8 +106,16 @@ define_class!( handler: &block2::Block)>, ) { unsafe { - if let Some(mtm) = MainThreadMarker::new() { - let open_panel = NSOpenPanel::openPanel(mtm); + if let Some(_mtm) = MainThreadMarker::new() { + // NSOpenPanel::openPanel() can return nil in rare macOS edge cases + // (e.g. code-signature mismatch after in-place app update, or system + // wake transient). The typed objc2 binding panics on nil, so we use + // a raw msg_send to handle it gracefully by cancelling the picker. + let ptr: *mut NSOpenPanel = msg_send![NSOpenPanel::class(), openPanel]; + let Some(open_panel) = Retained::retain(ptr) else { + (*handler).call((null_mut(),)); + return; + }; open_panel.setCanChooseFiles(true); let allow_multi = open_panel_params.allowsMultipleSelection(); open_panel.setAllowsMultipleSelection(allow_multi);