michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: const Cc = Components.classes; michael@0: const Ci = Components.interfaces; michael@0: michael@0: function run_test() { michael@0: michael@0: // Load the component manifest containing our test interface implementations. michael@0: Components.manager.autoRegister(do_get_file('../components/js/xpctest.manifest')); michael@0: michael@0: // Shortcut the interfaces we're using. michael@0: var ifs = { michael@0: a: Ci['nsIXPCTestInterfaceA'], michael@0: b: Ci['nsIXPCTestInterfaceB'], michael@0: c: Ci['nsIXPCTestInterfaceC'] michael@0: }; michael@0: michael@0: // Shortcut the class we're instantiating. This implements all three interfaces. michael@0: var cls = Cc["@mozilla.org/js/xpc/test/js/TestInterfaceAll;1"]; michael@0: michael@0: // Run through the logic a few times. michael@0: for (i = 0; i < 2; ++i) michael@0: play_with_tearoffs(ifs, cls); michael@0: } michael@0: michael@0: function play_with_tearoffs(ifs, cls) { michael@0: michael@0: // Allocate a bunch of objects, QI-ed to B. michael@0: var instances = []; michael@0: for (var i = 0; i < 300; ++i) michael@0: instances.push(cls.createInstance(ifs.b)); michael@0: michael@0: // Nothing to collect. michael@0: gc(); michael@0: michael@0: // QI them to A. michael@0: instances.forEach(function(v, i, a) { v.QueryInterface(ifs.a); }); michael@0: michael@0: // QI them to C. michael@0: instances.forEach(function(v, i, a) { v.QueryInterface(ifs.c); }); michael@0: michael@0: // Check michael@0: do_check_true('name' in instances[10], 'Have the prop from A/B'); michael@0: do_check_true('someInteger' in instances[10], 'Have the prop from C'); michael@0: michael@0: // Grab tearoff reflections for a and b. michael@0: var aTearOffs = instances.map(function(v, i, a) { return v.nsIXPCTestInterfaceA; } ); michael@0: var bTearOffs = instances.map(function(v, i, a) { return v.nsIXPCTestInterfaceB; } ); michael@0: michael@0: // Check michael@0: do_check_true('name' in aTearOffs[1], 'Have the prop from A'); michael@0: do_check_true(!('someInteger' in aTearOffs[1]), 'Dont have the prop from C'); michael@0: michael@0: // Nothing to collect. michael@0: gc(); michael@0: michael@0: // Null out every even instance pointer. michael@0: for (var i = 0; i < instances.length; ++i) michael@0: if (i % 2 == 0) michael@0: instances[i] = null; michael@0: michael@0: // Nothing to collect, since we still have the A and B tearoff reflections. michael@0: gc(); michael@0: michael@0: // Null out A tearoff reflections that are a multiple of 3. michael@0: for (var i = 0; i < aTearOffs.length; ++i) michael@0: if (i % 3 == 0) michael@0: aTearOffs[i] = null; michael@0: michael@0: // Nothing to collect, since we still have the B tearoff reflections. michael@0: gc(); michael@0: michael@0: // Null out B tearoff reflections that are a multiple of 5. michael@0: for (var i = 0; i < bTearOffs.length; ++i) michael@0: if (i % 5 == 0) michael@0: bTearOffs[i] = null; michael@0: michael@0: // This should collect every 30th object (indices that are multiples of 2, 3, and 5). michael@0: gc(); michael@0: michael@0: // Kill the b tearoffs entirely. michael@0: bTearOffs = 0; michael@0: michael@0: // Collect more. michael@0: gc(); michael@0: michael@0: // Get C tearoffs. michael@0: var cTearOffs = instances.map(function(v, i, a) { return v ? v.nsIXPCTestInterfaceC : null; } ); michael@0: michael@0: // Check. michael@0: do_check_true(!('name' in cTearOffs[1]), 'Dont have the prop from A'); michael@0: do_check_true('someInteger' in cTearOffs[1], 'have the prop from C'); michael@0: michael@0: // Null out the a tearoffs. michael@0: aTearOffs = null; michael@0: michael@0: // Collect all even indices. michael@0: gc(); michael@0: michael@0: // Collect all indices. michael@0: instances = null; michael@0: gc(); michael@0: michael@0: // Give ourselves a pat on the back. :-) michael@0: do_check_true(true, "Got all the way through without crashing!"); michael@0: }