[gjs/wip/jdahlin/generalised-array-args] Generalise array input arguments
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/wip/jdahlin/generalised-array-args] Generalise array input arguments
- Date: Sun, 4 Feb 2018 05:36:07 +0000 (UTC)
commit 0a54cc3bfb2ae5f6361eab17dc3671955426d3b9
Author: Chris Lord <chris linux intel com>
Date: Tue Feb 16 08:44:49 2010 +0000
Generalise array input arguments
Patch by Johan Dahlin <johan gnome org>
Generalise array input arguments instead of special casing particular
array types. Based on a patch by Johan, updated to apply against trunk
and work with arrays of GValue.
[skip ci] - This patch is quite stale and needs a lot of work, it's not
clear if it is salvageable (Philip Chimento)
gi/arg.cpp | 676 +++++++++++++++--------------------------------------
gi/arg.h | 12 +
gi/boxed.cpp | 7 +-
gi/function.cpp | 13 +-
gi/fundamental.cpp | 2 +-
gi/value.cpp | 9 +-
6 files changed, 210 insertions(+), 509 deletions(-)
---
diff --git a/gi/arg.cpp b/gi/arg.cpp
index cec0e9a3..54c0b5ab 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -26,6 +26,8 @@
#include <cstdlib>
#include <cmath>
+#include <girffi.h>
+
#include "arg.h"
#include "gtype.h"
#include "object.h"
@@ -304,7 +306,7 @@ gjs_array_to_g_list(JSContext *context,
if (!gjs_value_to_g_argument(context,
elem,
param_info,
- NULL,
+ g_type_info_get_tag(param_info), nullptr,
GJS_ARGUMENT_LIST_ELEMENT,
transfer,
false,
@@ -534,8 +536,9 @@ gjs_object_to_g_hash(JSContext *context,
goto free_hash_and_fail;
/* Type check and convert value to a c type */
- if (!gjs_value_to_g_argument(context, val_js, val_param_info, NULL,
- GJS_ARGUMENT_HASH_ELEMENT,
+ if (!gjs_value_to_g_argument(context, val_js, val_param_info,
+ g_type_info_get_tag(val_param_info),
+ nullptr, GJS_ARGUMENT_HASH_ELEMENT,
transfer,
true /* allow null */,
&val_arg))
@@ -606,42 +609,6 @@ gjs_array_from_strv(JSContext *context,
return true;
}
-bool
-gjs_array_to_strv(JSContext *context,
- JS::Value array_value,
- unsigned int length,
- void **arr_p)
-{
- char **result;
- guint32 i;
- JS::RootedObject array(context, array_value.toObjectOrNull());
- JS::RootedValue elem(context);
-
- result = g_new0(char *, length+1);
-
- for (i = 0; i < length; ++i) {
- elem = JS::UndefinedValue();
- if (!JS_GetElement(context, array, i, &elem)) {
- g_free(result);
- gjs_throw(context,
- "Missing array element %u",
- i);
- return false;
- }
-
- GjsAutoJSChar tmp_result;
- if (!gjs_string_to_utf8(context, elem, &tmp_result)) {
- g_strfreev(result);
- return false;
- }
- result[i] = tmp_result.copy();
- }
-
- *arr_p = result;
-
- return true;
-}
-
static bool
gjs_string_to_intarray(JSContext *context,
JS::HandleString str,
@@ -684,278 +651,28 @@ gjs_string_to_intarray(JSContext *context,
return false;
}
-static bool
-gjs_array_to_gboolean_array(JSContext *cx,
- JS::Value array_value,
- unsigned length,
- void **arr_p)
-{
- unsigned i;
- JS::RootedObject array(cx, array_value.toObjectOrNull());
- JS::RootedValue elem(cx);
-
- gboolean *result = g_new0(gboolean, length);
-
- for (i = 0; i < length; i++) {
- if (!JS_GetElement(cx, array, i, &elem)) {
- g_free(result);
- gjs_throw(cx, "Missing array element %u", i);
- return false;
- }
- bool val = JS::ToBoolean(elem);
- result[i] = val;
- }
-
- *arr_p = result;
- return true;
-}
-
-static bool
-gjs_array_to_intarray(JSContext *context,
- JS::Value array_value,
- unsigned int length,
- void **arr_p,
- unsigned intsize,
- bool is_signed)
-{
- /* nasty union types in an attempt to unify the various int types */
- union { uint64_t u; int64_t i; } intval;
- void *result;
- unsigned i;
- JS::RootedObject array(context, array_value.toObjectOrNull());
- JS::RootedValue elem(context);
-
- /* add one so we're always zero terminated */
- result = g_malloc0((length+1) * intsize);
-
- for (i = 0; i < length; ++i) {
- bool success;
-
- elem = JS::UndefinedValue();
- if (!JS_GetElement(context, array, i, &elem)) {
- g_free(result);
- gjs_throw(context,
- "Missing array element %u",
- i);
- return false;
- }
-
- /* do whatever sign extension is appropriate */
- success = (is_signed) ?
- JS::ToInt64(context, elem, &(intval.i)) :
- JS::ToUint64(context, elem, &(intval.u));
-
- if (!success) {
- g_free(result);
- gjs_throw(context,
- "Invalid element in int array");
- return false;
- }
- /* Note that this is truncating assignment. */
- switch (intsize) {
- case 1:
- ((guint8*)result)[i] = (gint8) intval.u; break;
- case 2:
- ((guint16*)result)[i] = (gint16) intval.u; break;
- case 4:
- ((guint32*)result)[i] = (gint32) intval.u; break;
- case 8:
- ((uint64_t *)result)[i] = (int64_t) intval.u; break;
- default:
- g_assert_not_reached();
- }
- }
-
- *arr_p = result;
-
- return true;
-}
-
-static bool
-gjs_gtypearray_to_array(JSContext *context,
- JS::Value array_value,
- unsigned int length,
- void **arr_p)
-{
- GType *result;
- unsigned i;
-
- /* add one so we're always zero terminated */
- result = (GType *) g_malloc0((length+1) * sizeof(GType));
-
- JS::RootedObject elem_obj(context), array(context, array_value.toObjectOrNull());
- JS::RootedValue elem(context);
- for (i = 0; i < length; ++i) {
- GType gtype;
-
- elem = JS::UndefinedValue();
- if (!JS_GetElement(context, array, i, &elem)) {
- g_free(result);
- gjs_throw(context, "Missing array element %u", i);
- return false;
- }
-
- if (!elem.isObjectOrNull())
- goto err;
-
- elem_obj = elem.toObjectOrNull();
- gtype = gjs_gtype_get_actual_gtype(context, elem_obj);
- if (gtype == G_TYPE_INVALID)
- goto err;
-
- result[i] = gtype;
- }
-
- *arr_p = result;
-
- return true;
-
- err:
- g_free(result);
- gjs_throw(context, "Invalid element in GType array");
- return false;
-}
-
-static bool
-gjs_array_to_floatarray(JSContext *context,
- JS::Value array_value,
- unsigned int length,
- void **arr_p,
- bool is_double)
-{
- unsigned int i;
- void *result;
- JS::RootedObject array(context, array_value.toObjectOrNull());
- JS::RootedValue elem(context);
-
- /* add one so we're always zero terminated */
- result = g_malloc0((length+1) * (is_double ? sizeof(double) : sizeof(float)));
-
- for (i = 0; i < length; ++i) {
- double val;
- bool success;
-
- elem = JS::UndefinedValue();
- if (!JS_GetElement(context, array, i, &elem)) {
- g_free(result);
- gjs_throw(context,
- "Missing array element %u",
- i);
- return false;
- }
-
- /* do whatever sign extension is appropriate */
- success = JS::ToNumber(context, elem, &val);
-
- if (!success) {
- g_free(result);
- gjs_throw(context,
- "Invalid element in array");
- return false;
- }
-
- /* Note that this is truncating assignment. */
- if (is_double) {
- double *darray = (double*)result;
- darray[i] = val;
- } else {
- float *farray = (float*)result;
- farray[i] = val;
- }
- }
-
- *arr_p = result;
-
- return true;
-}
-
-static bool
-gjs_array_to_ptrarray(JSContext *context,
- JS::Value array_value,
- unsigned int length,
- GITransfer transfer,
- GITypeInfo *param_info,
- void **arr_p)
-{
- unsigned int i;
- JS::RootedObject array_obj(context, array_value.toObjectOrNull());
- JS::RootedValue elem(context);
-
- /* Always one extra element, to cater for null terminated arrays */
- void **array = (void **) g_malloc((length + 1) * sizeof(gpointer));
- array[length] = NULL;
-
- for (i = 0; i < length; i++) {
- GIArgument arg;
- arg.v_pointer = NULL;
-
- bool success;
-
- elem = JS::UndefinedValue();
- if (!JS_GetElement(context, array_obj, i, &elem)) {
- g_free(array);
- gjs_throw(context,
- "Missing array element %u",
- i);
- return false;
- }
-
- success = gjs_value_to_g_argument (context,
- elem,
- param_info,
- NULL, /* arg name */
- GJS_ARGUMENT_ARRAY_ELEMENT,
- transfer,
- false, /* absent better information, false for now */
- &arg);
-
- if (!success) {
- g_free(array);
- gjs_throw(context,
- "Invalid element in array");
- return false;
- }
-
- array[i] = arg.v_pointer;
- }
-
- *arr_p = array;
- return true;
-}
-
-static bool
-gjs_array_to_flat_gvalue_array(JSContext *context,
- JS::Value array_value,
- unsigned int length,
- void **arr_p)
+static GType
+gjs_interface_get_gvalue(GIBaseInfo *interface_info)
{
- GValue *values = g_new0(GValue, length);
- unsigned int i;
- bool result = true;
- JS::RootedObject array(context, array_value.toObjectOrNull());
- JS::RootedValue elem(context);
-
- for (i = 0; i < length; i ++) {
- elem = JS::UndefinedValue();
-
- if (!JS_GetElement(context, array, i, &elem)) {
- g_free(values);
- gjs_throw(context,
- "Missing array element %u",
- i);
- return false;
- }
-
- result = gjs_value_to_g_value(context, elem, &values[i]);
-
- if (!result)
- break;
- }
-
- if (result)
- *arr_p = values;
-
- return result;
+ GIInfoType interface_type = g_base_info_get_type(interface_info);
+
+ /* These are subtypes of GIRegisteredTypeInfo for which the
+ * cast is safe */
+ if (interface_type == GI_INFO_TYPE_STRUCT ||
+ interface_type == GI_INFO_TYPE_ENUM ||
+ interface_type == GI_INFO_TYPE_FLAGS ||
+ interface_type == GI_INFO_TYPE_OBJECT ||
+ interface_type == GI_INFO_TYPE_INTERFACE ||
+ interface_type == GI_INFO_TYPE_UNION ||
+ interface_type == GI_INFO_TYPE_BOXED)
+ return g_registered_type_info_get_g_type(interface_info);
+
+ /* Special case for GValues */
+ if (interface_type == GI_INFO_TYPE_VALUE)
+ return G_TYPE_VALUE;
+
+ /* Everything else */
+ return G_TYPE_NONE;
}
static bool
@@ -1028,93 +745,93 @@ is_gvalue_flat_array(GITypeInfo *param_info,
return result;
}
-static bool
-gjs_array_to_array(JSContext *context,
+bool
+gjs_array_to_array(JSContext *cx,
JS::Value array_value,
gsize length,
GITransfer transfer,
+ GITypeTag param_type_tag,
GITypeInfo *param_info,
- void **arr_p)
+ bool zero_terminated,
+ void **arguments_p)
{
- enum { UNSIGNED=false, SIGNED=true };
- GITypeTag element_type;
+ bool copy_back = false;
+ bool failed = false;
- element_type = g_type_info_get_tag(param_info);
+ ffi_type *ftype = gi_type_tag_get_ffi_type(param_type_tag,
+ true /* FIXME is_pointer */);
+ JS::RootedObject array(cx, &array_value.toObject());
- /* Special case for GValue "flat arrays" */
- if (is_gvalue_flat_array(param_info, element_type))
- return gjs_array_to_flat_gvalue_array(context, array_value, length, arr_p);
+ size_t alloc_size = length;
+ if (zero_terminated)
+ alloc_size += 1;
- if (element_type == GI_TYPE_TAG_INTERFACE) {
+ size_t type_size = ftype->size;
+
+ /* Special case GValue - note, this might need to be done for other
+ * types that are marked as interfaces (e.g. structs), but this needs
+ * some investigation.
+ */
+ if (param_type_tag == GI_TYPE_TAG_INTERFACE) {
GIBaseInfo *interface_info = g_type_info_get_interface(param_info);
- GIInfoType info_type = g_base_info_get_type(interface_info);
- if (info_type == GI_INFO_TYPE_ENUM || info_type == GI_INFO_TYPE_FLAGS)
- element_type = g_enum_info_get_storage_type ((GIEnumInfo*) interface_info);
- g_base_info_unref(interface_info);
+
+ g_assert(interface_info);
+
+ GType gtype = gjs_interface_get_gvalue(interface_info);
+
+ if (gtype == G_TYPE_VALUE) {
+ type_size = sizeof (GValue);
+ copy_back = true;
+ }
}
- switch (element_type) {
- case GI_TYPE_TAG_UTF8:
- return gjs_array_to_strv (context, array_value, length, arr_p);
- case GI_TYPE_TAG_BOOLEAN:
- return gjs_array_to_gboolean_array(context, array_value, length, arr_p);
- case GI_TYPE_TAG_UNICHAR:
- return gjs_array_to_intarray(context, array_value, length, arr_p,
- sizeof(gunichar), UNSIGNED);
- case GI_TYPE_TAG_UINT8:
- return gjs_array_to_intarray
- (context, array_value, length, arr_p, 1, UNSIGNED);
- case GI_TYPE_TAG_INT8:
- return gjs_array_to_intarray
- (context, array_value, length, arr_p, 1, SIGNED);
- case GI_TYPE_TAG_UINT16:
- return gjs_array_to_intarray
- (context, array_value, length, arr_p, 2, UNSIGNED);
- case GI_TYPE_TAG_INT16:
- return gjs_array_to_intarray
- (context, array_value, length, arr_p, 2, SIGNED);
- case GI_TYPE_TAG_UINT32:
- return gjs_array_to_intarray
- (context, array_value, length, arr_p, 4, UNSIGNED);
- case GI_TYPE_TAG_INT32:
- return gjs_array_to_intarray
- (context, array_value, length, arr_p, 4, SIGNED);
- case GI_TYPE_TAG_INT64:
- return gjs_array_to_intarray(context, array_value, length, arr_p, 8,
- SIGNED);
- case GI_TYPE_TAG_UINT64:
- return gjs_array_to_intarray(context, array_value, length, arr_p, 8,
- UNSIGNED);
- case GI_TYPE_TAG_FLOAT:
- return gjs_array_to_floatarray
- (context, array_value, length, arr_p, false);
- 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);
+ std::unique_ptr<void, decltype(&g_free)> tmp {
+ g_malloc0(alloc_size * type_size),
+ g_free
+ };
- /* Everything else is a pointer type */
- case GI_TYPE_TAG_INTERFACE:
- case GI_TYPE_TAG_ARRAY:
- case GI_TYPE_TAG_GLIST:
- case GI_TYPE_TAG_GSLIST:
- case GI_TYPE_TAG_GHASH:
- case GI_TYPE_TAG_ERROR:
- case GI_TYPE_TAG_FILENAME:
- return gjs_array_to_ptrarray(context,
- array_value,
- length,
- transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer,
- param_info,
- arr_p);
- case GI_TYPE_TAG_VOID:
- default:
- gjs_throw(context,
- "Unhandled array element type %d", element_type);
+ JS::RootedValue elem(cx);
+ size_t i;
+ GArgument *arg;
+ for (i = 0; i < length; ++i) {
+ if (!JS_GetElement(cx, array, i, &elem)) {
+ gjs_throw(cx, "Missing array element %zu", i);
+ failed = true;
+ break;
+ }
+
+ arg = reinterpret_cast<GArgument *>(static_cast<uint8_t *>(tmp.get()) + i * type_size);
+
+ if (!gjs_value_to_g_argument(cx, elem, param_info, param_type_tag,
+ "element argument", GJS_ARGUMENT_ARGUMENT,
+ transfer, false /* FIXME nullable */, arg)) {
+ /* exception already set */
+ failed = true;
+ break;
+ } else if (copy_back) {
+ GValue *gvalue = static_cast<GValue *>(arg->v_pointer);
+ GValue gvalue_copy = *gvalue;
+
+ /* FIXME: This kind of relies on the knowledge that the GValue
+ * boxed type copy func uses g_new...?
+ */
+ g_free(arg->v_pointer);
+
+ gvalue = (GValue *)arg;
+ *((GValue *)arg) = gvalue_copy;
+ }
+ }
+
+ if (failed) {
+ for (size_t j = 0; j < i; ++j) {
+ gjs_g_argument_release(cx, {}, /* FIXME, JS_GetElement */
+ GI_TRANSFER_EVERYTHING, param_info, arg);
+ }
return false;
}
+
+ *arguments_p = tmp.release();
+ return true;
}
static GArray*
@@ -1263,6 +980,7 @@ gjs_array_to_explicit_array_internal(JSContext *context,
GITypeInfo *param_info;
bool found_length;
+ g_assert(type_info);
param_info = g_type_info_get_param_type(type_info, 0);
if ((value.isNull() && !may_be_null) ||
@@ -1291,12 +1009,10 @@ gjs_array_to_explicit_array_internal(JSContext *context,
GJS_STRING_LENGTH, &length)) {
goto out;
} else {
- if (!gjs_array_to_array(context,
- value,
- length,
- transfer,
- param_info,
- contents))
+ bool zero_terminated = g_type_info_is_zero_terminated(type_info);
+ if (!gjs_array_to_array(context, value, length, transfer,
+ g_type_info_get_tag(param_info),
+ param_info, zero_terminated, contents))
goto out;
*length_p = length;
@@ -1350,20 +1066,18 @@ bool
gjs_value_to_g_argument(JSContext *context,
JS::HandleValue value,
GITypeInfo *type_info,
+ GITypeTag type_tag,
const char *arg_name,
GjsArgumentType arg_type,
GITransfer transfer,
bool may_be_null,
GArgument *arg)
{
- GITypeTag type_tag;
bool wrong;
bool out_of_range;
bool report_type_mismatch;
bool nullable_type;
- type_tag = g_type_info_get_tag( (GITypeInfo*) type_info);
-
gjs_debug_marshal(GJS_DEBUG_GFUNCTION,
"Converting JS::Value to GArgument %s",
g_type_tag_to_string(type_tag));
@@ -1555,6 +1269,7 @@ gjs_value_to_g_argument(JSContext *context,
GType gtype;
bool expect_object;
+ g_assert(type_info);
interface_info = g_type_info_get_interface(type_info);
g_assert(interface_info != NULL);
@@ -1579,23 +1294,7 @@ gjs_value_to_g_argument(JSContext *context,
return ret;
}
- if (interface_type == GI_INFO_TYPE_STRUCT ||
- interface_type == GI_INFO_TYPE_ENUM ||
- interface_type == GI_INFO_TYPE_FLAGS ||
- interface_type == GI_INFO_TYPE_OBJECT ||
- interface_type == GI_INFO_TYPE_INTERFACE ||
- interface_type == GI_INFO_TYPE_UNION ||
- interface_type == GI_INFO_TYPE_BOXED) {
- /* These are subtypes of GIRegisteredTypeInfo for which the
- * cast is safe */
- gtype = g_registered_type_info_get_g_type
- ((GIRegisteredTypeInfo*)interface_info);
- } else if (interface_type == GI_INFO_TYPE_VALUE) {
- /* Special case for GValues */
- gtype = G_TYPE_VALUE;
- } else {
- gtype = G_TYPE_NONE;
- }
+ gtype = gjs_interface_get_gvalue(interface_info);
if (gtype != G_TYPE_NONE)
gjs_debug_marshal(GJS_DEBUG_GFUNCTION,
@@ -1868,6 +1567,7 @@ gjs_value_to_g_argument(JSContext *context,
GSList *slist;
GITypeInfo *param_info;
+ g_assert(type_info);
param_info = g_type_info_get_param_type(type_info, 0);
g_assert(param_info != NULL);
@@ -2168,6 +1868,7 @@ gjs_value_to_arg(JSContext *context,
return gjs_value_to_g_argument(context, value,
&type_info,
+ g_type_info_get_tag(&type_info),
g_base_info_get_name( (GIBaseInfo*) arg_info),
(g_arg_info_is_return_value(arg_info) ?
GJS_ARGUMENT_RETURN_VALUE : GJS_ARGUMENT_ARGUMENT),
@@ -3078,6 +2779,7 @@ gjs_value_from_g_argument (JSContext *context,
}
static bool gjs_g_arg_release_internal(JSContext *context,
+ JS::Value value,
GITransfer transfer,
GITypeInfo *type_info,
GITypeTag type_tag,
@@ -3096,7 +2798,8 @@ gjs_ghr_helper(gpointer key, gpointer val, gpointer user_data) {
GArgument key_arg, val_arg;
key_arg.v_pointer = key;
val_arg.v_pointer = val;
- if (!gjs_g_arg_release_internal(c->context, c->transfer,
+ /* FIXME: Should values be zero here? */
+ if (!gjs_g_arg_release_internal(c->context, {}, c->transfer,
c->key_param_info,
g_type_info_get_tag(c->key_param_info),
&key_arg))
@@ -3108,7 +2811,7 @@ gjs_ghr_helper(gpointer key, gpointer val, gpointer user_data) {
val_type == GI_TYPE_TAG_FLOAT ||
val_type == GI_TYPE_TAG_DOUBLE) {
g_free(val_arg.v_pointer);
- } else if (!gjs_g_arg_release_internal(c->context, c->transfer,
+ } else if (!gjs_g_arg_release_internal(c->context, {}, c->transfer,
c->val_param_info, val_type,
&val_arg)) {
c->failed = true;
@@ -3124,6 +2827,7 @@ gjs_ghr_helper(gpointer key, gpointer val, gpointer user_data) {
static bool
gjs_g_arg_release_internal(JSContext *context,
+ JS::Value value,
GITransfer transfer,
GITypeInfo *type_info,
GITypeTag type_tag,
@@ -3209,13 +2913,13 @@ gjs_g_arg_release_internal(JSContext *context,
g_closure_unref((GClosure *) arg->v_pointer);
} else if (g_type_is_a(gtype, G_TYPE_VALUE)) {
/* G_TYPE_VALUE is-a G_TYPE_BOXED, but we special case it */
- if (g_type_info_is_pointer (type_info))
+ /*if (g_type_info_is_pointer (type_info))
g_boxed_free(gtype, arg->v_pointer);
else
- g_value_unset ((GValue *) arg->v_pointer);
+ g_value_unset ((GValue *) arg->v_pointer);*/
} else if (g_type_is_a(gtype, G_TYPE_BOXED)) {
- if (transfer != TRANSFER_IN_NOTHING)
- g_boxed_free(gtype, arg->v_pointer);
+ /*if (transfer != TRANSFER_IN_NOTHING)
+ g_boxed_free(gtype, arg->v_pointer);*/
} else if (g_type_is_a(gtype, G_TYPE_VARIANT)) {
if (transfer != TRANSFER_IN_NOTHING)
g_variant_unref ((GVariant *) arg->v_pointer);
@@ -3253,6 +2957,7 @@ gjs_g_arg_release_internal(JSContext *context,
elem.v_pointer = list->data;
if (!gjs_g_arg_release_internal(context,
+ {}, /* FIXME: JS_GetElement */
transfer,
param_info,
g_type_info_get_tag(param_info),
@@ -3276,6 +2981,7 @@ gjs_g_arg_release_internal(JSContext *context,
} else if (array_type == GI_ARRAY_TYPE_C) {
GITypeInfo *param_info;
GITypeTag element_type;
+ void *arguments = arg->v_pointer;
param_info = g_type_info_get_param_type(type_info, 0);
element_type = g_type_info_get_tag(param_info);
@@ -3304,84 +3010,64 @@ gjs_g_arg_release_internal(JSContext *context,
return true;
}
- switch (element_type) {
- case GI_TYPE_TAG_UTF8:
- case GI_TYPE_TAG_FILENAME:
- if (transfer == GI_TRANSFER_CONTAINER)
- g_free(arg->v_pointer);
- else
- g_strfreev ((gchar **) arg->v_pointer);
- break;
+ if (element_type == GI_TYPE_TAG_UTF8 ||
+ element_type == GI_TYPE_TAG_FILENAME)
+ gjs_debug_marshal(GJS_DEBUG_MEMORY,
+ "Releasing memory for string arrays is "
+ "not properly implement. Leaking.");
- case GI_TYPE_TAG_BOOLEAN:
- case GI_TYPE_TAG_UINT8:
- case GI_TYPE_TAG_UINT16:
- case GI_TYPE_TAG_UINT32:
- case GI_TYPE_TAG_UINT64:
- case GI_TYPE_TAG_INT8:
- case GI_TYPE_TAG_INT16:
- case GI_TYPE_TAG_INT32:
- case GI_TYPE_TAG_INT64:
- case GI_TYPE_TAG_FLOAT:
- case GI_TYPE_TAG_DOUBLE:
- case GI_TYPE_TAG_UNICHAR:
- case GI_TYPE_TAG_GTYPE:
- g_free (arg->v_pointer);
- break;
+ ffi_type *ftype = g_type_info_get_ffi_type (param_info);
- case GI_TYPE_TAG_INTERFACE:
- case GI_TYPE_TAG_GLIST:
- case GI_TYPE_TAG_GSLIST:
- case GI_TYPE_TAG_ARRAY:
- case GI_TYPE_TAG_GHASH:
- case GI_TYPE_TAG_ERROR:
- if (transfer != GI_TRANSFER_CONTAINER
- && type_needs_out_release(param_info, element_type)) {
- if (g_type_info_is_zero_terminated (type_info)) {
- gpointer *array;
- GArgument elem;
-
- for (array = (void **) arg->v_pointer; *array; array++) {
- elem.v_pointer = *array;
- if (!gjs_g_arg_release_internal(context,
- GI_TRANSFER_EVERYTHING,
- param_info,
- element_type,
- &elem)) {
- failed = true;
- }
- }
- } else {
- gint len = g_type_info_get_array_fixed_size(type_info);
- gint i;
- GArgument elem;
-
- g_assert(len != -1);
-
- for (i = 0; i < len; i++) {
- elem.v_pointer = ((gpointer*)arg->v_pointer)[i];
- if (!gjs_g_arg_release_internal(context,
- GI_TRANSFER_EVERYTHING,
- param_info,
- element_type,
- &elem)) {
- failed = true;
- }
- }
- }
- }
- g_free (arg->v_pointer);
+ uint32_t length;
+ JS::RootedObject list(context, &value.toObject());
+ if (!gjs_object_require_converted_property(context, list, nullptr,
+ GJS_STRING_LENGTH,
+ &length)) {
+ g_error("Failed to release list element");
break;
+ }
- case GI_TYPE_TAG_VOID:
- default:
- gjs_throw(context,
- "Releasing a C array with explicit length, that was nested"
- "inside another container. This is not supported (and will leak)");
- failed = true;
+ /* FIXME: Special case GValue (see gjs_array_to_array) - may need
+ * to do this for other types too, not sure.
+ */
+ if (element_type == GI_TYPE_TAG_INTERFACE) {
+ GIBaseInfo *interface_info = g_type_info_get_interface(param_info);
+ g_assert(interface_info);
+
+ GType gtype = gjs_interface_get_gvalue (interface_info);
+
+ if (gtype == G_TYPE_VALUE) {
+ for (uint32_t i = 0; i < length; ++i)
+ g_value_unset(&static_cast<GValue *>(arguments)[i]);
+ g_free(arguments);
+ break;
+ }
}
+ bool zero_terminated = g_type_info_is_zero_terminated(type_info);
+ if (zero_terminated)
+ length += 1;
+
+ for (uint32_t i = 0; i < length; ++i) {
+ /* FIXME: Special case GValue for now - see
+ * gjs_array_to_array
+ */
+ void *ptr = static_cast<uint8_t *>(arguments) + i * ftype->size;
+ if (!gjs_g_argument_release(context,
+ {}, /* FIXME, JS_GetElement */
+ GI_TRANSFER_EVERYTHING,
+ param_info,
+ reinterpret_cast<GIArgument *>(ptr))) {
+ /* no way to recover here, and errors should
+ * not be possible.
+ */
+ g_error("Failed to release list element");
+ break;
+ }
+ }
g_base_info_unref((GIBaseInfo*) param_info);
+ g_free(arguments);
+
} else if (array_type == GI_ARRAY_TYPE_ARRAY) {
GITypeInfo *param_info;
GITypeTag element_type;
@@ -3425,6 +3111,7 @@ gjs_g_arg_release_internal(JSContext *context,
arg_iter.v_pointer = g_array_index (array, gpointer, i);
gjs_g_arg_release_internal(context,
+ {}, /* FIXME: JS_GetElement */
transfer,
param_info,
element_type,
@@ -3461,7 +3148,7 @@ gjs_g_arg_release_internal(JSContext *context,
GArgument arg_iter;
arg_iter.v_pointer = g_ptr_array_index (array, i);
- gjs_g_argument_release(context,
+ gjs_g_argument_release(context, {}, /* FIXME */
transfer,
param_info,
&arg_iter);
@@ -3491,7 +3178,7 @@ gjs_g_arg_release_internal(JSContext *context,
GArgument elem;
elem.v_pointer = slist->data;
- if (!gjs_g_arg_release_internal(context,
+ if (!gjs_g_arg_release_internal(context, {}, /* FIXME */
transfer,
param_info,
g_type_info_get_tag(param_info),
@@ -3546,6 +3233,7 @@ gjs_g_arg_release_internal(JSContext *context,
bool
gjs_g_argument_release(JSContext *context,
+ JS::Value value,
GITransfer transfer,
GITypeInfo *type_info,
GArgument *arg)
@@ -3561,11 +3249,13 @@ gjs_g_argument_release(JSContext *context,
"Releasing GArgument %s out param or return value",
g_type_tag_to_string(type_tag));
- return gjs_g_arg_release_internal(context, transfer, type_info, type_tag, arg);
+ return gjs_g_arg_release_internal(context, value, transfer, type_info,
+ type_tag, arg);
}
bool
gjs_g_argument_release_in_arg(JSContext *context,
+ JS::Value value,
GITransfer transfer,
GITypeInfo *type_info,
GArgument *arg)
@@ -3588,7 +3278,8 @@ gjs_g_argument_release_in_arg(JSContext *context,
g_type_tag_to_string(type_tag));
if (type_needs_release (type_info, type_tag))
- return gjs_g_arg_release_internal(context, (GITransfer) TRANSFER_IN_NOTHING,
+ return gjs_g_arg_release_internal(context, value,
+ GITransfer(TRANSFER_IN_NOTHING),
type_info, type_tag, arg);
return true;
@@ -3629,7 +3320,8 @@ gjs_g_argument_release_in_array (JSContext *context,
if (type_needs_release(param_type, type_tag)) {
for (i = 0; i < length; i++) {
elem.v_pointer = array[i];
- if (!gjs_g_arg_release_internal(context, (GITransfer) TRANSFER_IN_NOTHING,
+ if (!gjs_g_arg_release_internal(context, {}, /* FIXME */
+ GITransfer(TRANSFER_IN_NOTHING),
param_type, type_tag, &elem)) {
ret = false;
break;
@@ -3672,7 +3364,7 @@ gjs_g_argument_release_out_array (JSContext *context,
type_needs_out_release(param_type, type_tag)) {
for (i = 0; i < length; i++) {
elem.v_pointer = array[i];
- if (!gjs_g_arg_release_internal(context,
+ if (!gjs_g_arg_release_internal(context, {}, /* FIXME */
GI_TRANSFER_EVERYTHING,
param_type,
type_tag,
diff --git a/gi/arg.h b/gi/arg.h
index 06a41b31..ba7d123f 100644
--- a/gi/arg.h
+++ b/gi/arg.h
@@ -61,6 +61,7 @@ void gjs_g_argument_init_default (JSContext *context,
bool gjs_value_to_g_argument (JSContext *context,
JS::HandleValue value,
GITypeInfo *type_info,
+ GITypeTag type_tag,
const char *arg_name,
GjsArgumentType argument_type,
GITransfer transfer,
@@ -80,6 +81,7 @@ bool gjs_value_from_explicit_array(JSContext *context,
int length);
bool gjs_g_argument_release (JSContext *context,
+ JS::Value value,
GITransfer transfer,
GITypeInfo *type_info,
GArgument *arg);
@@ -94,6 +96,7 @@ bool gjs_g_argument_release_in_array (JSContext *context,
guint length,
GArgument *arg);
bool gjs_g_argument_release_in_arg (JSContext *context,
+ JS::Value value,
GITransfer transfer,
GITypeInfo *type_info,
GArgument *arg);
@@ -114,6 +117,15 @@ bool gjs_array_to_strv (JSContext *context,
unsigned int length,
void **arr_p);
+bool gjs_array_to_array(JSContext *cx,
+ JS::Value array_value,
+ unsigned length,
+ GITransfer transfer,
+ GITypeTag param_type_tag,
+ GITypeInfo *param_info,
+ bool zero_terminated,
+ void **arguments);
+
G_END_DECLS
#endif /* __GJS_ARG_H__ */
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index 231bd0f4..584012bb 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -757,7 +757,7 @@ boxed_set_field_from_value(JSContext *context,
}
if (!gjs_value_to_g_argument(context, value,
- type_info,
+ type_info, g_type_info_get_tag(type_info),
g_base_info_get_name ((GIBaseInfo *)field_info),
GJS_ARGUMENT_FIELD,
GI_TRANSFER_NOTHING,
@@ -777,9 +777,8 @@ boxed_set_field_from_value(JSContext *context,
out:
if (need_release)
- gjs_g_argument_release (context, GI_TRANSFER_NOTHING,
- type_info,
- &arg);
+ gjs_g_argument_release(context, value, GI_TRANSFER_NOTHING, type_info,
+ &arg);
g_base_info_unref ((GIBaseInfo *)type_info);
diff --git a/gi/function.cpp b/gi/function.cpp
index 56f6da95..c22f6a16 100644
--- a/gi/function.cpp
+++ b/gi/function.cpp
@@ -312,7 +312,7 @@ gjs_callback_closure(ffi_cif *cif,
* be a single return value. */
if (!gjs_value_to_g_argument(context,
rval,
- &ret_type,
+ &ret_type, g_type_info_get_tag(&ret_type),
"callback",
GJS_ARGUMENT_RETURN_VALUE,
transfer,
@@ -337,6 +337,7 @@ gjs_callback_closure(ffi_cif *cif,
if (!gjs_value_to_g_argument(context,
rval,
&type_info,
+ g_type_info_get_tag(&type_info),
"callback",
GJS_ARGUMENT_ARGUMENT,
GI_TRANSFER_NOTHING,
@@ -362,6 +363,7 @@ gjs_callback_closure(ffi_cif *cif,
if (!gjs_value_to_g_argument(context,
elem,
&ret_type,
+ g_type_info_get_tag(&ret_type),
"callback",
GJS_ARGUMENT_ARGUMENT,
GI_TRANSFER_NOTHING,
@@ -390,6 +392,7 @@ gjs_callback_closure(ffi_cif *cif,
if (!gjs_value_to_g_argument(context,
elem,
&type_info,
+ g_type_info_get_tag(&type_info),
"callback",
GJS_ARGUMENT_ARGUMENT,
GI_TRANSFER_NOTHING,
@@ -1135,7 +1138,7 @@ gjs_invoke_c_function(JSContext *context,
/* Free GArgument, the JS::Value should have ref'd or copied it */
if (!arg_failed &&
!r_value &&
- !gjs_g_argument_release(context,
+ !gjs_g_argument_release(context, return_values[next_rval],
transfer,
&return_info,
&return_gargument))
@@ -1215,8 +1218,7 @@ release:
postinvoke_release_failed = true;
}
} else if (param_type == PARAM_NORMAL) {
- if (!gjs_g_argument_release_in_arg(context,
- transfer,
+ if (!gjs_g_argument_release_in_arg(context, args[i], transfer,
&arg_type_info,
arg)) {
postinvoke_release_failed = true;
@@ -1285,8 +1287,7 @@ release:
array_length.toInt32(),
arg);
} else {
- gjs_g_argument_release(context,
- transfer,
+ gjs_g_argument_release(context, args[i], transfer,
&arg_type_info,
arg);
}
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index 282394bc..8fc11c92 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -446,7 +446,7 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(fundamental_instance)
g_callable_info_load_return_type((GICallableInfo*) priv->prototype->constructor_info, &return_info);
- if (!gjs_g_argument_release (context,
+ if (!gjs_g_argument_release (context, {}, /* FIXME */
g_callable_info_get_caller_owns((GICallableInfo*)
priv->prototype->constructor_info),
&return_info,
&ret_value))
diff --git a/gi/value.cpp b/gi/value.cpp
index b264cc71..66963014 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -498,15 +498,12 @@ gjs_value_to_g_value_internal(JSContext *context,
gjs_get_type_name(value));
return false;
} else {
- void *result;
char **strv;
- if (!gjs_array_to_strv (context,
- value,
- length, &result))
+ if (!gjs_array_to_array(context, value, length, transfer,
+ GI_TYPE_TAG_UTF8, nullptr, true,
+ reinterpret_cast<void **>(&strv)))
return false;
- /* cast to strv in a separate step to avoid type-punning */
- strv = (char**) result;
g_value_take_boxed (gvalue, strv);
}
} else {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]