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