diff --git a/shell/browser/api/electron_api_menu.cc b/shell/browser/api/electron_api_menu.cc index 269080dba7..95bf1a1e92 100644 --- a/shell/browser/api/electron_api_menu.cc +++ b/shell/browser/api/electron_api_menu.cc @@ -68,6 +68,10 @@ Menu::Menu(gin::Arguments* args) } Menu::~Menu() { + RemoveModelObserver(); +} + +void Menu::RemoveModelObserver() { if (model_) { model_->RemoveObserver(this); } diff --git a/shell/browser/api/electron_api_menu.h b/shell/browser/api/electron_api_menu.h index fc76a0c3df..1a06968233 100644 --- a/shell/browser/api/electron_api_menu.h +++ b/shell/browser/api/electron_api_menu.h @@ -61,6 +61,10 @@ class Menu : public gin::Wrappable, ElectronMenuModel* model() const { return model_.get(); } protected: + // Remove this instance as an observer from the model. Called by derived + // class destructors to ensure observer is removed before platform-specific + // cleanup that may trigger model callbacks. + void RemoveModelObserver(); // Returns a new callback which keeps references of the JS wrapper until the // passed |callback| is called. base::OnceClosure BindSelfToClosure(base::OnceClosure callback); diff --git a/shell/browser/api/electron_api_menu_mac.mm b/shell/browser/api/electron_api_menu_mac.mm index 0d260562fc..42d7f2778c 100644 --- a/shell/browser/api/electron_api_menu_mac.mm +++ b/shell/browser/api/electron_api_menu_mac.mm @@ -51,7 +51,11 @@ namespace electron::api { MenuMac::MenuMac(gin::Arguments* args) : Menu{args} {} -MenuMac::~MenuMac() = default; +MenuMac::~MenuMac() { + // Must remove observer before destroying menu_controller_, which holds + // a weak reference to model_ + RemoveModelObserver(); +} void MenuMac::PopupAt(BaseWindow* window, std::optional frame,