[gjs: 2/26] value: Support marshalling custom fundamental types
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs: 2/26] value: Support marshalling custom fundamental types
- Date: Sun, 14 Apr 2019 14:03:32 +0000 (UTC)
commit 067e7d753cc7c8e912be0575d7a99c75d7870aed
Author: Philip Chimento <philip chimento gmail com>
Date: Fri Jan 4 18:45:28 2019 -0800
value: Support marshalling custom fundamental types
Previously, passing a custom fundamental type to a function with a
GValue argument would throw a JS exception.
Fundamental types in g-i have a "set_value_function" which tells how to
convert them to a GValue. We were already storing a pointer to this
function in FundamentalPrototype, but never used it anywhere. This adds
API to FundamentalBase and a code path in gjs_value_to_g_value() which
calls the set_value_function.
Arguably this should be tried before the last-resort transform-to-int
code in gjs_value_to_g_value_internal(), but it's not clear that that
would preserve existing behaviour.
gi/fundamental.cpp | 10 ++++++++++
gi/fundamental.h | 13 +++++++++++++
gi/value.cpp | 9 +++++++++
gi/wrapperutils.h | 1 +
installed-tests/js/testFundamental.js | 7 ++++++-
5 files changed, 39 insertions(+), 1 deletion(-)
---
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index 0d5d3f6d..a1c0bf5d 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -493,6 +493,16 @@ gjs_fundamental_from_g_value(JSContext *context,
return gjs_object_from_g_fundamental(context, proto_priv->info(), fobj);
}
+bool FundamentalBase::to_gvalue(JSContext* cx, JS::HandleObject obj,
+ GValue* gvalue) {
+ auto* priv = FundamentalBase::for_js_typecheck(cx, obj);
+ if (!priv || !priv->check_is_instance(cx, "convert to GValue"))
+ return false;
+
+ priv->to_instance()->set_value(gvalue);
+ return true;
+}
+
void*
gjs_g_fundamental_from_object(JSContext *context,
JS::HandleObject obj)
diff --git a/gi/fundamental.h b/gi/fundamental.h
index 5c04558b..94b1dffe 100644
--- a/gi/fundamental.h
+++ b/gi/fundamental.h
@@ -62,6 +62,12 @@ class FundamentalBase
// Helper methods
GJS_USE const char* to_string_kind(void) const { return "fundamental"; }
+
+ // Public API
+
+ public:
+ GJS_JSAPI_RETURN_CONVENTION
+ static bool to_gvalue(JSContext* cx, JS::HandleObject obj, GValue* gvalue);
};
class FundamentalPrototype
@@ -101,6 +107,9 @@ class FundamentalPrototype
GJS_USE void* call_get_value_function(const GValue* value) const {
return m_get_value_function(value);
}
+ void call_set_value_function(GValue* value, void* object) const {
+ m_set_value_function(value, object);
+ }
// Helper methods
@@ -125,6 +134,7 @@ class FundamentalPrototype
class FundamentalInstance
: public GIWrapperInstance<FundamentalBase, FundamentalPrototype,
FundamentalInstance> {
+ friend class FundamentalBase; // for set_value()
friend class GIWrapperInstance<FundamentalBase, FundamentalPrototype,
FundamentalInstance>;
friend class GIWrapperBase<FundamentalBase, FundamentalPrototype,
@@ -142,6 +152,9 @@ class FundamentalInstance
void ref(void) { get_prototype()->call_ref_function(m_ptr); }
void unref(void) { get_prototype()->call_unref_function(m_ptr); }
+ void set_value(GValue* gvalue) const {
+ get_prototype()->call_set_value_function(gvalue, m_ptr);
+ }
// JS constructor
diff --git a/gi/value.cpp b/gi/value.cpp
index 1ad596e3..bf174326 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -683,6 +683,15 @@ gjs_value_to_g_value_internal(JSContext *context,
} else {
return throw_expect_type(context, value, "integer");
}
+ } else if (G_TYPE_IS_INSTANTIATABLE(gtype)) {
+ // The gtype is none of the above, it should be derived from a custom
+ // fundamental type.
+ if (!value.isObject())
+ return throw_expect_type(context, value, "object", gtype);
+
+ JS::RootedObject fundamental_object(context, &value.toObject());
+ if (!FundamentalBase::to_gvalue(context, fundamental_object, gvalue))
+ return false;
} else {
gjs_debug(GJS_DEBUG_GCLOSURE, "JS::Value is number %d gtype fundamental %d transformable to int %d
from int %d",
value.isNumber(),
diff --git a/gi/wrapperutils.h b/gi/wrapperutils.h
index c288a4a0..225dc0fa 100644
--- a/gi/wrapperutils.h
+++ b/gi/wrapperutils.h
@@ -26,6 +26,7 @@
#define GI_WRAPPERUTILS_H_
#include "gjs/context-private.h"
+#include "gjs/jsapi-class.h"
#include "gjs/jsapi-util.h"
#include "gjs/macros.h"
#include "util/log.h"
diff --git a/installed-tests/js/testFundamental.js b/installed-tests/js/testFundamental.js
index fc08de0f..a947f836 100644
--- a/installed-tests/js/testFundamental.js
+++ b/installed-tests/js/testFundamental.js
@@ -1,4 +1,4 @@
-const Regress = imports.gi.Regress;
+const {GObject, Regress} = imports.gi;
describe('Fundamental type support', function () {
it('constructs a subtype of a fundamental type', function () {
@@ -8,4 +8,9 @@ describe('Fundamental type support', function () {
it('constructs a subtype of a hidden (no introspection data) fundamental type', function() {
expect(() => Regress.test_create_fundamental_hidden_class_instance()).not.toThrow();
});
+
+ it('can marshal a subtype of a custom fundamental type into a GValue', function () {
+ const fund = new Regress.TestFundamentalSubObject('plop');
+ expect(() => GObject.strdup_value_contents(fund)).not.toThrow();
+ });
});
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]