Bug 722671: Components.utils.getWeakReference should get a reference to the underlying native object if possible. r=mrbkap
authorKyle Huey <khuey@kylehuey.com>
Sun, 01 Apr 2012 19:21:13 -0700
changeset 94116 447ede53509a3930d1ba5ecaa891af2b01460bed
parent 94115 ba43d5d6a6c300f6ba1c0eb21cd0df6483728434
child 94117 3e46009daea3ca4538a1fe4cd49c4ce3ed3546e6
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs722671
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 722671: Components.utils.getWeakReference should get a reference to the underlying native object if possible. r=mrbkap
js/xpconnect/src/XPCJSWeakReference.cpp
js/xpconnect/src/XPCJSWeakReference.h
js/xpconnect/tests/chrome/Makefile.in
js/xpconnect/tests/chrome/test_weakref.xul
--- a/js/xpconnect/src/XPCJSWeakReference.cpp
+++ b/js/xpconnect/src/XPCJSWeakReference.cpp
@@ -33,16 +33,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "xpcprivate.h"
 #include "XPCJSWeakReference.h"
 
+#include "nsContentUtils.h"
+
 xpcJSWeakReference::xpcJSWeakReference()
 {
 }
 
 NS_IMPL_ISUPPORTS1(xpcJSWeakReference, xpcIJSWeakReference)
 
 nsresult xpcJSWeakReference::Init(JSContext* cx, const JS::Value& object)
 {
@@ -50,42 +52,64 @@ nsresult xpcJSWeakReference::Init(JSCont
 
     if (!object.isObject())
         return NS_OK;
 
     JSObject& obj = object.toObject();
 
     XPCCallContext ccx(NATIVE_CALLER, cx);
 
+    // See if the object is a wrapped native that supports weak references.
+    nsISupports* supports =
+        nsXPConnect::GetXPConnect()->GetNativeOfWrapper(cx, &obj);
+    if (supports) {
+        mReferent = do_GetWeakReference(supports);
+        if (mReferent) {
+            return NS_OK;
+        }
+    }
+    // If it's not a wrapped native, or it is a wrapped native that does not
+    // support weak references, fall back to getting a weak ref to the object.
+
+    // See if object is a wrapped JSObject.
     nsRefPtr<nsXPCWrappedJS> wrapped;
     nsresult rv = nsXPCWrappedJS::GetNewOrUsed(ccx,
                                                &obj,
                                                NS_GET_IID(nsISupports),
                                                nsnull,
                                                getter_AddRefs(wrapped));
     if (!wrapped) {
         NS_ERROR("can't get nsISupportsWeakReference wrapper for obj");
         return rv;
     }
 
-    return wrapped->GetWeakReference(getter_AddRefs(mWrappedJSObject));
+    return wrapped->GetWeakReference(getter_AddRefs(mReferent));
 }
 
 NS_IMETHODIMP
 xpcJSWeakReference::Get(JSContext* aCx, JS::Value* aRetval)
 {
     *aRetval = JSVAL_NULL;
 
-    if (!mWrappedJSObject) {
+    if (!mReferent) {
         return NS_OK;
     }
 
-    nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryReferent(mWrappedJSObject);
+    nsCOMPtr<nsISupports> supports = do_QueryReferent(mReferent);
+    if (!supports) {
+        return NS_OK;
+    }
+
+    nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(supports);
     if (!wrappedObj) {
-        return NS_OK;
+        // We have a generic XPCOM object that supports weak references here.
+        // Wrap it and pass it out.
+        return nsContentUtils::WrapNative(aCx, JS_GetGlobalForScopeChain(aCx),
+                                          supports, &NS_GET_IID(nsISupports),
+                                          aRetval);
     }
 
     JSObject *obj;
     wrappedObj->GetJSObject(&obj);
     if (!obj) {
         return NS_OK;
     }
 
--- a/js/xpconnect/src/XPCJSWeakReference.h
+++ b/js/xpconnect/src/XPCJSWeakReference.h
@@ -45,12 +45,12 @@ class xpcJSWeakReference : public xpcIJS
 public:
     xpcJSWeakReference();
     nsresult Init(JSContext* cx, const JS::Value& object);
 
     NS_DECL_ISUPPORTS
     NS_DECL_XPCIJSWEAKREFERENCE
 
 private:
-    nsCOMPtr<nsIWeakReference> mWrappedJSObject;
+    nsCOMPtr<nsIWeakReference> mReferent;
 };
 
 #endif // xpcjsweakreference_h___
--- a/js/xpconnect/tests/chrome/Makefile.in
+++ b/js/xpconnect/tests/chrome/Makefile.in
@@ -72,16 +72,17 @@ include $(topsrcdir)/config/rules.mk
 		test_bug664689.xul \
 		test_precisegc.xul \
 		test_nodelists.xul \
 		test_getweakmapkeys.xul \
 		test_weakmaps.xul \
 		test_bug706301.xul \
 		test_watchpoints.xul \
 		test_exnstack.xul \
+		test_weakref.xul \
 		$(NULL)
 
 # Disabled until this test gets updated to test the new proxy based
 # wrappers.
 #		test_wrappers-2.xul \
 
 libs:: $(_CHROME_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/chrome/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/chrome/test_weakref.xul
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
+<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
+                 type="text/css"?>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=484459
+-->
+<window title="Weakrefs"
+  xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+  <script type="application/javascript"
+          src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+
+  <!-- test results are displayed in the html:body -->
+  <body xmlns="http://www.w3.org/1999/xhtml">
+    <iframe type="content" id="ifr">
+    </iframe>
+  </body>
+
+  <!-- test code goes here -->
+  <script type="application/javascript"><![CDATA[
+    SimpleTest.waitForExplicitFinish();
+    var util = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
+                     .getInterface(Components.interfaces.nsIDOMWindowUtils);
+    var weakUtil = Components.utils.getWeakReference(util);
+    util = null;
+
+    function callback() {
+      ok(weakUtil.get(), "Should still be alive here");
+      SimpleTest.finish();
+    }
+
+    SpecialPowers.exactGC(window, callback);
+  ]]></script>
+</window>