summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJasper St. Pierre <jstpierre@mecheye.net>2012-01-19 22:24:17 -0500
committerJasper St. Pierre <jstpierre@mecheye.net>2012-01-25 20:57:10 -0500
commitf1dc3188f5e7a3e9d9d5cd26879024441dcb26b4 (patch)
tree4d74c63b25e8b1f4938c80a8dcc020553087a232
parent97f0be7db9674a13630b73d4d4412d228a37322c (diff)
downloadgjs-f1dc3188f5e7a3e9d9d5cd26879024441dcb26b4.tar.gz
Represent GTypes as a new boxed wrapper type
We can't natively represent a pointer as a regular value in JS (we have at most 30-bit integers or doubles), so to store GTypes correctly, we need to box them. Create a new native object that simply represents a GType, give it a 'g_type_name' wrapper, and fix up the rest of the world so we no longer treat a GType as a special integer. https://bugzilla.gnome.org/show_bug.cgi?id=668427
-rw-r--r--Makefile.am6
-rw-r--r--gi/arg.c105
-rw-r--r--gi/enumeration.c3
-rw-r--r--gi/gtype.c171
-rw-r--r--gi/gtype.h50
-rw-r--r--gi/object.c31
-rw-r--r--gi/object.h2
-rw-r--r--gi/param.c19
-rw-r--r--test/js/testGIMarshalling.js29
9 files changed, 349 insertions, 67 deletions
diff --git a/Makefile.am b/Makefile.am
index ddf30d17..83c6ebb3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -50,7 +50,8 @@ nobase_gjs_module_include_HEADERS = \
gi/enumeration.h \
gi/function.h \
gi/keep-alive.h \
- gi/interface.h
+ gi/interface.h \
+ gi/gtype.h
noinst_HEADERS += \
gjs/jsapi-private.h \
@@ -133,7 +134,8 @@ libgjs_la_SOURCES += \
gi/repo.c \
gi/union.c \
gi/value.c \
- gi/interface.c
+ gi/interface.c \
+ gi/gtype.c
if ENABLE_DTRACE
gjs_gi_probes.h: gi/gjs_gi_probes.d
diff --git a/gi/arg.c b/gi/arg.c
index a653d791..5e9d8f82 100644
--- a/gi/arg.c
+++ b/gi/arg.c
@@ -24,6 +24,7 @@
#include <config.h>
#include "arg.h"
+#include "gtype.h"
#include "object.h"
#include "foreign.h"
#include "boxed.h"
@@ -150,25 +151,6 @@ _gjs_enum_to_int (GIEnumInfo *enum_info,
return (int)value;
}
-/* The typelib used to have machine-independent types like
- * GI_TYPE_TAG_LONG that had to be converted; now we only
- * handle GType specially here.
- */
-static inline GITypeTag
-replace_gtype(GITypeTag type) {
- if (type == GI_TYPE_TAG_GTYPE) {
- /* Constant folding should handle this hopefully */
- switch (sizeof(GType)) {
- case 1: return GI_TYPE_TAG_UINT8;
- case 2: return GI_TYPE_TAG_UINT16;
- case 4: return GI_TYPE_TAG_UINT32;
- case 8: return GI_TYPE_TAG_UINT64;
- default: g_assert_not_reached ();
- }
- }
- return type;
-}
-
/* Check if an argument of the given needs to be released if we created it
* from a JS value to pass it into a function and aren't transfering ownership.
*/
@@ -537,7 +519,6 @@ gjs_string_to_intarray(JSContext *context,
guint16 *result16;
element_type = g_type_info_get_tag(param_info);
- element_type = replace_gtype(element_type);
switch (element_type) {
case GI_TYPE_TAG_INT8:
@@ -624,6 +605,46 @@ gjs_array_to_intarray(JSContext *context,
}
static JSBool
+gjs_gtypearray_to_array(JSContext *context,
+ jsval array_value,
+ unsigned int length,
+ void **arr_p)
+{
+ GType *result;
+ unsigned i;
+
+ /* add one so we're always zero terminated */
+ result = g_malloc0((length+1) * sizeof(GType));
+
+ for (i = 0; i < length; ++i) {
+ jsval elem;
+ GType gtype;
+
+ elem = JSVAL_VOID;
+ if (!JS_GetElement(context, JSVAL_TO_OBJECT(array_value),
+ i, &elem)) {
+ g_free(result);
+ gjs_throw(context, "Missing array element %u", i);
+ return JS_FALSE;
+ }
+
+ gtype = gjs_gtype_get_actual_gtype(context, JSVAL_TO_OBJECT(elem));
+
+ if (gtype == G_TYPE_INVALID) {
+ g_free(result);
+ gjs_throw(context, "Invalid element in GType array");
+ return JS_FALSE;
+ }
+
+ result[i] = gtype;
+ }
+
+ *arr_p = result;
+
+ return JS_TRUE;
+}
+
+static JSBool
gjs_array_to_floatarray(JSContext *context,
jsval array_value,
unsigned int length,
@@ -854,7 +875,6 @@ gjs_array_to_array(JSContext *context,
GITypeTag element_type;
element_type = g_type_info_get_tag(param_info);
- element_type = replace_gtype(element_type);
/* Special case for GValue "flat arrays" */
if (is_gvalue_flat_array(param_info, element_type))
@@ -895,6 +915,9 @@ gjs_array_to_array(JSContext *context,
case GI_TYPE_TAG_DOUBLE:
return gjs_array_to_floatarray
(context, array_value, length, arr_p, TRUE);
+ case GI_TYPE_TAG_GTYPE:
+ return gjs_gtypearray_to_array
+ (context, array_value, length, arr_p);
/* Everything else is a pointer type */
case GI_TYPE_TAG_INTERFACE:
@@ -924,7 +947,6 @@ gjs_g_array_new_for_type(JSContext *context,
guint element_size;
element_type = g_type_info_get_tag(param_info);
- element_type = replace_gtype(element_type);
if (element_type == GI_TYPE_TAG_INTERFACE) {
GIInterfaceInfo *interface_info = g_type_info_get_interface(param_info);
@@ -960,6 +982,9 @@ gjs_g_array_new_for_type(JSContext *context,
case GI_TYPE_TAG_DOUBLE:
element_size = sizeof(gdouble);
break;
+ case GI_TYPE_TAG_GTYPE:
+ element_size = sizeof(GType);
+ break;
case GI_TYPE_TAG_INTERFACE:
case GI_TYPE_TAG_UTF8:
case GI_TYPE_TAG_FILENAME:
@@ -1085,7 +1110,6 @@ gjs_value_to_g_argument(JSContext *context,
gboolean nullable_type;
type_tag = g_type_info_get_tag( (GITypeInfo*) type_info);
- type_tag = replace_gtype(type_tag);
gjs_debug_marshal(GJS_DEBUG_GFUNCTION,
"Converting jsval to GArgument %s",
@@ -1206,6 +1230,19 @@ gjs_value_to_g_argument(JSContext *context,
}
break;
+ case GI_TYPE_TAG_GTYPE:
+ if (JSVAL_IS_OBJECT(value)) {
+ GType gtype;
+ gtype = gjs_gtype_get_actual_gtype(context, JSVAL_TO_OBJECT(value));
+ if (gtype == G_TYPE_INVALID)
+ wrong = TRUE;
+ arg->v_ssize = gtype;
+ } else {
+ wrong = TRUE;
+ report_type_mismatch = TRUE;
+ }
+ break;
+
case GI_TYPE_TAG_FILENAME:
nullable_type = TRUE;
if (JSVAL_IS_NULL(value)) {
@@ -1643,7 +1680,6 @@ gjs_g_argument_init_default(JSContext *context,
GITypeTag type_tag;
type_tag = g_type_info_get_tag( (GITypeInfo*) type_info);
- type_tag = replace_gtype(type_tag);
switch (type_tag) {
case GI_TYPE_TAG_VOID:
@@ -1694,6 +1730,10 @@ gjs_g_argument_init_default(JSContext *context,
arg->v_double = 0.0;
break;
+ case GI_TYPE_TAG_GTYPE:
+ arg->v_ssize = 0;
+ break;
+
case GI_TYPE_TAG_FILENAME:
case GI_TYPE_TAG_UTF8:
case GI_TYPE_TAG_GLIST:
@@ -1869,7 +1909,6 @@ gjs_array_from_carray_internal (JSContext *context,
guint i;
element_type = g_type_info_get_tag(param_info);
- element_type = replace_gtype(element_type);
if (is_gvalue_flat_array(param_info, element_type))
return gjs_array_from_flat_gvalue_array(context, array, length, value_p);
@@ -1938,6 +1977,7 @@ gjs_array_from_carray_internal (JSContext *context,
case GI_TYPE_TAG_DOUBLE:
ITERATE(double);
break;
+ case GI_TYPE_TAG_GTYPE:
case GI_TYPE_TAG_UTF8:
case GI_TYPE_TAG_FILENAME:
case GI_TYPE_TAG_ARRAY:
@@ -2050,7 +2090,6 @@ gjs_array_from_zero_terminated_c_array (JSContext *context,
guint i;
element_type = g_type_info_get_tag(param_info);
- element_type = replace_gtype(element_type);
/* Special case array(guint8) */
if (element_type == GI_TYPE_TAG_UINT8) {
@@ -2119,6 +2158,7 @@ gjs_array_from_zero_terminated_c_array (JSContext *context,
case GI_TYPE_TAG_DOUBLE:
ITERATE(double);
break;
+ case GI_TYPE_TAG_GTYPE:
case GI_TYPE_TAG_UTF8:
case GI_TYPE_TAG_FILENAME:
case GI_TYPE_TAG_ARRAY:
@@ -2230,7 +2270,6 @@ gjs_value_from_g_argument (JSContext *context,
GITypeTag type_tag;
type_tag = g_type_info_get_tag( (GITypeInfo*) type_info);
- type_tag = replace_gtype(type_tag);
gjs_debug_marshal(GJS_DEBUG_GFUNCTION,
"Converting GArgument %s to jsval",
@@ -2277,6 +2316,14 @@ gjs_value_from_g_argument (JSContext *context,
case GI_TYPE_TAG_DOUBLE:
return JS_NewNumberValue(context, arg->v_double, value_p);
+ case GI_TYPE_TAG_GTYPE:
+ {
+ JSObject *obj;
+ obj = gjs_gtype_create_gtype_wrapper(context, arg->v_ssize);
+ *value_p = OBJECT_TO_JSVAL(obj);
+ }
+ break;
+
case GI_TYPE_TAG_UNICHAR:
{
char utf8[7];
@@ -2722,7 +2769,6 @@ gjs_g_arg_release_internal(JSContext *context,
param_info = g_type_info_get_param_type(type_info, 0);
element_type = g_type_info_get_tag(param_info);
- element_type = replace_gtype(element_type);
if (transfer != GI_TRANSFER_CONTAINER && is_gvalue_flat_array(param_info, element_type)) {
g_free(arg->v_pointer);
@@ -2744,6 +2790,7 @@ gjs_g_arg_release_internal(JSContext *context,
case GI_TYPE_TAG_INT8:
case GI_TYPE_TAG_INT16:
case GI_TYPE_TAG_INT32:
+ case GI_TYPE_TAG_GTYPE:
g_free (arg->v_pointer);
break;
@@ -2804,7 +2851,6 @@ gjs_g_arg_release_internal(JSContext *context,
param_info = g_type_info_get_param_type(type_info, 0);
element_type = g_type_info_get_tag(param_info);
- element_type = replace_gtype(element_type);
switch (element_type) {
case GI_TYPE_TAG_UINT8:
@@ -2815,6 +2861,7 @@ gjs_g_arg_release_internal(JSContext *context,
case GI_TYPE_TAG_INT16:
case GI_TYPE_TAG_INT32:
case GI_TYPE_TAG_INT64:
+ case GI_TYPE_TAG_GTYPE:
g_array_free((GArray*) arg->v_pointer, TRUE);
break;
diff --git a/gi/enumeration.c b/gi/enumeration.c
index c7734b47..fac98547 100644
--- a/gi/enumeration.c
+++ b/gi/enumeration.c
@@ -28,6 +28,7 @@
#include <gjs/gjs-module.h>
#include <gjs/compat.h>
#include "repo.h"
+#include "gtype.h"
#include <util/log.h>
@@ -167,7 +168,7 @@ gjs_define_enumeration(JSContext *context,
}
gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo*)info);
- value = INT_TO_JSVAL(gtype);
+ value = OBJECT_TO_JSVAL(gjs_gtype_create_gtype_wrapper(context, gtype));
JS_DefineProperty(context, enum_obj, "$gtype", value,
NULL, NULL, JSPROP_PERMANENT);
diff --git a/gi/gtype.c b/gi/gtype.c
new file mode 100644
index 00000000..501903ae
--- /dev/null
+++ b/gi/gtype.c
@@ -0,0 +1,171 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (c) 2008 litl, LLC
+ * Copyright (c) 2012 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#include <config.h>
+
+#include "gtype.h"
+
+#include <gjs/gjs-module.h>
+#include <gjs/compat.h>
+#include <util/log.h>
+
+#include <jsapi.h>
+#include <girepository.h>
+
+GJS_DEFINE_PROTO_ABSTRACT("GIRepositoryGType", gtype);
+
+/* priv_from_js adds a "*", so this returns "void *" */
+GJS_DEFINE_PRIV_FROM_JS(void, gjs_gtype_class);
+
+static GQuark
+gjs_get_gtype_wrapper_quark(void)
+{
+ static gsize once_init = 0;
+ static GQuark value = 0;
+ if (g_once_init_enter(&once_init)) {
+ value = g_quark_from_string("gjs-gtype-wrapper");
+ g_once_init_leave(&once_init, 1);
+ }
+ return value;
+}
+
+static void
+gjs_gtype_finalize(JSContext *context,
+ JSObject *obj)
+{
+ GType gtype = GPOINTER_TO_SIZE(priv_from_js(context, obj));
+
+ /* proto doesn't have a private set */
+ if (G_UNLIKELY(gtype == 0))
+ return;
+
+ g_type_set_qdata(gtype, gjs_get_gtype_wrapper_quark(), NULL);
+}
+
+static JSBool
+to_string_func(JSContext *context,
+ uintN argc,
+ jsval *vp)
+{
+ JSObject *obj = JS_THIS_OBJECT(context, vp);
+ GType gtype;
+ gchar *strval;
+ JSBool ret;
+ jsval retval;
+
+ gtype = GPOINTER_TO_SIZE(priv_from_js(context, obj));
+
+ strval = g_strdup_printf("[object GType for '%s']",
+ g_type_name(gtype));
+ ret = gjs_string_from_utf8(context, strval, -1, &retval);
+ if (ret)
+ JS_SET_RVAL(context, vp, retval);
+ g_free(strval);
+ return ret;
+}
+
+static JSBool
+get_name_func (JSContext *context,
+ JSObject *obj,
+ jsid id,
+ jsval *vp)
+{
+ GType gtype;
+ JSBool ret;
+ jsval retval;
+
+ gtype = GPOINTER_TO_SIZE(priv_from_js(context, obj));
+
+ ret = gjs_string_from_utf8(context, g_type_name(gtype), -1, &retval);
+ if (ret)
+ JS_SET_RVAL(context, vp, retval);
+ return ret;
+}
+
+/* Properties */
+static JSPropertySpec gjs_gtype_proto_props[] = {
+ { "name", 0, JSPROP_READONLY | JSPROP_PERMANENT | JSPROP_SHARED, (JSPropertyOp)get_name_func, NULL }
+};
+
+/* Functions */
+static JSFunctionSpec gjs_gtype_proto_funcs[] = {
+ { "toString", (JSNative)to_string_func, 0, 0 }
+};
+
+JSObject *
+gjs_gtype_create_gtype_wrapper (JSContext *context,
+ GType gtype)
+{
+ JSObject *object;
+ JSObject *global;
+
+ JS_BeginRequest(context);
+
+ /* put constructor for GIRepositoryGType() in the global namespace */
+ global = gjs_get_import_global(context);
+ gjs_gtype_create_proto(context, global, "GIRepositoryGType", NULL);
+
+ object = g_type_get_qdata(gtype, gjs_get_gtype_wrapper_quark());
+ if (object != NULL)
+ goto out;
+
+ object = JS_NewObject(context, &gjs_gtype_class, NULL, NULL);
+ if (object == NULL)
+ goto out;
+
+ JS_SetPrivate(context, object, GSIZE_TO_POINTER(gtype));
+ g_type_set_qdata(gtype, gjs_get_gtype_wrapper_quark(), object);
+
+ out:
+ JS_EndRequest(context);
+ return object;
+}
+
+GType
+gjs_gtype_get_actual_gtype (JSContext *context,
+ JSObject *object)
+{
+ GType gtype = G_TYPE_INVALID;
+ jsval gtype_val;
+
+ JS_BeginRequest(context);
+ if (JS_InstanceOf(context, object, &gjs_gtype_class, NULL)) {
+ gtype = GPOINTER_TO_SIZE(priv_from_js(context, object));
+ goto out;
+ }
+
+ /* OK, we don't have a GType wrapper object -- grab the "$gtype"
+ * property on that and hope it's a GType wrapper object */
+ if (!JS_GetProperty(context, object, "$gtype", &gtype_val))
+ goto out;
+
+ if (!JSVAL_IS_OBJECT(gtype_val))
+ goto out;
+
+ gtype = gjs_gtype_get_actual_gtype(context, JSVAL_TO_OBJECT(gtype_val));
+
+ out:
+ JS_EndRequest(context);
+ return gtype;
+}
diff --git a/gi/gtype.h b/gi/gtype.h
new file mode 100644
index 00000000..645d6f54
--- /dev/null
+++ b/gi/gtype.h
@@ -0,0 +1,50 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+/*
+ * Copyright (c) 2008 litl, LLC
+ * Copyright (c) 2012 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef __GJS_GTYPE_H__
+#define __GJS_GTYPE_H__
+
+#include <glib.h>
+
+#include <jsapi.h>
+
+#include <girepository.h>
+
+G_BEGIN_DECLS
+
+jsval gjs_gtype_create_proto (JSContext *context,
+ JSObject *module,
+ const char *proto_name,
+ JSObject *parent);
+
+JSObject * gjs_gtype_create_gtype_wrapper (JSContext *context,
+ GType gtype);
+
+GType gjs_gtype_get_actual_gtype (JSContext *context,
+ JSObject *object);
+
+
+G_END_DECLS
+
+#endif /* __GJS_INTERFACE_H__ */
diff --git a/gi/object.c b/gi/object.c
index adb11f84..effc6d52 100644
--- a/gi/object.c
+++ b/gi/object.c
@@ -26,6 +26,7 @@
#include <string.h>
#include "object.h"
+#include "gtype.h"
#include "arg.h"
#include "repo.h"
#include "function.h"
@@ -1395,7 +1396,7 @@ gjs_define_object_class(JSContext *context,
gjs_define_static_methods(context, constructor, info);
}
- value = INT_TO_JSVAL(gtype);
+ value = OBJECT_TO_JSVAL(gjs_gtype_create_gtype_wrapper(context, gtype));
JS_DefineProperty(context, constructor, "$gtype", value,
NULL, NULL, JSPROP_PERMANENT);
@@ -1551,31 +1552,3 @@ gjs_g_object_from_object(JSContext *context,
return priv->gobj;
}
-
-GType
-gjs_gtype_from_value(JSContext *context,
- jsval val)
-{
- GType gtype = G_TYPE_NONE;
-
- if (JSVAL_IS_INT(val))
- return JSVAL_TO_INT(val);
-
- if (JSVAL_IS_OBJECT(val)) {
- JS_BeginRequest(context);
-
- JSObject *obj = JSVAL_TO_OBJECT(val);
- jsval gtype_val;
- if (!JS_GetProperty(context, obj, "$gtype", &gtype_val))
- goto out;
-
- if (!JSVAL_IS_INT(gtype_val))
- goto out;
-
- gtype = JSVAL_TO_INT(gtype_val);
- }
-
- out:
- JS_EndRequest(context);
- return gtype;
-}
diff --git a/gi/object.h b/gi/object.h
index d6b93758..e0dc3a43 100644
--- a/gi/object.h
+++ b/gi/object.h
@@ -44,8 +44,6 @@ JSObject* gjs_object_from_g_object (JSContext *context,
GObject *gobj);
GObject* gjs_g_object_from_object (JSContext *context,
JSObject *obj);
-GType gjs_gtype_from_value (JSContext *context,
- jsval value);
G_END_DECLS
diff --git a/gi/param.c b/gi/param.c
index 9535499f..fd61665b 100644
--- a/gi/param.c
+++ b/gi/param.c
@@ -29,6 +29,7 @@
#include "arg.h"
#include "object.h"
#include "repo.h"
+#include "gtype.h"
#include <gjs/gjs-module.h>
#include <gjs/compat.h>
@@ -189,14 +190,14 @@ param_new_internal(JSContext *cx,
return JS_FALSE;
if (!JSVAL_IS_STRING(argv[0]) ||
- !JSVAL_IS_INT(argv[1]) ||
+ !JSVAL_IS_OBJECT(argv[1]) ||
!JSVAL_IS_STRING(argv[2]) ||
!JSVAL_IS_STRING(argv[3]) ||
!JSVAL_IS_INT(argv[4]))
return JS_FALSE;
prop_name = gjs_string_get_ascii(cx, argv[0]);
- prop_gtype = JSVAL_TO_INT(argv[1]);
+ prop_gtype = gjs_gtype_get_actual_gtype(cx, JSVAL_TO_OBJECT(argv[1]));
prop_type = G_TYPE_FUNDAMENTAL(prop_gtype);
nick = gjs_string_get_ascii(cx, argv[2]);
blurb = gjs_string_get_ascii(cx, argv[3]);
@@ -298,7 +299,12 @@ param_new_internal(JSContext *cx,
GIEnumInfo *info;
gint64 default_value;
- gtype = gjs_gtype_from_value(cx, argv[0]);
+ if (!JSVAL_IS_OBJECT(argv[0])) {
+ gjs_throw(cx, "Passed invalid GType to GParamSpecEnum constructor");
+ goto out;
+ }
+
+ gtype = gjs_gtype_get_actual_gtype(cx, JSVAL_TO_OBJECT(argv[0]));
if (gtype == G_TYPE_NONE) {
gjs_throw(cx, "Passed invalid GType to GParamSpecEnum constructor");
goto out;
@@ -321,7 +327,12 @@ param_new_internal(JSContext *cx,
GType gtype;
gint64 default_value;
- gtype = gjs_gtype_from_value(cx, argv[0]);
+ if (!JSVAL_IS_OBJECT(argv[0])) {
+ gjs_throw(cx, "Passed invalid GType to GParamSpecFlags constructor");
+ goto out;
+ }
+
+ gtype = gjs_gtype_get_actual_gtype(cx, JSVAL_TO_OBJECT(argv[0]));
if (gtype == G_TYPE_NONE) {
gjs_throw(cx, "Passed invalid GType to GParamSpecFlags constructor");
goto out;
diff --git a/test/js/testGIMarshalling.js b/test/js/testGIMarshalling.js
index 5b10c3c6..57dcbfcb 100644
--- a/test/js/testGIMarshalling.js
+++ b/test/js/testGIMarshalling.js
@@ -16,6 +16,7 @@ const GIMarshallingTests = imports.gi.GIMarshallingTests;
// We use Gio to have some objects that we know exist
const Gio = imports.gi.Gio;
+const GObject = imports.gi.GObject;
const Lang = imports.lang;
function testCArray() {
@@ -201,4 +202,32 @@ function testGValue() {
assertArrayEquals([42, "42", true], thing);
}
+function testGType() {
+ assertEquals("void", GObject.TYPE_NONE.name);
+ assertEquals("gchararray", GObject.TYPE_STRING.name);
+
+ // Make sure "name" is readonly
+ GObject.TYPE_STRING.name = "foo";
+ assertEquals("gchararray", GObject.TYPE_STRING.name);
+
+ // Make sure "name" is permanent
+ assertFalse((delete GObject.TYPE_STRING.name));
+
+ // Make sure "toString" works
+ assertEquals("[object GType for 'void']", GObject.TYPE_NONE.toString());
+ assertEquals("[object GType for 'gchararray']", GObject.TYPE_STRING.toString());
+
+ // Marshalling tests
+ assertEquals(GObject.TYPE_NONE, GIMarshallingTests.gtype_return());
+ assertEquals(GObject.TYPE_STRING, GIMarshallingTests.gtype_string_return());
+
+ GIMarshallingTests.gtype_in(GObject.TYPE_NONE);
+ GIMarshallingTests.gtype_string_in(GObject.TYPE_STRING);
+
+ assertEquals(GObject.TYPE_NONE, GIMarshallingTests.gtype_out());
+ assertEquals(GObject.TYPE_STRING, GIMarshallingTests.gtype_string_out());
+
+ assertEquals(GObject.TYPE_INT, GIMarshallingTests.gtype_inout(GObject.TYPE_NONE));
+}
+
gjstestRun();