fix: set prototype names on gin::Constructible classes (#39006)

* fix: set prototype names on gin::Constructible classes

* test: add tests
This commit is contained in:
Shelley Vohr 2023-07-10 11:49:20 +02:00 committed by GitHub
parent 56b5c00312
commit c7bdd907d7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
23 changed files with 71 additions and 15 deletions

View file

@ -198,7 +198,7 @@ v8::Local<v8::Value> BrowserView::GetWebContents(v8::Isolate* isolate) {
// static // static
void BrowserView::FillObjectTemplate(v8::Isolate* isolate, void BrowserView::FillObjectTemplate(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> templ) { v8::Local<v8::ObjectTemplate> templ) {
gin::ObjectTemplateBuilder(isolate, "BrowserView", templ) gin::ObjectTemplateBuilder(isolate, GetClassName(), templ)
.SetMethod("setAutoResize", &BrowserView::SetAutoResize) .SetMethod("setAutoResize", &BrowserView::SetAutoResize)
.SetMethod("setBounds", &BrowserView::SetBounds) .SetMethod("setBounds", &BrowserView::SetBounds)
.SetMethod("getBounds", &BrowserView::GetBounds) .SetMethod("getBounds", &BrowserView::GetBounds)
@ -207,6 +207,10 @@ void BrowserView::FillObjectTemplate(v8::Isolate* isolate,
.Build(); .Build();
} }
const char* BrowserView::GetTypeName() {
return GetClassName();
}
} // namespace electron::api } // namespace electron::api
namespace { namespace {

View file

@ -45,9 +45,11 @@ class BrowserView : public gin::Wrappable<BrowserView>,
static gin::Handle<BrowserView> New(gin_helper::ErrorThrower thrower, static gin::Handle<BrowserView> New(gin_helper::ErrorThrower thrower,
gin::Arguments* args); gin::Arguments* args);
static void FillObjectTemplate(v8::Isolate*, v8::Local<v8::ObjectTemplate>); static void FillObjectTemplate(v8::Isolate*, v8::Local<v8::ObjectTemplate>);
static const char* GetClassName() { return "BrowserView"; }
// gin::Wrappable // gin::Wrappable
static gin::WrapperInfo kWrapperInfo; static gin::WrapperInfo kWrapperInfo;
const char* GetTypeName() override;
WebContents* web_contents() const { return api_web_contents_; } WebContents* web_contents() const { return api_web_contents_; }
NativeBrowserView* view() const { return view_.get(); } NativeBrowserView* view() const { return view_.get(); }

View file

@ -299,6 +299,10 @@ void Menu::FillObjectTemplate(v8::Isolate* isolate,
.Build(); .Build();
} }
const char* Menu::GetTypeName() {
return GetClassName();
}
} // namespace electron::api } // namespace electron::api
namespace { namespace {

View file

@ -29,9 +29,11 @@ class Menu : public gin::Wrappable<Menu>,
// gin_helper::Constructible // gin_helper::Constructible
static gin::Handle<Menu> New(gin::Arguments* args); static gin::Handle<Menu> New(gin::Arguments* args);
static void FillObjectTemplate(v8::Isolate*, v8::Local<v8::ObjectTemplate>); static void FillObjectTemplate(v8::Isolate*, v8::Local<v8::ObjectTemplate>);
static const char* GetClassName() { return "Menu"; }
// gin::Wrappable // gin::Wrappable
static gin::WrapperInfo kWrapperInfo; static gin::WrapperInfo kWrapperInfo;
const char* GetTypeName() override;
#if BUILDFLAG(IS_MAC) #if BUILDFLAG(IS_MAC)
// Set the global menubar. // Set the global menubar.

View file

@ -256,7 +256,7 @@ bool Notification::IsSupported() {
void Notification::FillObjectTemplate(v8::Isolate* isolate, void Notification::FillObjectTemplate(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> templ) { v8::Local<v8::ObjectTemplate> templ) {
gin::ObjectTemplateBuilder(isolate, "Notification", templ) gin::ObjectTemplateBuilder(isolate, GetClassName(), templ)
.SetMethod("show", &Notification::Show) .SetMethod("show", &Notification::Show)
.SetMethod("close", &Notification::Close) .SetMethod("close", &Notification::Close)
.SetProperty("title", &Notification::GetTitle, &Notification::SetTitle) .SetProperty("title", &Notification::GetTitle, &Notification::SetTitle)
@ -282,6 +282,10 @@ void Notification::FillObjectTemplate(v8::Isolate* isolate,
.Build(); .Build();
} }
const char* Notification::GetTypeName() {
return GetClassName();
}
} // namespace electron::api } // namespace electron::api
namespace { namespace {

View file

@ -40,6 +40,7 @@ class Notification : public gin::Wrappable<Notification>,
static gin::Handle<Notification> New(gin_helper::ErrorThrower thrower, static gin::Handle<Notification> New(gin_helper::ErrorThrower thrower,
gin::Arguments* args); gin::Arguments* args);
static void FillObjectTemplate(v8::Isolate*, v8::Local<v8::ObjectTemplate>); static void FillObjectTemplate(v8::Isolate*, v8::Local<v8::ObjectTemplate>);
static const char* GetClassName() { return "Notification"; }
// NotificationDelegate: // NotificationDelegate:
void NotificationAction(int index) override; void NotificationAction(int index) override;
@ -52,6 +53,7 @@ class Notification : public gin::Wrappable<Notification>,
// gin::Wrappable // gin::Wrappable
static gin::WrapperInfo kWrapperInfo; static gin::WrapperInfo kWrapperInfo;
const char* GetTypeName() override;
// disable copy // disable copy
Notification(const Notification&) = delete; Notification(const Notification&) = delete;

View file

@ -283,7 +283,7 @@ gin::Handle<Protocol> Protocol::New(gin_helper::ErrorThrower thrower) {
v8::Local<v8::ObjectTemplate> Protocol::FillObjectTemplate( v8::Local<v8::ObjectTemplate> Protocol::FillObjectTemplate(
v8::Isolate* isolate, v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> tmpl) { v8::Local<v8::ObjectTemplate> tmpl) {
return gin::ObjectTemplateBuilder(isolate, "Protocol", tmpl) return gin::ObjectTemplateBuilder(isolate, GetClassName(), tmpl)
.SetMethod("registerStringProtocol", .SetMethod("registerStringProtocol",
&Protocol::RegisterProtocolFor<ProtocolType::kString>) &Protocol::RegisterProtocolFor<ProtocolType::kString>)
.SetMethod("registerBufferProtocol", .SetMethod("registerBufferProtocol",
@ -317,7 +317,7 @@ v8::Local<v8::ObjectTemplate> Protocol::FillObjectTemplate(
} }
const char* Protocol::GetTypeName() { const char* Protocol::GetTypeName() {
return "Protocol"; return GetClassName();
} }
} // namespace electron::api } // namespace electron::api

View file

@ -45,13 +45,15 @@ class Protocol : public gin::Wrappable<Protocol>,
static gin::Handle<Protocol> Create(v8::Isolate* isolate, static gin::Handle<Protocol> Create(v8::Isolate* isolate,
ElectronBrowserContext* browser_context); ElectronBrowserContext* browser_context);
// gin_helper::Constructible
static gin::Handle<Protocol> New(gin_helper::ErrorThrower thrower); static gin::Handle<Protocol> New(gin_helper::ErrorThrower thrower);
// gin::Wrappable
static gin::WrapperInfo kWrapperInfo;
static v8::Local<v8::ObjectTemplate> FillObjectTemplate( static v8::Local<v8::ObjectTemplate> FillObjectTemplate(
v8::Isolate* isolate, v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> tmpl); v8::Local<v8::ObjectTemplate> tmpl);
static const char* GetClassName() { return "Protocol"; }
// gin::Wrappable
static gin::WrapperInfo kWrapperInfo;
const char* GetTypeName() override; const char* GetTypeName() override;
private: private:

View file

@ -1301,7 +1301,7 @@ gin::Handle<Session> Session::New() {
void Session::FillObjectTemplate(v8::Isolate* isolate, void Session::FillObjectTemplate(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> templ) { v8::Local<v8::ObjectTemplate> templ) {
gin::ObjectTemplateBuilder(isolate, "Session", templ) gin::ObjectTemplateBuilder(isolate, GetClassName(), templ)
.SetMethod("resolveHost", &Session::ResolveHost) .SetMethod("resolveHost", &Session::ResolveHost)
.SetMethod("resolveProxy", &Session::ResolveProxy) .SetMethod("resolveProxy", &Session::ResolveProxy)
.SetMethod("getCacheSize", &Session::GetCacheSize) .SetMethod("getCacheSize", &Session::GetCacheSize)
@ -1379,7 +1379,7 @@ void Session::FillObjectTemplate(v8::Isolate* isolate,
} }
const char* Session::GetTypeName() { const char* Session::GetTypeName() {
return "Session"; return GetClassName();
} }
} // namespace electron::api } // namespace electron::api

View file

@ -95,6 +95,7 @@ class Session : public gin::Wrappable<Session>,
// gin::Wrappable // gin::Wrappable
static gin::WrapperInfo kWrapperInfo; static gin::WrapperInfo kWrapperInfo;
static void FillObjectTemplate(v8::Isolate*, v8::Local<v8::ObjectTemplate>); static void FillObjectTemplate(v8::Isolate*, v8::Local<v8::ObjectTemplate>);
static const char* GetClassName() { return "Session"; }
const char* GetTypeName() override; const char* GetTypeName() override;
// Methods. // Methods.

View file

@ -386,7 +386,7 @@ bool Tray::CheckAlive() {
// static // static
void Tray::FillObjectTemplate(v8::Isolate* isolate, void Tray::FillObjectTemplate(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> templ) { v8::Local<v8::ObjectTemplate> templ) {
gin::ObjectTemplateBuilder(isolate, "Tray", templ) gin::ObjectTemplateBuilder(isolate, GetClassName(), templ)
.SetMethod("destroy", &Tray::Destroy) .SetMethod("destroy", &Tray::Destroy)
.SetMethod("isDestroyed", &Tray::IsDestroyed) .SetMethod("isDestroyed", &Tray::IsDestroyed)
.SetMethod("setImage", &Tray::SetImage) .SetMethod("setImage", &Tray::SetImage)
@ -408,6 +408,10 @@ void Tray::FillObjectTemplate(v8::Isolate* isolate,
.Build(); .Build();
} }
const char* Tray::GetTypeName() {
return GetClassName();
}
} // namespace electron::api } // namespace electron::api
namespace { namespace {

View file

@ -45,10 +45,13 @@ class Tray : public gin::Wrappable<Tray>,
v8::Local<v8::Value> image, v8::Local<v8::Value> image,
absl::optional<UUID> guid, absl::optional<UUID> guid,
gin::Arguments* args); gin::Arguments* args);
static void FillObjectTemplate(v8::Isolate*, v8::Local<v8::ObjectTemplate>); static void FillObjectTemplate(v8::Isolate*, v8::Local<v8::ObjectTemplate>);
static const char* GetClassName() { return "Tray"; }
// gin::Wrappable // gin::Wrappable
static gin::WrapperInfo kWrapperInfo; static gin::WrapperInfo kWrapperInfo;
const char* GetTypeName() override;
// disable copy // disable copy
Tray(const Tray&) = delete; Tray(const Tray&) = delete;

View file

@ -4161,7 +4161,7 @@ void WebContents::FillObjectTemplate(v8::Isolate* isolate,
v8::Local<v8::ObjectTemplate> templ) { v8::Local<v8::ObjectTemplate> templ) {
gin::InvokerOptions options; gin::InvokerOptions options;
options.holder_is_first_argument = true; options.holder_is_first_argument = true;
options.holder_type = "WebContents"; options.holder_type = GetClassName();
templ->Set( templ->Set(
gin::StringToSymbol(isolate, "isDestroyed"), gin::StringToSymbol(isolate, "isDestroyed"),
gin::CreateFunctionTemplate( gin::CreateFunctionTemplate(
@ -4301,7 +4301,7 @@ void WebContents::FillObjectTemplate(v8::Isolate* isolate,
} }
const char* WebContents::GetTypeName() { const char* WebContents::GetTypeName() {
return "WebContents"; return GetClassName();
} }
ElectronBrowserContext* WebContents::GetBrowserContext() const { ElectronBrowserContext* WebContents::GetBrowserContext() const {

View file

@ -147,9 +147,12 @@ class WebContents : public ExclusiveAccessContext,
v8::Isolate* isolate, v8::Isolate* isolate,
const gin_helper::Dictionary& web_preferences); const gin_helper::Dictionary& web_preferences);
// gin_helper::Constructible
static void FillObjectTemplate(v8::Isolate*, v8::Local<v8::ObjectTemplate>);
static const char* GetClassName() { return "WebContents"; }
// gin::Wrappable // gin::Wrappable
static gin::WrapperInfo kWrapperInfo; static gin::WrapperInfo kWrapperInfo;
static void FillObjectTemplate(v8::Isolate*, v8::Local<v8::ObjectTemplate>);
const char* GetTypeName() override; const char* GetTypeName() override;
void Destroy(); void Destroy();

View file

@ -409,7 +409,7 @@ void WebFrameMain::FillObjectTemplate(v8::Isolate* isolate,
} }
const char* WebFrameMain::GetTypeName() { const char* WebFrameMain::GetTypeName() {
return "WebFrameMain"; return GetClassName();
} }
} // namespace electron::api } // namespace electron::api

View file

@ -52,9 +52,12 @@ class WebFrameMain : public gin::Wrappable<WebFrameMain>,
static WebFrameMain* FromRenderFrameHost( static WebFrameMain* FromRenderFrameHost(
content::RenderFrameHost* render_frame_host); content::RenderFrameHost* render_frame_host);
// gin_helper::Constructible
static void FillObjectTemplate(v8::Isolate*, v8::Local<v8::ObjectTemplate>);
static const char* GetClassName() { return "WebFrameMain"; }
// gin::Wrappable // gin::Wrappable
static gin::WrapperInfo kWrapperInfo; static gin::WrapperInfo kWrapperInfo;
static void FillObjectTemplate(v8::Isolate*, v8::Local<v8::ObjectTemplate>);
const char* GetTypeName() override; const char* GetTypeName() override;
content::RenderFrameHost* render_frame_host() const { return render_frame_; } content::RenderFrameHost* render_frame_host() const { return render_frame_; }

View file

@ -55,6 +55,7 @@ class Constructible {
} }
constructor->InstanceTemplate()->SetInternalFieldCount( constructor->InstanceTemplate()->SetInternalFieldCount(
gin::kNumberOfInternalFields); gin::kNumberOfInternalFields);
constructor->SetClassName(gin::StringToV8(isolate, T::GetClassName()));
T::FillObjectTemplate(isolate, constructor->PrototypeTemplate()); T::FillObjectTemplate(isolate, constructor->PrototypeTemplate());
data->SetObjectTemplate(wrapper_info, constructor->InstanceTemplate()); data->SetObjectTemplate(wrapper_info, constructor->InstanceTemplate());
data->SetFunctionTemplate(wrapper_info, constructor); data->SetFunctionTemplate(wrapper_info, constructor);

View file

@ -27,6 +27,7 @@ class Event : public gin::Wrappable<Event>,
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"; }
// gin::Wrappable // gin::Wrappable
static gin::WrapperInfo kWrapperInfo; static gin::WrapperInfo kWrapperInfo;

View file

@ -40,6 +40,10 @@ describe('BrowserView module', () => {
expect(webContents.getAllWebContents()).to.have.length(0); expect(webContents.getAllWebContents()).to.have.length(0);
}); });
it('sets the correct class name on the prototype', () => {
expect(BrowserView.prototype.constructor.name).to.equal('BrowserView');
});
it('can be created with an existing webContents', async () => { it('can be created with an existing webContents', async () => {
const wc = (webContents as typeof ElectronInternal.WebContents).create({ sandbox: true }); const wc = (webContents as typeof ElectronInternal.WebContents).create({ sandbox: true });
await wc.loadURL('about:blank'); await wc.loadURL('about:blank');

View file

@ -47,6 +47,10 @@ const isBeforeUnload = (event: Event, level: number, message: string) => {
}; };
describe('BrowserWindow module', () => { describe('BrowserWindow module', () => {
it('sets the correct class name on the prototype', () => {
expect(BrowserWindow.prototype.constructor.name).to.equal('BrowserWindow');
});
describe('BrowserWindow constructor', () => { describe('BrowserWindow constructor', () => {
it('allows passing void 0 as the webContents', async () => { it('allows passing void 0 as the webContents', async () => {
expect(() => { expect(() => {

View file

@ -11,6 +11,10 @@ import { setTimeout } from 'node:timers/promises';
const fixturesPath = path.resolve(__dirname, 'fixtures'); const fixturesPath = path.resolve(__dirname, 'fixtures');
describe('Menu module', function () { describe('Menu module', function () {
it('sets the correct class name on the prototype', () => {
expect(Menu.prototype.constructor.name).to.equal('Menu');
});
describe('Menu.buildFromTemplate', () => { describe('Menu.buildFromTemplate', () => {
it('should be able to attach extra fields', () => { it('should be able to attach extra fields', () => {
const menu = Menu.buildFromTemplate([ const menu = Menu.buildFromTemplate([

View file

@ -4,6 +4,10 @@ import { once } from 'node:events';
import { ifit } from './lib/spec-helpers'; import { ifit } from './lib/spec-helpers';
describe('Notification module', () => { describe('Notification module', () => {
it('sets the correct class name on the prototype', () => {
expect(Notification.prototype.constructor.name).to.equal('Notification');
});
it('is supported', () => { it('is supported', () => {
expect(Notification.isSupported()).to.be.a('boolean'); expect(Notification.isSupported()).to.be.a('boolean');
}); });

View file

@ -15,6 +15,10 @@ describe('tray module', () => {
}); });
describe('new Tray', () => { describe('new Tray', () => {
it('sets the correct class name on the prototype', () => {
expect(Tray.prototype.constructor.name).to.equal('Tray');
});
it('throws a descriptive error for a missing file', () => { it('throws a descriptive error for a missing file', () => {
const badPath = path.resolve('I', 'Do', 'Not', 'Exist'); const badPath = path.resolve('I', 'Do', 'Not', 'Exist');
expect(() => { expect(() => {