Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 <?xml version="1.0"?>
2 <?xml-stylesheet type="text/css" href="chrome://global/skin"?>
3 <?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
4 <!--
5 https://bugzilla.mozilla.org/show_bug.cgi?id=668855
6 -->
7 <window title="Mozilla Bug "
8 xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
9 <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
11 <!-- test results are displayed in the html:body -->
12 <body xmlns="http://www.w3.org/1999/xhtml">
13 <a href="https://bugzilla.mozilla.org/show_bug.cgi?id="
14 target="_blank">Mozilla Bug 668855</a>
15 </body>
17 <!-- test code goes here -->
18 <script type="application/javascript">
19 <![CDATA[
20 /** Test for Bug 668855 **/
22 let Cu = Components.utils;
23 let Ci = Components.interfaces;
25 /* Create a weak reference, with a single-element weak map. */
26 let make_weak_ref = function (obj) {
27 let m = new WeakMap;
28 m.set(obj, {});
29 return m;
30 };
32 /* Check to see if a weak reference is dead. */
33 let weak_ref_dead = function (r) {
34 return Cu.nondeterministicGetWeakMapKeys(r).length == 0;
35 }
37 /* Deterministically grab an arbitrary DOM element. */
38 let get_live_dom = function () {
39 let elems = document.getElementsByTagName("a");
40 return elems[0];
41 };
44 /* Test case from bug 653248, adapted into a standard test.
46 This is a dead cycle involving a DOM edge, so the cycle collector can free it. Keys and
47 values reachable only from XPConnect must be marked gray for this to work, and the cycle collector
48 must know the proper structure of the heap.
50 */
51 let make_gray_loop = function () {
52 let map = new WeakMap;
53 let div = document.createElement("div");
54 let key = {};
55 div.setUserData("entrain", {m:map, k:key}, null);
56 //div.entrain = {m:map, k:key}; This is not sufficient to cause a leak in Fx9
57 map.set(key, div);
58 return make_weak_ref(map);
59 };
61 let weakref = make_gray_loop();
64 /* Combinations of live and dead gray maps/keys. */
65 let basic_weak_ref = null;
66 let basic_map_weak_ref = null;
67 let black_map = new WeakMap;
68 let black_key = {};
70 let basic_unit_tests = function () {
71 let live_dom = get_live_dom();
72 let dead_dom = document.createElement("div");
73 let live_map = new WeakMap;
74 let dead_map = new WeakMap;
75 let live_key = {};
76 let dead_key = {};
78 // put the live/dead maps/keys into the appropriate DOM elements
79 live_dom.basic_unit_tests = {m:live_map, k:live_key};
80 dead_dom.setUserData("hook", {m:dead_map, k:dead_key}, null);
81 // dead_dom.hook = {m:dead_map, k:dead_key};
83 // Create a dead value, and a weak ref to it.
84 // The loop keeps dead_dom alive unless the CC is smart enough to kill it.
85 let dead_val = {loop:dead_dom};
86 basic_weak_ref = make_weak_ref(dead_val);
87 basic_map_weak_ref = make_weak_ref(dead_map);
89 // set up the actual entries. most will die.
90 live_map.set(live_key, {my_key:'live_live'});
91 live_map.set(dead_key, dead_val);
92 live_map.set(black_key, {my_key:'live_black'});
94 dead_map.set(live_key, dead_val);
95 dead_map.set(dead_key, dead_val);
96 dead_map.set(black_key, dead_val);
98 black_map.set(live_key, {my_key:'black_live'});
99 black_map.set(dead_key, dead_val);
100 black_map.set(black_key, {my_key:'black_black'});
102 };
104 basic_unit_tests();
107 let check_basic_unit = function () {
108 let live_dom = get_live_dom();
109 let live_map = live_dom.basic_unit_tests.m;
110 let live_key = live_dom.basic_unit_tests.k;
112 // check the dead elements
113 ok(weak_ref_dead(basic_weak_ref), "Dead value was kept alive.");
114 ok(weak_ref_dead(basic_map_weak_ref), "Dead map was kept alive.");
116 // check the live gray map
117 is(live_map.get(live_key).my_key, 'live_live',
118 "Live key should have the same value in live map.");
119 is(live_map.get(black_key).my_key, 'live_black',
120 "Black key should have the same value in live map.");
121 is(Cu.nondeterministicGetWeakMapKeys(live_map).length, 2,
122 "Live map should have two entries.");
124 // check the live black map
125 is(black_map.get(live_key).my_key, 'black_live',
126 "Live key should have the same value in black map.");
127 is(black_map.get(black_key).my_key, 'black_black',
128 "Black key should have the same value in black map.");
129 is(Cu.nondeterministicGetWeakMapKeys(black_map).length, 2,
130 "Black map should have two entries.");
132 };
135 /* live gray chained weak map entries, involving the cycle collector. */
136 let chainm = new WeakMap;
137 let num_chains = 5;
139 let nested_cc_maps = function () {
140 let dom = get_live_dom();
141 for(let i = 0; i < num_chains; i++) {
142 let k = {count:i};
143 dom.key = k;
144 dom0 = document.createElement("div");
145 chainm.set(k, {d:dom0});
146 dom = document.createElement("div");
147 dom0.appendChild(dom);
148 };
149 };
151 let check_nested_cc_maps = function () {
152 let dom = get_live_dom();
153 let all_ok = true;
154 for(let i = 0; i < num_chains; i++) {
155 let k = dom.key;
156 all_ok = all_ok && k.count == i;
157 dom = chainm.get(k).d.firstChild;
158 };
159 ok(all_ok, "Count was invalid on a key in chained weak map entries.");
160 };
162 nested_cc_maps();
165 /* black weak map, chained garbage cycle involving DOM */
166 let garbage_map = new WeakMap;
168 let chained_garbage_maps = function () {
169 let dom0 = document.createElement("div");
170 let dom = dom0;
171 for(let i = 0; i < num_chains; i++) {
172 let k = {};
173 dom.key = k;
174 let new_dom = document.createElement("div");
175 garbage_map.set(k, {val_child:new_dom});
176 dom = document.createElement("div");
177 new_dom.appendChild(dom);
178 };
179 // tie the knot
180 dom.appendChild(dom0);
181 };
183 chained_garbage_maps();
186 /* black weak map, chained garbage cycle involving DOM, XPCWN keys */
187 let wn_garbage_map = new WeakMap;
189 let wn_chained_garbage_maps = function () {
190 let dom0 = document.createElement("div");
191 let dom = dom0;
192 for(let i = 0; i < num_chains; i++) {
193 let new_dom = document.createElement("div");
194 wn_garbage_map.set(dom, {wn_val_child:new_dom});
195 dom = document.createElement("div");
196 new_dom.appendChild(dom);
197 };
198 // tie the knot
199 dom.appendChild(dom0);
200 };
202 wn_chained_garbage_maps();
205 /* The cycle collector shouldn't remove a live wrapped native key. */
207 let wn_live_map = new WeakMap;
209 let make_live_map = function () {
210 let live = get_live_dom();
211 wn_live_map.set(live, {});
212 ok(wn_live_map.has(get_live_dom()), "Live map should have live DOM node before GC.");
213 }
215 make_live_map();
217 let unpreservable_native_key = function () {
218 // We only allow natives that support wrapper preservation to be used as weak
219 // map keys. We should be able to try to add unpreservable natives as keys without
220 // crashing (bug 711616), but we should throw an error (bug 761620).
222 let dummy_test_map = new WeakMap;
224 let rule_fail = false;
225 let got_rule = false;
226 try {
227 var rule = document.styleSheets[0].cssRules[0];
228 got_rule = true;
229 dummy_test_map.set(rule, 1);
230 } catch (e) {
231 rule_fail = true;
232 }
233 ok(got_rule, "Got the CSS rule");
234 ok(rule_fail, "Using a CSS rule as a weak map key should produce an exception because it can't be wrapper preserved.");
236 }
238 unpreservable_native_key();
240 /* set up for running precise GC/CC then checking the results */
242 SimpleTest.waitForExplicitFinish();
244 Cu.schedulePreciseGC(function () {
245 SpecialPowers.DOMWindowUtils.cycleCollect();
246 SpecialPowers.DOMWindowUtils.garbageCollect();
247 SpecialPowers.DOMWindowUtils.garbageCollect();
249 ok(weak_ref_dead(weakref), "Garbage gray cycle should be collected.");
251 check_nested_cc_maps();
253 is(Cu.nondeterministicGetWeakMapKeys(garbage_map).length, 0, "Chained garbage weak map entries should not leak.");
255 check_basic_unit();
257 // fixed by Bug 680937
258 is(Cu.nondeterministicGetWeakMapKeys(wn_garbage_map).length, 0,
259 "Chained garbage WN weak map entries should not leak.");
261 // fixed by Bug 680937
262 is(Cu.nondeterministicGetWeakMapKeys(wn_live_map).length, 1,
263 "Live weak map wrapped native key should not be removed.");
265 ok(wn_live_map.has(get_live_dom()), "Live map should have live dom.");
267 SimpleTest.finish();
268 });
270 ]]>
271 </script>
272 </window>