[gjs/gnome-3-28] object: Set up a single weak ref on the context



commit e5742d55f7e7ead246637a1c259d444ba031f081
Author: Carlos Garnacho <carlosg gnome org>
Date:   Sun Apr 15 17:59:58 2018 +0200

    object: Set up a single weak ref on the context
    
    Instead of setting up a callback when rooting GjsMaybeOwned objects,
    set up a single weak ref on the GjsContext to reset all currently
    rooted objects by iterating the ObjectInstance list.
    
    https://gitlab.gnome.org/GNOME/gjs/issues/144
    
    Closes: #144
    
    (cherry picked from commit 0f5c81e07c79f74d1b1a6a2365defaeb1452b11d)

 gi/object.cpp | 42 +++++++++++++++++++++++++++++-------------
 1 file changed, 29 insertions(+), 13 deletions(-)
---
diff --git a/gi/object.cpp b/gi/object.cpp
index 913823d0..f25e2685 100644
--- a/gi/object.cpp
+++ b/gi/object.cpp
@@ -144,6 +144,7 @@ using ParamRef = std::unique_ptr<GParamSpec, decltype(&g_param_spec_unref)>;
 using ParamRefArray = std::vector<ParamRef>;
 static std::unordered_map<GType, ParamRefArray> class_init_properties;
 
+static bool context_weak_pointer_callback = false;
 static bool weak_pointer_callback = false;
 ObjectInstance *wrapped_gobject_list;
 
@@ -1043,20 +1044,24 @@ wrapped_gobj_dispose_notify(gpointer      data,
 }
 
 static void
-gobj_no_longer_kept_alive_func(JS::HandleObject obj,
-                               void            *data)
+context_dispose_notify(gpointer      data,
+                       GObject      *where_the_object_was)
 {
-    ObjectInstance *priv;
-
-    priv = (ObjectInstance *) data;
+    ObjectInstance *priv = wrapped_gobject_list;
+    while (priv) {
+        ObjectInstance *next = priv->instance_link.next();
 
-    gjs_debug_lifecycle(GJS_DEBUG_GOBJECT, "GObject wrapper %p for GObject "
-                        "%p (%s) was rooted but is now unrooted due to "
-                        "GjsContext dispose", obj.get(), priv->gobj,
-                        G_OBJECT_TYPE_NAME(priv->gobj));
+        if (priv->keep_alive.rooted()) {
+            gjs_debug_lifecycle(GJS_DEBUG_GOBJECT, "GObject wrapper %p for GObject "
+                                "%p (%s) was rooted but is now unrooted due to "
+                                "GjsContext dispose", obj.get(), priv->gobj,
+                                G_OBJECT_TYPE_NAME(priv->gobj));
+            priv->keep_alive.reset();
+            object_instance_unlink(priv);
+        }
 
-    priv->keep_alive.reset();
-    object_instance_unlink(priv);
+        priv = next;
+    }
 }
 
 static void
@@ -1124,7 +1129,7 @@ handle_toggle_up(GObject   *gobj)
         GjsContext *context = gjs_context_get_current();
         gjs_debug_lifecycle(GJS_DEBUG_GOBJECT, "Rooting object");
         auto cx = static_cast<JSContext *>(gjs_context_get_native_context(context));
-        priv->keep_alive.switch_to_rooted(cx, gobj_no_longer_kept_alive_func, priv);
+        priv->keep_alive.switch_to_rooted(cx);
     }
 }
 
@@ -1362,6 +1367,16 @@ ensure_weak_pointer_callback(JSContext *cx)
     }
 }
 
+static void
+ensure_context_weak_pointer_callback(JSContext *cx)
+{
+    if (!context_weak_pointer_callback) {
+        auto gjs_cx = static_cast<GjsContext *>(JS_GetContextPrivate(cx));
+        g_object_weak_ref(G_OBJECT(gjs_cx), context_dispose_notify, NULL);
+        context_weak_pointer_callback = true;
+    }
+}
+
 static void
 associate_js_gobject (JSContext       *context,
                       JS::HandleObject object,
@@ -1379,6 +1394,7 @@ associate_js_gobject (JSContext       *context,
 
     priv->keep_alive = object;
     ensure_weak_pointer_callback(context);
+    ensure_context_weak_pointer_callback(context);
     object_instance_link(priv);
 
     g_object_weak_ref(gobj, wrapped_gobj_dispose_notify, priv);
@@ -1405,7 +1421,7 @@ ensure_uses_toggle_ref(JSContext      *cx,
      * wrappee).
      */
     priv->uses_toggle_ref = true;
-    priv->keep_alive.switch_to_rooted(cx, gobj_no_longer_kept_alive_func, priv);
+    priv->keep_alive.switch_to_rooted(cx);
     g_object_add_toggle_ref(priv->gobj, wrapped_gobj_toggle_notify, nullptr);
 
     /* We now have both a ref and a toggle ref, we only want the toggle ref.


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