[gjs: 1/8] object: Use GjsAutoInfo throughout
- From: Cosimo Cecchi <cosimoc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs: 1/8] object: Use GjsAutoInfo throughout
- Date: Wed, 13 Jun 2018 14:39:27 +0000 (UTC)
commit dcce0ef9fe52d11605fea9e7ff123e37856b9841
Author: Philip Chimento <philip chimento gmail com>
Date: Sun Jun 10 02:44:04 2018 -0700
object: Use GjsAutoInfo throughout
This makes the recently refactored code safer against memory leaks.
gi/object.cpp | 203 +++++++++++++++----------------------------------------
gjs/jsapi-util.h | 3 +-
2 files changed, 56 insertions(+), 150 deletions(-)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index b7a74940..34afaf5f 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -697,30 +697,24 @@ ObjectInstance::prop_getter_impl(JSContext *cx,
return true;
}
-static GIFieldInfo *
+static GjsAutoInfo<GIFieldInfo>
lookup_field_info(GIObjectInfo *info,
const char *name)
{
int n_fields = g_object_info_get_n_fields(info);
int ix;
- GIFieldInfo *retval = NULL;
+ GjsAutoInfo<GIFieldInfo> retval;
for (ix = 0; ix < n_fields; ix++) {
retval = g_object_info_get_field(info, ix);
- const char *field_name = g_base_info_get_name((GIBaseInfo *) retval);
- if (strcmp(name, field_name) == 0)
+ if (strcmp(name, retval.name()) == 0)
break;
- g_clear_pointer(&retval, g_base_info_unref);
+ retval.reset();
}
- if (!retval)
+ if (!retval || !(g_field_info_get_flags(retval) & GI_FIELD_IS_READABLE))
return nullptr;
- if (!(g_field_info_get_flags(retval) & GI_FIELD_IS_READABLE)) {
- g_base_info_unref(retval);
- return nullptr;
- }
-
return retval;
}
@@ -785,15 +779,13 @@ ObjectInstance::field_getter_impl(JSContext *cx,
/* This is guaranteed because we resolved the property before */
g_assert(field);
- bool retval = true;
- GITypeInfo *type = NULL;
GITypeTag tag;
GIArgument arg = { 0 };
gjs_debug_jsprop(GJS_DEBUG_GOBJECT, "Overriding %s with GObject field",
gjs_debug_string(name).c_str());
- type = g_field_info_get_type(field);
+ GjsAutoInfo<GITypeInfo> type = g_field_info_get_type(field);
tag = g_type_info_get_tag(type);
if (tag == GI_TYPE_TAG_ARRAY ||
tag == GI_TYPE_TAG_INTERFACE ||
@@ -804,25 +796,18 @@ ObjectInstance::field_getter_impl(JSContext *cx,
gjs_throw(cx, "Can't get field %s; GObject introspection supports only "
"fields with simple types, not %s",
gjs_debug_string(name).c_str(), g_type_tag_to_string(tag));
- retval = false;
- goto out;
+ return false;
}
- retval = g_field_info_get_field(field, m_gobj, &arg);
- if (!retval) {
+ if (!g_field_info_get_field(field, m_gobj, &arg)) {
gjs_throw(cx, "Error getting field %s from object",
gjs_debug_string(name).c_str());
- goto out;
+ return false;
}
- retval = gjs_value_from_g_argument(cx, rval, type, &arg, true);
+ return gjs_value_from_g_argument(cx, rval, type, &arg, true);
/* copy_structs is irrelevant because g_field_info_get_field() doesn't
* handle boxed types */
-
-out:
- if (type != NULL)
- g_base_info_unref((GIBaseInfo *) type);
- return retval;
}
/* Dynamic setter for GObject properties. Returns false on OOM/exception.
@@ -963,37 +948,30 @@ ObjectInstance::is_vfunc_unchanged(GIVFuncInfo *info)
return addr1 == addr2;
}
-static GIVFuncInfo *
+static GjsAutoInfo<GIVFuncInfo>
find_vfunc_on_parents(GIObjectInfo *info,
const char *name,
bool *out_defined_by_parent)
{
- GIVFuncInfo *vfunc = NULL;
- GIObjectInfo *parent;
bool defined_by_parent = false;
/* ref the first info so that we don't destroy
* it when unrefing parents later */
- g_base_info_ref(info);
- parent = info;
+ GjsAutoInfo<GIObjectInfo> parent = g_base_info_ref(info);
/* Since it isn't possible to override a vfunc on
* an interface without reimplementing it, we don't need
* to search the parent types when looking for a vfunc. */
- vfunc = g_object_info_find_vfunc_using_interfaces(parent, name, NULL);
+ GjsAutoInfo<GIVFuncInfo> vfunc =
+ g_object_info_find_vfunc_using_interfaces(parent, name, nullptr);
while (!vfunc && parent) {
- GIObjectInfo *tmp = parent;
- parent = g_object_info_get_parent(tmp);
- g_base_info_unref(tmp);
+ parent = g_object_info_get_parent(parent);
if (parent)
vfunc = g_object_info_find_vfunc(parent, name);
defined_by_parent = true;
}
- if (parent)
- g_base_info_unref(parent);
-
if (out_defined_by_parent)
*out_defined_by_parent = defined_by_parent;
@@ -1006,46 +984,32 @@ ObjectInstance::resolve_no_info(JSContext *cx,
bool *resolved,
const char *name)
{
- GIFunctionInfo *method_info;
guint n_interfaces;
guint i;
GType *interfaces = g_type_interfaces(m_gtype, &n_interfaces);
for (i = 0; i < n_interfaces; i++) {
- GIBaseInfo *base_info;
- GIInterfaceInfo *iface_info;
-
- base_info = g_irepository_find_by_gtype(g_irepository_get_default(),
- interfaces[i]);
-
- if (base_info == NULL)
+ GjsAutoInfo<GIInterfaceInfo> iface_info =
+ g_irepository_find_by_gtype(nullptr, interfaces[i]);
+ if (!iface_info)
continue;
/* An interface GType ought to have interface introspection info */
- g_assert (g_base_info_get_type(base_info) == GI_INFO_TYPE_INTERFACE);
-
- iface_info = (GIInterfaceInfo*) base_info;
-
- method_info = g_interface_info_find_method(iface_info, name);
-
- g_base_info_unref(base_info);
-
+ g_assert(iface_info.type() == GI_INFO_TYPE_INTERFACE);
+ GjsAutoInfo<GIFunctionInfo> method_info =
+ g_interface_info_find_method(iface_info, name);
if (method_info != NULL) {
if (g_function_info_get_flags (method_info) & GI_FUNCTION_IS_METHOD) {
if (!gjs_define_function(cx, obj, m_gtype, method_info)) {
- g_base_info_unref((GIBaseInfo*) method_info);
g_free(interfaces);
return false;
}
- g_base_info_unref((GIBaseInfo*) method_info);
*resolved = true;
g_free(interfaces);
return true;
}
-
- g_base_info_unref( (GIBaseInfo*) method_info);
}
}
@@ -1075,17 +1039,16 @@ is_gobject_property_name(GIObjectInfo *info,
{
int n_props = g_object_info_get_n_properties(info);
int ix;
- GIPropertyInfo *prop_info = nullptr;
+ GjsAutoInfo<GIPropertyInfo> prop_info;
char *canonical_name = gjs_hyphen_from_camel(name);
canonicalize_key(canonical_name);
for (ix = 0; ix < n_props; ix++) {
prop_info = g_object_info_get_property(info, ix);
- const char *prop_name = g_base_info_get_name(prop_info);
- if (strcmp(canonical_name, prop_name) == 0)
+ if (strcmp(canonical_name, prop_info.name()) == 0)
break;
- g_clear_pointer(&prop_info, g_base_info_unref);
+ prop_info.reset();
}
g_free(canonical_name);
@@ -1093,29 +1056,7 @@ is_gobject_property_name(GIObjectInfo *info,
if (!prop_info)
return false;
- if (!(g_property_info_get_flags(prop_info) & G_PARAM_READABLE)) {
- g_base_info_unref(prop_info);
- return false;
- }
-
- g_base_info_unref(prop_info);
- return true;
-}
-
-static bool
-is_gobject_field_name(GIObjectInfo *info,
- const char *name,
- GIFieldInfo **field_info_out)
-{
- GIFieldInfo *field_info = lookup_field_info(info, name);
- if (!field_info)
- return false;
-
- if (field_info_out)
- *field_info_out = field_info;
- else
- g_base_info_unref(field_info);
- return true;
+ return g_property_info_get_flags(prop_info) & G_PARAM_READABLE;
}
bool
@@ -1235,8 +1176,8 @@ ObjectInstance::resolve_impl(JSContext *context,
return true;
}
- GIFieldInfo *field_info;
- if (is_gobject_field_name(m_info, name, &field_info)) {
+ GjsAutoInfo<GIFieldInfo> field_info = lookup_field_info(m_info, name);
+ if (field_info) {
JS::RootedObject proto(context);
JS_GetPrototype(context, obj, &proto);
@@ -2104,15 +2045,9 @@ static JSObject *
gjs_lookup_object_prototype(JSContext *context,
GType gtype)
{
- GIObjectInfo *info;
- JSObject *proto;
-
- info = (GIObjectInfo*)g_irepository_find_by_gtype(g_irepository_get_default(), gtype);
- proto = gjs_lookup_object_prototype_from_info(context, info, gtype);
- if (info)
- g_base_info_unref((GIBaseInfo*)info);
-
- return proto;
+ GjsAutoInfo<GIObjectInfo> info =
+ g_irepository_find_by_gtype(nullptr, gtype);
+ return gjs_lookup_object_prototype_from_info(context, info, gtype);
}
void
@@ -2388,17 +2323,16 @@ gjs_object_define_static_methods(JSContext *context,
GType gtype,
GIObjectInfo *object_info)
{
- GIStructInfo *gtype_struct;
int i;
int n_methods;
n_methods = g_object_info_get_n_methods(object_info);
for (i = 0; i < n_methods; i++) {
- GIFunctionInfo *meth_info;
GIFunctionInfoFlags flags;
- meth_info = g_object_info_get_method(object_info, i);
+ GjsAutoInfo<GICallableInfo> meth_info =
+ g_object_info_get_method(object_info, i);
flags = g_function_info_get_flags (meth_info);
/* Anything that isn't a method we put on the prototype of the
@@ -2409,34 +2343,25 @@ gjs_object_define_static_methods(JSContext *context,
* like in the near future.
*/
if (!(flags & GI_FUNCTION_IS_METHOD)) {
- if (!gjs_define_function(context, constructor, gtype,
- (GICallableInfo *) meth_info))
+ if (!gjs_define_function(context, constructor, gtype, meth_info))
gjs_log_exception(context);
}
-
- g_base_info_unref((GIBaseInfo*) meth_info);
}
- gtype_struct = g_object_info_get_class_struct(object_info);
-
+ GjsAutoInfo<GIStructInfo> gtype_struct =
+ g_object_info_get_class_struct(object_info);
if (gtype_struct == NULL)
return;
n_methods = g_struct_info_get_n_methods(gtype_struct);
for (i = 0; i < n_methods; i++) {
- GIFunctionInfo *meth_info;
+ GjsAutoInfo<GICallableInfo> meth_info =
+ g_struct_info_get_method(gtype_struct, i);
- meth_info = g_struct_info_get_method(gtype_struct, i);
-
- if (!gjs_define_function(context, constructor, gtype,
- (GICallableInfo *) meth_info))
+ if (!gjs_define_function(context, constructor, gtype, meth_info))
gjs_log_exception(context);
-
- g_base_info_unref((GIBaseInfo*) meth_info);
}
-
- g_base_info_unref((GIBaseInfo*) gtype_struct);
}
void
@@ -2666,16 +2591,16 @@ find_vfunc_info (JSContext *context,
GIBaseInfo *vfunc_info,
const char *vfunc_name,
gpointer *implementor_vtable_ret,
- GIFieldInfo **field_info_ret)
+ GjsAutoInfo<GIFieldInfo> *field_info_ret)
{
GType ancestor_gtype;
int length, i;
GIBaseInfo *ancestor_info;
- GIStructInfo *struct_info;
+ GjsAutoInfo<GIStructInfo> struct_info;
gpointer implementor_class;
bool is_interface;
- *field_info_ret = NULL;
+ field_info_ret->reset();
*implementor_vtable_ret = NULL;
ancestor_info = g_base_info_get_container(vfunc_info);
@@ -2707,32 +2632,22 @@ find_vfunc_info (JSContext *context,
length = g_struct_info_get_n_fields(struct_info);
for (i = 0; i < length; i++) {
- GIFieldInfo *field_info;
- GITypeInfo *type_info;
-
- field_info = g_struct_info_get_field(struct_info, i);
-
- if (strcmp(g_base_info_get_name((GIBaseInfo*)field_info), vfunc_name) != 0) {
- g_base_info_unref(field_info);
+ GjsAutoInfo<GIFieldInfo> field_info =
+ g_struct_info_get_field(struct_info, i);
+ if (strcmp(field_info.name(), vfunc_name) != 0)
continue;
- }
- type_info = g_field_info_get_type(field_info);
+ GjsAutoInfo<GITypeInfo> type_info = g_field_info_get_type(field_info);
if (g_type_info_get_tag(type_info) != GI_TYPE_TAG_INTERFACE) {
/* We have a field with the same name, but it's not a callback.
* There's no hope of being another field with a correct name,
* so just abort early. */
- g_base_info_unref(type_info);
- g_base_info_unref(field_info);
- break;
+ return;
} else {
- g_base_info_unref(type_info);
- *field_info_ret = field_info;
- break;
+ *field_info_ret = std::move(field_info);
+ return;
}
}
-
- g_base_info_unref(struct_info);
}
static bool
@@ -2786,21 +2701,18 @@ ObjectInstance::hook_up_vfunc(JSContext *cx,
if (!vfunc) {
guint i, n_interfaces;
GType *interface_list;
- GIInterfaceInfo *interface;
interface_list = g_type_interfaces(m_gtype, &n_interfaces);
for (i = 0; i < n_interfaces; i++) {
- interface = (GIInterfaceInfo*)g_irepository_find_by_gtype(g_irepository_get_default(),
- interface_list[i]);
+ GjsAutoInfo<GIInterfaceInfo> interface =
+ g_irepository_find_by_gtype(nullptr, interface_list[i]);
/* The interface doesn't have to exist -- it could be private
* or dynamic. */
if (interface) {
vfunc = g_interface_info_find_vfunc(interface, name);
- g_base_info_unref((GIBaseInfo*)interface);
-
if (vfunc)
break;
}
@@ -2815,7 +2727,7 @@ ObjectInstance::hook_up_vfunc(JSContext *cx,
}
void *implementor_vtable;
- GIFieldInfo *field_info;
+ GjsAutoInfo<GIFieldInfo> field_info;
find_vfunc_info(cx, m_gtype, vfunc, name, &implementor_vtable, &field_info);
if (field_info != NULL) {
gint offset;
@@ -2831,8 +2743,6 @@ ObjectInstance::hook_up_vfunc(JSContext *cx,
wrapper, true);
*((ffi_closure **)method_ptr) = trampoline->closure;
-
- g_base_info_unref(field_info);
}
return true;
@@ -3517,22 +3427,17 @@ gjs_lookup_object_constructor(JSContext *context,
JS::MutableHandleValue value_p)
{
JSObject *constructor;
- GIObjectInfo *object_info;
- object_info = (GIObjectInfo*)g_irepository_find_by_gtype(NULL, gtype);
+ GjsAutoInfo<GIObjectInfo> object_info =
+ g_irepository_find_by_gtype(nullptr, gtype);
- g_assert(object_info == NULL ||
- g_base_info_get_type((GIBaseInfo*)object_info) ==
- GI_INFO_TYPE_OBJECT);
+ g_assert(!object_info || object_info.type() == GI_INFO_TYPE_OBJECT);
constructor = gjs_lookup_object_constructor_from_info(context, object_info, gtype);
if (G_UNLIKELY (constructor == NULL))
return false;
- if (object_info)
- g_base_info_unref((GIBaseInfo*)object_info);
-
value_p.setObject(*constructor);
return true;
}
diff --git a/gjs/jsapi-util.h b/gjs/jsapi-util.h
index e009f127..d751b87c 100644
--- a/gjs/jsapi-util.h
+++ b/gjs/jsapi-util.h
@@ -73,7 +73,8 @@ public:
operator T *() { return GjsAutoInfo::unique_ptr::get(); }
- const char *name(void) { return g_base_info_get_name(*this); }
+ const char *name(void) const { return g_base_info_get_name(this->get()); }
+ GIInfoType type(void) const { return g_base_info_get_type(this->get()); }
};
/* For use of GjsAutoInfo<T> in GC hash maps */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]