summaryrefslogtreecommitdiffstats
path: root/js/xpconnect/tests/browser/browser_weak_xpcwn.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/xpconnect/tests/browser/browser_weak_xpcwn.js')
-rw-r--r--js/xpconnect/tests/browser/browser_weak_xpcwn.js94
1 files changed, 94 insertions, 0 deletions
diff --git a/js/xpconnect/tests/browser/browser_weak_xpcwn.js b/js/xpconnect/tests/browser/browser_weak_xpcwn.js
new file mode 100644
index 0000000000..fc0fb502e0
--- /dev/null
+++ b/js/xpconnect/tests/browser/browser_weak_xpcwn.js
@@ -0,0 +1,94 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+// Check to see if a weak reference is dead.
+let weak_ref_dead = function (r) {
+ return !SpecialPowers.nondeterministicGetWeakMapKeys(r).length;
+};
+
+add_task(async function cc_xpcwn_dead() {
+ // This test demonstrates that a JS reflector for an XPCOM object
+ // (implemented via XPCWrappedNative) can be used as a weak map key, but it
+ // won't persist across a GC/CC if there are no other references to the key in
+ // JS. It would be nice if it did work, in which case we could delete this
+ // test, but it would be difficult to implement.
+
+ let wnMap = new WeakMap();
+
+ // Create a new C++ XPCOM container.
+ let container = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
+
+ {
+ // Create a new C++ XPCOM object, with a new JS reflector.
+ let str = Cc["@mozilla.org/supports-string;1"].createInstance(
+ Ci.nsISupportsString
+ );
+
+ // Set the string data so we can recognize it later.
+ str.data = "canary123";
+
+ // Store the C++ object in the C++ container.
+ container.appendElement(str);
+ is(container.Count(), 1, "The array should have one element");
+
+ // Use the JS reflector as a weak map key.
+ wnMap.set(str, {});
+ ok(!weak_ref_dead(wnMap), "weak map should have an entry");
+
+ // Make sure there are no references to the JS reflector.
+ str = null;
+ }
+
+ // Clean up the JS reflector.
+ SpecialPowers.forceGC();
+ SpecialPowers.forceCC();
+
+ ok(weak_ref_dead(wnMap), "The JS reflector has been freed.");
+
+ // Make a new JS reflector for the C++ XPCOM object.
+ let str2 = container.GetElementAt(0).QueryInterface(Ci.nsISupportsString);
+
+ is(str2.data, "canary123", "The C++ object we created still exists.");
+});
+
+add_task(async function cc_xpcwn_live() {
+ // This test is a slight variation of the previous one. It keeps a reference
+ // to the JS reflector for the C++ object, and shows that this keeps it from
+ // being removed from the weak map. This is mostly to show why it will work
+ // under some conditions.
+
+ let wnMap = new WeakMap();
+
+ // Create a new C++ XPCOM container.
+ let container = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray);
+
+ // Create a new C++ XPCOM object, with a new JS reflector, and hold alive
+ // the reflector.
+ let str = Cc["@mozilla.org/supports-string;1"].createInstance(
+ Ci.nsISupportsString
+ );
+
+ // Set the string data so we can recognize it later.
+ str.data = "canary345";
+
+ // Store the C++ object in the C++ container.
+ container.appendElement(str);
+ is(container.Count(), 1, "The array should have one element");
+
+ // Use the JS reflector as a weak map key.
+ wnMap.set(str, {});
+ ok(!weak_ref_dead(wnMap), "weak map should have an entry");
+
+ // Clean up the JS reflector.
+ SpecialPowers.forceGC();
+ SpecialPowers.forceCC();
+
+ ok(!weak_ref_dead(wnMap), "The JS reflector hasn't been freed.");
+
+ // Get a JS reflector from scratch for the C++ XPCOM object.
+ let str2 = container.GetElementAt(0).QueryInterface(Ci.nsISupportsString);
+ is(str, str2, "The JS reflector is the same");
+ is(str2.data, "canary345", "The C++ object hasn't changed");
+});