Weak Reference proposal

Domenic Denicola d at domenic.me
Wed Feb 17 07:02:36 UTC 2016

From: es-discuss [mailto:es-discuss-bounces at mozilla.org] On Behalf Of Mark S. Miller

> On Tue, Feb 16, 2016 at 7:04 PM, Isiah Meadows <mailto:isiahmeadows at gmail.com> wrote:
>> I know this is only tangentially related, but I just remembered weak refs are required for a fully conforming DOM implementation because of their GC semantics. I feel this is relevant with the semi-recent DOM-in-JS efforts. 
> What are the GC semantics specified for DOM? How are these observable?

Adding Sebastian and Joris, my co-collaborators on [the jsdom project][1], which has at times found the lack of weakrefs in JavaScript troubling. I'm not sure if any of the cases we've run into are required, per se, so this might not answer your question directly. But answering the related question of "how would weakrefs be useful when implementing a self-hosted DOM", I know of at least one instance Joris ran into so far. From [the DOM spec][2]:

> For each NodeIterator object iterator whose root’s node document is node’s node document, run the NodeIterator pre-removing steps given node and iterator.

Rephrased: every time you remove a Node from a document, you must go through all of the document's NodeIterators and run some cleanup steps (which have the effect of changing observable properties and behavior of the NodeIterator).

The weak references come in with the phrase "the document's NodeIterators". The only way to implement this that comes to mind is for the document to keep weak references to all of the relevant NodeIterators (or, equivalently, to keep an *iterable* weak set of them). You don't want the document to hold a strong reference, since otherwise the NodeIterators will be kept alive as long as the document is, even if they are unreachable from author code. And if they are unreachable from author code, they don't matter, since the cleanup steps don't have any side effects outside of the NodeIterator itself. 

[How Joris worked around this in jsdom][3] was to have a user-configurable option "maxNodeIterators" per jsdom-Document, which gives the maximum number of well-behaved NodeIterators the user is allowed to use (default 10). The Document holds strong references to these. If the user users more than maxNodeIterators NodeIterators, the strong references to the oldest NodeIterators are dropped, and all of their public APIs which can change due to the aforementioned cleanup steps start throwing errors (instead of giving potentially incorrect results). This caps the memory usage at maxNodeIterators strong references, in the hope that older ones will not be relevant to the user code (e.g. because they would have otherwise been GCed, if not for the strong reference).

Obviously this is all pretty silly and weak references would make things a lot easier.


Other places to look:

- https://dom.spec.whatwg.org/#garbage-collection
- https://xhr.spec.whatwg.org/#garbage-collection (last sentence)
- https://fetch.spec.whatwg.org/#garbage-collection
- https://html.spec.whatwg.org/#garbage-collection-2 (notable by the circumstances where there is *not* a strong reference, as well as the last clause)

[1]: https://github.com/tmpvar/jsdom
[2]: https://dom.spec.whatwg.org/#concept-node-remove
[3]: https://github.com/tmpvar/jsdom/blob/master/lib/jsdom/living/node-iterator.js

More information about the es-discuss mailing list