Files
electron/shell/browser/api/electron_api_debugger.h
RoboandSamuel Attard 1e1ddcc3d9 refactor: add a native peer helper for cppgc wrappers (#54410)
* refactor: add a native peer helper for cppgc wrappers

cppgc wrapper destructors run during sweeping, where they must not touch
other GC objects, run JavaScript, or tear down native registrations.
Debugger, Notification and WebContents each hand rolled an off-heap peer
for this.

Add NativePeer<Wrapper>, which owns native registrations, resources, and
independent V8 roots for a wrapper. The wrapper's deleter only queues the
peer. Queued peers are released and deleted from a posted task. At
shutdown they are released while V8 can still run and deleted after the
isolate is disposed, so peer teardown never runs inside a cppgc finalizer
and nothing leaks.

* chore: apply review feedback

Co-authored-by: Samuel Attard <sam@electronjs.org>

* chore: apply review feedback

Co-authored-by: Samuel Attard <sam@electronjs.org>

---------

Co-authored-by: Samuel Attard <sam@electronjs.org>
2026-09-28 16:58:43 +00:00

68 lines
1.9 KiB
C++

// Copyright (c) 2016 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ELECTRON_SHELL_BROWSER_API_ELECTRON_API_DEBUGGER_H_
#define ELECTRON_SHELL_BROWSER_API_ELECTRON_API_DEBUGGER_H_
#include <memory>
#include <string>
#include "base/values.h"
#include "gin/wrappable.h"
#include "shell/browser/event_emitter_mixin.h"
#include "shell/browser/native_peer.h"
namespace content {
class DevToolsAgentHost;
class WebContents;
} // namespace content
namespace gin {
class Arguments;
} // namespace gin
namespace electron::api {
class Debugger final : public gin::Wrappable<Debugger>,
public gin_helper::EventEmitterMixin<Debugger> {
public:
static Debugger* Create(v8::Isolate* isolate,
content::WebContents* web_contents);
// Make public for cppgc::MakeGarbageCollected.
explicit Debugger(content::WebContents* web_contents);
~Debugger() override;
// gin_helper::Wrappable
static gin::WrapperInfo kWrapperInfo;
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override;
const gin::WrapperInfo* wrapper_info() const override;
const char* GetHumanReadableName() const override;
const char* GetClassName() const { return "Debugger"; }
// disable copy
Debugger(const Debugger&) = delete;
Debugger& operator=(const Debugger&) = delete;
private:
class AgentHostLifecycle;
void AgentHostClosed();
void EmitProtocolMessage(const std::string& method,
base::DictValue params,
const std::string& session_id);
void Attach(gin::Arguments* args);
bool IsAttached();
void Detach();
v8::Local<v8::Promise> SendCommand(gin::Arguments* args);
std::unique_ptr<AgentHostLifecycle, NativePeerBase::Deleter>
agent_host_lifecycle_;
};
} // namespace electron::api
#endif // ELECTRON_SHELL_BROWSER_API_ELECTRON_API_DEBUGGER_H_