gjs r131 - trunk/gi



Author: otaylor
Date: Thu Dec  4 21:08:30 2008
New Revision: 131
URL: http://svn.gnome.org/viewvc/gjs?rev=131&view=rev

Log:
Fix handling of enum/flags return values

A number of related issues:

* gjs_value_to_g_argument() converted null to argument->v_pointer = NULL
  even if the interface type was enum or flags.

* gjs_value_from_g_argument() checked argument->v_pointer == NULL before
  checking if the interface type was enum or flag

* gjs_g_arg_release_internal() didn't properly handle enum types not
  registered as a GObject type.

This patch also cleans up gjs_value_from_g_argument() to uniformly use the
cleanup out: label, fixing one memory leak.

Modified:
   trunk/gi/arg.c

Modified: trunk/gi/arg.c
==============================================================================
--- trunk/gi/arg.c	(original)
+++ trunk/gi/arg.c	Thu Dec  4 21:08:30 2008
@@ -442,7 +442,9 @@
 
                 arg->v_pointer = gvalue;
 
-            } else if (JSVAL_IS_NULL(value)) {
+            } else if (JSVAL_IS_NULL(value) &&
+                       symbol_type != GI_INFO_TYPE_ENUM &&
+                       symbol_type != GI_INFO_TYPE_FLAGS) {
                 arg->v_pointer = NULL;
             } else if (JSVAL_IS_OBJECT(value)) {
                 /* Handle Struct/Union first since we don't necessarily need a GType for them */
@@ -866,95 +868,114 @@
 
     case GI_TYPE_TAG_INTERFACE:
         {
-            if (arg->v_pointer == NULL) {
-                /* OK, but no conversion to do */
-            } else {
-                jsval value;
-                GIBaseInfo* symbol_info;
-                GIInfoType symbol_type;
-                GType gtype;
+            jsval value;
+            GIBaseInfo* symbol_info;
+            GIInfoType symbol_type;
+            GType gtype;
+
+            symbol_info = g_type_info_get_interface(type_info);
+            g_assert(symbol_info != NULL);
+
+            value = JSVAL_VOID;
+
+            symbol_type = g_base_info_get_type(symbol_info);
+
+            if (symbol_type == GI_INFO_TYPE_UNRESOLVED) {
+                gjs_throw(context,
+                          "Unable to resolve arg type '%s'",
+                          g_base_info_get_name(symbol_info));
+                goto out;
+            }
 
-                symbol_info = g_type_info_get_interface(type_info);
-                g_assert(symbol_info != NULL);
+            /* Enum/Flags are aren't pointer types, unlike the other interface subtypes */
+            if (symbol_type == GI_INFO_TYPE_ENUM) {
+                if (_gjs_enum_value_is_valid(context, (GIEnumInfo *)symbol_info, arg->v_int))
+                    value = INT_TO_JSVAL(arg->v_int);
 
-                symbol_type = g_base_info_get_type(symbol_info);
+                goto out;
+            } else if (symbol_type == GI_INFO_TYPE_FLAGS) {
+                /* This should be fixed to work without a GType, just like Enum */
+                void *klass;
 
-                if (symbol_type == GI_INFO_TYPE_UNRESOLVED) {
+                gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo*)symbol_info);
+                if (gtype == G_TYPE_NONE) {
                     gjs_throw(context,
-                              "Unable to resolve arg type '%s'",
+                              "Can't yet handle flags type '%s' that is not registered with GObject",
                               g_base_info_get_name(symbol_info));
-                    g_base_info_unref( (GIBaseInfo*) symbol_info);
-                    return JS_FALSE;
+                    goto out;
                 }
 
-                value = JSVAL_VOID;
+                klass = g_type_class_ref(gtype);
 
-                gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo*)symbol_info);
-
-                gjs_debug_marshal(GJS_DEBUG_GFUNCTION,
-                                  "gtype of SYMBOL is %s", g_type_name(gtype));
+                if (_gjs_flags_value_is_valid(context, G_FLAGS_CLASS(klass), arg->v_int))
+                    value = INT_TO_JSVAL(arg->v_int);
 
-                if (g_type_is_a(gtype, G_TYPE_VALUE)) {
-                    if (!gjs_value_from_g_value(context, &value, arg->v_pointer)) {
-                        g_base_info_unref( (GIBaseInfo*) symbol_info);
-                        return JS_FALSE;
-                    }
+                g_type_class_unref(klass);
 
-                    goto out;
-                /* Handle Struct/Union first since we don't necessarily need a GType for them */
-                } else if (symbol_type == GI_INFO_TYPE_STRUCT || symbol_type == GI_INFO_TYPE_BOXED) {
-                    JSObject *obj;
-                    obj = gjs_boxed_from_c_struct(context, (GIStructInfo *)symbol_info, arg->v_pointer);
-                    if (obj)
-                        value = OBJECT_TO_JSVAL(obj);
+                goto out;
+            }
 
-                    goto out;
-                } else if (symbol_type == GI_INFO_TYPE_UNION) {
-                    JSObject *obj;
-                    obj = gjs_union_from_c_union(context, (GIUnionInfo *)symbol_info, arg->v_pointer);
-                    if (obj)
-                        value = OBJECT_TO_JSVAL(obj);
+            /* Everything else is a pointer type, NULL is the easy case */
+            if (arg->v_pointer == NULL) {
+                value = JSVAL_NULL;
+                goto out;
+            }
 
-                    goto out;
-                }
+            /* Handle Struct/Union first since we don't necessarily need a GType for them */
+            if (symbol_type == GI_INFO_TYPE_STRUCT || symbol_type == GI_INFO_TYPE_BOXED) {
+                JSObject *obj;
+                obj = gjs_boxed_from_c_struct(context, (GIStructInfo *)symbol_info, arg->v_pointer);
+                if (obj)
+                    value = OBJECT_TO_JSVAL(obj);
 
-                if (g_type_is_a(gtype, G_TYPE_OBJECT) || g_type_is_a(gtype, G_TYPE_INTERFACE)) {
-                    JSObject *obj;
-                    obj = gjs_object_from_g_object(context, G_OBJECT(arg->v_pointer));
-                    if (obj)
+                goto out;
+            } else if (symbol_type == GI_INFO_TYPE_UNION) {
+                JSObject *obj;
+                obj = gjs_union_from_c_union(context, (GIUnionInfo *)symbol_info, arg->v_pointer);
+                if (obj)
                         value = OBJECT_TO_JSVAL(obj);
-                } else if (g_type_is_a(gtype, G_TYPE_BOXED)) {
-                    /* Should have been caught above as STRUCT/BOXED/UNION */
-                    gjs_throw(context,
-                              "Boxed type %s registered for unexpected symbol_type %d",
-                              g_type_name(gtype),
-                              symbol_type);
-                    return JS_FALSE;
-                } else if (symbol_type == GI_INFO_TYPE_ENUM) {
-                    if (_gjs_enum_value_is_valid(context, (GIEnumInfo *)symbol_info, arg->v_int))
-                        value = INT_TO_JSVAL(arg->v_int);
-                } else if (g_type_is_a(gtype, G_TYPE_FLAGS)) {
-                    void *klass;
 
-                    klass = g_type_class_ref(gtype);
+                goto out;
+            }
 
-                    if (_gjs_flags_value_is_valid(context, G_FLAGS_CLASS(klass), arg->v_int))
-                        value = INT_TO_JSVAL(arg->v_int);
+            gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo*)symbol_info);
+            gjs_debug_marshal(GJS_DEBUG_GFUNCTION,
+                              "gtype of SYMBOL is %s", g_type_name(gtype));
 
