[gjs] Use std::unique_ptr instead of g_autofree/g_autoptr()
- From: Chun-wei Fan <fanchunwei src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs] Use std::unique_ptr instead of g_autofree/g_autoptr()
- Date: Wed, 24 May 2017 08:26:44 +0000 (UTC)
commit bcd1f395801f6928c419a6bd99a35eb004be9e54
Author: Chun-wei Fan <fanchunwei src gnome org>
Date: Wed Apr 19 23:35:48 2017 +0800
Use std::unique_ptr instead of g_autofree/g_autoptr()
This completes the transition of the code to std::unique_ptr so that we
can be assured that we use JS_free() on items that are acquired via
pass-by-reference via SpiderMonkey APIs, and thus we can remove more of
the g_free() calls on those as SpiderMonkey may switch to a different
allocation/deallocation implementation internally (which is currently
free()).
https://bugzilla.gnome.org/show_bug.cgi?id=777597
gi/arg.cpp | 49 ++++++++------------
gi/boxed.cpp | 23 +++-------
gi/fundamental.cpp | 12 +----
gi/interface.cpp | 9 +---
gi/ns.cpp | 7 +---
gi/object.cpp | 109 ++++++++++++++++----------------------------
gi/param.cpp | 4 +-
gi/repo.cpp | 6 +--
gi/union.cpp | 9 +---
gi/value.cpp | 4 +-
gjs/byteArray.cpp | 29 +++---------
gjs/context.cpp | 9 +---
gjs/coverage.cpp | 29 ++++++------
gjs/importer.cpp | 36 +++++----------
gjs/jsapi-util-args.h | 9 +++-
gjs/jsapi-util-string.cpp | 23 +++------
gjs/jsapi-util.cpp | 65 ++++++++++++--------------
gjs/jsapi-util.h | 61 ++++++++++++++++++++++++-
gjs/runtime.cpp | 19 ++------
gjs/stack.cpp | 5 +-
test/gjs-tests.cpp | 6 +--
21 files changed, 228 insertions(+), 295 deletions(-)
---
diff --git a/gi/arg.cpp b/gi/arg.cpp
index 81ebf4d..0457673 100644
--- a/gi/arg.cpp
+++ b/gi/arg.cpp
@@ -416,7 +416,7 @@ value_to_ghashtable_key(JSContext *cx,
#define HANDLE_STRING(type, lctype) \
case GI_TYPE_TAG_##type: { \
- char *cstr; \
+ GjsAutoJSChar cstr(cx); \
JS::RootedValue str_val(cx, value); \
if (!str_val.isString()) { \
JS::RootedString str(cx, JS::ToString(cx, str_val)); \
@@ -424,7 +424,7 @@ value_to_ghashtable_key(JSContext *cx,
} \
if (!gjs_string_to_##lctype(cx, str_val, &cstr)) \
return false; \
- *pointer_out = cstr; \
+ *pointer_out = cstr.copy(); \
break; \
}
@@ -610,6 +610,8 @@ gjs_array_to_strv(JSContext *context,
result = g_new0(char *, length+1);
for (i = 0; i < length; ++i) {
+ GjsAutoJSChar tmp_result(context);
+
elem = JS::UndefinedValue();
if (!JS_GetElement(context, array, i, &elem)) {
g_free(result);
@@ -625,10 +627,11 @@ gjs_array_to_strv(JSContext *context,
g_strfreev(result);
return false;
}
- if (!gjs_string_to_utf8(context, elem, (char **)&(result[i]))) {
+ if (!gjs_string_to_utf8(context, elem, &tmp_result)) {
g_strfreev(result);
return false;
}
+ result[i] = tmp_result.copy();
}
*arr_p = result;
@@ -644,16 +647,17 @@ gjs_string_to_intarray(JSContext *context,
gsize *length)
{
GITypeTag element_type;
- char *result;
char16_t *result16;
element_type = g_type_info_get_tag(param_info);
if (element_type == GI_TYPE_TAG_INT8 || element_type == GI_TYPE_TAG_UINT8) {
+ GjsAutoJSChar result(context);
+
if (!gjs_string_to_utf8(context, string_val, &result))
return false;
- *arr_p = result;
*length = strlen(result);
+ *arr_p = result.copy();
return true;
}
@@ -1463,10 +1467,9 @@ gjs_value_to_g_argument(JSContext *context,
if (value.isNull()) {
arg->v_pointer = NULL;
} else if (value.isString()) {
- char *filename_str;
+ GjsAutoJSChar filename_str(context);
if (gjs_string_to_filename(context, value, &filename_str))
- // doing this as a separate step to avoid type-punning
- arg->v_pointer = filename_str;
+ arg->v_pointer = filename_str.copy();
else
wrong = true;
} else {
@@ -1479,10 +1482,9 @@ gjs_value_to_g_argument(JSContext *context,
if (value.isNull()) {
arg->v_pointer = NULL;
} else if (value.isString()) {
- char *utf8_str;
+ GjsAutoJSChar utf8_str(context);
if (gjs_string_to_utf8(context, value, &utf8_str))
- // doing this as a separate step to avoid type-punning
- arg->v_pointer = utf8_str;
+ arg->v_pointer = utf8_str.copy();
else
wrong = true;
} else {
@@ -2526,9 +2528,7 @@ gjs_object_from_g_hash (JSContext *context,
GHashTable *hash)
{
GHashTableIter iter;
- char *keyutf8 = NULL;
GArgument keyarg, valarg;
- bool result;
// a NULL hash table becomes a null JS value
if (hash==NULL) {
@@ -2545,41 +2545,32 @@ gjs_object_from_g_hash (JSContext *context,
JS::RootedValue keyjs(context), valjs(context);
JS::RootedString keystr(context);
- result = false;
-
g_hash_table_iter_init(&iter, hash);
while (g_hash_table_iter_next
(&iter, &keyarg.v_pointer, &valarg.v_pointer)) {
if (!gjs_value_from_g_argument(context, &keyjs,
key_param_info, &keyarg,
true))
- goto out;
+ return false;
keystr = JS::ToString(context, keyjs);
if (!keystr)
- goto out;
+ return false;
+ GjsAutoJSChar keyutf8(context);
if (!gjs_string_to_utf8(context, JS::StringValue(keystr), &keyutf8))
- goto out;
+ return false;
if (!gjs_value_from_g_argument(context, &valjs,
val_param_info, &valarg,
true))
- goto out;
+ return false;
if (!JS_DefineProperty(context, obj, keyutf8, valjs, JSPROP_ENUMERATE))
- goto out;
-
- g_free(keyutf8);
- keyutf8 = NULL;
+ return false;
}
- result = true;
-
- out:
- if (keyutf8) g_free(keyutf8);
-
- return result;
+ return true;
}
static const int64_t MAX_SAFE_INT64 =
diff --git a/gi/boxed.cpp b/gi/boxed.cpp
index e6500d3..3fe037d 100644
--- a/gi/boxed.cpp
+++ b/gi/boxed.cpp
@@ -122,7 +122,7 @@ boxed_resolve(JSContext *context,
bool *resolved)
{
Boxed *priv;
- char *name = NULL;
+ GjsAutoJSChar name(context);
if (!gjs_get_string_id(context, id, &name)) {
*resolved = false;
@@ -133,10 +133,8 @@ boxed_resolve(JSContext *context,
gjs_debug_jsprop(GJS_DEBUG_GBOXED, "Resolve prop '%s' hook obj %p priv %p",
name, obj.get(), priv);
- if (priv == NULL) {
- g_free(name);
+ if (priv == nullptr)
return false; /* wrong class */
- }
if (priv->gboxed == NULL) {
/* We are the prototype, so look for methods and other class properties */
@@ -164,7 +162,6 @@ boxed_resolve(JSContext *context,
if (gjs_define_function(context, obj, priv->gtype,
(GICallableInfo *)method_info) == NULL) {
g_base_info_unref( (GIBaseInfo*) method_info);
- g_free(name);
return false;
}
@@ -185,7 +182,6 @@ boxed_resolve(JSContext *context,
*/
*resolved = false;
}
- g_free(name);
return true;
}
@@ -283,7 +279,7 @@ boxed_init_from_props(JSContext *context,
JS::RootedId prop_id(context);
for (ix = 0, length = ids.length(); ix < length; ix++) {
GIFieldInfo *field_info;
- char *name = NULL;
+ GjsAutoJSChar name(context);
if (!gjs_get_string_id(context, ids[ix], &name))
return false;
@@ -291,8 +287,7 @@ boxed_init_from_props(JSContext *context,
field_info = (GIFieldInfo *) g_hash_table_lookup(priv->field_map, name);
if (field_info == NULL) {
gjs_throw(context, "No field %s on boxed type %s",
- name, g_base_info_get_name((GIBaseInfo *)priv->info));
- g_free(name);
+ name.get(), g_base_info_get_name((GIBaseInfo *)priv->info));
return false;
}
@@ -300,17 +295,11 @@ boxed_init_from_props(JSContext *context,
* doesn't know that */
prop_id = ids[ix];
if (!gjs_object_require_property(context, props, "property list",
- prop_id, &value)) {
- g_free(name);
+ prop_id, &value))
return false;
- }
- if (!boxed_set_field_from_value(context, priv, field_info, value)) {
- g_free(name);
+ if (!boxed_set_field_from_value(context, priv, field_info, value))
return false;
- }
-
- g_free(name);
}
return true;
diff --git a/gi/fundamental.cpp b/gi/fundamental.cpp
index 2242bc8..4ff6702 100644
--- a/gi/fundamental.cpp
+++ b/gi/fundamental.cpp
@@ -241,7 +241,7 @@ fundamental_instance_resolve_interface(JSContext *context,
JS::HandleObject obj,
bool *resolved,
Fundamental *proto_priv,
- char *name)
+ const char *name)
{
GIFunctionInfo *method_info;
bool ret;
@@ -301,7 +301,7 @@ fundamental_instance_resolve(JSContext *context,
bool *resolved)
{
FundamentalInstance *priv;
- char *name = NULL;
+ GjsAutoJSChar name(context);
if (!gjs_get_string_id(context, id, &name)) {
*resolved = false;
@@ -313,10 +313,8 @@ fundamental_instance_resolve(JSContext *context,
"Resolve prop '%s' hook obj %p priv %p",
name, obj.get(), priv);
- if (priv == NULL) {
- g_free(name);
+ if (priv == nullptr)
return false; /* wrong class */
- }
if (!fundamental_is_prototype(priv)) {
/* We are an instance, not a prototype, so look for
@@ -327,7 +325,6 @@ fundamental_instance_resolve(JSContext *context,
* hooks, not this resolve hook.
*/
*resolved = false;
- g_free(name);
return true;
}
@@ -356,7 +353,6 @@ fundamental_instance_resolve(JSContext *context,
g_base_info_get_name((GIBaseInfo *) proto_priv->info));
g_base_info_unref((GIBaseInfo *) method_info);
*resolved = false;
- g_free(name);
return true;
}
@@ -369,7 +365,6 @@ fundamental_instance_resolve(JSContext *context,
if (gjs_define_function(context, obj, proto_priv->gtype,
method_info) == NULL) {
g_base_info_unref((GIBaseInfo *) method_info);
- g_free(name);
return false;
}
@@ -384,7 +379,6 @@ fundamental_instance_resolve(JSContext *context,
bool status =
fundamental_instance_resolve_interface(context, obj, resolved,
proto_priv, name);
- g_free(name);
return status;
}
diff --git a/gi/interface.cpp b/gi/interface.cpp
index 712702b..c9c8573 100644
--- a/gi/interface.cpp
+++ b/gi/interface.cpp
@@ -112,7 +112,7 @@ interface_resolve(JSContext *context,
bool *resolved)
{
Interface *priv;
- char *name = NULL;
+ GjsAutoJSChar name(context);
GIFunctionInfo *method_info;
if (!gjs_get_string_id(context, id, &name)) {
@@ -122,17 +122,14 @@ interface_resolve(JSContext *context,
priv = priv_from_js(context, obj);
- if (priv == NULL) {
- g_free(name);
+ if (priv == nullptr)
return false;
- }
/* If we have no GIRepository information then this interface was defined
* from within GJS. In that case, it has no properties that need to be
* resolved from within C code, as interfaces cannot inherit. */
if (priv->info == NULL) {
*resolved = false;
- g_free(name);
return true;
}
@@ -144,7 +141,6 @@ interface_resolve(JSContext *context,
priv->gtype,
(GICallableInfo*)method_info) == NULL) {
g_base_info_unref((GIBaseInfo*)method_info);
- g_free(name);
return false;
}
@@ -158,7 +154,6 @@ interface_resolve(JSContext *context,
*resolved = false;
}
- g_free(name);
return true;
}
diff --git a/gi/ns.cpp b/gi/ns.cpp
index 9406cd6..830e4e9 100644
--- a/gi/ns.cpp
+++ b/gi/ns.cpp
@@ -55,7 +55,7 @@ ns_resolve(JSContext *context,
bool *resolved)
{
Ns *priv;
- char *name = NULL;
+ GjsAutoJSChar name(context);
GIRepository *repo;
GIBaseInfo *info;
bool defined;
@@ -69,7 +69,6 @@ ns_resolve(JSContext *context,
if (strcmp(name, "valueOf") == 0 ||
strcmp(name, "toString") == 0) {
*resolved = false;
- g_free(name);
return true;
}
@@ -80,7 +79,6 @@ ns_resolve(JSContext *context,
if (priv == NULL) {
*resolved = false; /* we are the prototype, or have the wrong class */
- g_free(name);
return true;
}
@@ -89,7 +87,6 @@ ns_resolve(JSContext *context,
info = g_irepository_find_by_name(repo, priv->gi_namespace, name);
if (info == NULL) {
*resolved = false; /* No property defined, but no error either */
- g_free(name);
return true;
}
@@ -107,14 +104,12 @@ ns_resolve(JSContext *context,
g_base_info_get_name(info));
g_base_info_unref(info);
- g_free(name);
return false;
}
/* we defined the property in this object? */
g_base_info_unref(info);
*resolved = defined;
- g_free(name);
return true;
}
diff --git a/gi/object.cpp b/gi/object.cpp
index d98c126..fab3225 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -390,8 +390,7 @@ object_instance_get_prop(JSContext *context,
JS::MutableHandleValue value_p)
{
ObjectInstance *priv;
- char *name;
- bool ret = true;
+ GjsAutoJSChar name(context);
if (!gjs_get_string_id(context, id, &name))
return true; /* not resolved, but no error */
@@ -401,28 +400,23 @@ object_instance_get_prop(JSContext *context,
"Get prop '%s' hook obj %p priv %p",
name, obj.get(), priv);
- if (priv == NULL) {
+ if (priv == nullptr)
/* If we reach this point, either object_instance_new_resolve
* did not throw (so name == "_init"), or the property actually
* exists and it's not something we should be concerned with */
- goto out;
- }
+ return true;
+
if (priv->gobj == NULL) /* prototype, not an instance. */
- goto out;
+ return true;
- ret = get_prop_from_g_param(context, obj, priv, name, value_p);
- if (!ret)
- goto out;
+ if (!get_prop_from_g_param(context, obj, priv, name, value_p))
+ return false;
if (!value_p.isUndefined())
- goto out;
+ return true;
/* Fall back to fields */
- ret = get_prop_from_field(context, obj, priv, name, value_p);
-
- out:
- g_free(name);
- return ret;
+ return get_prop_from_field(context, obj, priv, name, value_p);
}
static bool
@@ -509,7 +503,7 @@ object_instance_set_prop(JSContext *context,
JS::MutableHandleValue value_p)
{
ObjectInstance *priv;
- char *name;
+ GjsAutoJSChar name(context);
bool ret = true;
bool g_param_was_set = false;
@@ -521,28 +515,23 @@ object_instance_set_prop(JSContext *context,
"Set prop '%s' hook obj %p priv %p",
name, obj.get(), priv);
- if (priv == NULL) {
+ if (priv == nullptr)
/* see the comment in object_instance_get_prop() on this */
- goto out;
- }
+ return true;
+
if (priv->gobj == NULL) /* prototype, not an instance. */
- goto out;
+ return true;
ret = set_g_param_from_prop(context, priv, name, g_param_was_set, value_p);
if (g_param_was_set || !ret)
- goto out;
-
- ret = check_set_field_from_prop(context, priv, name, strict, value_p);
+ return ret;
/* note that the prop will also have been set in JS, which I think
* is OK, since we hook get and set so will always override that
* value. We could also use JS_DefineProperty though and specify a
* getter/setter maybe, don't know if that is better.
*/
-
- out:
- g_free(name);
- return ret;
+ return check_set_field_from_prop(context, priv, name, strict, value_p);
}
static bool
@@ -610,7 +599,7 @@ object_instance_resolve_no_info(JSContext *context,
JS::HandleObject obj,
bool *resolved,
ObjectInstance *priv,
- char *name)
+ const char *name)
{
GIFunctionInfo *method_info;
guint n_interfaces;
@@ -674,7 +663,7 @@ object_instance_resolve(JSContext *context,
{
GIFunctionInfo *method_info;
ObjectInstance *priv;
- char *name = NULL;
+ GjsAutoJSChar name(context);
if (!gjs_get_string_id(context, id, &name)) {
*resolved = false;
@@ -703,13 +692,11 @@ object_instance_resolve(JSContext *context,
* check there.
*/
*resolved = false;
- g_free(name);
return true;
}
if (priv->gobj != NULL) {
*resolved = false;
- g_free(name);
return true;
}
@@ -718,7 +705,6 @@ object_instance_resolve(JSContext *context,
* GType data, and then hope that *those* are introspectable. */
if (priv->info == NULL) {
bool status = object_instance_resolve_no_info(context, obj, resolved, priv, name);
- g_free(name);
return status;
}
@@ -737,13 +723,12 @@ object_instance_resolve(JSContext *context,
* rest.
*/
- const char *name_without_vfunc_ = &name[6]; /* lifetime tied to name */
+ const char *name_without_vfunc_ = &(name[6]); /* lifetime tied to name */
GIVFuncInfo *vfunc;
bool defined_by_parent;
vfunc = find_vfunc_on_parents(priv->info, name_without_vfunc_, &defined_by_parent);
if (vfunc != NULL) {
- g_free(name);
/* In the event that the vfunc is unchanged, let regular
* prototypal inheritance take over. */
@@ -785,11 +770,9 @@ object_instance_resolve(JSContext *context,
*/
if (method_info == NULL) {
bool retval = object_instance_resolve_no_info(context, obj, resolved, priv, name);
- g_free(name);
return retval;
}
- g_free(name);
#if GJS_VERBOSE_ENABLE_GI_USAGE
_gjs_log_info_usage((GIBaseInfo*) method_info);
@@ -859,7 +842,7 @@ object_instance_props_to_g_parameters(JSContext *context,
}
for (ix = 0, length = ids.length(); ix < length; ix++) {
- char *name = NULL;
+ GjsAutoJSChar name(context);
GParameter gparam = { NULL, { 0, }};
/* ids[ix] is reachable because props is rooted, but require_property
@@ -880,18 +863,15 @@ object_instance_props_to_g_parameters(JSContext *context,
true /* constructing */)) {
case NO_SUCH_G_PROPERTY:
gjs_throw(context, "No property %s on this GObject %s",
- name, g_type_name(gtype));
+ name.get(), g_type_name(gtype));
/* fallthrough */
case SOME_ERROR_OCCURRED:
- g_free(name);
goto free_array_and_fail;
case VALUE_WAS_SET:
default:
break;
}
- g_free(name);
-
gparams.push_back(gparam);
}
@@ -1596,10 +1576,9 @@ real_connect_func(JSContext *context,
GClosure *closure;
gulong id;
guint signal_id;
- char *signal_name;
+ GjsAutoJSChar signal_name(context);
GQuark signal_detail;
ConnectData *connect_data;
- bool ret = false;
gjs_debug_gsignal("connect obj %p priv %p argc %d", obj.get(), priv, argc);
if (priv == NULL) {
@@ -1629,14 +1608,14 @@ real_connect_func(JSContext *context,
&signal_detail,
true)) {
gjs_throw(context, "No signal '%s' on object '%s'",
- signal_name,
- g_type_name(G_OBJECT_TYPE(priv->gobj)));
- goto out;
+ signal_name.get(),
+ g_type_name(G_OBJECT_TYPE(priv->gobj)));
+ return false;
}
closure = gjs_closure_new_for_signal(context, &argv[1].toObject(), "signal callback", signal_id);
if (closure == NULL)
- goto out;
+ return false;
connect_data = g_slice_new(ConnectData);
priv->signals = g_list_prepend(priv->signals, connect_data);
@@ -1654,10 +1633,7 @@ real_connect_func(JSContext *context,
argv.rval().setDouble(id);
- ret = true;
- out:
- g_free(signal_name);
- return ret;
+ return true;
}
static bool
@@ -1685,12 +1661,11 @@ emit_func(JSContext *context,
guint signal_id;
GQuark signal_detail;
GSignalQuery signal_query;
- char *signal_name;
+ GjsAutoJSChar signal_name(context);
GValue *instance_and_args;
GValue rvalue = G_VALUE_INIT;
unsigned int i;
bool failed;
- bool ret = false;
gjs_debug_gsignal("emit obj %p priv %p argc %d", obj.get(), priv, argc);
@@ -1721,20 +1696,20 @@ emit_func(JSContext *context,
&signal_detail,
false)) {
gjs_throw(context, "No signal '%s' on object '%s'",
- signal_name,
- g_type_name(G_OBJECT_TYPE(priv->gobj)));
- goto out;
+ signal_name.get(),
+ g_type_name(G_OBJECT_TYPE(priv->gobj)));
+ return false;
}
g_signal_query(signal_id, &signal_query);
if ((argc - 1) != signal_query.n_params) {
gjs_throw(context, "Signal '%s' on %s requires %d args got %d",
- signal_name,
- g_type_name(G_OBJECT_TYPE(priv->gobj)),
- signal_query.n_params,
- argc - 1);
- goto out;
+ signal_name.get(),
+ g_type_name(G_OBJECT_TYPE(priv->gobj)),
+ signal_query.n_params,
+ argc - 1);
+ return false;
}
if (signal_query.return_type != G_TYPE_NONE) {
@@ -1780,10 +1755,7 @@ emit_func(JSContext *context,
g_value_unset(&instance_and_args[i]);
}
- ret = !failed;
- out:
- g_free(signal_name);
- return ret;
+ return !failed;
}
static bool
@@ -2902,7 +2874,7 @@ gjs_signal_new(JSContext *cx,
{
JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
GType gtype;
- char *signal_name_tmp = NULL;
+ GjsAutoJSChar signal_name(cx);
GSignalAccumulator accumulator;
gint signal_id;
guint i, n_parameters;
@@ -2913,9 +2885,8 @@ gjs_signal_new(JSContext *cx,
JSAutoRequest ar(cx);
- if (!gjs_string_to_utf8(cx, argv[1], &signal_name_tmp))
+ if (!gjs_string_to_utf8(cx, argv[1], &signal_name))
return false;
- std::unique_ptr<char, decltype(&g_free)> signal_name(signal_name_tmp, g_free);
JS::RootedObject obj(cx, &argv[0].toObject());
if (!gjs_typecheck_gtype(cx, obj, true))
@@ -2961,7 +2932,7 @@ gjs_signal_new(JSContext *cx,
gtype = gjs_gtype_get_actual_gtype(cx, obj);
- signal_id = g_signal_newv(signal_name.get(),
+ signal_id = g_signal_newv(signal_name,
gtype,
(GSignalFlags) argv[2].toInt32(), /* signal_flags */
NULL, /* class closure */
diff --git a/gi/param.cpp b/gi/param.cpp
index c38eebb..6fe1c06 100644
--- a/gi/param.cpp
+++ b/gi/param.cpp
@@ -58,7 +58,7 @@ param_resolve(JSContext *context,
GIObjectInfo *info = NULL;
GIFunctionInfo *method_info;
Param *priv;
- char *name = NULL;
+ GjsAutoJSChar name(context);
bool ret = false;
if (!gjs_get_string_id(context, id, &name))
@@ -69,7 +69,6 @@ param_resolve(JSContext *context,
if (priv != NULL) {
/* instance, not prototype */
*resolved = false;
- g_free(name);
return true;
}
@@ -102,7 +101,6 @@ param_resolve(JSContext *context,
ret = true;
out:
- g_free(name);
if (info != NULL)
g_base_info_unref( (GIBaseInfo*)info);
diff --git a/gi/repo.cpp b/gi/repo.cpp
index 10fd465..6102c58 100644
--- a/gi/repo.cpp
+++ b/gi/repo.cpp
@@ -167,7 +167,7 @@ repo_resolve(JSContext *context,
bool *resolved)
{
Repo *priv;
- char *name = NULL;
+ GjsAutoJSChar name(context);
if (!gjs_get_string_id(context, id, &name)) {
*resolved = false;
@@ -178,7 +178,6 @@ repo_resolve(JSContext *context,
if (strcmp(name, "valueOf") == 0 ||
strcmp(name, "toString") == 0) {
*resolved = false;
- g_free(name);
return true;
}
@@ -189,17 +188,14 @@ repo_resolve(JSContext *context,
if (priv == NULL) {
/* we are the prototype, or have the wrong class */
*resolved = false;
- g_free(name);
return true;
}
if (!resolve_namespace_object(context, obj, id, name)) {
- g_free(name);
return false;
}
*resolved = true;
- g_free(name);
return true;
}
diff --git a/gi/union.cpp b/gi/union.cpp
index c4ef103..c18e367 100644
--- a/gi/union.cpp
+++ b/gi/union.cpp
@@ -61,7 +61,7 @@ union_resolve(JSContext *context,
bool *resolved)
{
Union *priv;
- char *name = NULL;
+ GjsAutoJSChar name(context);
if (!gjs_get_string_id(context, id, &name)) {
*resolved = false;
@@ -72,10 +72,8 @@ union_resolve(JSContext *context,
gjs_debug_jsprop(GJS_DEBUG_GBOXED, "Resolve prop '%s' hook obj %p priv %p",
name, obj.get(), priv);
- if (priv == NULL) {
- g_free(name);
+ if (priv == nullptr)
return false; /* wrong class */
- }
if (priv->gboxed != NULL) {
/* We are an instance, not a prototype, so look for
@@ -86,7 +84,6 @@ union_resolve(JSContext *context,
* hooks, not this resolve hook.
*/
*resolved = false;
- g_free(name);
return true;
}
@@ -116,7 +113,6 @@ union_resolve(JSContext *context,
g_registered_type_info_get_g_type(priv->info),
method_info) == NULL) {
g_base_info_unref( (GIBaseInfo*) method_info);
- g_free(name);
return false;
}
@@ -130,7 +126,6 @@ union_resolve(JSContext *context,
*resolved = false;
}
- g_free(name);
return true;
}
diff --git a/gi/value.cpp b/gi/value.cpp
index 2ad9592..9c95ead 100644
--- a/gi/value.cpp
+++ b/gi/value.cpp
@@ -380,12 +380,12 @@ gjs_value_to_g_value_internal(JSContext *context,
if (value.isNull()) {
g_value_set_string(gvalue, NULL);
} else if (value.isString()) {
- gchar *utf8_string;
+ GjsAutoJSChar utf8_string(context);
if (!gjs_string_to_utf8(context, value, &utf8_string))
return false;
- g_value_take_string(gvalue, utf8_string);
+ g_value_take_string(gvalue, utf8_string.copy());
} else {
gjs_throw(context,
"Wrong type %s; string expected",
diff --git a/gjs/byteArray.cpp b/gjs/byteArray.cpp
index 3f55150..89211e0 100644
--- a/gjs/byteArray.cpp
+++ b/gjs/byteArray.cpp
@@ -405,7 +405,7 @@ to_string_func(JSContext *context,
JS::Value *vp)
{
GJS_GET_PRIV(context, argc, vp, argv, to, ByteArrayInstance, priv);
- char *encoding;
+ GjsAutoJSChar encoding(context);
bool encoding_is_utf8;
gchar *data;
@@ -422,13 +422,7 @@ to_string_func(JSContext *context,
* doesn't matter much though. encoding_is_utf8 is
* just an optimization anyway.
*/
- if (strcmp(encoding, "UTF-8") == 0) {
- encoding_is_utf8 = true;
- g_free(encoding);
- encoding = NULL;
- } else {
- encoding_is_utf8 = false;
- }
+ encoding_is_utf8 = (strcmp(encoding, "UTF-8") == 0);
} else {
encoding_is_utf8 = true;
}
@@ -461,7 +455,6 @@ to_string_func(JSContext *context,
NULL, /* bytes read */
&bytes_written,
&error);
- g_free(encoding);
if (u16_str == NULL) {
/* frees the GError */
gjs_throw_g_error(context, error);
@@ -534,7 +527,7 @@ from_string_func(JSContext *context,
{
JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
ByteArrayInstance *priv;
- char *encoding;
+ GjsAutoJSChar encoding(context);
bool encoding_is_utf8;
JS::RootedObject obj(context, byte_array_new(context));
@@ -562,13 +555,7 @@ from_string_func(JSContext *context,
* doesn't matter much though. encoding_is_utf8 is
* just an optimization anyway.
*/
- if (strcmp(encoding, "UTF-8") == 0) {
- encoding_is_utf8 = true;
- g_free(encoding);
- encoding = NULL;
- } else {
- encoding_is_utf8 = false;
- }
+ encoding_is_utf8 = (strcmp(encoding, "UTF-8") == 0);
} else {
encoding_is_utf8 = true;
}
@@ -577,15 +564,16 @@ from_string_func(JSContext *context,
/* optimization? avoids iconv overhead and runs
* libmozjs hardwired utf16-to-utf8.
*/
- char *utf8 = NULL;
+ GjsAutoJSChar utf8(context);
if (!gjs_string_to_utf8(context,
argv[0],
&utf8))
return false;
g_byte_array_set_size(priv->array, 0);
- g_byte_array_append(priv->array, (guint8*) utf8, strlen(utf8));
- g_free(utf8);
+ g_byte_array_append(priv->array,
+ reinterpret_cast<const guint8*>(utf8.get()),
+ strlen(utf8));
} else {
JSString *str = argv[0].toString(); /* Rooted by argv */
GError *error = NULL;
@@ -623,7 +611,6 @@ from_string_func(JSContext *context,
}
}
- g_free(encoding);
if (encoded == NULL) {
/* frees the GError */
gjs_throw_g_error(context, error);
diff --git a/gjs/context.cpp b/gjs/context.cpp
index 2b506c2..ca8d43d 100644
--- a/gjs/context.cpp
+++ b/gjs/context.cpp
@@ -119,7 +119,6 @@ gjs_log(JSContext *context,
JS::Value *vp)
{
JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
- char *s;
if (argc != 1) {
gjs_throw(context, "Must pass a single argument to log()");
@@ -140,13 +139,12 @@ gjs_log(JSContext *context,
return true;
}
+ GjsAutoJSChar s(context);
if (!gjs_string_to_utf8(context, JS::StringValue(jstr), &s)) {
JS_EndRequest(context);
return false;
}
-
- g_message("JS LOG: %s", s);
- g_free(s);
+ g_message("JS LOG: %s", s.get());
JS_EndRequest(context);
argv.rval().setUndefined();
@@ -190,7 +188,6 @@ gjs_print_parse_args(JSContext *context,
char **buffer)
{
GString *str;
- gchar *s;
guint n;
JS_BeginRequest(context);
@@ -204,6 +201,7 @@ gjs_print_parse_args(JSContext *context,
exc_state.restore();
if (jstr != NULL) {
+ GjsAutoJSChar s(context);
if (!gjs_string_to_utf8(context, JS::StringValue(jstr), &s)) {
JS_EndRequest(context);
g_string_free(str, true);
@@ -211,7 +209,6 @@ gjs_print_parse_args(JSContext *context,
}
g_string_append(str, s);
- g_free(s);
if (n < (argv.length()-1))
g_string_append_c(str, ' ');
} else {
diff --git a/gjs/coverage.cpp b/gjs/coverage.cpp
index 579b141..52a39df 100644
--- a/gjs/coverage.cpp
+++ b/gjs/coverage.cpp
@@ -493,11 +493,11 @@ get_executed_lines_for(JSContext *context,
static void
init_covered_function(GjsCoverageFunction *function,
- char *key,
+ const char *key,
unsigned int line_number,
unsigned int hit_count)
{
- function->key = key;
+ function->key = g_strdup(key);
function->line_number = line_number;
function->hit_count = hit_count;
}
@@ -543,7 +543,7 @@ convert_and_insert_function_decl(GArray *array,
&function_name_property_value))
return false;
- char *utf8_string;
+ GjsAutoJSChar utf8_string(context);
if (function_name_property_value.isString()) {
if (!gjs_string_to_utf8(context,
@@ -552,9 +552,7 @@ convert_and_insert_function_decl(GArray *array,
gjs_throw(context, "Failed to convert function_name to string");
return false;
}
- } else if (function_name_property_value.isNull()) {
- utf8_string = NULL;
- } else {
+ } else if (!function_name_property_value.isNull()) {
gjs_throw(context, "Unexpected type for function_name");
return false;
}
@@ -869,14 +867,14 @@ get_covered_files(GjsCoverage *coverage)
files = g_new0(char *, n_files + 1);
JS::RootedValue element(context);
for (uint32_t i = 0; i < n_files; i++) {
- char *file;
+ GjsAutoJSChar file(context);
if (!JS_GetElement(context, files_obj, i, &element))
goto error;
if (!gjs_string_to_utf8(context, element, &file))
goto error;
- files[i] = file;
+ files[i] = file.copy();
}
files[n_files] = NULL;
@@ -1012,7 +1010,7 @@ gjs_serialize_statistics(GjsCoverage *coverage)
return NULL;
/* Free'd by g_bytes_new_take */
- char *statistics_as_json_string = NULL;
+ GjsAutoJSChar statistics_as_json_string(js_context);
if (!gjs_string_to_utf8(js_context,
string_value_return.get(),
@@ -1021,8 +1019,12 @@ gjs_serialize_statistics(GjsCoverage *coverage)
return NULL;
}
- return g_bytes_new_take((guint8 *) statistics_as_json_string,
- strlen(statistics_as_json_string));
+ int json_string_len = strlen(statistics_as_json_string);
+ auto json_bytes =
+ reinterpret_cast<uint8_t*>(statistics_as_json_string.copy());
+
+ return g_bytes_new_take(json_bytes,
+ json_string_len);
}
static JSString *
@@ -1333,7 +1335,7 @@ coverage_log(JSContext *context,
JS::Value *vp)
{
JS::CallArgs argv = JS::CallArgsFromVp (argc, vp);
- char *s;
+ GjsAutoJSChar s(context);
JSExceptionState *exc_state;
if (argc != 1) {
@@ -1366,8 +1368,7 @@ coverage_log(JSContext *context,
return false;
}
- g_message("JS COVERAGE MESSAGE: %s", s);
- g_free(s);
+ g_message("JS COVERAGE MESSAGE: %s", s.get());
argv.rval().setUndefined();
return true;
diff --git a/gjs/importer.cpp b/gjs/importer.cpp
index 5ee128e..ff592c1 100644
--- a/gjs/importer.cpp
+++ b/gjs/importer.cpp
@@ -75,7 +75,7 @@ importer_to_string(JSContext *cx,
&module_path))
return false;
- char *path = NULL;
+ GjsAutoJSChar path(cx);
GjsAutoChar output;
if (module_path.isNull()) {
@@ -83,11 +83,10 @@ importer_to_string(JSContext *cx,
} else {
if (!gjs_string_to_utf8(cx, module_path, &path))
return false;
- output = g_strdup_printf("[%s %s]", klass->name, path);
+ output = g_strdup_printf("[%s %s]", klass->name, path.get());
}
args.rval().setString(JS_NewStringCopyZ(cx, output));
- g_free(path);
return true;
}
@@ -139,11 +138,10 @@ define_meta_properties(JSContext *context,
if (parent_module_path.isNull()) {
module_path_buf = g_strdup(module_name);
} else {
- char *parent_path = NULL;
+ GjsAutoJSChar parent_path(context);
if (!gjs_string_to_utf8(context, parent_module_path, &parent_path))
return false;
- module_path_buf = g_strdup_printf("%s.%s", parent_path, module_name);
- g_free(parent_path);
+ module_path_buf = g_strdup_printf("%s.%s", parent_path.get(), module_name);
}
module_path.setString(JS_NewStringCopyZ(context, module_path_buf));
}
@@ -286,13 +284,12 @@ module_to_string(JSContext *cx,
g_assert(!module_path.isNull());
- char *path = NULL;
+ GjsAutoJSChar path(cx);
if (!gjs_string_to_utf8(cx, module_path, &path))
return false;
- GjsAutoChar output = g_strdup_printf("[GjsModule %s]", path);
+ GjsAutoChar output = g_strdup_printf("[GjsModule %s]", path.get());
args.rval().setString(JS_NewStringCopyZ(cx, output));
- g_free(path);
return true;
}
@@ -502,7 +499,6 @@ do_import(JSContext *context,
{
char *filename;
char *full_path;
- char *dirname = NULL;
JS::RootedObject search_path(context);
guint32 search_path_len;
guint32 i;
@@ -544,6 +540,8 @@ do_import(JSContext *context,
}
for (i = 0; i < search_path_len; ++i) {
+ GjsAutoJSChar dirname(context);
+
elem.setUndefined();
if (!JS_GetElement(context, search_path, i, &elem)) {
/* this means there was an exception, while elem.isUndefined()
@@ -560,9 +558,6 @@ do_import(JSContext *context,
goto out;
}
- g_free(dirname);
- dirname = NULL;
-
if (!gjs_string_to_utf8(context, elem, &dirname))
goto out; /* Error message already set */
@@ -616,7 +611,7 @@ do_import(JSContext *context,
if (!exists) {
gjs_debug(GJS_DEBUG_IMPORTER,
"JS import '%s' not found in %s",
- name, dirname);
+ name, dirname.get());
g_object_unref(gfile);
continue;
@@ -665,7 +660,6 @@ do_import(JSContext *context,
g_free(full_path);
g_free(filename);
- g_free(dirname);
if (!result &&
!JS_IsExceptionPending(context)) {
@@ -715,7 +709,7 @@ importer_enumerate(JSContext *context,
JS::RootedValue elem(context);
for (i = 0; i < search_path_len; ++i) {
- char *dirname = NULL;
+ GjsAutoJSChar dirname(context);
char *init_path;
elem.setUndefined();
@@ -745,7 +739,6 @@ importer_enumerate(JSContext *context,
/* new_for_commandline_arg handles resource:/// paths */
GjsAutoUnref<GFile> dir = g_file_new_for_commandline_arg(dirname);
- g_free(dirname);
GjsAutoUnref<GFileEnumerator> direnum =
g_file_enumerate_children(dir, G_FILE_ATTRIBUTE_STANDARD_TYPE,
G_FILE_QUERY_INFO_NONE, NULL, NULL);
@@ -793,8 +786,8 @@ importer_resolve(JSContext *context,
bool *resolved)
{
Importer *priv;
- char *name = NULL;
jsid module_init_name;
+ GjsAutoJSChar name(context);
module_init_name = gjs_context_get_const_string(context, GJS_STRING_MODULE_INIT);
if (id == module_init_name) {
@@ -810,7 +803,6 @@ importer_resolve(JSContext *context,
strcmp(name, "toString") == 0 ||
strcmp(name, "__iterator__") == 0) {
*resolved = false;
- g_free(name);
return true;
}
priv = priv_from_js(context, obj);
@@ -821,18 +813,14 @@ importer_resolve(JSContext *context,
if (priv == NULL) {
/* we are the prototype, or have the wrong class */
*resolved = false;
- g_free(name);
return true;
}
JSAutoRequest ar(context);
- if (!do_import(context, obj, priv, name)) {
- g_free(name);
+ if (!do_import(context, obj, priv, name))
return false;
- }
*resolved = true;
- g_free(name);
return true;
}
diff --git a/gjs/jsapi-util-args.h b/gjs/jsapi-util-args.h
index c572fab..1fb3ec7 100644
--- a/gjs/jsapi-util-args.h
+++ b/gjs/jsapi-util-args.h
@@ -103,15 +103,20 @@ assign(JSContext *cx,
*ref = NULL;
return;
}
+
+ GjsAutoJSChar tmp_ref(cx);
+
if (c == 's') {
- if (!gjs_string_to_utf8(cx, value, ref))
+ if (!gjs_string_to_utf8(cx, value, &tmp_ref))
throw g_strdup("Couldn't convert to string");
} else if (c == 'F') {
- if (!gjs_string_to_filename(cx, value, ref))
+ if (!gjs_string_to_filename(cx, value, &tmp_ref))
throw g_strdup("Couldn't convert to filename");
} else {
throw g_strdup_printf("Wrong type for %c, got char**", c);
}
+
+ *ref = tmp_ref.copy();
}
GNUC_ALWAYS_INLINE
static inline void
diff --git a/gjs/jsapi-util-string.cpp b/gjs/jsapi-util-string.cpp
index a0be7b8..e01d595 100644
--- a/gjs/jsapi-util-string.cpp
+++ b/gjs/jsapi-util-string.cpp
@@ -32,10 +32,9 @@
bool
gjs_string_to_utf8 (JSContext *context,
const JS::Value value,
- char **utf8_string_p)
+ GjsAutoJSChar *utf8_string_p)
{
gsize len;
- char *bytes;
JS_BeginRequest(context);
@@ -54,10 +53,7 @@ gjs_string_to_utf8 (JSContext *context,
return false;
}
- if (utf8_string_p) {
- bytes = JS_EncodeStringToUTF8(context, str);
- *utf8_string_p = bytes;
- }
+ utf8_string_p->reset(context, JS_EncodeStringToUTF8(context, str));
JS_EndRequest(context);
@@ -106,10 +102,11 @@ gjs_string_from_utf8(JSContext *context,
bool
gjs_string_to_filename(JSContext *context,
const JS::Value filename_val,
- char **filename_string_p)
+ GjsAutoJSChar *filename_string_p)
{
GError *error;
- gchar *tmp, *filename_string;
+ GjsAutoJSChar tmp(context);
+ char *filename_string;
/* gjs_string_to_filename verifies that filename_val is a string */
@@ -122,12 +119,10 @@ gjs_string_to_filename(JSContext *context,
filename_string = g_filename_from_utf8(tmp, -1, NULL, NULL, &error);
if (!filename_string) {
gjs_throw_g_error(context, error);
- g_free(tmp);
return false;
}
- *filename_string_p = filename_string;
- g_free(tmp);
+ filename_string_p->reset(context, filename_string);
return true;
}
@@ -352,7 +347,7 @@ gjs_string_from_ucs4(JSContext *cx,
bool
gjs_get_string_id (JSContext *context,
jsid id,
- char **name_p)
+ GjsAutoJSChar *name_p)
{
JS::RootedValue id_val(context);
@@ -362,7 +357,6 @@ gjs_get_string_id (JSContext *context,
if (id_val.isString()) {
return gjs_string_to_utf8(context, id_val, name_p);
} else {
- *name_p = NULL;
return false;
}
}
@@ -384,10 +378,9 @@ gjs_unichar_from_string (JSContext *context,
JS::Value value,
gunichar *result)
{
- char *utf8_str;
+ GjsAutoJSChar utf8_str(context);
if (gjs_string_to_utf8(context, value, &utf8_str)) {
*result = g_utf8_get_char(utf8_str);
- g_free(utf8_str);
return true;
}
return false;
diff --git a/gjs/jsapi-util.cpp b/gjs/jsapi-util.cpp
index 900b1b4..7c7de73 100644
--- a/gjs/jsapi-util.cpp
+++ b/gjs/jsapi-util.cpp
@@ -211,17 +211,15 @@ throw_property_lookup_error(JSContext *cx,
/* remember gjs_throw() is a no-op if JS_GetProperty()
* already set an exception
*/
- char *name;
+ GjsAutoJSChar name(cx);
gjs_get_string_id(cx, property_name, &name);
if (description)
- gjs_throw(cx, "No property '%s' in %s (or %s)", name, description,
+ gjs_throw(cx, "No property '%s' in %s (or %s)", name.get(), description,
reason);
else
- gjs_throw(cx, "No property '%s' in object %p (or %s)", name,
+ gjs_throw(cx, "No property '%s' in object %p (or %s)", name.get(),
obj.address(), reason);
-
- g_free(name);
}
/* Returns whether the object had the property; if the object did
@@ -302,8 +300,10 @@ gjs_object_require_property(JSContext *cx,
char **value)
{
JS::RootedValue prop_value(cx);
+ GjsAutoJSChar value_tmp(cx);
if (JS_GetPropertyById(cx, obj, property_name, &prop_value) &&
- gjs_string_to_utf8(cx, prop_value, value)) {
+ gjs_string_to_utf8(cx, prop_value, &value_tmp)) {
+ *value = value_tmp.copy();
return true;
}
@@ -432,7 +432,7 @@ gjs_string_readable (JSContext *context,
JSString *string)
{
GString *buf = g_string_new("");
- char *chars;
+ GjsAutoJSChar chars(context);
JS_BeginRequest(context);
@@ -454,7 +454,6 @@ gjs_string_readable (JSContext *context,
g_free(escaped);
} else {
g_string_append(buf, chars);
- g_free(chars);
}
g_string_append_c(buf, '"');
@@ -565,11 +564,11 @@ static char *
utf8_exception_from_non_gerror_value(JSContext *cx,
JS::HandleValue exc)
{
- char *utf8_exception = NULL;
+ GjsAutoJSChar utf8_exception(cx);
JS::RootedString exc_str(cx, JS::ToString(cx, exc));
if (exc_str != NULL)
gjs_string_to_utf8(cx, JS::StringValue(exc_str), &utf8_exception);
- return utf8_exception;
+ return utf8_exception.copy();
}
bool
@@ -577,7 +576,8 @@ gjs_log_exception_full(JSContext *context,
JS::HandleValue exc,
JS::HandleString message)
{
- char *utf8_exception, *utf8_message;
+ char *utf8_exception;
+ GjsAutoJSChar utf8_message(context);
bool is_syntax;
JS_BeginRequest(context);
@@ -596,7 +596,7 @@ gjs_log_exception_full(JSContext *context,
gerror->message);
} else {
JS::RootedValue js_name(context);
- char *utf8_name;
+ GjsAutoJSChar utf8_name(context);
if (gjs_object_get_property(context, exc_obj,
GJS_STRING_NAME, &js_name) &&
@@ -611,8 +611,6 @@ gjs_log_exception_full(JSContext *context,
if (message != NULL)
gjs_string_to_utf8(context, JS::StringValue(message), &utf8_message);
- else
- utf8_message = NULL;
/* We log syntax errors differently, because the stack for those includes
only the referencing module, but we want to print out the filename and
@@ -622,7 +620,7 @@ gjs_log_exception_full(JSContext *context,
if (is_syntax) {
JS::RootedValue js_lineNumber(context), js_fileName(context);
unsigned lineNumber;
- char *utf8_fileName;
+ GjsAutoJSChar utf8_filename(context);
gjs_object_get_property(context, exc_obj, GJS_STRING_LINE_NUMBER,
&js_lineNumber);
@@ -630,50 +628,47 @@ gjs_log_exception_full(JSContext *context,
&js_fileName);
if (js_fileName.isString())
- gjs_string_to_utf8(context, js_fileName, &utf8_fileName);
+ gjs_string_to_utf8(context, js_fileName, &utf8_filename);
else
- utf8_fileName = g_strdup("unknown");
+ utf8_filename.reset(context, JS_strdup(context, "unknown"));
lineNumber = js_lineNumber.toInt32();
- if (utf8_message) {
- g_critical("JS ERROR: %s: %s @ %s:%u", utf8_message, utf8_exception,
- utf8_fileName, lineNumber);
+ if (message != NULL) {
+ g_critical("JS ERROR: %s: %s @ %s:%u", utf8_message.get(), utf8_exception,
+ utf8_filename.get(), lineNumber);
} else {
g_critical("JS ERROR: %s @ %s:%u", utf8_exception,
- utf8_fileName, lineNumber);
+ utf8_filename.get(), lineNumber);
}
- g_free(utf8_fileName);
} else {
- char *utf8_stack;
+ GjsAutoJSChar utf8_stack(context);
JS::RootedValue stack(context);
+ bool have_utf8_stack = false;
if (exc.isObject() &&
gjs_object_get_property(context, exc_obj, GJS_STRING_STACK,
&stack) &&
- stack.isString())
+ stack.isString()) {
gjs_string_to_utf8(context, stack, &utf8_stack);
- else
- utf8_stack = NULL;
+ have_utf8_stack = true;
+ }
- if (utf8_message) {
- if (utf8_stack)
- g_warning("JS ERROR: %s: %s\n%s", utf8_message, utf8_exception, utf8_stack);
+ if (message != nullptr) {
+ if (have_utf8_stack)
+ g_warning("JS ERROR: %s: %s\n%s", utf8_message.get(), utf8_exception, utf8_stack.get());
else
- g_warning("JS ERROR: %s: %s", utf8_message, utf8_exception);
+ g_warning("JS ERROR: %s: %s", utf8_message.get(), utf8_exception);
} else {
- if (utf8_stack)
- g_warning("JS ERROR: %s\n%s", utf8_exception, utf8_stack);
+ if (have_utf8_stack)
+ g_warning("JS ERROR: %s\n%s", utf8_exception, utf8_stack.get());
else
g_warning("JS ERROR: %s", utf8_exception);
}
-
- g_free(utf8_stack);
}
g_free(utf8_exception);
- g_free(utf8_message);
JS_EndRequest(context);
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index e05e12b..44bc372 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -60,6 +60,61 @@ public:
}
};
+class GjsJSFreeArgs {
+private:
+ JSContext *m_cx;
+
+public:
+ explicit GjsJSFreeArgs(JSContext *cx) : m_cx(cx)
+ {}
+
+ void operator() (char *str) {
+ JS_free(m_cx, str);
+ }
+
+ JSContext* get_context() {
+ return m_cx;
+ }
+
+ void set_context(JSContext *cx) {
+ m_cx = cx;
+ }
+};
+
+class GjsAutoJSChar {
+private:
+ std::unique_ptr<char, GjsJSFreeArgs> m_ptr;
+
+public:
+ GjsAutoJSChar(JSContext *cx, char *str = nullptr)
+ : m_ptr (str, GjsJSFreeArgs(cx)) {
+ g_assert(cx != nullptr);
+ }
+
+ operator const char*() {
+ return m_ptr.get();
+ }
+
+ const char* get() {
+ return m_ptr.get();
+ }
+
+ char* copy() {
+ /* Strings acquired by this should be g_free()'ed */
+ return g_strdup(m_ptr.get());
+ }
+
+ char* js_copy() {
+ /* Strings acquired by this should be JS_free()'ed */
+ return JS_strdup(m_ptr.get_deleter().get_context(), m_ptr.get());
+ }
+
+ void reset(JSContext *cx, char *str) {
+ m_ptr.get_deleter().set_context(cx);
+ m_ptr.reset(str);
+ }
+};
+
G_BEGIN_DECLS
#define GJS_UTIL_ERROR gjs_util_error_quark ()
@@ -184,7 +239,7 @@ void gjs_error_reporter (JSContext *context,
bool gjs_string_to_utf8 (JSContext *context,
const JS::Value string_val,
- char **utf8_string_p);
+ GjsAutoJSChar *utf8_string_p);
bool gjs_string_from_utf8(JSContext *context,
const char *utf8_string,
ssize_t n_bytes,
@@ -192,7 +247,7 @@ bool gjs_string_from_utf8(JSContext *context,
bool gjs_string_to_filename (JSContext *context,
const JS::Value string_val,
- char **filename_string_p);
+ GjsAutoJSChar *filename_string_p);
bool gjs_string_from_filename(JSContext *context,
const char *filename_string,
ssize_t n_bytes,
@@ -214,7 +269,7 @@ bool gjs_string_from_ucs4(JSContext *cx,
bool gjs_get_string_id (JSContext *context,
jsid id,
- char **name_p);
+ GjsAutoJSChar *name_p);
jsid gjs_intern_string_to_id (JSContext *context,
const char *string);
diff --git a/gjs/runtime.cpp b/gjs/runtime.cpp
index 5a81638..eb9677b 100644
--- a/gjs/runtime.cpp
+++ b/gjs/runtime.cpp
@@ -57,7 +57,7 @@ gjs_locale_to_upper_case (JSContext *context,
JS::MutableHandleValue retval)
{
bool success = false;
- char *utf8 = NULL;
+ GjsAutoJSChar utf8(context);
char *upper_case_utf8 = NULL;
if (!gjs_string_to_utf8(context, JS::StringValue(src), &utf8))
@@ -71,7 +71,6 @@ gjs_locale_to_upper_case (JSContext *context,
success = true;
out:
- g_free(utf8);
g_free(upper_case_utf8);
return success;
@@ -83,7 +82,7 @@ gjs_locale_to_lower_case (JSContext *context,
JS::MutableHandleValue retval)
{
bool success = false;
- char *utf8 = NULL;
+ GjsAutoJSChar utf8(context);
char *lower_case_utf8 = NULL;
if (!gjs_string_to_utf8(context, JS::StringValue(src), &utf8))
@@ -97,7 +96,6 @@ gjs_locale_to_lower_case (JSContext *context,
success = true;
out:
- g_free(utf8);
g_free(lower_case_utf8);
return success;
@@ -109,22 +107,15 @@ gjs_locale_compare (JSContext *context,
JS::HandleString src_2,
JS::MutableHandleValue retval)
{
- bool success = false;
- char *utf8_1 = NULL, *utf8_2 = NULL;
+ GjsAutoJSChar utf8_1(context), utf8_2(context);
if (!gjs_string_to_utf8(context, JS::StringValue(src_1), &utf8_1) ||
!gjs_string_to_utf8(context, JS::StringValue(src_2), &utf8_2))
- goto out;
+ return false;
retval.setInt32(g_utf8_collate(utf8_1, utf8_2));
- success = true;
-
-out:
- g_free(utf8_1);
- g_free(utf8_2);
-
- return success;
+ return true;
}
static bool
diff --git a/gjs/stack.cpp b/gjs/stack.cpp
index e49a77f..0096393 100644
--- a/gjs/stack.cpp
+++ b/gjs/stack.cpp
@@ -89,7 +89,7 @@ gjs_context_print_stack_stderr(GjsContext *context)
{
JSContext *cx = (JSContext*) gjs_context_get_native_context(context);
JS::RootedValue v_stack(cx);
- char *stack;
+ GjsAutoJSChar stack(cx);
g_printerr("== Stack trace for context %p ==\n", context);
@@ -101,8 +101,7 @@ gjs_context_print_stack_stderr(GjsContext *context)
return;
}
- g_printerr("%s\n", stack);
- g_free(stack);
+ g_printerr("%s\n", stack.get());
}
void
diff --git a/test/gjs-tests.cpp b/test/gjs-tests.cpp
index f5119e5..fefc2ef 100644
--- a/test/gjs-tests.cpp
+++ b/test/gjs-tests.cpp
@@ -124,14 +124,13 @@ static void
gjstest_test_func_gjs_jsapi_util_string_js_string_utf8(GjsUnitTestFixture *fx,
gconstpointer unused)
{
- char *utf8_result;
+ GjsAutoJSChar utf8_result(fx->cx);
JS::RootedValue js_string(fx->cx);
g_assert_true(gjs_string_from_utf8(fx->cx, VALID_UTF8_STRING, -1, &js_string));
g_assert(js_string.isString());
g_assert(gjs_string_to_utf8(fx->cx, js_string, &utf8_result));
g_assert_cmpstr(VALID_UTF8_STRING, ==, utf8_result);
- g_free(utf8_result);
}
static void
@@ -139,7 +138,7 @@ gjstest_test_func_gjs_jsapi_util_error_throw(GjsUnitTestFixture *fx,
gconstpointer unused)
{
JS::RootedValue exc(fx->cx), value(fx->cx);
- char *s = NULL;
+ GjsAutoJSChar s(fx->cx);
/* Test that we can throw */
@@ -158,7 +157,6 @@ gjstest_test_func_gjs_jsapi_util_error_throw(GjsUnitTestFixture *fx,
gjs_string_to_utf8(fx->cx, value, &s);
g_assert_nonnull(s);
g_assert_cmpstr(s, ==, "This is an exception 42");
- JS_free(fx->cx, s);
/* keep this around before we clear it */
JS::RootedValue previous(fx->cx, exc);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]