test_tearoffs.js (3252B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 function TestInterfaceAll() {} 6 TestInterfaceAll.prototype = { 7 QueryInterface: ChromeUtils.generateQI(["nsIXPCTestInterfaceA", 8 "nsIXPCTestInterfaceB", 9 "nsIXPCTestInterfaceC"]), 10 11 /* nsIXPCTestInterfaceA / nsIXPCTestInterfaceB */ 12 name: "TestInterfaceAllDefaultName", 13 14 /* nsIXPCTestInterfaceC */ 15 someInteger: 42 16 }; 17 18 function newWrappedJS() { 19 return xpcWrap(new TestInterfaceAll()); 20 } 21 22 function run_test() { 23 // Shortcut the interfaces we're using. 24 var ifs = { 25 a: Ci['nsIXPCTestInterfaceA'], 26 b: Ci['nsIXPCTestInterfaceB'], 27 c: Ci['nsIXPCTestInterfaceC'] 28 }; 29 30 // Run through the logic a few times. 31 for (let i = 0; i < 2; ++i) 32 play_with_tearoffs(ifs); 33 } 34 35 function play_with_tearoffs(ifs) { 36 37 // Allocate a bunch of objects, QI-ed to B. 38 var instances = []; 39 for (var i = 0; i < 300; ++i) 40 instances.push(newWrappedJS().QueryInterface(ifs.b)); 41 42 // Nothing to collect. 43 gc(); 44 45 // QI them to A. 46 instances.forEach(function(v, i, a) { v.QueryInterface(ifs.a); }); 47 48 // QI them to C. 49 instances.forEach(function(v, i, a) { v.QueryInterface(ifs.c); }); 50 51 // Check 52 Assert.ok('name' in instances[10], 'Have the prop from A/B'); 53 Assert.ok('someInteger' in instances[10], 'Have the prop from C'); 54 55 // Grab tearoff reflections for a and b. 56 var aTearOffs = instances.map(function(v, i, a) { return v.nsIXPCTestInterfaceA; } ); 57 var bTearOffs = instances.map(function(v, i, a) { return v.nsIXPCTestInterfaceB; } ); 58 59 // Check 60 Assert.ok('name' in aTearOffs[1], 'Have the prop from A'); 61 Assert.ok(!('someInteger' in aTearOffs[1]), 'Dont have the prop from C'); 62 63 // Nothing to collect. 64 gc(); 65 66 // Null out every even instance pointer. 67 for (var i = 0; i < instances.length; ++i) 68 if (i % 2 == 0) 69 instances[i] = null; 70 71 // Nothing to collect, since we still have the A and B tearoff reflections. 72 gc(); 73 74 // Null out A tearoff reflections that are a multiple of 3. 75 for (var i = 0; i < aTearOffs.length; ++i) 76 if (i % 3 == 0) 77 aTearOffs[i] = null; 78 79 // Nothing to collect, since we still have the B tearoff reflections. 80 gc(); 81 82 // Null out B tearoff reflections that are a multiple of 5. 83 for (var i = 0; i < bTearOffs.length; ++i) 84 if (i % 5 == 0) 85 bTearOffs[i] = null; 86 87 // This should collect every 30th object (indices that are multiples of 2, 3, and 5). 88 gc(); 89 90 // Kill the b tearoffs entirely. 91 bTearOffs = 0; 92 93 // Collect more. 94 gc(); 95 96 // Get C tearoffs. 97 var cTearOffs = instances.map(function(v, i, a) { return v ? v.nsIXPCTestInterfaceC : null; } ); 98 99 // Check. 100 Assert.ok(!('name' in cTearOffs[1]), 'Dont have the prop from A'); 101 Assert.ok('someInteger' in cTearOffs[1], 'have the prop from C'); 102 103 // Null out the a tearoffs. 104 aTearOffs = null; 105 106 // Collect all even indices. 107 gc(); 108 109 // Collect all indices. 110 instances = null; 111 gc(); 112 113 // Give ourselves a pat on the back. :-) 114 Assert.ok(true, "Got all the way through without crashing!"); 115 }