-                    g_type_class_unref(klass);
-                } else {
-                    gjs_throw(context, "Unhandled GType %s packing SYMBOL GArgument into jsval",
-                                 g_type_name(gtype));
-                }
 
-            out:
-                g_base_info_unref( (GIBaseInfo*) symbol_info);
+            if (g_type_is_a(gtype, G_TYPE_VALUE)) {
+                if (!gjs_value_from_g_value(context, &value, arg->v_pointer))
+                    value = JSVAL_VOID; /* Make sure error is flagged */
 
-                if (JSVAL_IS_VOID(value))
-                    return JS_FALSE;
+                goto out;
+            }
 
-                *value_p = value;
+            if (g_type_is_a(gtype, G_TYPE_OBJECT) || g_type_is_a(gtype, G_TYPE_INTERFACE)) {
+                JSObject *obj;
+                obj = gjs_object_from_g_object(context, G_OBJECT(arg->v_pointer));
+                if (obj)
+                    value = OBJECT_TO_JSVAL(obj);
+            } else if (g_type_is_a(gtype, G_TYPE_BOXED) ||
+                       g_type_is_a(gtype, G_TYPE_ENUM) ||
+                       g_type_is_a(gtype, G_TYPE_FLAGS)) {
+                /* Should have been handled above */
+                gjs_throw(context,
+                          "Type %s registered for unexpected symbol_type %d",
+                          g_type_name(gtype),
+                          symbol_type);
+                return JS_FALSE;
+            } else {
+                gjs_throw(context, "Unhandled GType %s packing SYMBOL GArgument into jsval",
+                          g_type_name(gtype));
             }
