browser_weak_xpcwn.js (3232B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 // Check to see if a weak reference is dead. 7 let weak_ref_dead = function (r) { 8 return !SpecialPowers.nondeterministicGetWeakMapKeys(r).length; 9 }; 10 11 add_task(async function cc_xpcwn_dead() { 12 // This test demonstrates that a JS reflector for an XPCOM object 13 // (implemented via XPCWrappedNative) can be used as a weak map key, but it 14 // won't persist across a GC/CC if there are no other references to the key in 15 // JS. It would be nice if it did work, in which case we could delete this 16 // test, but it would be difficult to implement. 17 18 let wnMap = new WeakMap(); 19 20 // Create a new C++ XPCOM container. 21 let container = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray); 22 23 { 24 // Create a new C++ XPCOM object, with a new JS reflector. 25 let str = Cc["@mozilla.org/supports-string;1"].createInstance( 26 Ci.nsISupportsString 27 ); 28 29 // Set the string data so we can recognize it later. 30 str.data = "canary123"; 31 32 // Store the C++ object in the C++ container. 33 container.appendElement(str); 34 is(container.Count(), 1, "The array should have one element"); 35 36 // Use the JS reflector as a weak map key. 37 wnMap.set(str, {}); 38 ok(!weak_ref_dead(wnMap), "weak map should have an entry"); 39 40 // Make sure there are no references to the JS reflector. 41 str = null; 42 } 43 44 // Clean up the JS reflector. 45 SpecialPowers.forceGC(); 46 SpecialPowers.forceCC(); 47 48 ok(weak_ref_dead(wnMap), "The JS reflector has been freed."); 49 50 // Make a new JS reflector for the C++ XPCOM object. 51 let str2 = container.GetElementAt(0).QueryInterface(Ci.nsISupportsString); 52 53 is(str2.data, "canary123", "The C++ object we created still exists."); 54 }); 55 56 add_task(async function cc_xpcwn_live() { 57 // This test is a slight variation of the previous one. It keeps a reference 58 // to the JS reflector for the C++ object, and shows that this keeps it from 59 // being removed from the weak map. This is mostly to show why it will work 60 // under some conditions. 61 62 let wnMap = new WeakMap(); 63 64 // Create a new C++ XPCOM container. 65 let container = Cc["@mozilla.org/array;1"].createInstance(Ci.nsIMutableArray); 66 67 // Create a new C++ XPCOM object, with a new JS reflector, and hold alive 68 // the reflector. 69 let str = Cc["@mozilla.org/supports-string;1"].createInstance( 70 Ci.nsISupportsString 71 ); 72 73 // Set the string data so we can recognize it later. 74 str.data = "canary345"; 75 76 // Store the C++ object in the C++ container. 77 container.appendElement(str); 78 is(container.Count(), 1, "The array should have one element"); 79 80 // Use the JS reflector as a weak map key. 81 wnMap.set(str, {}); 82 ok(!weak_ref_dead(wnMap), "weak map should have an entry"); 83 84 // Clean up the JS reflector. 85 SpecialPowers.forceGC(); 86 SpecialPowers.forceCC(); 87 88 ok(!weak_ref_dead(wnMap), "The JS reflector hasn't been freed."); 89 90 // Get a JS reflector from scratch for the C++ XPCOM object. 91 let str2 = container.GetElementAt(0).QueryInterface(Ci.nsISupportsString); 92 is(str, str2, "The JS reflector is the same"); 93 is(str2.data, "canary345", "The C++ object hasn't changed"); 94 });