[gjs] gjs_define_object_class(): generate correct object hierarchy
- From: Maxim Ermilov <mermilov src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [gjs] gjs_define_object_class(): generate correct object hierarchy
- Date: Tue, 26 Jan 2010 22:00:06 +0000 (UTC)
commit a16783bd3bd2b8e0549d341f216a544b79841187
Author: Maxim Ermilov <zaspire rambler ru>
Date: Wed Jan 27 00:59:21 2010 +0300
gjs_define_object_class(): generate correct object hierarchy
When we are creating a new JS class for a GObject class and look up the JS
class for the parent class, we must make sure that we use a consistent GType
and GITypeInfo. If the GITypeInfo and the GType are mismatched, then the parent
class might be incorrectly registered. To fix this we remove the 'info'
argument from gjs_define_object_class() and always just pass in a GType.
The unused functions gjs_lookup_object_constructor() and
gjs_lookup_object_class() are removed.
https://bugzilla.gnome.org/show_bug.cgi?id=602864
gi/object.c | 188 ++++++++++++++++++++++++-----------------------------------
gi/object.h | 13 +---
gi/repo.c | 12 +++-
3 files changed, 88 insertions(+), 125 deletions(-)
---
diff --git a/gi/object.c b/gi/object.c
index 0941fae..6ea2c49 100644
--- a/gi/object.c
+++ b/gi/object.c
@@ -826,54 +826,14 @@ object_instance_finalize(JSContext *context,
}
JSObject*
-gjs_lookup_object_constructor(JSContext *context,
- GType gtype,
- GIObjectInfo *info)
-{
- JSObject *ns;
- JSObject *constructor;
-
- ns = gjs_lookup_namespace_object(context, (GIBaseInfo*) info);
-
- if (ns == NULL)
- return NULL;
-
- if (gjs_define_object_class(context, ns, gtype, info,
- &constructor, NULL))
- return constructor;
- else
- return NULL;
-}
-
-JSObject*
gjs_lookup_object_prototype(JSContext *context,
- GType gtype,
- GIObjectInfo *info)
+ GType gtype)
{
- JSObject *ns;
JSObject *proto;
- ns = gjs_lookup_namespace_object(context, (GIBaseInfo*) info);
-
- if (ns == NULL)
- return NULL;
-
- if (gjs_define_object_class(context, ns, gtype, info, NULL, &proto))
- return proto;
- else
+ if (!gjs_define_object_class(context, NULL, gtype, NULL, &proto, NULL))
return NULL;
-}
-
-JSClass*
-gjs_lookup_object_class(JSContext *context,
- GType gtype,
- GIObjectInfo *info)
-{
- JSObject *prototype;
-
- prototype = gjs_lookup_object_prototype(context, gtype, info);
-
- return JS_GetClass(context, prototype);
+ return proto;
}
static JSBool
@@ -1236,23 +1196,62 @@ gjs_define_static_methods(JSContext *context,
return JS_TRUE;
}
+static GIObjectInfo*
+get_base_info(JSContext *context,
+ GType gtype)
+{
+ GIBaseInfo *info = NULL;
+
+ while (TRUE) {
+ info = g_irepository_find_by_gtype(g_irepository_get_default(),
+ gtype);
+ if (info != NULL)
+ break;
+ if (gtype == G_TYPE_OBJECT)
+ gjs_fatal("No introspection data on GObject - pretty much screwed");
+
+ gjs_debug(GJS_DEBUG_GOBJECT,
+ "No introspection data on '%s' so trying parent type '%s'",
+ g_type_name(gtype), g_type_name(g_type_parent(gtype)));
+
+ gtype = g_type_parent(gtype);
+ }
+ return (GIObjectInfo*)info;
+}
JSBool
-gjs_define_object_class(JSContext *context,
- JSObject *in_object,
- GType gtype,
- GIObjectInfo *info,
- JSObject **constructor_p,
- JSObject **prototype_p)
+gjs_define_object_class(JSContext *context,
+ JSObject *in_object,
+ GType gtype,
+ JSObject **constructor_p,
+ JSObject **prototype_p,
+ GIObjectInfo **class_info_p)
{
const char *constructor_name;
JSObject *prototype;
JSObject *constructor;
- GIObjectInfo *parent_info;
JSObject *parent_proto;
jsval value;
ObjectInstance *priv;
+ GIObjectInfo *info = NULL;
+ gboolean has_own_info = TRUE;
+
+ g_assert(gtype != G_TYPE_INVALID);
+
+ info = (GIObjectInfo*)g_irepository_find_by_gtype(g_irepository_get_default(), gtype);
+ if (!info) {
+ has_own_info = FALSE;
+ info = get_base_info(context, gtype);
+ }
+ if (!in_object) {
+ in_object = gjs_lookup_namespace_object(context, (GIBaseInfo*) info);
+
+ if (!in_object) {
+ g_base_info_unref((GIBaseInfo*)info);
+ return FALSE;
+ }
+ }
/* http://egachine.berlios.de/embedding-sm-best-practice/apa.html
* http://www.sitepoint.com/blogs/2006/01/17/javascript-inheritance/
* http://www.cs.rit.edu/~atk/JavaScript/manuals/jsobj/
@@ -1293,8 +1292,6 @@ gjs_define_object_class(JSContext *context,
* JavaScript is SO AWESOME
*/
- constructor_name = g_base_info_get_name( (GIBaseInfo*) info);
-
/* 'gtype' is the GType of a concrete class (if any) which may or may not
* be defined in the GIRepository. 'info' corresponds to the first known
* ancestor of 'gtype' (or the gtype itself.)
@@ -1312,19 +1309,11 @@ gjs_define_object_class(JSContext *context,
* constructor assuming it is unique enough instead of sharing
* 'Object' (or whatever the first known ancestor is)
*
- * 'gtype' can be invalid when called from gjs_define_info()
*/
- if (gtype != G_TYPE_INVALID) {
- GIBaseInfo *gtype_info;
-
- gtype_info = g_irepository_find_by_gtype(g_irepository_get_default(),
- gtype);
- if (gtype_info != NULL) {
- g_base_info_unref(gtype_info);
- } else {
- /* defining a class not known to GIRepository */
- constructor_name = g_type_name(gtype);
- }
+ if (!has_own_info) {
+ constructor_name = g_type_name(gtype);
+ } else {
+ constructor_name = g_base_info_get_name((GIBaseInfo*) info);
}
if (gjs_object_get_property(context, in_object, constructor_name, &value)) {
@@ -1332,7 +1321,8 @@ gjs_define_object_class(JSContext *context,
if (!JSVAL_IS_OBJECT(value)) {
gjs_throw(context, "Existing property '%s' does not look like a constructor",
constructor_name);
- return JS_FALSE;
+ g_base_info_unref((GIBaseInfo*)info);
+ return FALSE;
}
constructor = JSVAL_TO_OBJECT(value);
@@ -1340,35 +1330,28 @@ gjs_define_object_class(JSContext *context,
gjs_object_get_property(context, constructor, "prototype", &value);
if (!JSVAL_IS_OBJECT(value)) {
gjs_throw(context, "prototype property does not appear to exist or has wrong type");
- return JS_FALSE;
+ g_base_info_unref((GIBaseInfo*)info);
+ return FALSE;
} else {
if (prototype_p)
*prototype_p = JSVAL_TO_OBJECT(value);
if (constructor_p)
*constructor_p = constructor;
- return JS_TRUE;
+ if (class_info_p)
+ *class_info_p = info;
+ else
+ g_base_info_unref((GIBaseInfo*)info);
+ return TRUE;
}
}
parent_proto = NULL;
+ if (g_type_parent(gtype) != G_TYPE_INVALID) {
+ GType parent_gtype;
- /* FIXME: this traverses GIObjectInfo hierarchy too quickly. Should go up
- * the GType hierarchy to find the closest parent GIObjectInfo, but we
- * don't always have valid 'gtype' to do that. (This is only a problem when
- * g-i has only partial knowledge about the GType hierarchy, for example
- * with GIO where most concrete types are private and meant to be accessed
- * through interfaces only.)
- */
- parent_info = g_object_info_get_parent(info);
- if (parent_info != NULL) {
- GType parent_gtype;
-
- parent_gtype = g_type_parent(gtype);
- parent_proto = gjs_lookup_object_prototype(context, parent_gtype, parent_info);
-
- g_base_info_unref( (GIBaseInfo*) parent_info);
- parent_info = NULL;
+ parent_gtype = g_type_parent(gtype);
+ parent_proto = gjs_lookup_object_prototype(context, parent_gtype);
}
prototype = gjs_init_class_dynamic(context, in_object,
@@ -1420,7 +1403,8 @@ gjs_define_object_class(JSContext *context,
if (!JSVAL_IS_OBJECT(value)) {
gjs_throw(context, "Property '%s' does not look like a constructor",
constructor_name);
- return JS_FALSE;
+ g_base_info_unref((GIBaseInfo*)info);
+ return FALSE;
}
constructor = JSVAL_TO_OBJECT(value);
@@ -1433,7 +1417,11 @@ gjs_define_object_class(JSContext *context,
if (constructor_p)
*constructor_p = constructor;
- return JS_TRUE;
+ if (class_info_p)
+ *class_info_p = info;
+ else
+ g_base_info_unref((GIBaseInfo*)info);
+ return TRUE;
}
/* multiple JSRuntime could have a proxy to the same GObject, in theory
@@ -1513,39 +1501,15 @@ gjs_object_from_g_object(JSContext *context,
if (obj == NULL) {
/* We have to create a wrapper */
JSObject *proto;
- GIBaseInfo *info;
- GType gtype;
+ GIObjectInfo *info;
gjs_debug_marshal(GJS_DEBUG_GOBJECT,
"Wrapping %s with JSObject",
g_type_name_from_instance((GTypeInstance*) gobj));
- info = NULL;
- gtype = G_TYPE_FROM_INSTANCE(gobj);
- while (info == NULL) {
- info = g_irepository_find_by_gtype(g_irepository_get_default(),
- gtype);
- if (info != NULL)
- break;
- if (gtype == G_TYPE_OBJECT)
- gjs_fatal("No introspection data on GObject - pretty much screwed");
-
- gjs_debug(GJS_DEBUG_GOBJECT,
- "No introspection data on '%s' so trying parent type '%s'",
- g_type_name(gtype), g_type_name(g_type_parent(gtype)));
- gtype = g_type_parent(gtype);
- }
-
- if (info == NULL) {
- gjs_throw(context,
- "Unknown object type %s",
- g_type_name(G_TYPE_FROM_INSTANCE(gobj)));
+ if (!gjs_define_object_class(context, NULL, G_TYPE_FROM_INSTANCE(gobj), NULL, &proto, &info))
return NULL;
- }
-
- proto = gjs_lookup_object_prototype(context, G_TYPE_FROM_INSTANCE(gobj), (GIObjectInfo*) info);
-
/* can't come up with a better approach... */
unthreadsafe_template_for_constructor.info = (GIObjectInfo*) info;
unthreadsafe_template_for_constructor.gobj = gobj;
@@ -1563,7 +1527,7 @@ gjs_object_from_g_object(JSContext *context,
GObject*
gjs_g_object_from_object(JSContext *context,
- JSObject *obj)
+ JSObject *obj)
{
ObjectInstance *priv;
diff --git a/gi/object.h b/gi/object.h
index c14e919..e0dc3a4 100644
--- a/gi/object.h
+++ b/gi/object.h
@@ -35,18 +35,11 @@ G_BEGIN_DECLS
JSBool gjs_define_object_class (JSContext *context,
JSObject *in_object,
GType gtype,
- GIObjectInfo *info,
JSObject **constructor_p,
- JSObject **prototype_p);
-JSClass* gjs_lookup_object_class (JSContext *context,
- GType gtype,
- GIObjectInfo *info);
+ JSObject **prototype_p,
+ GIObjectInfo **class_info_p);
JSObject* gjs_lookup_object_prototype (JSContext *context,
- GType gtype,
- GIObjectInfo *info);
-JSObject* gjs_lookup_object_constructor (JSContext *context,
- GType gtype,
- GIObjectInfo *info);
+ GType gtype);
JSObject* gjs_object_from_g_object (JSContext *context,
GObject *gobj);
GObject* gjs_g_object_from_object (JSContext *context,
diff --git a/gi/repo.c b/gi/repo.c
index 69114e1..747161f 100644
--- a/gi/repo.c
+++ b/gi/repo.c
@@ -421,7 +421,6 @@ gjs_define_info(JSContext *context,
#if GJS_VERBOSE_ENABLE_GI_USAGE
_gjs_log_info_usage(info);
#endif
-
switch (g_base_info_get_type(info)) {
case GI_INFO_TYPE_FUNCTION:
{
@@ -432,8 +431,15 @@ gjs_define_info(JSContext *context,
}
break;
case GI_INFO_TYPE_OBJECT:
- if (!gjs_define_object_class(context, in_object, G_TYPE_INVALID, (GIObjectInfo*) info, NULL, NULL))
- return JS_FALSE;
+ {
+ GType gtype;
+ GIBaseInfo *info_for_gtype;
+ gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo*)info);
+ if (!gjs_define_object_class(context, in_object, gtype, NULL, NULL, &info_for_gtype))
+ return JS_FALSE;
+ g_assert(g_base_info_equal(info, info_for_gtype));
+ g_base_info_unref(info_for_gtype);
+ }
break;
case GI_INFO_TYPE_STRUCT:
case GI_INFO_TYPE_BOXED:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]