refactor: allocate gin_helper::internal::Event on cpp heap (#48161)

This commit is contained in:
Robo 2025-08-27 09:30:50 +09:00 committed by GitHub
commit e0db4046b2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 156 additions and 116 deletions

View file

@ -8,17 +8,18 @@ electron objects that extend gin::Wrappable and gets
allocated on the cpp heap allocated on the cpp heap
diff --git a/gin/public/wrappable_pointer_tags.h b/gin/public/wrappable_pointer_tags.h diff --git a/gin/public/wrappable_pointer_tags.h b/gin/public/wrappable_pointer_tags.h
index a507d1d837ab3ec2b2d3ae7978d9d410ab2ec2d1..5a69c5c7c5ed0e834e09ff3a2d0f0126ba4ccf99 100644 index a507d1d837ab3ec2b2d3ae7978d9d410ab2ec2d1..2f4b90949972c3c4641bc9e489bd0c73c2f0a981 100644
--- a/gin/public/wrappable_pointer_tags.h --- a/gin/public/wrappable_pointer_tags.h
+++ b/gin/public/wrappable_pointer_tags.h +++ b/gin/public/wrappable_pointer_tags.h
@@ -72,7 +72,9 @@ enum WrappablePointerTag : uint16_t { @@ -72,7 +72,10 @@ enum WrappablePointerTag : uint16_t {
kTextInputControllerBindings, // content::TextInputControllerBindings kTextInputControllerBindings, // content::TextInputControllerBindings
kWebAXObjectProxy, // content::WebAXObjectProxy kWebAXObjectProxy, // content::WebAXObjectProxy
kWrappedExceptionHandler, // extensions::WrappedExceptionHandler kWrappedExceptionHandler, // extensions::WrappedExceptionHandler
- kLastPointerTag = kWrappedExceptionHandler, - kLastPointerTag = kWrappedExceptionHandler,
+ kElectronApp, // electron::api::App + kElectronApp, // electron::api::App
+ kElectronSession, // electron::api::Session + kElectronSession, // electron::api::Session
+ kLastPointerTag = kElectronSession, + kElectronEvent, // gin_helper::internal::Event
+ kLastPointerTag = kElectronEvent,
}; };
static_assert(kLastPointerTag < static_assert(kLastPointerTag <

View file

@ -194,14 +194,15 @@ void BaseWindow::OnWindowQueryEndSession(
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
gin_helper::Handle<gin_helper::internal::Event> event = gin_helper::internal::Event* event =
gin_helper::internal::Event::New(isolate); gin_helper::internal::Event::New(isolate);
v8::Local<v8::Object> event_object = event.ToV8().As<v8::Object>(); v8::Local<v8::Object> event_object =
event->GetWrapper(isolate).ToLocalChecked();
gin::Dictionary dict(isolate, event_object); gin::Dictionary dict(isolate, event_object);
dict.Set("reasons", reasons); dict.Set("reasons", reasons);
EmitWithoutEvent("query-session-end", event); EmitWithoutEvent("query-session-end", event_object);
if (event->GetDefaultPrevented()) { if (event->GetDefaultPrevented()) {
*prevent_default = true; *prevent_default = true;
} }
@ -211,14 +212,15 @@ void BaseWindow::OnWindowEndSession(const std::vector<std::string>& reasons) {
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
gin_helper::Handle<gin_helper::internal::Event> event = gin_helper::internal::Event* event =
gin_helper::internal::Event::New(isolate); gin_helper::internal::Event::New(isolate);
v8::Local<v8::Object> event_object = event.ToV8().As<v8::Object>(); v8::Local<v8::Object> event_object =
event->GetWrapper(isolate).ToLocalChecked();
gin::Dictionary dict(isolate, event_object); gin::Dictionary dict(isolate, event_object);
dict.Set("reasons", reasons); dict.Set("reasons", reasons);
EmitWithoutEvent("session-end", event); EmitWithoutEvent("session-end", event_object);
} }
void BaseWindow::OnWindowBlur() { void BaseWindow::OnWindowBlur() {

View file

@ -1117,9 +1117,10 @@ void WebContents::OnDidAddMessageToConsole(
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
gin_helper::Handle<gin_helper::internal::Event> event = gin_helper::internal::Event* event =
gin_helper::internal::Event::New(isolate); gin_helper::internal::Event::New(isolate);
v8::Local<v8::Object> event_object = event.ToV8().As<v8::Object>(); v8::Local<v8::Object> event_object =
event->GetWrapper(isolate).ToLocalChecked();
gin_helper::Dictionary dict(isolate, event_object); gin_helper::Dictionary dict(isolate, event_object);
dict.SetGetter("frame", source_frame); dict.SetGetter("frame", source_frame);
@ -1131,7 +1132,7 @@ void WebContents::OnDidAddMessageToConsole(
// TODO(samuelmaddock): Delete when deprecated arguments are fully removed. // TODO(samuelmaddock): Delete when deprecated arguments are fully removed.
dict.Set("_level", static_cast<int32_t>(level)); dict.Set("_level", static_cast<int32_t>(level));
EmitWithoutEvent("-console-message", event); EmitWithoutEvent("-console-message", event_object);
} }
void WebContents::OnCreateWindow( void WebContents::OnCreateWindow(
@ -1515,9 +1516,10 @@ void WebContents::RendererUnresponsive(
base::RepeatingClosure hang_monitor_restarter) { base::RepeatingClosure hang_monitor_restarter) {
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
gin_helper::Handle<gin_helper::internal::Event> event = gin_helper::internal::Event* event =
gin_helper::internal::Event::New(isolate); gin_helper::internal::Event::New(isolate);
v8::Local<v8::Object> event_object = event.ToV8().As<v8::Object>(); v8::Local<v8::Object> event_object =
event->GetWrapper(isolate).ToLocalChecked();
gin::Dictionary dict(isolate, event_object); gin::Dictionary dict(isolate, event_object);
auto* web_contents_impl = static_cast<content::WebContentsImpl*>(source); auto* web_contents_impl = static_cast<content::WebContentsImpl*>(source);
@ -1531,7 +1533,7 @@ void WebContents::RendererUnresponsive(
static_cast<content::RenderWidgetHostImpl*>(render_widget_host); static_cast<content::RenderWidgetHostImpl*>(render_widget_host);
dict.Set("rendererInitialized", rwh_impl->renderer_initialized()); dict.Set("rendererInitialized", rwh_impl->renderer_initialized());
EmitWithoutEvent("-unresponsive", event); EmitWithoutEvent("-unresponsive", event_object);
} }
void WebContents::RendererResponsive( void WebContents::RendererResponsive(
@ -1700,12 +1702,13 @@ content::JavaScriptDialogManager* WebContents::GetJavaScriptDialogManager(
void WebContents::OnAudioStateChanged(bool audible) { void WebContents::OnAudioStateChanged(bool audible) {
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
gin_helper::Handle<gin_helper::internal::Event> event = gin_helper::internal::Event* event =
gin_helper::internal::Event::New(isolate); gin_helper::internal::Event::New(isolate);
v8::Local<v8::Object> event_object = event.ToV8().As<v8::Object>(); v8::Local<v8::Object> event_object =
event->GetWrapper(isolate).ToLocalChecked();
gin::Dictionary dict(isolate, event_object); gin::Dictionary dict(isolate, event_object);
dict.Set("audible", audible); dict.Set("audible", audible);
EmitWithoutEvent("audio-state-changed", event); EmitWithoutEvent("audio-state-changed", event_object);
} }
void WebContents::BeforeUnloadFired(bool proceed) { void WebContents::BeforeUnloadFired(bool proceed) {
@ -1968,9 +1971,10 @@ bool WebContents::EmitNavigationEvent(
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
gin_helper::Handle<gin_helper::internal::Event> event = gin_helper::internal::Event* event =
gin_helper::internal::Event::New(isolate); gin_helper::internal::Event::New(isolate);
v8::Local<v8::Object> event_object = event.ToV8().As<v8::Object>(); v8::Local<v8::Object> event_object =
event->GetWrapper(isolate).ToLocalChecked();
gin_helper::Dictionary dict(isolate, event_object); gin_helper::Dictionary dict(isolate, event_object);
dict.Set("url", url); dict.Set("url", url);
@ -1981,8 +1985,8 @@ bool WebContents::EmitNavigationEvent(
dict.SetGetter("frame", frame_host); dict.SetGetter("frame", frame_host);
dict.SetGetter("initiator", initiator_frame_host); dict.SetGetter("initiator", initiator_frame_host);
EmitWithoutEvent(event_name, event, url, is_same_document, is_main_frame, EmitWithoutEvent(event_name, event_object, url, is_same_document,
frame_process_id, frame_routing_id); is_main_frame, frame_process_id, frame_routing_id);
return event->GetDefaultPrevented(); return event->GetDefaultPrevented();
} }
@ -3632,16 +3636,17 @@ void WebContents::OnPaint(const gfx::Rect& dirty_rect,
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
gin_helper::Handle<gin_helper::internal::Event> event = gin_helper::internal::Event* event =
gin_helper::internal::Event::New(isolate); gin_helper::internal::Event::New(isolate);
v8::Local<v8::Object> event_object = event.ToV8().As<v8::Object>(); v8::Local<v8::Object> event_object =
event->GetWrapper(isolate).ToLocalChecked();
gin_helper::Dictionary dict(isolate, event_object); gin_helper::Dictionary dict(isolate, event_object);
if (offscreen_use_shared_texture_) { if (offscreen_use_shared_texture_) {
dict.Set("texture", tex); dict.Set("texture", tex);
} }
EmitWithoutEvent("paint", event, dirty_rect, EmitWithoutEvent("paint", event_object, dirty_rect,
gfx::Image::CreateFrom1xBitmap(bitmap)); gfx::Image::CreateFrom1xBitmap(bitmap));
} }

View file

@ -18,6 +18,7 @@
#include "shell/common/gin_helper/handle.h" #include "shell/common/gin_helper/handle.h"
#include "shell/common/gin_helper/reply_channel.h" #include "shell/common/gin_helper/reply_channel.h"
#include "shell/common/v8_util.h" #include "shell/common/v8_util.h"
#include "v8/include/cppgc/macros.h"
namespace electron { namespace electron {
@ -25,15 +26,17 @@ namespace electron {
// See ipc-dispatch.ts for JS listeners. // See ipc-dispatch.ts for JS listeners.
template <typename T> template <typename T>
class IpcDispatcher { class IpcDispatcher {
CPPGC_DISALLOW_NEW();
public: public:
void Message(gin_helper::Handle<gin_helper::internal::Event>& event, void Message(v8::Local<v8::Object> event,
const std::string& channel, const std::string& channel,
blink::CloneableMessage args) { blink::CloneableMessage args) {
TRACE_EVENT1("electron", "IpcDispatcher::Message", "channel", channel); TRACE_EVENT1("electron", "IpcDispatcher::Message", "channel", channel);
emitter()->EmitWithoutEvent("-ipc-message", event, channel, args); emitter()->EmitWithoutEvent("-ipc-message", event, channel, args);
} }
void Invoke(gin_helper::Handle<gin_helper::internal::Event>& event, void Invoke(v8::Local<v8::Object> event,
const std::string& channel, const std::string& channel,
blink::CloneableMessage arguments) { blink::CloneableMessage arguments) {
TRACE_EVENT1("electron", "IpcDispatcher::Invoke", "channel", channel); TRACE_EVENT1("electron", "IpcDispatcher::Invoke", "channel", channel);
@ -41,10 +44,9 @@ class IpcDispatcher {
std::move(arguments)); std::move(arguments));
} }
void ReceivePostMessage( void ReceivePostMessage(v8::Local<v8::Object> event,
gin_helper::Handle<gin_helper::internal::Event>& event, const std::string& channel,
const std::string& channel, blink::TransferableMessage message) {
blink::TransferableMessage message) {
TRACE_EVENT1("electron", "IpcDispatcher::ReceivePostMessage", "channel", TRACE_EVENT1("electron", "IpcDispatcher::ReceivePostMessage", "channel",
channel); channel);
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
@ -57,7 +59,7 @@ class IpcDispatcher {
std::move(wrapped_ports)); std::move(wrapped_ports));
} }
void MessageSync(gin_helper::Handle<gin_helper::internal::Event>& event, void MessageSync(v8::Local<v8::Object> event,
const std::string& channel, const std::string& channel,
blink::CloneableMessage arguments) { blink::CloneableMessage arguments) {
TRACE_EVENT1("electron", "IpcDispatcher::MessageSync", "channel", channel); TRACE_EVENT1("electron", "IpcDispatcher::MessageSync", "channel", channel);
@ -65,7 +67,7 @@ class IpcDispatcher {
std::move(arguments)); std::move(arguments));
} }
void MessageHost(gin_helper::Handle<gin_helper::internal::Event>& event, void MessageHost(v8::Local<v8::Object> event,
const std::string& channel, const std::string& channel,
blink::CloneableMessage arguments) { blink::CloneableMessage arguments) {
TRACE_EVENT1("electron", "IpcDispatcher::MessageHost", "channel", channel); TRACE_EVENT1("electron", "IpcDispatcher::MessageHost", "channel", channel);

View file

@ -48,10 +48,10 @@ void ElectronApiIPCHandlerImpl::Message(bool internal,
if (session && session->Get()) { if (session && session->Get()) {
v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
auto event = MakeIPCEvent(isolate, session->Get(), internal); auto* event = MakeIPCEvent(isolate, session->Get(), internal);
if (event.IsEmpty()) v8::Local<v8::Object> event_object =
return; event->GetWrapper(isolate).ToLocalChecked();
session->Get()->Message(event, channel, std::move(arguments)); session->Get()->Message(event_object, channel, std::move(arguments));
} }
} }
void ElectronApiIPCHandlerImpl::Invoke(bool internal, void ElectronApiIPCHandlerImpl::Invoke(bool internal,
@ -62,11 +62,11 @@ void ElectronApiIPCHandlerImpl::Invoke(bool internal,
if (session && session->Get()) { if (session && session->Get()) {
v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
auto event = auto* event =
MakeIPCEvent(isolate, session->Get(), internal, std::move(callback)); MakeIPCEvent(isolate, session->Get(), internal, std::move(callback));
if (event.IsEmpty()) v8::Local<v8::Object> event_object =
return; event->GetWrapper(isolate).ToLocalChecked();
session->Get()->Invoke(event, channel, std::move(arguments)); session->Get()->Invoke(event_object, channel, std::move(arguments));
} }
} }
@ -77,10 +77,11 @@ void ElectronApiIPCHandlerImpl::ReceivePostMessage(
if (session && session->Get()) { if (session && session->Get()) {
v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
auto event = MakeIPCEvent(isolate, session->Get(), false); auto* event = MakeIPCEvent(isolate, session->Get(), false);
if (event.IsEmpty()) v8::Local<v8::Object> event_object =
return; event->GetWrapper(isolate).ToLocalChecked();
session->Get()->ReceivePostMessage(event, channel, std::move(message)); session->Get()->ReceivePostMessage(event_object, channel,
std::move(message));
} }
} }
@ -92,11 +93,11 @@ void ElectronApiIPCHandlerImpl::MessageSync(bool internal,
if (session && session->Get()) { if (session && session->Get()) {
v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
auto event = auto* event =
MakeIPCEvent(isolate, session->Get(), internal, std::move(callback)); MakeIPCEvent(isolate, session->Get(), internal, std::move(callback));
if (event.IsEmpty()) v8::Local<v8::Object> event_object =
return; event->GetWrapper(isolate).ToLocalChecked();
session->Get()->MessageSync(event, channel, std::move(arguments)); session->Get()->MessageSync(event_object, channel, std::move(arguments));
} }
} }
@ -106,10 +107,10 @@ void ElectronApiIPCHandlerImpl::MessageHost(const std::string& channel,
if (session && session->Get()) { if (session && session->Get()) {
v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
auto event = MakeIPCEvent(isolate, session->Get(), false); auto* event = MakeIPCEvent(isolate, session->Get(), false);
if (event.IsEmpty()) v8::Local<v8::Object> event_object =
return; event->GetWrapper(isolate).ToLocalChecked();
session->Get()->MessageHost(event, channel, std::move(arguments)); session->Get()->MessageHost(event_object, channel, std::move(arguments));
} }
} }
@ -123,8 +124,7 @@ gin::WeakCell<api::Session>* ElectronApiIPCHandlerImpl::GetSession() {
: nullptr; : nullptr;
} }
gin_helper::Handle<gin_helper::internal::Event> gin_helper::internal::Event* ElectronApiIPCHandlerImpl::MakeIPCEvent(
ElectronApiIPCHandlerImpl::MakeIPCEvent(
v8::Isolate* isolate, v8::Isolate* isolate,
api::Session* session, api::Session* session,
bool internal, bool internal,
@ -159,9 +159,11 @@ ElectronApiIPCHandlerImpl::MakeIPCEvent(
} }
content::RenderFrameHost* frame = GetRenderFrameHost(); content::RenderFrameHost* frame = GetRenderFrameHost();
gin_helper::Handle<gin_helper::internal::Event> event = gin_helper::internal::Event* event =
gin_helper::internal::Event::New(isolate); gin_helper::internal::Event::New(isolate);
gin_helper::Dictionary dict(isolate, event.ToV8().As<v8::Object>()); v8::Local<v8::Object> event_object =
event->GetWrapper(isolate).ToLocalChecked();
gin_helper::Dictionary dict(isolate, event_object);
dict.Set("type", "frame"); dict.Set("type", "frame");
dict.Set("sender", web_contents()); dict.Set("sender", web_contents());
if (internal) if (internal)

View file

@ -72,7 +72,7 @@ class ElectronApiIPCHandlerImpl : public mojom::ElectronApiIPC,
content::RenderFrameHost* GetRenderFrameHost(); content::RenderFrameHost* GetRenderFrameHost();
gin::WeakCell<api::Session>* GetSession(); gin::WeakCell<api::Session>* GetSession();
gin_helper::Handle<gin_helper::internal::Event> MakeIPCEvent( gin_helper::internal::Event* MakeIPCEvent(
v8::Isolate* isolate, v8::Isolate* isolate,
api::Session* session, api::Session* session,
bool internal, bool internal,

View file

@ -75,10 +75,10 @@ void ElectronApiSWIPCHandlerImpl::Message(bool internal,
if (session && session->Get()) { if (session && session->Get()) {
v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
auto event = MakeIPCEvent(isolate, session->Get(), internal); auto* event = MakeIPCEvent(isolate, session->Get(), internal);
if (event.IsEmpty()) v8::Local<v8::Object> event_object =
return; event->GetWrapper(isolate).ToLocalChecked();
session->Get()->Message(event, channel, std::move(arguments)); session->Get()->Message(event_object, channel, std::move(arguments));
} }
} }
@ -90,11 +90,11 @@ void ElectronApiSWIPCHandlerImpl::Invoke(bool internal,
if (session && session->Get()) { if (session && session->Get()) {
v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
auto event = auto* event =
MakeIPCEvent(isolate, session->Get(), internal, std::move(callback)); MakeIPCEvent(isolate, session->Get(), internal, std::move(callback));
if (event.IsEmpty()) v8::Local<v8::Object> event_object =
return; event->GetWrapper(isolate).ToLocalChecked();
session->Get()->Invoke(event, channel, std::move(arguments)); session->Get()->Invoke(event_object, channel, std::move(arguments));
} }
} }
@ -105,10 +105,11 @@ void ElectronApiSWIPCHandlerImpl::ReceivePostMessage(
if (session && session->Get()) { if (session && session->Get()) {
v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
auto event = MakeIPCEvent(isolate, session->Get(), false); auto* event = MakeIPCEvent(isolate, session->Get(), false);
if (event.IsEmpty()) v8::Local<v8::Object> event_object =
return; event->GetWrapper(isolate).ToLocalChecked();
session->Get()->ReceivePostMessage(event, channel, std::move(message)); session->Get()->ReceivePostMessage(event_object, channel,
std::move(message));
} }
} }
@ -120,11 +121,11 @@ void ElectronApiSWIPCHandlerImpl::MessageSync(bool internal,
if (session && session->Get()) { if (session && session->Get()) {
v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
auto event = auto* event =
MakeIPCEvent(isolate, session->Get(), internal, std::move(callback)); MakeIPCEvent(isolate, session->Get(), internal, std::move(callback));
if (event.IsEmpty()) v8::Local<v8::Object> event_object =
return; event->GetWrapper(isolate).ToLocalChecked();
session->Get()->MessageSync(event, channel, std::move(arguments)); session->Get()->MessageSync(event_object, channel, std::move(arguments));
} }
} }
@ -144,8 +145,7 @@ gin::WeakCell<api::Session>* ElectronApiSWIPCHandlerImpl::GetSession() {
return api::Session::FromBrowserContext(GetBrowserContext()); return api::Session::FromBrowserContext(GetBrowserContext());
} }
gin_helper::Handle<gin_helper::internal::Event> gin_helper::internal::Event* ElectronApiSWIPCHandlerImpl::MakeIPCEvent(
ElectronApiSWIPCHandlerImpl::MakeIPCEvent(
v8::Isolate* isolate, v8::Isolate* isolate,
api::Session* session, api::Session* session,
bool internal, bool internal,
@ -159,9 +159,10 @@ ElectronApiSWIPCHandlerImpl::MakeIPCEvent(
return {}; return {};
} }
gin_helper::Handle<gin_helper::internal::Event> event = gin_helper::internal::Event* event =
gin_helper::internal::Event::New(isolate); gin_helper::internal::Event::New(isolate);
v8::Local<v8::Object> event_object = event.ToV8().As<v8::Object>(); v8::Local<v8::Object> event_object =
event->GetWrapper(isolate).ToLocalChecked();
gin_helper::Dictionary dict(isolate, event_object); gin_helper::Dictionary dict(isolate, event_object);
dict.Set("type", "service-worker"); dict.Set("type", "service-worker");

View file

@ -13,7 +13,6 @@
#include "electron/shell/common/api/api.mojom.h" #include "electron/shell/common/api/api.mojom.h"
#include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/associated_receiver.h"
#include "shell/common/gin_helper/event.h" #include "shell/common/gin_helper/event.h"
#include "shell/common/gin_helper/handle.h"
namespace content { namespace content {
class RenderProcessHost; class RenderProcessHost;
@ -75,7 +74,7 @@ class ElectronApiSWIPCHandlerImpl : public mojom::ElectronApiIPC,
ElectronBrowserContext* GetBrowserContext(); ElectronBrowserContext* GetBrowserContext();
gin::WeakCell<api::Session>* GetSession(); gin::WeakCell<api::Session>* GetSession();
gin_helper::Handle<gin_helper::internal::Event> MakeIPCEvent( gin_helper::internal::Event* MakeIPCEvent(
v8::Isolate* isolate, v8::Isolate* isolate,
api::Session* session, api::Session* session,
bool internal, bool internal,

View file

@ -48,9 +48,10 @@ void ElectronNSSCryptoModuleDelegate::RequestPasswordOnUIThread(
v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate(); v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate); v8::HandleScope handle_scope(isolate);
gin_helper::Handle<gin_helper::internal::Event> event = gin_helper::internal::Event* event =
gin_helper::internal::Event::New(isolate); gin_helper::internal::Event::New(isolate);
v8::Local<v8::Object> event_object = event.ToV8().As<v8::Object>(); v8::Local<v8::Object> event_object =
event->GetWrapper(isolate).ToLocalChecked();
gin_helper::Dictionary dict(isolate, event_object); gin_helper::Dictionary dict(isolate, event_object);
dict.Set("hostname", server_.host()); dict.Set("hostname", server_.host());
dict.Set("tokenName", token_name); dict.Set("tokenName", token_name);

View file

@ -32,8 +32,10 @@ class EventEmitterMixin {
v8::Local<v8::Object> wrapper; v8::Local<v8::Object> wrapper;
if (!static_cast<T*>(this)->GetWrapper(isolate).ToLocal(&wrapper)) if (!static_cast<T*>(this)->GetWrapper(isolate).ToLocal(&wrapper))
return false; return false;
gin_helper::Handle<internal::Event> event = internal::Event::New(isolate); internal::Event* event = internal::Event::New(isolate);
gin_helper::EmitEvent(isolate, wrapper, name, event, v8::Local<v8::Object> event_object =
event->GetWrapper(isolate).ToLocalChecked();
gin_helper::EmitEvent(isolate, wrapper, name, event_object,
std::forward<Args>(args)...); std::forward<Args>(args)...);
return event->GetDefaultPrevented(); return event->GetDefaultPrevented();
} }

View file

@ -3,21 +3,24 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "shell/common/gin_helper/event.h" #include "shell/common/gin_helper/event.h"
#include "gin/dictionary.h"
#include "gin/object_template_builder.h" #include "gin/object_template_builder.h"
#include "shell/common/gin_helper/handle.h" #include "v8/include/cppgc/allocation.h"
#include "v8/include/v8-cppgc.h"
namespace gin_helper::internal { namespace gin_helper::internal {
// static // static
gin_helper::Handle<Event> Event::New(v8::Isolate* isolate) { Event* Event::New(v8::Isolate* isolate) {
return gin_helper::CreateHandle(isolate, new Event()); auto* event = cppgc::MakeGarbageCollected<Event>(
isolate->GetCppHeap()->GetAllocationHandle());
return event;
} }
// static // static
v8::Local<v8::ObjectTemplate> Event::FillObjectTemplate( v8::Local<v8::ObjectTemplate> Event::FillObjectTemplate(
v8::Isolate* isolate, v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> templ) { v8::Local<v8::ObjectTemplate> templ) {
return gin::ObjectTemplateBuilder(isolate, "Event", templ) return gin::ObjectTemplateBuilder(isolate, GetClassName(), templ)
.SetMethod("preventDefault", &Event::PreventDefault) .SetMethod("preventDefault", &Event::PreventDefault)
.SetProperty("defaultPrevented", &Event::GetDefaultPrevented) .SetProperty("defaultPrevented", &Event::GetDefaultPrevented)
.Build(); .Build();
@ -27,10 +30,15 @@ Event::Event() = default;
Event::~Event() = default; Event::~Event() = default;
gin::DeprecatedWrapperInfo Event::kWrapperInfo = {gin::kEmbedderNativeGin}; gin::WrapperInfo Event::kWrapperInfo = {{gin::kEmbedderNativeGin},
gin::kElectronEvent};
const char* Event::GetTypeName() { const gin::WrapperInfo* Event::wrapper_info() const {
return GetClassName(); return &kWrapperInfo;
}
const char* Event::GetHumanReadableName() const {
return "Electron / Event";
} }
} // namespace gin_helper::internal } // namespace gin_helper::internal

View file

@ -5,38 +5,27 @@
#ifndef ELECTRON_SHELL_COMMON_GIN_HELPER_EVENT_H_ #ifndef ELECTRON_SHELL_COMMON_GIN_HELPER_EVENT_H_
#define ELECTRON_SHELL_COMMON_GIN_HELPER_EVENT_H_ #define ELECTRON_SHELL_COMMON_GIN_HELPER_EVENT_H_
#include "gin/wrappable.h"
#include "shell/common/gin_helper/constructible.h" #include "shell/common/gin_helper/constructible.h"
#include "shell/common/gin_helper/wrappable.h"
namespace gin_helper {
template <typename T>
class Handle;
} // namespace gin_helper
namespace v8 {
class Isolate;
template <typename T>
class Local;
class Object;
class ObjectTemplate;
} // namespace v8
namespace gin_helper::internal { namespace gin_helper::internal {
class Event final : public gin_helper::DeprecatedWrappable<Event>, class Event final : public gin::Wrappable<Event>,
public gin_helper::Constructible<Event> { public gin_helper::Constructible<Event> {
public: public:
// gin_helper::Constructible // gin_helper::Constructible
static gin_helper::Handle<Event> New(v8::Isolate* isolate); static Event* New(v8::Isolate* isolate);
static v8::Local<v8::ObjectTemplate> FillObjectTemplate( static v8::Local<v8::ObjectTemplate> FillObjectTemplate(
v8::Isolate* isolate, v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> prototype); v8::Local<v8::ObjectTemplate> prototype);
static const char* GetClassName() { return "Event"; } static const char* GetClassName() { return "Event"; }
// gin_helper::Wrappable // gin::Wrappable
static gin::DeprecatedWrapperInfo kWrapperInfo; static gin::WrapperInfo kWrapperInfo;
const char* GetTypeName() override; const gin::WrapperInfo* wrapper_info() const override;
const char* GetHumanReadableName() const override;
Event();
~Event() override; ~Event() override;
void PreventDefault() { default_prevented_ = true; } void PreventDefault() { default_prevented_ = true; }
@ -44,8 +33,6 @@ class Event final : public gin_helper::DeprecatedWrappable<Event>,
bool GetDefaultPrevented() { return default_prevented_; } bool GetDefaultPrevented() { return default_prevented_; }
private: private:
Event();
bool default_prevented_ = false; bool default_prevented_ = false;
}; };

View file

@ -31,10 +31,13 @@ class EventEmitter : public gin_helper::Wrappable<T> {
v8::Local<v8::Object> wrapper = this->GetWrapper(); v8::Local<v8::Object> wrapper = this->GetWrapper();
if (wrapper.IsEmpty()) if (wrapper.IsEmpty())
return false; return false;
gin_helper::Handle<internal::Event> event = internal::Event::New(isolate); internal::Event* event = internal::Event::New(isolate);
v8::Local<v8::Object> event_object =
event->GetWrapper(isolate).ToLocalChecked();
// It's possible that |this| will be deleted by EmitEvent, so save anything // It's possible that |this| will be deleted by EmitEvent, so save anything
// we need from |this| before calling EmitEvent. // we need from |this| before calling EmitEvent.
EmitEvent(isolate, wrapper, name, event, std::forward<Args>(args)...); EmitEvent(isolate, wrapper, name, event_object,
std::forward<Args>(args)...);
return event->GetDefaultPrevented(); return event->GetDefaultPrevented();
} }

View file

@ -644,7 +644,8 @@ void NodeBindings::Initialize(v8::Isolate* const isolate,
SetErrorMode(GetErrorMode() & ~SEM_NOGPFAULTERRORBOX); SetErrorMode(GetErrorMode() & ~SEM_NOGPFAULTERRORBOX);
#endif #endif
gin_helper::internal::Event::GetConstructor(isolate, context); gin_helper::internal::Event::GetConstructor(
isolate, context, &gin_helper::internal::Event::kWrapperInfo);
g_is_initialized = true; g_is_initialized = true;
} }

View file

@ -76,4 +76,30 @@ describe('cpp heap', () => {
expect(result).to.equal(true); expect(result).to.equal(true);
}); });
}); });
describe('internal event', () => {
it('should record as node in heap snapshot', async () => {
const { remotely } = await startRemoteControlApp(['--expose-internals']);
const result = await remotely(async (heap: string, snapshotHelper: string) => {
const { BrowserWindow } = require('electron');
const { once } = require('node:events');
const { recordState } = require(heap);
const { containsRetainingPath } = require(snapshotHelper);
const w = new BrowserWindow({
show: false
});
await w.loadURL('about:blank');
const state = recordState();
const isClosed = once(w, 'closed');
w.destroy();
await isClosed;
const eventNativeStackReference = containsRetainingPath(state.snapshot, ['C++ native stack roots', 'Electron / Event']);
const noPersistentReference = !containsRetainingPath(state.snapshot, ['C++ Persistent roots', 'Electron / Event']);
return eventNativeStackReference && noPersistentReference;
}, path.join(__dirname, '../../third_party/electron_node/test/common/heap'),
path.join(__dirname, 'lib', 'heapsnapshot-helpers.js'));
expect(result).to.equal(true);
});
});
}); });