summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvan Welsh <noreply@evanwelsh.com>2020-10-06 22:55:46 -0500
committerPhilip Chimento <philip.chimento@gmail.com>2020-10-08 12:22:20 -0700
commitde15f65fbd7bf3b0297f454d8d4788c13df1a03d (patch)
tree5efa62bc19d45889475fb654990a7e5f1b2c0a6a
parent6d68a572624b88c1dda37040ca52ded380adbd86 (diff)
downloadgjs-de15f65fbd7bf3b0297f454d8d4788c13df1a03d.tar.gz
arg-cache: Add fundamental marshaller.ewlsh/fix-fundamental-parameters
Addresses regression where fundamental objects cannot be passed into functions. Fixes #353
-rw-r--r--gi/arg-cache.cpp78
1 files changed, 76 insertions, 2 deletions
diff --git a/gi/arg-cache.cpp b/gi/arg-cache.cpp
index 737afe56..14d46d00 100644
--- a/gi/arg-cache.cpp
+++ b/gi/arg-cache.cpp
@@ -29,6 +29,7 @@
#include "gi/boxed.h"
#include "gi/foreign.h"
#include "gi/function.h"
+#include "gi/fundamental.h"
#include "gi/gerror.h"
#include "gi/gtype.h"
#include "gi/js-value-inl.h"
@@ -649,6 +650,35 @@ static bool gjs_marshal_gbytes_in_in(JSContext* cx, GjsArgumentCache* self,
}
GJS_JSAPI_RETURN_CONVENTION
+static bool gjs_marshal_interface_in_in(JSContext* cx, GjsArgumentCache* self,
+ GjsFunctionCallState*, GIArgument* arg,
+ JS::HandleValue value) {
+ if (value.isNull())
+ return self->handle_nullable(cx, arg);
+
+ GType gtype = g_registered_type_info_get_g_type(self->contents.info);
+ g_assert(gtype != G_TYPE_NONE);
+
+ if (!value.isObject())
+ return report_gtype_mismatch(cx, self->arg_name, value, gtype);
+
+ JS::RootedObject object(cx, &value.toObject());
+
+ // Could be a GObject interface that's missing a prerequisite,
+ // or could be a fundamental
+ if (ObjectBase::typecheck(cx, object, nullptr, gtype,
+ GjsTypecheckNoThrow())) {
+ return ObjectBase::transfer_to_gi_argument(
+ cx, object, arg, GI_DIRECTION_IN, self->transfer, gtype);
+ }
+
+ // If this typecheck fails, then it's neither an object nor a
+ // fundamental
+ return FundamentalBase::transfer_to_gi_argument(
+ cx, object, arg, GI_DIRECTION_IN, self->transfer, gtype);
+}
+
+GJS_JSAPI_RETURN_CONVENTION
static bool gjs_marshal_object_in_in(JSContext* cx, GjsArgumentCache* self,
GjsFunctionCallState*, GIArgument* arg,
JS::HandleValue value) {
@@ -667,6 +697,25 @@ static bool gjs_marshal_object_in_in(JSContext* cx, GjsArgumentCache* self,
}
GJS_JSAPI_RETURN_CONVENTION
+static bool gjs_marshal_fundamental_in_in(JSContext* cx, GjsArgumentCache* self,
+ GjsFunctionCallState*,
+ GIArgument* arg,
+ JS::HandleValue value) {
+ if (value.isNull())
+ return self->handle_nullable(cx, arg);
+
+ GType gtype = g_registered_type_info_get_g_type(self->contents.info);
+ g_assert(gtype != G_TYPE_NONE);
+
+ if (!value.isObject())
+ return report_gtype_mismatch(cx, self->arg_name, value, gtype);
+
+ JS::RootedObject object(cx, &value.toObject());
+ return FundamentalBase::transfer_to_gi_argument(
+ cx, object, arg, GI_DIRECTION_IN, self->transfer, gtype);
+}
+
+GJS_JSAPI_RETURN_CONVENTION
static bool gjs_marshal_gtype_struct_instance_in(JSContext* cx,
GjsArgumentCache* self,
GjsFunctionCallState*,
@@ -1054,6 +1103,22 @@ static const GjsArgumentMarshallers object_in_marshallers = {
gjs_arg_cache_interface_free, // free
};
+static const GjsArgumentMarshallers interface_in_marshallers = {
+ gjs_marshal_interface_in_in, // in
+ gjs_marshal_skipped_out, // out
+ // This is a smart marshaller, no release needed
+ gjs_marshal_skipped_release, // release
+ gjs_arg_cache_interface_free, // free
+};
+
+static const GjsArgumentMarshallers fundamental_in_marshallers = {
+ gjs_marshal_fundamental_in_in, // in
+ gjs_marshal_skipped_out, // out
+ // This is a smart marshaller, no release needed
+ gjs_marshal_skipped_release, // release
+ gjs_arg_cache_interface_free, // free
+};
+
static const GjsArgumentMarshallers union_in_marshallers = {
gjs_marshal_union_in_in, // in
gjs_marshal_skipped_out, // out
@@ -1336,8 +1401,7 @@ static bool gjs_arg_cache_build_interface_in_arg(JSContext* cx,
return true;
}
- if (g_type_is_a(gtype, G_TYPE_OBJECT) ||
- g_type_is_a(gtype, G_TYPE_INTERFACE)) {
+ if (g_type_is_a(gtype, G_TYPE_OBJECT)) {
self->marshallers = &object_in_marshallers;
return true;
}
@@ -1359,6 +1423,16 @@ static bool gjs_arg_cache_build_interface_in_arg(JSContext* cx,
return true;
}
+ if (G_TYPE_IS_INSTANTIATABLE(gtype)) {
+ self->marshallers = &fundamental_in_marshallers;
+ return true;
+ }
+
+ if (g_type_is_a(gtype, G_TYPE_INTERFACE)) {
+ self->marshallers = &interface_in_marshallers;
+ return true;
+ }
+
// generic boxed type
if (gtype == G_TYPE_NONE && self->transfer != GI_TRANSFER_NOTHING) {
// Can't transfer ownership of a structure type not