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
|
/* 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");
});
|