refactor: make api::Menu inherit from gin::Wrappable (#48351)

* refactor: make api::Menu inherit from gin::Wrappable*

* refactor: make api::Menu::kWrapperInfo const

* refactor: use three-arg version of GetConstructor in Menu

refactor: undo branch changes to two-arg version of GetConstructor

* fixup! refactor: make api::Menu inherit from gin::Wrappable*

fix: return type of Menu::New

* fixup! refactor: make api::Menu inherit from gin::Wrappable*

make MenuMac's constructor public so that cppgc can use it

* refactor: Pinnable -> SelfKeepAlive
This commit is contained in:
Charles Kerr
2025-09-24 19:42:22 -05:00
committed by GitHub
parent 6661457cdf
commit 26a473db98
7 changed files with 56 additions and 39 deletions

View File

@@ -50,7 +50,8 @@ struct Converter<SharingItem> {
namespace electron::api {
gin::DeprecatedWrapperInfo Menu::kWrapperInfo = {gin::kEmbedderNativeGin};
const gin::WrapperInfo Menu::kWrapperInfo = {{gin::kEmbedderNativeGin},
gin::kElectronMenu};
Menu::Menu(gin::Arguments* args)
: model_(std::make_unique<ElectronMenuModel>(this)) {
@@ -268,12 +269,11 @@ bool Menu::WorksWhenHiddenAt(int index) const {
}
void Menu::OnMenuWillClose() {
Unpin();
keep_alive_.Clear();
Emit("menu-will-close");
}
void Menu::OnMenuWillShow() {
Pin(JavascriptEnvironment::GetIsolate());
Emit("menu-will-show");
}
@@ -311,8 +311,12 @@ void Menu::FillObjectTemplate(v8::Isolate* isolate,
.Build();
}
const char* Menu::GetTypeName() {
return GetClassName();
const gin::WrapperInfo* Menu::wrapper_info() const {
return &kWrapperInfo;
}
const char* Menu::GetHumanReadableName() const {
return "Electron / Menu";
}
} // namespace electron::api
@@ -327,7 +331,7 @@ void Initialize(v8::Local<v8::Object> exports,
void* priv) {
v8::Isolate* const isolate = electron::JavascriptEnvironment::GetIsolate();
gin_helper::Dictionary dict{isolate, exports};
dict.Set("Menu", Menu::GetConstructor(isolate, context));
dict.Set("Menu", Menu::GetConstructor(isolate, context, &Menu::kWrapperInfo));
#if BUILDFLAG(IS_MAC)
dict.SetMethod("setApplicationMenu", &Menu::SetApplicationMenu);
dict.SetMethod("sendActionToFirstResponder",

View File

@@ -9,11 +9,11 @@
#include <string>
#include "base/memory/raw_ptr.h"
#include "gin/wrappable.h"
#include "shell/browser/event_emitter_mixin.h"
#include "shell/browser/ui/electron_menu_model.h"
#include "shell/common/gin_helper/constructible.h"
#include "shell/common/gin_helper/pinnable.h"
#include "shell/common/gin_helper/wrappable.h"
#include "shell/common/gin_helper/self_keep_alive.h"
#include "ui/base/mojom/menu_source_type.mojom-forward.h"
namespace gin {
@@ -25,22 +25,31 @@ namespace electron::api {
class BaseWindow;
class WebFrameMain;
class Menu : public gin_helper::DeprecatedWrappable<Menu>,
class Menu : public gin::Wrappable<Menu>,
public gin_helper::EventEmitterMixin<Menu>,
public gin_helper::Constructible<Menu>,
public gin_helper::Pinnable<Menu>,
public ElectronMenuModel::Delegate,
private ElectronMenuModel::Observer {
public:
static Menu* New(gin::Arguments* args);
// Make public for cppgc::MakeGarbageCollected.
explicit Menu(gin::Arguments* args);
~Menu() override;
// disable copy
Menu(const Menu&) = delete;
Menu& operator=(const Menu&) = delete;
// gin::Wrappable
static const gin::WrapperInfo kWrapperInfo;
const gin::WrapperInfo* wrapper_info() const override;
const char* GetHumanReadableName() const override;
// gin_helper::Constructible
static gin_helper::Handle<Menu> New(gin::Arguments* args);
static void FillObjectTemplate(v8::Isolate*, v8::Local<v8::ObjectTemplate>);
static const char* GetClassName() { return "Menu"; }
// gin_helper::Wrappable
static gin::DeprecatedWrapperInfo kWrapperInfo;
const char* GetTypeName() override;
#if BUILDFLAG(IS_MAC)
// Set the global menubar.
static void SetApplicationMenu(Menu* menu);
@@ -51,14 +60,7 @@ class Menu : public gin_helper::DeprecatedWrappable<Menu>,
ElectronMenuModel* model() const { return model_.get(); }
// disable copy
Menu(const Menu&) = delete;
Menu& operator=(const Menu&) = delete;
protected:
explicit Menu(gin::Arguments* args);
~Menu() override;
// Returns a new callback which keeps references of the JS wrapper until the
// passed |callback| is called.
base::OnceClosure BindSelfToClosure(base::OnceClosure callback);
@@ -129,6 +131,8 @@ class Menu : public gin_helper::DeprecatedWrappable<Menu>,
bool IsEnabledAt(int index) const;
bool IsVisibleAt(int index) const;
bool WorksWhenHiddenAt(int index) const;
gin_helper::SelfKeepAlive<Menu> keep_alive_{this};
};
} // namespace electron::api

View File

@@ -18,10 +18,12 @@ class WebFrameMain;
namespace api {
class MenuMac : public Menu {
protected:
public:
// Make public for cppgc::MakeGarbageCollected.
explicit MenuMac(gin::Arguments* args);
~MenuMac() override;
protected:
// Menu
void PopupAt(BaseWindow* window,
std::optional<WebFrameMain*> frame,

View File

@@ -20,6 +20,8 @@
#include "shell/common/keyboard_util.h"
#include "shell/common/node_includes.h"
#include "ui/base/cocoa/menu_utils.h"
#include "v8/include/cppgc/allocation.h"
#include "v8/include/v8-cppgc.h"
namespace {
@@ -47,7 +49,7 @@ ui::Accelerator GetAcceleratorFromKeyEquivalentAndModifierMask(
namespace electron::api {
MenuMac::MenuMac(gin::Arguments* args) : Menu(args) {}
MenuMac::MenuMac(gin::Arguments* args) : Menu{args} {}
MenuMac::~MenuMac() = default;
@@ -288,11 +290,12 @@ void Menu::SendActionToFirstResponder(const std::string& action) {
}
// static
gin_helper::Handle<Menu> Menu::New(gin::Arguments* args) {
auto handle = gin_helper::CreateHandle(args->isolate(),
static_cast<Menu*>(new MenuMac(args)));
gin_helper::CallMethod(args->isolate(), handle.get(), "_init");
return handle;
Menu* Menu::New(gin::Arguments* args) {
v8::Isolate* const isolate = args->isolate();
Menu* const menu = cppgc::MakeGarbageCollected<MenuMac>(
isolate->GetCppHeap()->GetAllocationHandle(), args);
gin_helper::CallMethod(isolate, menu, "_init");
return menu;
}
} // namespace electron::api

View File

@@ -11,6 +11,8 @@
#include "shell/browser/api/electron_api_web_frame_main.h"
#include "shell/browser/native_window_views.h"
#include "ui/display/screen.h"
#include "v8/include/cppgc/allocation.h"
#include "v8/include/v8-cppgc.h"
using views::MenuRunner;
@@ -84,11 +86,12 @@ void MenuViews::OnClosed(int32_t window_id, base::OnceClosure callback) {
}
// static
gin_helper::Handle<Menu> Menu::New(gin::Arguments* args) {
auto handle = gin_helper::CreateHandle(
args->isolate(), static_cast<Menu*>(new MenuViews(args)));
gin_helper::CallMethod(args->isolate(), handle.get(), "_init");
return handle;
Menu* Menu::New(gin::Arguments* args) {
v8::Isolate* const isolate = args->isolate();
Menu* menu = cppgc::MakeGarbageCollected<MenuViews>(
isolate->GetCppHeap()->GetAllocationHandle(), args);
gin_helper::CallMethod(isolate, menu, "_init");
return menu;
}
} // namespace electron::api

View File

@@ -43,7 +43,7 @@ class Constructible {
v8::Isolate* const isolate,
v8::Local<v8::Context> context) {
gin::PerIsolateData* data = gin::PerIsolateData::From(isolate);
auto* wrapper_info = &T::kWrapperInfo;
auto* const wrapper_info = &T::kWrapperInfo;
v8::Local<v8::FunctionTemplate> constructor =
data->DeprecatedGetFunctionTemplate(wrapper_info);
if (constructor.IsEmpty()) {
@@ -67,7 +67,7 @@ class Constructible {
static v8::Local<v8::Function> GetConstructor(
v8::Isolate* const isolate,
v8::Local<v8::Context> context,
gin::WrapperInfo* wrapper_info) {
const gin::WrapperInfo* const wrapper_info) {
gin::PerIsolateData* data = gin::PerIsolateData::From(isolate);
v8::Local<v8::FunctionTemplate> constructor =
data->GetFunctionTemplate(wrapper_info);