[gjs] Remove usage of JSCLASS_CONSTRUCT_PROTOTYPE



commit f9276d77652cb0acecd8347610924053a8fc7649
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Fri Nov 4 22:11:39 2011 -0400

    Remove usage of JSCLASS_CONSTRUCT_PROTOTYPE
    
    JSCLASS_CONSTRUCT_PROTOTYPE is an old hack that upstream wants to remove. We're
    only using it to set the private instance, something we can do ourselves after
    initting the class.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=663441

 gi/boxed.c      |  215 +++++++++++++++++++++-----------------------------
 gi/function.c   |    8 --
 gi/keep-alive.c |    8 --
 gi/ns.c         |    8 --
 gi/object.c     |  237 ++++++++++++++++++++++++-------------------------------
 gi/param.c      |   73 ++++++-----------
 gi/repo.c       |    8 --
 gi/union.c      |  126 ++++++++++++------------------
 8 files changed, 267 insertions(+), 416 deletions(-)
---
diff --git a/gi/boxed.c b/gi/boxed.c
index 0d09b79..2be87e5 100644
--- a/gi/boxed.c
+++ b/gi/boxed.c
@@ -427,23 +427,12 @@ boxed_init(JSContext   *context,
     return JS_FALSE;
 }
 
-/* If we set JSCLASS_CONSTRUCT_PROTOTYPE flag, then this is called on
- * the prototype in addition to on each instance. When called on the
- * prototype, "obj" is the prototype, and "retval" is the prototype
- * also, but can be replaced with another object to use instead as the
- * prototype. If we don't set JSCLASS_CONSTRUCT_PROTOTYPE we can
- * identify the prototype as an object of our class with NULL private
- * data.
- */
 GJS_NATIVE_CONSTRUCTOR_DECLARE(boxed)
 {
     GJS_NATIVE_CONSTRUCTOR_VARIABLES(boxed)
     Boxed *priv;
     Boxed *proto_priv;
-    JSClass *obj_class;
-    JSClass *proto_class;
     JSObject *proto;
-    gboolean is_proto;
 
     GJS_NATIVE_CONSTRUCTOR_PRELUDE(boxed);
 
@@ -460,127 +449,111 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(boxed)
 
     proto = JS_GetPrototype(context, object);
     gjs_debug_lifecycle(GJS_DEBUG_GBOXED, "boxed instance __proto__ is %p", proto);
+    /* If we're the prototype, then post-construct we'll fill in priv->info.
+     * If we are not the prototype, though, then we'll get ->info from the
+     * prototype and then create a GObject if we don't have one already.
+     */
+    proto_priv = priv_from_js(context, proto);
+    if (proto_priv == NULL) {
+        gjs_debug(GJS_DEBUG_GBOXED,
+                  "Bad prototype set on boxed? Must match JSClass of object. JS error should have been reported.");
+        return JS_FALSE;
+    }
 
-    /* If we're constructing the prototype, its __proto__ is not the same
-     * class as us, but if we're constructing an instance, the prototype
-     * has the same class.
+    priv->info = proto_priv->info;
+    priv->can_allocate_directly = proto_priv->can_allocate_directly;
+    g_base_info_ref( (GIBaseInfo*) priv->info);
+
+    /* Since gobject-introspection is always creating new info
+     * objects, == is not meaningful on them, only comparison of
+     * their names. We prefer to use the info that is already ref'd
+     * by the prototype for the class.
      */
-    obj_class = JS_GET_CLASS(context, object);
-    proto_class = JS_GET_CLASS(context, proto);
+    g_assert(unthreadsafe_template_for_constructor.info == NULL ||
+             strcmp(g_base_info_get_name( (GIBaseInfo*) priv->info),
+                    g_base_info_get_name( (GIBaseInfo*) unthreadsafe_template_for_constructor.info))
+             == 0);
+    unthreadsafe_template_for_constructor.info = NULL;
 
-    is_proto = (obj_class != proto_class);
+    if (unthreadsafe_template_for_constructor.gboxed == NULL) {
+        Boxed *source_priv;
+        GType gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
 
-    gjs_debug_lifecycle(GJS_DEBUG_GBOXED,
-                        "boxed instance constructing proto %d, obj class %s proto class %s",
-                        is_proto, obj_class->name, proto_class->name);
+        /* Short-circuit copy-construction in the case where we can use g_boxed_copy */
+        if (argc == 1 &&
+            boxed_get_copy_source(context, priv, argv[0], &source_priv)) {
 
-    if (!is_proto) {
-        /* If we're the prototype, then post-construct we'll fill in priv->info.
-         * If we are not the prototype, though, then we'll get ->info from the
-         * prototype and then create a GObject if we don't have one already.
-         */
-        proto_priv = priv_from_js(context, proto);
-        if (proto_priv == NULL) {
-            gjs_debug(GJS_DEBUG_GBOXED,
-                      "Bad prototype set on boxed? Must match JSClass of object. JS error should have been reported.");
-            return JS_FALSE;
+            if (gtype != G_TYPE_NONE && g_type_is_a (gtype, G_TYPE_BOXED)) {
+                priv->gboxed = g_boxed_copy(gtype, source_priv->gboxed);
+                GJS_NATIVE_CONSTRUCTOR_FINISH(boxed);
+                return JS_TRUE;
+            }
         }
 
-        priv->info = proto_priv->info;
-        priv->can_allocate_directly = proto_priv->can_allocate_directly;
-        g_base_info_ref( (GIBaseInfo*) priv->info);
-
-        /* Since gobject-introspection is always creating new info
-         * objects, == is not meaningful on them, only comparison of
-         * their names. We prefer to use the info that is already ref'd
-         * by the prototype for the class.
-         */
-        g_assert(unthreadsafe_template_for_constructor.info == NULL ||
-                 strcmp(g_base_info_get_name( (GIBaseInfo*) priv->info),
-                        g_base_info_get_name( (GIBaseInfo*) unthreadsafe_template_for_constructor.info))
-                 == 0);
-        unthreadsafe_template_for_constructor.info = NULL;
-
-        if (unthreadsafe_template_for_constructor.gboxed == NULL) {
-            Boxed *source_priv;
-            GType gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
+        /* Short-circuit construction for GVariants (simply cannot construct here,
+           the constructor should be overridden) */
+        if (g_type_is_a(gtype, G_TYPE_VARIANT)) {
+            gjs_throw(context,
+                      "Can't create instance of GVariant directly, use GVariant.new_*");
+            return JS_FALSE;
+        }
 
-            /* Short-circuit copy-construction in the case where we can use g_boxed_copy */
-            if (argc == 1 &&
-                boxed_get_copy_source(context, priv, argv[0], &source_priv)) {
+        if (!boxed_new(context, object, priv))
+            return JS_FALSE;
 
-                if (gtype != G_TYPE_NONE && g_type_is_a (gtype, G_TYPE_BOXED)) {
-                    priv->gboxed = g_boxed_copy(gtype, source_priv->gboxed);
-                    GJS_NATIVE_CONSTRUCTOR_FINISH(boxed);
-                    return JS_TRUE;
-                }
-            }
+        if (!boxed_init(context, object, priv, argc, argv))
+            return JS_FALSE;
 
-            /* Short-circuit construction for GVariants (simply cannot construct here,
-               the constructor should be overridden) */
-            if (g_type_is_a(gtype, G_TYPE_VARIANT)) {
-                gjs_throw(context,
-                          "Can't create instance of GVariant directly, use GVariant.new_*");
-                return JS_FALSE;
-            }
+    } else if (!JSVAL_IS_NULL(unthreadsafe_template_for_constructor.parent_jsval)) {
+        /* A structure nested inside a parent object; doens't have an independent allocation */
 
-            if (!boxed_new(context, object, priv))
-                return JS_FALSE;
+        priv->gboxed = unthreadsafe_template_for_constructor.gboxed;
+        priv->not_owning_gboxed = TRUE;
 
-            if (!boxed_init(context, object, priv, argc, argv))
+        /* We never actually read the reserved slot, but we put the parent object
+         * into it to hold onto the parent object.
+         */
+        JS_SetReservedSlot(context, object, 0,
+                           unthreadsafe_template_for_constructor.parent_jsval);
+
+        unthreadsafe_template_for_constructor.parent_jsval = JSVAL_NULL;
+        unthreadsafe_template_for_constructor.gboxed = NULL;
+    } else if (unthreadsafe_template_for_constructor.no_copy) {
+        /* we need to create a JS Boxed which references the
+         * original C struct, not a copy of it. Used for
+         * G_SIGNAL_TYPE_STATIC_SCOPE
+         */
+        priv->gboxed = unthreadsafe_template_for_constructor.gboxed;
+        priv->not_owning_gboxed = TRUE;
+        unthreadsafe_template_for_constructor.gboxed = NULL;
+    } else {
+        GType gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
+        JSBool retval;
+
+        if (gtype != G_TYPE_NONE && g_type_is_a (gtype, G_TYPE_BOXED)) {
+            priv->gboxed = g_boxed_copy(gtype,
+                                        unthreadsafe_template_for_constructor.gboxed);
+        } else if (g_type_is_a(gtype, G_TYPE_VARIANT)) {
+            priv->gboxed = g_variant_ref_sink (unthreadsafe_template_for_constructor.gboxed);
+        } else if (priv->can_allocate_directly) {
+            if (!boxed_new_direct(context, object, priv))
                 return JS_FALSE;
 
-        } else if (!JSVAL_IS_NULL(unthreadsafe_template_for_constructor.parent_jsval)) {
-            /* A structure nested inside a parent object; doens't have an independent allocation */
-
-            priv->gboxed = unthreadsafe_template_for_constructor.gboxed;
-            priv->not_owning_gboxed = TRUE;
-
-            /* We never actually read the reserved slot, but we put the parent object
-             * into it to hold onto the parent object.
-             */
-            JS_SetReservedSlot(context, object, 0,
-                               unthreadsafe_template_for_constructor.parent_jsval);
-
-            unthreadsafe_template_for_constructor.parent_jsval = JSVAL_NULL;
-            unthreadsafe_template_for_constructor.gboxed = NULL;
-        } else if (unthreadsafe_template_for_constructor.no_copy) {
-            /* we need to create a JS Boxed which references the
-             * original C struct, not a copy of it. Used for
-             * G_SIGNAL_TYPE_STATIC_SCOPE
-             */
-            priv->gboxed = unthreadsafe_template_for_constructor.gboxed;
-            priv->not_owning_gboxed = TRUE;
-            unthreadsafe_template_for_constructor.gboxed = NULL;
+            memcpy(priv->gboxed,
+                   unthreadsafe_template_for_constructor.gboxed,
+                   g_struct_info_get_size (priv->info));
         } else {
-            GType gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
-            JSBool retval;
-            
-            if (gtype != G_TYPE_NONE && g_type_is_a (gtype, G_TYPE_BOXED)) {
-                priv->gboxed = g_boxed_copy(gtype,
-                                            unthreadsafe_template_for_constructor.gboxed);
-            } else if (g_type_is_a(gtype, G_TYPE_VARIANT)) {
-                priv->gboxed = g_variant_ref_sink (unthreadsafe_template_for_constructor.gboxed);
-            } else if (priv->can_allocate_directly) {
-                if (!boxed_new_direct(context, object, priv))
-                    return JS_FALSE;
-
-                memcpy(priv->gboxed,
-                       unthreadsafe_template_for_constructor.gboxed,
-                       g_struct_info_get_size (priv->info));
-            } else {
-                gjs_throw(context,
-                          "Can't create a Javascript object for %s; no way to copy",
-                          g_base_info_get_name( (GIBaseInfo*) priv->info));
-            }
+            gjs_throw(context,
+                      "Can't create a Javascript object for %s; no way to copy",
+                      g_base_info_get_name( (GIBaseInfo*) priv->info));
+        }
 
-            unthreadsafe_template_for_constructor.gboxed = NULL;
+        unthreadsafe_template_for_constructor.gboxed = NULL;
 
-            retval = priv->gboxed != NULL;
-            if (retval)
-                GJS_NATIVE_CONSTRUCTOR_FINISH(boxed);
-            return retval;
-        }
+        retval = priv->gboxed != NULL;
+        if (retval)
+            GJS_NATIVE_CONSTRUCTOR_FINISH(boxed);
+        return retval;
     }
 
     GJS_NATIVE_CONSTRUCTOR_FINISH(boxed);
@@ -974,11 +947,6 @@ define_boxed_class_fields (JSContext *context,
  * instances of the object, and to the prototype that instances of the
  * class have.
  *
- * Also, there's a constructor field in here, but as far as I can
- * tell, it would only be used if no constructor were provided to
- * JS_InitClass. The constructor from JS_InitClass is not applied to
- * the prototype unless JSCLASS_CONSTRUCT_PROTOTYPE is in flags.
- *
  * We allocate 1 reserved slot; this is typically unused, but if the
  * boxed is for a nested structure inside a parent structure, the
  * reserved slot is used to hold onto the parent Javascript object and
@@ -989,7 +957,6 @@ static struct JSClass gjs_boxed_class = {
     JSCLASS_HAS_PRIVATE |
     JSCLASS_NEW_RESOLVE |
     JSCLASS_NEW_RESOLVE_GETS_START |
-    JSCLASS_CONSTRUCT_PROTOTYPE |
     JSCLASS_HAS_RESERVED_SLOTS(1),
     JS_PropertyStub,
     JS_PropertyStub,
@@ -1251,12 +1218,10 @@ gjs_define_boxed_class(JSContext    *context,
 
     g_assert(gjs_object_has_property(context, in_object, constructor_name));
 
-    /* Put the info in the prototype */
-    priv = priv_from_js(context, prototype);
-    g_assert(priv != NULL);
-    g_assert(priv->info == NULL);
+    priv = g_slice_new0(Boxed);
     priv->info = info;
     g_base_info_ref( (GIBaseInfo*) priv->info);
+    JS_SetPrivate(context, prototype, priv);
 
     gjs_debug(GJS_DEBUG_GBOXED, "Defined class %s prototype is %p class %p in object %p",
               constructor_name, prototype, JS_GET_CLASS(context, prototype), in_object);
diff --git a/gi/function.c b/gi/function.c
index ef644da..5da2a9c 100644
--- a/gi/function.c
+++ b/gi/function.c
@@ -977,14 +977,6 @@ function_call(JSContext *context,
     return success;
 }
 
-/* If we set JSCLASS_CONSTRUCT_PROTOTYPE flag, then this is called on
- * the prototype in addition to on each instance. When called on the
- * prototype, "obj" is the prototype, and "retval" is the prototype
- * also, but can be replaced with another object to use instead as the
- * prototype. If we don't set JSCLASS_CONSTRUCT_PROTOTYPE we can
- * identify the prototype as an object of our class with NULL private
- * data.
- */
 #ifdef JSFUN_CONSTRUCTOR
 static JSBool
 function_constructor(JSContext *context,
diff --git a/gi/keep-alive.c b/gi/keep-alive.c
index 28a7259..7553918 100644
--- a/gi/keep-alive.c
+++ b/gi/keep-alive.c
@@ -80,14 +80,6 @@ child_free(void *data)
     g_slice_free(Child, child);
 }
 
-/* If we set JSCLASS_CONSTRUCT_PROTOTYPE flag, then this is called on
- * the prototype in addition to on each instance. When called on the
- * prototype, "obj" is the prototype, and "retval" is the prototype
- * also, but can be replaced with another object to use instead as the
- * prototype. If we don't set JSCLASS_CONSTRUCT_PROTOTYPE we can
- * identify the prototype as an object of our class with NULL private
- * data.
- */
 GJS_NATIVE_CONSTRUCTOR_DECLARE(keep_alive)
 {
     GJS_NATIVE_CONSTRUCTOR_VARIABLES(keep_alive)
diff --git a/gi/ns.c b/gi/ns.c
index 1033969..25057c0 100644
--- a/gi/ns.c
+++ b/gi/ns.c
@@ -145,14 +145,6 @@ ns_new_resolve(JSContext *context,
     return ret;
 }
 
-/* If we set JSCLASS_CONSTRUCT_PROTOTYPE flag, then this is called on
- * the prototype in addition to on each instance. When called on the
- * prototype, "obj" is the prototype, and "retval" is the prototype
- * also, but can be replaced with another object to use instead as the
- * prototype. If we don't set JSCLASS_CONSTRUCT_PROTOTYPE we can
- * identify the prototype as an object of our class with NULL private
- * data.
- */
 GJS_NATIVE_CONSTRUCTOR_DECLARE(ns)
 {
     GJS_NATIVE_CONSTRUCTOR_VARIABLES(ns)
diff --git a/gi/object.c b/gi/object.c
index 6fefc61..a97bd8d 100644
--- a/gi/object.c
+++ b/gi/object.c
@@ -599,21 +599,13 @@ wrapped_gobj_toggle_notify(gpointer      data,
     }
 }
 
-/* If we set JSCLASS_CONSTRUCT_PROTOTYPE flag, then this is called on
- * the prototype in addition to on each instance. When called on the
- * prototype, "obj" is the prototype, and "retval" is the prototype
- * also, but can be replaced with another object to use instead as the
- * prototype.
- */
 GJS_NATIVE_CONSTRUCTOR_DECLARE(object_instance)
 {
     GJS_NATIVE_CONSTRUCTOR_VARIABLES(object_instance)
     ObjectInstance *priv;
     ObjectInstance *proto_priv;
     JSObject *proto;
-    gboolean is_proto;
-    JSClass *obj_class;
-    JSClass *proto_class;
+    GType gtype;
 
     GJS_NATIVE_CONSTRUCTOR_PRELUDE(object_instance);
 
@@ -630,135 +622,122 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(object_instance)
     proto = JS_GetPrototype(context, object);
     gjs_debug_lifecycle(GJS_DEBUG_GOBJECT, "obj instance __proto__ is %p", proto);
 
-    /* If we're constructing the prototype, its __proto__ is not the same
-     * class as us, but if we're constructing an instance, the prototype
-     * has the same class.
-     */
-    obj_class = JS_GET_CLASS(context, object);
-    proto_class = JS_GET_CLASS(context, proto);
-
-    is_proto = (obj_class != proto_class);
-
     gjs_debug_lifecycle(GJS_DEBUG_GOBJECT,
-                        "obj instance constructing proto %d, obj class %s proto class %s",
-                        is_proto, obj_class->name, proto_class->name);
+                        "obj instance constructing, obj class %s proto class %s",
+                        obj_class->name, proto_class->name);
 
-    if (!is_proto) {
-        GType gtype;
+    /* If we're the prototype, then post-construct we'll fill in priv->info.
+     * If we are not the prototype, though, then we'll get ->info from the
+     * prototype and then create a GObject if we don't have one already.
+     */
+    proto_priv = priv_from_js(context, proto);
+    if (proto_priv == NULL) {
+        gjs_debug(GJS_DEBUG_GOBJECT,
+                  "Bad prototype set on object? Must match JSClass of object. JS error should have been reported.");
+        return JS_FALSE;
+    }
 
-        /* If we're the prototype, then post-construct we'll fill in priv->info.
-         * If we are not the prototype, though, then we'll get ->info from the
-         * prototype and then create a GObject if we don't have one already.
-         */
-        proto_priv = priv_from_js(context, proto);
-        if (proto_priv == NULL) {
-            gjs_debug(GJS_DEBUG_GOBJECT,
-                      "Bad prototype set on object? Must match JSClass of object. JS error should have been reported.");
+    priv->info = proto_priv->info;
+    g_base_info_ref( (GIBaseInfo*) priv->info);
+
+    /* Since gobject-introspection is always creating new info
+     * objects, == is not meaningful on them, only comparison of
+     * their names. We prefer to use the info that is already ref'd
+     * by the prototype for the class.
+     */
+    g_assert(unthreadsafe_template_for_constructor.info == NULL ||
+             strcmp(g_base_info_get_name( (GIBaseInfo*) priv->info),
+                    g_base_info_get_name( (GIBaseInfo*) unthreadsafe_template_for_constructor.info))
+             == 0);
+    unthreadsafe_template_for_constructor.info = NULL;
+
+    if (unthreadsafe_template_for_constructor.gobj == NULL) {
+        GParameter *params;
+        int n_params;
+        GTypeQuery query;
+
+        gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
+        if (gtype == G_TYPE_NONE) {
+            gjs_throw(context,
+                      "No GType for object '%s'???",
+                      g_base_info_get_name( (GIBaseInfo*) priv->info));
             return JS_FALSE;
         }
 
-        priv->info = proto_priv->info;
-        g_base_info_ref( (GIBaseInfo*) priv->info);
-
-        /* Since gobject-introspection is always creating new info
-         * objects, == is not meaningful on them, only comparison of
-         * their names. We prefer to use the info that is already ref'd
-         * by the prototype for the class.
-         */
-        g_assert(unthreadsafe_template_for_constructor.info == NULL ||
-                 strcmp(g_base_info_get_name( (GIBaseInfo*) priv->info),
-                        g_base_info_get_name( (GIBaseInfo*) unthreadsafe_template_for_constructor.info))
-                 == 0);
-        unthreadsafe_template_for_constructor.info = NULL;
-
-        if (unthreadsafe_template_for_constructor.gobj == NULL) {
-            GParameter *params;
-            int n_params;
-            GTypeQuery query;
-
-            gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
-            if (gtype == G_TYPE_NONE) {
-                gjs_throw(context,
-                          "No GType for object '%s'???",
-                          g_base_info_get_name( (GIBaseInfo*) priv->info));
-                return JS_FALSE;
-            }
+        if (!object_instance_props_to_g_parameters(context, object, argc, argv,
+                                                   gtype,
+                                                   &params, &n_params)) {
+            return JS_FALSE;
+        }
 
-            if (!object_instance_props_to_g_parameters(context, object, argc, argv,
-                                                       gtype,
-                                                       &params, &n_params)) {
-                return JS_FALSE;
-            }
+        priv->gobj = g_object_newv(gtype, n_params, params);
+        free_g_params(params, n_params);
 
-            priv->gobj = g_object_newv(gtype, n_params, params);
-            free_g_params(params, n_params);
-
-            g_type_query(gtype, &query);
-            JS_updateMallocCounter(context, query.instance_size);
-
-            if (G_IS_INITIALLY_UNOWNED(priv->gobj) &&
-                !g_object_is_floating(priv->gobj)) {
-                /* GtkWindow does not return a ref to caller of g_object_new.
-                 * Need a flag in gobject-introspection to tell us this.
-                 */
-                gjs_debug(GJS_DEBUG_GOBJECT,
-                          "Newly-created object is initially unowned but we did not get the "
-                          "floating ref, probably GtkWindow, using hacky workaround");
-                g_object_ref(priv->gobj);
-            } else if (g_object_is_floating(priv->gobj)) {
-                g_object_ref_sink(priv->gobj);
-            } else {
-                /* we should already have a ref */
-            }
-        } else {
-            priv->gobj = unthreadsafe_template_for_constructor.gobj;
-            unthreadsafe_template_for_constructor.gobj = NULL;
+        g_type_query(gtype, &query);
+        JS_updateMallocCounter(context, query.instance_size);
 
+        if (G_IS_INITIALLY_UNOWNED(priv->gobj) &&
+            !g_object_is_floating(priv->gobj)) {
+            /* GtkWindow does not return a ref to caller of g_object_new.
+             * Need a flag in gobject-introspection to tell us this.
+             */
+            gjs_debug(GJS_DEBUG_GOBJECT,
+                      "Newly-created object is initially unowned but we did not get the "
+                      "floating ref, probably GtkWindow, using hacky workaround");
+            g_object_ref(priv->gobj);
+        } else if (g_object_is_floating(priv->gobj)) {
             g_object_ref_sink(priv->gobj);
+        } else {
+            /* we should already have a ref */
         }
+    } else {
+        priv->gobj = unthreadsafe_template_for_constructor.gobj;
+        unthreadsafe_template_for_constructor.gobj = NULL;
 
-        g_assert(peek_js_obj(context, priv->gobj) == NULL);
-        set_js_obj(context, priv->gobj, object);
+        g_object_ref_sink(priv->gobj);
+    }
+
+    g_assert(peek_js_obj(context, priv->gobj) == NULL);
+    set_js_obj(context, priv->gobj, object);
 
 #if DEBUG_DISPOSE
-        g_object_weak_ref(priv->gobj, wrapped_gobj_dispose_notify, object);
+    g_object_weak_ref(priv->gobj, wrapped_gobj_dispose_notify, object);
 #endif
 
-        /* OK, here is where things get complicated. We want the
-         * wrapped gobj to keep the JSObject* wrapper alive, because
-         * people might set properties on the JSObject* that they care
-         * about. Therefore, whenever the refcount on the wrapped gobj
-         * is >1, i.e. whenever something other than the wrapper is
-         * referencing the wrapped gobj, the wrapped gobj has a strong
-         * ref (gc-roots the wrapper). When the refcount on the
-         * wrapped gobj is 1, then we change to a weak ref to allow
-         * the wrapper to be garbage collected (and thus unref the
-         * wrappee).
-         */
-        priv->keep_alive = gjs_keep_alive_get_for_import_global(context);
-        gjs_keep_alive_add_child(context,
-                                 priv->keep_alive,
-                                 gobj_no_longer_kept_alive_func,
-                                 object,
-                                 priv);
-
-        g_object_add_toggle_ref(priv->gobj,
-                                wrapped_gobj_toggle_notify,
-                                JS_GetRuntime(context));
-
-        /* We now have both a ref and a toggle ref, we only want the
-         * toggle ref. This may immediately remove the GC root
-         * we just added, since refcount may drop to 1.
-         */
-        g_object_unref(priv->gobj);
+    /* OK, here is where things get complicated. We want the
+     * wrapped gobj to keep the JSObject* wrapper alive, because
+     * people might set properties on the JSObject* that they care
+     * about. Therefore, whenever the refcount on the wrapped gobj
+     * is >1, i.e. whenever something other than the wrapper is
+     * referencing the wrapped gobj, the wrapped gobj has a strong
+     * ref (gc-roots the wrapper). When the refcount on the
+     * wrapped gobj is 1, then we change to a weak ref to allow
+     * the wrapper to be garbage collected (and thus unref the
+     * wrappee).
+     */
+    priv->keep_alive = gjs_keep_alive_get_for_import_global(context);
+    gjs_keep_alive_add_child(context,
+                             priv->keep_alive,
+                             gobj_no_longer_kept_alive_func,
+                             object,
+                             priv);
+
+    g_object_add_toggle_ref(priv->gobj,
+                            wrapped_gobj_toggle_notify,
+                            JS_GetRuntime(context));
+
+    /* We now have both a ref and a toggle ref, we only want the
+     * toggle ref. This may immediately remove the GC root
+     * we just added, since refcount may drop to 1.
+     */
+    g_object_unref(priv->gobj);
 
-        gjs_debug_lifecycle(GJS_DEBUG_GOBJECT,
-                            "JSObject created with GObject %p %s",
-                            priv->gobj, g_type_name_from_instance((GTypeInstance*) priv->gobj));
+    gjs_debug_lifecycle(GJS_DEBUG_GOBJECT,
+                        "JSObject created with GObject %p %s",
+                        priv->gobj, g_type_name_from_instance((GTypeInstance*) priv->gobj));
 
-        TRACE(GJS_OBJECT_PROXY_NEW(priv, priv->gobj, g_base_info_get_namespace ( (GIBaseInfo*) priv->info),
-                                    g_base_info_get_name ( (GIBaseInfo*) priv->info) ));
-    }
+    TRACE(GJS_OBJECT_PROXY_NEW(priv, priv->gobj, g_base_info_get_namespace ( (GIBaseInfo*) priv->info),
+                               g_base_info_get_name ( (GIBaseInfo*) priv->info) ));
 
     GJS_NATIVE_CONSTRUCTOR_FINISH(object_instance);
 
@@ -1129,21 +1108,11 @@ to_string_func(JSContext *context,
     return ret;
 }
 
-/* The bizarre thing about this vtable is that it applies to both
- * instances of the object, and to the prototype that instances of the
- * class have.
- *
- * Also, there's a constructor field in here, but as far as I can
- * tell, it would only be used if no constructor were provided to
- * JS_InitClass. The constructor from JS_InitClass is not applied to
- * the prototype unless JSCLASS_CONSTRUCT_PROTOTYPE is in flags.
- */
 static struct JSClass gjs_object_instance_class = {
     NULL, /* We copy this class struct with multiple names */
     JSCLASS_HAS_PRIVATE |
     JSCLASS_NEW_RESOLVE |
-    JSCLASS_NEW_RESOLVE_GETS_START |
-    JSCLASS_CONSTRUCT_PROTOTYPE,
+    JSCLASS_NEW_RESOLVE_GETS_START,
     JS_PropertyStub,
     JS_PropertyStub,
     object_instance_get_prop,
@@ -1388,13 +1357,11 @@ gjs_define_object_class(JSContext     *context,
 
     g_assert(gjs_object_has_property(context, in_object, constructor_name));
 
-    /* Put the info in the prototype */
-    priv = priv_from_js(context, prototype);
-    g_assert(priv != NULL);
-    g_assert(priv->info == NULL);
+    priv = g_slice_new0(ObjectInstance);
     priv->info = info;
     g_base_info_ref( (GIBaseInfo*) priv->info);
     priv->gtype = gtype;
+    JS_SetPrivate(context, prototype, priv);
 
     gjs_debug(GJS_DEBUG_GOBJECT, "Defined class %s prototype %p class %p in object %p",
               constructor_name, prototype, JS_GET_CLASS(context, prototype), in_object);
diff --git a/gi/param.c b/gi/param.c
index 7949f7e..8114a4a 100644
--- a/gi/param.c
+++ b/gi/param.c
@@ -140,23 +140,12 @@ param_new_resolve(JSContext *context,
     return JS_TRUE;
 }
 
-/* If we set JSCLASS_CONSTRUCT_PROTOTYPE flag, then this is called on
- * the prototype in addition to on each instance. When called on the
- * prototype, "obj" is the prototype, and "retval" is the prototype
- * also, but can be replaced with another object to use instead as the
- * prototype. If we don't set JSCLASS_CONSTRUCT_PROTOTYPE we can
- * identify the prototype as an object of our class with NULL private
- * data.
- */
 GJS_NATIVE_CONSTRUCTOR_DECLARE(param)
 {
     GJS_NATIVE_CONSTRUCTOR_VARIABLES(param)
     Param *priv;
     Param *proto_priv;
-    JSClass *obj_class;
-    JSClass *proto_class;
     JSObject *proto;
-    gboolean is_proto;
 
     GJS_NATIVE_CONSTRUCTOR_PRELUDE(param);
 
@@ -175,48 +164,37 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(param)
     proto = JS_GetPrototype(context, object);
     gjs_debug_lifecycle(GJS_DEBUG_GPARAM, "param instance __proto__ is %p", proto);
 
-    /* If we're constructing the prototype, its __proto__ is not the same
-     * class as us, but if we're constructing an instance, the prototype
-     * has the same class.
-     */
-    obj_class = JS_GET_CLASS(context, object);
-    proto_class = JS_GET_CLASS(context, proto);
-
-    is_proto = (obj_class != proto_class);
-
     gjs_debug_lifecycle(GJS_DEBUG_GPARAM,
                         "param instance constructing proto %d, obj class %s proto class %s",
                         is_proto, obj_class->name, proto_class->name);
 
-    if (!is_proto) {
-        /* If we're the prototype, then post-construct we'll fill in priv->info.
-         * If we are not the prototype, though, then we'll get ->info from the
-         * prototype and then create a GObject if we don't have one already.
-         */
-        proto_priv = priv_from_js(context, proto);
-        if (proto_priv == NULL) {
-            gjs_debug(GJS_DEBUG_GPARAM,
-                      "Bad prototype set on object? Must match JSClass of object. JS error should have been reported.");
-            return JS_FALSE;
-        }
-
-        if (unthreadsafe_template_for_constructor.gparam == NULL) {
-            /* To construct these we'd have to wrap all the annoying subclasses.
-             * Since we only bind ParamSpec for purposes of the GObject::notify signal,
-             * there isn't much point.
-             */
-            gjs_throw(context, "Unable to construct ParamSpec, can only wrap an existing one");
-            return JS_FALSE;
-        } else {
-            priv->gparam = g_param_spec_ref(unthreadsafe_template_for_constructor.gparam);
-            unthreadsafe_template_for_constructor.gparam = NULL;
-        }
-
+    /* If we're the prototype, then post-construct we'll fill in priv->info.
+     * If we are not the prototype, though, then we'll get ->info from the
+     * prototype and then create a GObject if we don't have one already.
+     */
+    proto_priv = priv_from_js(context, proto);
+    if (proto_priv == NULL) {
         gjs_debug(GJS_DEBUG_GPARAM,
-                  "JSObject created with param instance %p type %s",
-                  priv->gparam, g_type_name(G_TYPE_FROM_INSTANCE((GTypeInstance*) priv->gparam)));
+                  "Bad prototype set on object? Must match JSClass of object. JS error should have been reported.");
+        return JS_FALSE;
     }
 
+    if (unthreadsafe_template_for_constructor.gparam == NULL) {
+        /* To construct these we'd have to wrap all the annoying subclasses.
+         * Since we only bind ParamSpec for purposes of the GObject::notify signal,
+         * there isn't much point.
+         */
+        gjs_throw(context, "Unable to construct ParamSpec, can only wrap an existing one");
+        return JS_FALSE;
+    } else {
+        priv->gparam = g_param_spec_ref(unthreadsafe_template_for_constructor.gparam);
+        unthreadsafe_template_for_constructor.gparam = NULL;
+    }
+
+    gjs_debug(GJS_DEBUG_GPARAM,
+              "JSObject created with param instance %p type %s",
+              priv->gparam, g_type_name(G_TYPE_FROM_INSTANCE((GTypeInstance*) priv->gparam)));
+
     GJS_NATIVE_CONSTRUCTOR_FINISH(param);
 
     return JS_TRUE;
@@ -256,8 +234,7 @@ static struct JSClass gjs_param_class = {
     NULL, /* dynamic */
     JSCLASS_HAS_PRIVATE |
     JSCLASS_NEW_RESOLVE |
-    JSCLASS_NEW_RESOLVE_GETS_START |
-    JSCLASS_CONSTRUCT_PROTOTYPE,
+    JSCLASS_NEW_RESOLVE_GETS_START,
     JS_PropertyStub,
     JS_PropertyStub,
     param_get_prop,
diff --git a/gi/repo.c b/gi/repo.c
index 6a92f08..b7637b8 100644
--- a/gi/repo.c
+++ b/gi/repo.c
@@ -189,14 +189,6 @@ repo_new_resolve(JSContext *context,
     return ret;
 }
 
-/* If we set JSCLASS_CONSTRUCT_PROTOTYPE flag, then this is called on
- * the prototype in addition to on each instance. When called on the
- * prototype, "obj" is the prototype, and "retval" is the prototype
- * also, but can be replaced with another object to use instead as the
- * prototype. If we don't set JSCLASS_CONSTRUCT_PROTOTYPE we can
- * identify the prototype as an object of our class with NULL private
- * data.
- */
 GJS_NATIVE_CONSTRUCTOR_DECLARE(repo)
 {
     GJS_NATIVE_CONSTRUCTOR_VARIABLES(repo)
diff --git a/gi/union.c b/gi/union.c
index b5f8f9a..06d9300 100644
--- a/gi/union.c
+++ b/gi/union.c
@@ -188,23 +188,13 @@ union_new(JSContext   *context,
     return NULL;
 }
 
-/* If we set JSCLASS_CONSTRUCT_PROTOTYPE flag, then this is called on
- * the prototype in addition to on each instance. When called on the
- * prototype, "obj" is the prototype, and "retval" is the prototype
- * also, but can be replaced with another object to use instead as the
- * prototype. If we don't set JSCLASS_CONSTRUCT_PROTOTYPE we can
- * identify the prototype as an object of our class with NULL private
- * data.
- */
 GJS_NATIVE_CONSTRUCTOR_DECLARE(union)
 {
     GJS_NATIVE_CONSTRUCTOR_VARIABLES(union)
     Union *priv;
     Union *proto_priv;
-    JSClass *obj_class;
-    JSClass *proto_class;
     JSObject *proto;
-    gboolean is_proto;
+    GType gtype;
 
     GJS_NATIVE_CONSTRUCTOR_PRELUDE(union);
 
@@ -224,78 +214,65 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(union)
     proto = JS_GetPrototype(context, object);
     gjs_debug_lifecycle(GJS_DEBUG_GBOXED, "union instance __proto__ is %p", proto);
 
-    /* If we're constructing the prototype, its __proto__ is not the same
-     * class as us, but if we're constructing an instance, the prototype
-     * has the same class.
-     */
-    obj_class = JS_GET_CLASS(context, object);
-    proto_class = JS_GET_CLASS(context, proto);
-
-    is_proto = (obj_class != proto_class);
-
     gjs_debug_lifecycle(GJS_DEBUG_GBOXED,
                         "union instance constructing proto %d, obj class %s proto class %s",
                         is_proto, obj_class->name, proto_class->name);
 
-    if (!is_proto) {
-        GType gtype;
-
-        /* If we're the prototype, then post-construct we'll fill in priv->info.
-         * If we are not the prototype, though, then we'll get ->info from the
-         * prototype and then create a GObject if we don't have one already.
-         */
-        proto_priv = priv_from_js(context, proto);
-        if (proto_priv == NULL) {
-            gjs_debug(GJS_DEBUG_GBOXED,
-                      "Bad prototype set on union? Must match JSClass of object. JS error should have been reported.");
-            return JS_FALSE;
-        }
+    /* If we're the prototype, then post-construct we'll fill in priv->info.
+     * If we are not the prototype, though, then we'll get ->info from the
+     * prototype and then create a GObject if we don't have one already.
+     */
+    proto_priv = priv_from_js(context, proto);
+    if (proto_priv == NULL) {
+        gjs_debug(GJS_DEBUG_GBOXED,
+                  "Bad prototype set on union? Must match JSClass of object. JS error should have been reported.");
+        return JS_FALSE;
+    }
 
-        priv->info = proto_priv->info;
-        g_base_info_ref( (GIBaseInfo*) priv->info);
+    priv->info = proto_priv->info;
+    g_base_info_ref( (GIBaseInfo*) priv->info);
 
-        gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
+    gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
 
-        /* Since gobject-introspection is always creating new info
-         * objects, == is not meaningful on them, only comparison of
-         * their names. We prefer to use the info that is already ref'd
-         * by the prototype for the class.
+    /* Since gobject-introspection is always creating new info
+     * objects, == is not meaningful on them, only comparison of
+     * their names. We prefer to use the info that is already ref'd
+     * by the prototype for the class.
+     */
+    g_assert(unthreadsafe_template_for_constructor.info == NULL ||
+             strcmp(g_base_info_get_name( (GIBaseInfo*) priv->info),
+                    g_base_info_get_name( (GIBaseInfo*) unthreadsafe_template_for_constructor.info))
+             == 0);
+    unthreadsafe_template_for_constructor.info = NULL;
+
+    if (unthreadsafe_template_for_constructor.gboxed == NULL) {
+        void *gboxed;
+
+        /* union_new happens to be implemented by calling
+         * gjs_invoke_c_function(), which returns a jsval.
+         * The returned "gboxed" here is owned by that jsval,
+         * not by us.
          */
-        g_assert(unthreadsafe_template_for_constructor.info == NULL ||
-                 strcmp(g_base_info_get_name( (GIBaseInfo*) priv->info),
-                        g_base_info_get_name( (GIBaseInfo*) unthreadsafe_template_for_constructor.info))
-                 == 0);
-        unthreadsafe_template_for_constructor.info = NULL;
-
-        if (unthreadsafe_template_for_constructor.gboxed == NULL) {
-            void *gboxed;
-
-            /* union_new happens to be implemented by calling
-             * gjs_invoke_c_function(), which returns a jsval.
-             * The returned "gboxed" here is owned by that jsval,
-             * not by us.
-             */
-            gboxed = union_new(context, object, priv->info);
+        gboxed = union_new(context, object, priv->info);
 
-            if (gboxed == NULL) {
-                return JS_FALSE;
-            }
-
-            /* Because "gboxed" is owned by a jsval and will
-             * be garbage colleced, we make a copy here to be
-             * owned by us.
-             */
-            priv->gboxed = g_boxed_copy(gtype, gboxed);
-        } else {
-            priv->gboxed = g_boxed_copy(gtype, unthreadsafe_template_for_constructor.gboxed);
-            unthreadsafe_template_for_constructor.gboxed = NULL;
+        if (gboxed == NULL) {
+            return JS_FALSE;
         }
 
-        gjs_debug_lifecycle(GJS_DEBUG_GBOXED,
-                            "JSObject created with union instance %p type %s",
-                            priv->gboxed, g_type_name(gtype));
+        /* Because "gboxed" is owned by a jsval and will
+         * be garbage colleced, we make a copy here to be
+         * owned by us.
+         */
+        priv->gboxed = g_boxed_copy(gtype, gboxed);
+    } else {
+        priv->gboxed = g_boxed_copy(gtype, unthreadsafe_template_for_constructor.gboxed);
+        unthreadsafe_template_for_constructor.gboxed = NULL;
     }
 
+    gjs_debug_lifecycle(GJS_DEBUG_GBOXED,
+                        "JSObject created with union instance %p type %s",
+                        priv->gboxed, g_type_name(gtype));
+
     GJS_NATIVE_CONSTRUCTOR_FINISH(union);
 
     return JS_TRUE;
@@ -341,8 +318,7 @@ static struct JSClass gjs_union_class = {
     NULL, /* dynamic class, no name here */
     JSCLASS_HAS_PRIVATE |
     JSCLASS_NEW_RESOLVE |
-    JSCLASS_NEW_RESOLVE_GETS_START |
-    JSCLASS_CONSTRUCT_PROTOTYPE,
+    JSCLASS_NEW_RESOLVE_GETS_START,
     JS_PropertyStub,
     JS_PropertyStub,
     JS_PropertyStub,
@@ -498,12 +474,10 @@ gjs_define_union_class(JSContext    *context,
 
     g_assert(gjs_object_has_property(context, in_object, constructor_name));
 
-    /* Put the info in the prototype */
-    priv = priv_from_js(context, prototype);
-    g_assert(priv != NULL);
-    g_assert(priv->info == NULL);
+    priv = g_slice_new0(Union);
     priv->info = info;
     g_base_info_ref( (GIBaseInfo*) priv->info);
+    JS_SetPrivate(context, prototype, priv);
 
     gjs_debug(GJS_DEBUG_GBOXED, "Defined class %s prototype is %p class %p in object %p",
               constructor_name, prototype, JS_GET_CLASS(context, prototype), in_object);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]