+
+         out:
+            g_base_info_unref( (GIBaseInfo*) symbol_info);
+
+            if (JSVAL_IS_VOID(value))
+                return JS_FALSE;
+
+            *value_p = value;
         }
         break;
 
@@ -1038,42 +1059,49 @@
 
     case GI_TYPE_TAG_INTERFACE:
         {
-            if (arg->v_pointer == NULL) {
-                /* nothing to do */
-            } else {
-                jsval value;
-                GIBaseInfo* symbol_info;
-                GType gtype;
+            GIBaseInfo* symbol_info;
+            GIInfoType symbol_type;
+            GType gtype;
 
-                symbol_info = g_type_info_get_interface(type_info);
-                g_assert(symbol_info != NULL);
+            symbol_info = g_type_info_get_interface(type_info);
+            g_assert(symbol_info != NULL);
 
-                gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo*)symbol_info);
+            symbol_type = g_base_info_get_type(symbol_info);
 
-                gjs_debug_marshal(GJS_DEBUG_GFUNCTION,
-                                  "gtype of SYMBOL is %s", g_type_name(gtype));
+            if (symbol_type == GI_INFO_TYPE_ENUM || symbol_type == GI_INFO_TYPE_FLAGS)
+                goto out;
 
-                value = JSVAL_NULL;
+            /* Anything else is a pointer */
+            if (arg->v_pointer == NULL)
+                goto out;
 
-                if (g_type_is_a(gtype, G_TYPE_OBJECT) || g_type_is_a(gtype, G_TYPE_INTERFACE)) {
-                    g_object_unref(G_OBJECT(arg->v_pointer));
-                } else if (g_type_is_a(gtype, G_TYPE_CLOSURE)) {
-                    g_closure_unref(arg->v_pointer);
-                } else if (g_type_is_a(gtype, G_TYPE_BOXED)) {
-                    g_boxed_free(gtype, arg->v_pointer);
-                } else if (g_type_is_a(gtype, G_TYPE_VALUE)) {
-                    GValue *value = arg->v_pointer;
-                    g_value_unset(value);
-                    g_slice_free(GValue, value);
-                } else if (g_type_is_a(gtype, G_TYPE_ENUM) || g_type_is_a(gtype, G_TYPE_FLAGS)) {
-                    /* nothing to do */
-                } else {
-                    gjs_throw(context, "Unhandled GType %s releasing SYMBOL GArgument",
-                              g_type_name(gtype));
-                }
+            gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo*)symbol_info);
+            gjs_debug_marshal(GJS_DEBUG_GFUNCTION,
+                              "gtype of SYMBOL is %s", g_type_name(gtype));
+
+            /* In gjs_value_from_g_argument we handle Struct/Union types without a
+             * registered GType, but here we are specifically handling a GArgument that
+             * *owns* its value, and that is non-sensical for such types, so we
+             * don't have to worry about it.
+             */
 
-                g_base_info_unref( (GIBaseInfo*) symbol_info);
+            if (g_type_is_a(gtype, G_TYPE_OBJECT) || g_type_is_a(gtype, G_TYPE_INTERFACE)) {
+                g_object_unref(G_OBJECT(arg->v_pointer));
+            } else if (g_type_is_a(gtype, G_TYPE_CLOSURE)) {
+                g_closure_unref(arg->v_pointer);
+            } else if (g_type_is_a(gtype, G_TYPE_BOXED)) {
+                g_boxed_free(gtype, arg->v_pointer);
+            } else if (g_type_is_a(gtype, G_TYPE_VALUE)) {
+                GValue *value = arg->v_pointer;
+                g_value_unset(value);
+                g_slice_free(GValue, value);
+            } else {
+                gjs_throw(context, "Unhandled GType %s releasing SYMBOL GArgument",
+                          g_type_name(gtype));
             }
+
+        out:
+            g_base_info_unref( (GIBaseInfo*) symbol_info);
         }
         break;
 



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