diff options
author | Evan Welsh <noreply@evanwelsh.com> | 2020-10-06 22:55:46 -0500 |
---|---|---|
committer | Philip Chimento <philip.chimento@gmail.com> | 2020-10-08 12:22:20 -0700 |
commit | de15f65fbd7bf3b0297f454d8d4788c13df1a03d (patch) | |
tree | 5efa62bc19d45889475fb654990a7e5f1b2c0a6a | |
parent | 6d68a572624b88c1dda37040ca52ded380adbd86 (diff) | |
download | gjs-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.cpp | 78 |
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 |