Jacek Caban (@jacek) commented about dlls/jscript/set.c:
+static HRESULT WeakMap_gc_traverse(struct gc_ctx *gc_ctx, enum gc_traverse_op op, jsdisp_t *dispex) +{
- WeakMapInstance *weakmap = (WeakMapInstance*)dispex;
- struct weakmap_entry *entry, *entry2;
- HRESULT hres;
- if(op == GC_TRAVERSE_UNLINK) {
RB_FOR_EACH_ENTRY_DESTRUCTOR(entry, entry2, &weakmap->map, struct weakmap_entry, entry)
release_weakmap_entry(entry);
rb_destroy(&weakmap->map, NULL, NULL);
return S_OK;
- }
- RB_FOR_EACH_ENTRY(entry, &weakmap->map, struct weakmap_entry, entry) {
hres = gc_process_linked_val(gc_ctx, op, dispex, &entry->value);
This is not exactly enough for weak references. Note that weak entry should also be released when key is released, which is an information that you don't feed to GC. For example: ``` var m = new WeakMap(); var k = {}; m.set(k, k); k = null; ``` In this example the entry may be collected, but unless I'm missing something, GC won't be able to do it as long as m is alive.
BTW, it would be nice to have some tests for leaks. We could have, for example, two new host object. One would be purely for ref counting, while the other one could opaque it with a predictable single reference and a way to query current ref count. ``` var m = new WeakMap(); var t = createTestRef(); // a builtin function returning a builtin object var k = { val: t.get() }; // t.get() returns a separated object, who's ref count we will be testing m.set(k, k); ok(t.ref > 1, "map entry not released"); // t.ref is t.get()'s ref count, there is a reference from k.val k = null; CollectGarbage(); ok(t.ref === 1, "map entry not released"); // there are no more JS references ```