Skip to content
This repository has been archived by the owner on Jan 25, 2022. It is now read-only.

Example use case (not resource management; convenient via iterable weak set) #17

Closed
domenic opened this issue Jan 29, 2018 · 8 comments
Closed

Comments

@domenic
Copy link
Member

domenic commented Jan 29, 2018

I have a definite use case for weak references in one of my projects, jsdom. It runs primarily in Node, but also in the browser. Of note, this case isn't related to resource management.

jsdom implements, among other things, the DOM Standard. In particular, there is one line that concerns us here: when removing a node:

  1. 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.

To correctly implement this step, you need a reference to every NodeIterator object that's ever been created, so you can update it correctly (by running the pre-removing steps).

This really requires weak references, as otherwise you end up holding a strong reference to every NodeIterator ever created, never releasing their memory, or the memory of the other objects that the NodeIterator references (e.g. the two DOM nodes it points to, root and reference node).


Of note:

  • This is not being used as any sort of backstop for cleaning things up. It's just plain required for correctness without massive memory leaks.
  • This doesn't require finalization at all.
  • What we really need is an "iterable weak set"; weak references of course can be used to build one of these (and an iterable weak set can be used to build a weak reference).

Finally, people may be amused by how we currently work around this. We have a user-configurable number, "max working NodeIterators", which we default to 10. We hold strong references to the last 10 created NodeIterators. If an 11th NodeIterator is created, we remove it from the list, then set an internal bit on it that says "sorry, this one's broken", and any methods you try to call on that NodeIterator will throw an exception, helpfully telling you to up the max working NodeIterators configuration.

We then loop over those 10 strongly-held NodeIterators whenever a node is removed from the document, and update them appropriately per the spec.

@dtribble
Copy link
Contributor

This is a great use. Thanks. Can you post a pointer to the code so that we can try enhancing it with weak ref code? I will be interested in trying the proposed weakref approach and trying it with various weak collection options.

Also, is there anything in the standard or other source of desire/requirement for making a similar cleanup step if the node is just dropped on the floor (e.g., some incidental additional value in triggering the cleanup).

@titzer
Copy link

titzer commented Jan 30, 2018

+1 to "iterable weak set", as another use case I have heard is implementing the "become" operator in languages like Smalltalk.

Is it possible to change the title of an issue? If so, I suggest adding "iterable weak set" to the title here.

@axkibe
Copy link

axkibe commented Jan 30, 2018

I got a rather simple other usecase, I've objects representing points in a 2d plane, I like to freeze them and I would like to intern them, so a simple a === b would test them for equality. For this I'd put all the points generated in a weak table with some kind of hash value to test if this object already exists before creating a new one. Similar for objects representing lines or other geometric objects.

@domenic
Copy link
Member Author

domenic commented Jan 30, 2018

@dtribble the code is in roughly these locations:

I'm not sure which node you'd be referring to in "is there anything in the standard or other source of desire/requirement for making a similar cleanup step if the node is just dropped on the floor", but I don't think there is any such desire/requirement.

@titzer I'm not sure why we'd call out the iterable weak set API shape specifically here; this could be accomplished with any API shape, from the proposal's weak ref, to an iterable weak map, to an iterable weak set, ...

@titzer
Copy link

titzer commented Jan 31, 2018

@domenic I simply meant using "iterable weak set" in a conceptual sense to summarize the use case described here, not any particular API commitment.

@domenic
Copy link
Member Author

domenic commented Jan 31, 2018

Ah OK, sure, I'll do that if you think that there's a tie between a generalization of this use case and the API shape.

@domenic domenic changed the title Example use case (not resource management) Example use case (not resource management; convenient via iterable weak set) Jan 31, 2018
cscott added a commit to cscott/domino that referenced this issue Aug 13, 2018
Note that in the absence of weak references, there is no way to remove a
registered NodeIterator once it has been created for a document.  If you
create a large number of NodeIterators on your document, node removal
operations will begin to slow down.  See
tc39/proposal-weakrefs#17 for more details.
@littledan
Copy link
Member

@mathiasbynens wrote up something related to this use case in the explainer. Is there anything else to add, or is it OK to close this issue?

@littledan
Copy link
Member

Closing due to #17 (comment)

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants