mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
273 lines
8.2 KiB
XML
273 lines
8.2 KiB
XML
<?xml version="1.0"?>
|
|
<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
|
|
<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
|
|
<!--
|
|
https://bugzilla.mozilla.org/show_bug.cgi?id=668855
|
|
-->
|
|
<window title="Mozilla Bug "
|
|
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
|
|
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
|
|
|
|
<!-- test results are displayed in the html:body -->
|
|
<body xmlns="http://www.w3.org/1999/xhtml">
|
|
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id="
|
|
target="_blank">Mozilla Bug 668855</a>
|
|
</body>
|
|
|
|
<!-- test code goes here -->
|
|
<script type="application/javascript">
|
|
<![CDATA[
|
|
/** Test for Bug 668855 **/
|
|
|
|
let Cu = Components.utils;
|
|
let Ci = Components.interfaces;
|
|
|
|
/* Create a weak reference, with a single-element weak map. */
|
|
let make_weak_ref = function (obj) {
|
|
let m = new WeakMap;
|
|
m.set(obj, {});
|
|
return m;
|
|
};
|
|
|
|
/* Check to see if a weak reference is dead. */
|
|
let weak_ref_dead = function (r) {
|
|
return Cu.nondeterministicGetWeakMapKeys(r).length == 0;
|
|
}
|
|
|
|
/* Deterministically grab an arbitrary DOM element. */
|
|
let get_live_dom = function () {
|
|
let elems = document.getElementsByTagName("a");
|
|
return elems[0];
|
|
};
|
|
|
|
|
|
/* Test case from bug 653248, adapted into a standard test.
|
|
|
|
This is a dead cycle involving a DOM edge, so the cycle collector can free it. Keys and
|
|
values reachable only from XPConnect must be marked gray for this to work, and the cycle collector
|
|
must know the proper structure of the heap.
|
|
|
|
*/
|
|
let make_gray_loop = function () {
|
|
let map = new WeakMap;
|
|
let div = document.createElement("div");
|
|
let key = {};
|
|
div.setUserData("entrain", {m:map, k:key}, null);
|
|
//div.entrain = {m:map, k:key}; This is not sufficient to cause a leak in Fx9
|
|
map.set(key, div);
|
|
return make_weak_ref(map);
|
|
};
|
|
|
|
let weakref = make_gray_loop();
|
|
|
|
|
|
/* Combinations of live and dead gray maps/keys. */
|
|
let basic_weak_ref = null;
|
|
let basic_map_weak_ref = null;
|
|
let black_map = new WeakMap;
|
|
let black_key = {};
|
|
|
|
let basic_unit_tests = function () {
|
|
let live_dom = get_live_dom();
|
|
let dead_dom = document.createElement("div");
|
|
let live_map = new WeakMap;
|
|
let dead_map = new WeakMap;
|
|
let live_key = {};
|
|
let dead_key = {};
|
|
|
|
// put the live/dead maps/keys into the appropriate DOM elements
|
|
live_dom.basic_unit_tests = {m:live_map, k:live_key};
|
|
dead_dom.setUserData("hook", {m:dead_map, k:dead_key}, null);
|
|
// dead_dom.hook = {m:dead_map, k:dead_key};
|
|
|
|
// Create a dead value, and a weak ref to it.
|
|
// The loop keeps dead_dom alive unless the CC is smart enough to kill it.
|
|
let dead_val = {loop:dead_dom};
|
|
basic_weak_ref = make_weak_ref(dead_val);
|
|
basic_map_weak_ref = make_weak_ref(dead_map);
|
|
|
|
// set up the actual entries. most will die.
|
|
live_map.set(live_key, {my_key:'live_live'});
|
|
live_map.set(dead_key, dead_val);
|
|
live_map.set(black_key, {my_key:'live_black'});
|
|
|
|
dead_map.set(live_key, dead_val);
|
|
dead_map.set(dead_key, dead_val);
|
|
dead_map.set(black_key, dead_val);
|
|
|
|
black_map.set(live_key, {my_key:'black_live'});
|
|
black_map.set(dead_key, dead_val);
|
|
black_map.set(black_key, {my_key:'black_black'});
|
|
|
|
};
|
|
|
|
basic_unit_tests();
|
|
|
|
|
|
let check_basic_unit = function () {
|
|
let live_dom = get_live_dom();
|
|
let live_map = live_dom.basic_unit_tests.m;
|
|
let live_key = live_dom.basic_unit_tests.k;
|
|
|
|
// check the dead elements
|
|
ok(weak_ref_dead(basic_weak_ref), "Dead value was kept alive.");
|
|
ok(weak_ref_dead(basic_map_weak_ref), "Dead map was kept alive.");
|
|
|
|
// check the live gray map
|
|
is(live_map.get(live_key).my_key, 'live_live',
|
|
"Live key should have the same value in live map.");
|
|
is(live_map.get(black_key).my_key, 'live_black',
|
|
"Black key should have the same value in live map.");
|
|
is(Cu.nondeterministicGetWeakMapKeys(live_map).length, 2,
|
|
"Live map should have two entries.");
|
|
|
|
// check the live black map
|
|
is(black_map.get(live_key).my_key, 'black_live',
|
|
"Live key should have the same value in black map.");
|
|
is(black_map.get(black_key).my_key, 'black_black',
|
|
"Black key should have the same value in black map.");
|
|
is(Cu.nondeterministicGetWeakMapKeys(black_map).length, 2,
|
|
"Black map should have two entries.");
|
|
|
|
};
|
|
|
|
|
|
/* live gray chained weak map entries, involving the cycle collector. */
|
|
let chainm = new WeakMap;
|
|
let num_chains = 5;
|
|
|
|
let nested_cc_maps = function () {
|
|
let dom = get_live_dom();
|
|
for(let i = 0; i < num_chains; i++) {
|
|
let k = {count:i};
|
|
dom.key = k;
|
|
dom0 = document.createElement("div");
|
|
chainm.set(k, {d:dom0});
|
|
dom = document.createElement("div");
|
|
dom0.appendChild(dom);
|
|
};
|
|
};
|
|
|
|
let check_nested_cc_maps = function () {
|
|
let dom = get_live_dom();
|
|
let all_ok = true;
|
|
for(let i = 0; i < num_chains; i++) {
|
|
let k = dom.key;
|
|
all_ok = all_ok && k.count == i;
|
|
dom = chainm.get(k).d.firstChild;
|
|
};
|
|
ok(all_ok, "Count was invalid on a key in chained weak map entries.");
|
|
};
|
|
|
|
nested_cc_maps();
|
|
|
|
|
|
/* black weak map, chained garbage cycle involving DOM */
|
|
let garbage_map = new WeakMap;
|
|
|
|
let chained_garbage_maps = function () {
|
|
let dom0 = document.createElement("div");
|
|
let dom = dom0;
|
|
for(let i = 0; i < num_chains; i++) {
|
|
let k = {};
|
|
dom.key = k;
|
|
let new_dom = document.createElement("div");
|
|
garbage_map.set(k, {val_child:new_dom});
|
|
dom = document.createElement("div");
|
|
new_dom.appendChild(dom);
|
|
};
|
|
// tie the knot
|
|
dom.appendChild(dom0);
|
|
};
|
|
|
|
chained_garbage_maps();
|
|
|
|
|
|
/* black weak map, chained garbage cycle involving DOM, XPCWN keys */
|
|
let wn_garbage_map = new WeakMap;
|
|
|
|
let wn_chained_garbage_maps = function () {
|
|
let dom0 = document.createElement("div");
|
|
let dom = dom0;
|
|
for(let i = 0; i < num_chains; i++) {
|
|
let new_dom = document.createElement("div");
|
|
wn_garbage_map.set(dom, {wn_val_child:new_dom});
|
|
dom = document.createElement("div");
|
|
new_dom.appendChild(dom);
|
|
};
|
|
// tie the knot
|
|
dom.appendChild(dom0);
|
|
};
|
|
|
|
wn_chained_garbage_maps();
|
|
|
|
|
|
/* The cycle collector shouldn't remove a live wrapped native key. */
|
|
|
|
let wn_live_map = new WeakMap;
|
|
|
|
let make_live_map = function () {
|
|
let live = get_live_dom();
|
|
wn_live_map.set(live, {});
|
|
ok(wn_live_map.has(get_live_dom()), "Live map should have live DOM node before GC.");
|
|
}
|
|
|
|
make_live_map();
|
|
|
|
let unpreservable_native_key = function () {
|
|
// We only allow natives that support wrapper preservation to be used as weak
|
|
// map keys. We should be able to try to add unpreservable natives as keys without
|
|
// crashing (bug 711616), but we should throw an error (bug 761620).
|
|
|
|
let dummy_test_map = new WeakMap;
|
|
|
|
let rule_fail = false;
|
|
let got_rule = false;
|
|
try {
|
|
var rule = document.styleSheets[0].cssRules[0];
|
|
got_rule = true;
|
|
dummy_test_map.set(rule, 1);
|
|
} catch (e) {
|
|
rule_fail = true;
|
|
}
|
|
ok(got_rule, "Got the CSS rule");
|
|
ok(rule_fail, "Using a CSS rule as a weak map key should produce an exception because it can't be wrapper preserved.");
|
|
|
|
}
|
|
|
|
unpreservable_native_key();
|
|
|
|
/* set up for running precise GC/CC then checking the results */
|
|
|
|
SimpleTest.waitForExplicitFinish();
|
|
|
|
Cu.schedulePreciseGC(function () {
|
|
SpecialPowers.DOMWindowUtils.cycleCollect();
|
|
SpecialPowers.DOMWindowUtils.garbageCollect();
|
|
SpecialPowers.DOMWindowUtils.garbageCollect();
|
|
|
|
ok(weak_ref_dead(weakref), "Garbage gray cycle should be collected.");
|
|
|
|
check_nested_cc_maps();
|
|
|
|
is(Cu.nondeterministicGetWeakMapKeys(garbage_map).length, 0, "Chained garbage weak map entries should not leak.");
|
|
|
|
check_basic_unit();
|
|
|
|
// fixed by Bug 680937
|
|
is(Cu.nondeterministicGetWeakMapKeys(wn_garbage_map).length, 0,
|
|
"Chained garbage WN weak map entries should not leak.");
|
|
|
|
// fixed by Bug 680937
|
|
is(Cu.nondeterministicGetWeakMapKeys(wn_live_map).length, 1,
|
|
"Live weak map wrapped native key should not be removed.");
|
|
|
|
ok(wn_live_map.has(get_live_dom()), "Live map should have live dom.");
|
|
|
|
SimpleTest.finish();
|
|
});
|
|
|
|
]]>
|
|
</script>
|
|
</window>
|