[gjs/ewlsh/register-type: 100/100] Correctly chain constructor prototypes to enable static inheritance
- From: Evan Welsh <ewlsh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/ewlsh/register-type: 100/100] Correctly chain constructor prototypes to enable static inheritance
- Date: Sat, 4 Sep 2021 19:59:53 +0000 (UTC)
commit 250eec6c3230512468087d9fa19425fbcf1b6dba
Author: Evan Welsh <contact evanwelsh com>
Date: Fri Aug 6 06:20:40 2021 -0700
Correctly chain constructor prototypes to enable static inheritance
gi/object.cpp | 29 +++++++++++++++++++++++++++--
gi/object.h | 3 +++
modules/core/overrides/Gtk.js | 39 +++++++++++++++++++++++++++++++++++++++
3 files changed, 69 insertions(+), 2 deletions(-)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index d27e2a9d..4be5eece 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -2384,6 +2384,20 @@ bool ObjectPrototype::get_parent_proto(JSContext* cx,
return true;
}
+bool ObjectPrototype::get_parent_constructor(
+ JSContext* cx, JS::MutableHandleObject constructor) const {
+ GType parent_type = g_type_parent(gtype());
+
+ if (parent_type != G_TYPE_INVALID) {
+ JS::RootedValue v_constructor(cx);
+ if (!gjs_lookup_object_constructor(cx, parent_type, &v_constructor))
+ return false;
+
+ constructor.set(&v_constructor.toObject());
+ }
+ return true;
+}
+
/*
* ObjectPrototype::define_class:
* @in_object: Object where the constructor is stored, typically a repo object.
@@ -2402,9 +2416,20 @@ bool ObjectPrototype::define_class(JSContext* context,
GIObjectInfo* info, GType gtype,
JS::MutableHandleObject constructor,
JS::MutableHandleObject prototype) {
- if (!ObjectPrototype::create_class(context, in_object, info, gtype,
- constructor, prototype))
+ ObjectPrototype* priv = ObjectPrototype::create_class(
+ context, in_object, info, gtype, constructor, prototype);
+ if (!priv)
+ return false;
+
+ JS::RootedObject parent_constructor(context);
+ if (!priv->get_parent_constructor(context, &parent_constructor))
return false;
+ // If this is a fundamental constructor (e.g. GObject.Object) the
+ // parent constructor may be null.
+ if (parent_constructor) {
+ if (!JS_SetPrototype(context, constructor, parent_constructor))
+ return false;
+ }
// hook_up_vfunc and the signal handler matcher functions can't be included
// in gjs_object_instance_proto_funcs because they are custom symbols.
diff --git a/gi/object.h b/gi/object.h
index 0d9d40fe..8bef43b7 100644
--- a/gi/object.h
+++ b/gi/object.h
@@ -211,6 +211,9 @@ class ObjectPrototype
private:
GJS_JSAPI_RETURN_CONVENTION
bool get_parent_proto(JSContext* cx, JS::MutableHandleObject proto) const;
+ GJS_JSAPI_RETURN_CONVENTION
+ bool get_parent_constructor(JSContext* cx,
+ JS::MutableHandleObject constructor) const;
[[nodiscard]] bool is_vfunc_unchanged(GIVFuncInfo* info);
static void vfunc_invalidated_notify(void* data, GClosure* closure);
diff --git a/modules/core/overrides/Gtk.js b/modules/core/overrides/Gtk.js
index 306f7d3f..2db80a39 100644
--- a/modules/core/overrides/Gtk.js
+++ b/modules/core/overrides/Gtk.js
@@ -107,6 +107,45 @@ function _init() {
return klass;
};
+ Gtk.registerWidgetType = function registerWidgetType(klass) {
+ let template = klass[Gtk.template];
+ let cssName = klass[Gtk.cssName];
+ let children = klass[Gtk.children];
+ let internalChildren = klass[Gtk.internalChildren];
+
+ if (template) {
+ klass.prototype._instance_init = function () {
+ this.init_template();
+ };
+ }
+
+ GObject.registerType(klass);
+
+ if (cssName)
+ Gtk.Widget.set_css_name.call(klass, cssName);
+
+ if (template) {
+ if (typeof template === 'string')
+ Gtk.Widget.set_template_from_uri.call(klass, template);
+ else
+ Gtk.Widget.set_template.call(klass, template);
+
+
+ if (BuilderScope)
+ Gtk.Widget.set_template_scope.call(klass, new BuilderScope());
+ }
+
+ if (children) {
+ children.forEach(child =>
+ Gtk.Widget.bind_template_child_full.call(klass, child, false, 0));
+ }
+
+ if (internalChildren) {
+ internalChildren.forEach(child =>
+ Gtk.Widget.bind_template_child_full.call(klass, child, true, 0));
+ }
+ };
+
if (Gtk.Widget.prototype.get_first_child) {
Gtk.Widget.prototype[Symbol.iterator] = function* () {
for (let c = this.get_first_child(); c; c = c.get_next_sibling())
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]