[gjs/ewlsh/fix-fundamental-parameters] arg-cache: Add fundamental marshaller.




commit de15f65fbd7bf3b0297f454d8d4788c13df1a03d
Author: Evan Welsh <noreply evanwelsh com>
Date:   Tue Oct 6 22:55:46 2020 -0500

    arg-cache: Add fundamental marshaller.
    
    Addresses regression where fundamental objects cannot be passed into functions.
    
    Fixes #353

 gi/arg-cache.cpp | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file 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"
@@ -648,6 +649,35 @@ static bool gjs_marshal_gbytes_in_in(JSContext* cx, GjsArgumentCache* self,
         self->contents.info);
 }
 
+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,
@@ -666,6 +696,25 @@ static bool gjs_marshal_object_in_in(JSContext* cx, GjsArgumentCache* self,
                                                self->transfer, gtype);
 }
 
+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,
@@ -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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]