[gjs/ewlsh/register-type] GObject.registerType more functional prototype
- From: Evan Welsh <ewlsh src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/ewlsh/register-type] GObject.registerType more functional prototype
- Date: Mon, 19 Oct 2020 05:39:00 +0000 (UTC)
commit 1d5d526ce5d47a790d0d77893d653faa47252416
Author: Evan Welsh <noreply evanwelsh com>
Date: Thu Oct 15 10:36:44 2020 -0500
GObject.registerType more functional prototype
gi/object.cpp | 22 +++++++++++++++++++---
gi/wrapperutils.h | 28 +++++++++++++++++++++++++++-
gjs/atoms.h | 1 +
modules/core/overrides/GObject.js | 16 ++++++++++++++++
4 files changed, 63 insertions(+), 4 deletions(-)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index fd338090..9079d4f1 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -1595,9 +1595,25 @@ bool ObjectInstance::constructor_impl(JSContext* context,
return false;
}
- return gjs_object_require_property(context, object, "GObject instance",
- gjs->atoms().init(), &initer) &&
- gjs->call_function(object, initer, argv, argv.rval());
+ // If our instance is an instance of &klass it is an instance of a native
+ // class.
+ if (JS_InstanceOf(context, object, &klass, nullptr)) {
+ return gjs_object_require_property(context, object, "GObject instance",
+ gjs->atoms().init(), &initer) &&
+ gjs->call_function(object, initer, argv, argv.rval());
+ // Otherwise it is a JS-based class and we should call the constructor
+ // directly.
+ } else {
+ // TODO: This needs error guards.
+ ObjectBase* priv = ObjectBase::for_js(context, object);
+
+ if (!priv->check_is_instance(context, "initialize"))
+ return false;
+
+ JS::RootedObject obj(context, object);
+
+ return priv->to_instance()->init_impl(context, argv, &obj);
+ }
}
void ObjectInstance::trace_impl(JSTracer* tracer) {
diff --git a/gi/wrapperutils.h b/gi/wrapperutils.h
index 89b77342..fc819b99 100644
--- a/gi/wrapperutils.h
+++ b/gi/wrapperutils.h
@@ -514,7 +514,19 @@ class GIWrapperBase {
JS::RootedObject proto(cx);
if (!JS_GetPrototype(cx, obj, &proto))
return false;
- if (JS_GetClass(proto) != &Base::klass) {
+
+ JS::RootedValue gproto(cx);
+
+ bool has_property = false;
+
+ if (!JS_HasOwnProperty(cx, proto, "$gprototype", &has_property)) {
+ return false;
+ }
+
+ if (JS_GetClass(proto) != &Base::klass &&
+ (!has_property ||
+ (JS_GetProperty(cx, proto, "$gprototype", &gproto) &&
+ gproto.isObject()))) {
gjs_throw(cx, "Tried to construct an object without a GType");
return false;
}
@@ -976,6 +988,20 @@ class GIWrapperPrototype : public Base {
JS::HandleObject wrapper) {
JS::RootedObject proto(cx);
JS_GetPrototype(cx, wrapper, &proto);
+
+ if (JS_GetClass(proto) != &Base::klass) {
+ JS::RootedValue gproto(cx);
+
+ // TODO: Use a unique symbol instead.
+ // TODO: Don't store the entire prototype in $gprototype
+ if (JS_GetProperty(cx, proto, "$gprototype", &gproto) &&
+ gproto.isObject()) {
+ proto.set(&gproto.toObject());
+ }
+
+ // TODO: Handle assertions with errors instead.
+ }
+
Base* retval = Base::for_js(cx, proto);
g_assert(retval);
return retval->to_prototype();
diff --git a/gjs/atoms.h b/gjs/atoms.h
index 966999c8..2705678a 100644
--- a/gjs/atoms.h
+++ b/gjs/atoms.h
@@ -33,6 +33,7 @@ class JSTracer;
macro(glib, "GLib") \
macro(gobject, "GObject") \
macro(gtype, "$gtype") \
+ macro(gprototype, "$gprototype") \
macro(height, "height") \
macro(imports, "imports") \
macro(init, "_init") \
diff --git a/modules/core/overrides/GObject.js b/modules/core/overrides/GObject.js
index 50deb7dc..3bf30c6d 100644
--- a/modules/core/overrides/GObject.js
+++ b/modules/core/overrides/GObject.js
@@ -78,6 +78,21 @@ function registerClass(...args) {
return initclass._classInit(klass);
}
+function registerType(klass, options) {
+ let gtypename = _createGTypeName(klass);
+ let gflags = klass.hasOwnProperty(GTypeFlags) ? klass[GTypeFlags] : 0;
+
+ let parent = Object.getPrototypeOf(klass);
+
+ let registered_type = Gi.register_type(parent.prototype, gtypename, gflags, [], []);
+
+ // TODO: Construct a better "wrapper" than the registered prototype
+ // TODO: Avoid discarding a constructed constructor
+ klass.prototype.$gprototype = registered_type.prototype;
+
+ return registered_type.$gtype;
+}
+
// Some common functions between GObject.Class and GObject.Interface
function _createSignals(gtype, sigs) {
@@ -420,6 +435,7 @@ function _init() {
};
GObject.registerClass = registerClass;
+ GObject.registerType = registerType;
GObject.Object._classInit = function (klass) {
let gtypename = _createGTypeName(klass);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]