Closed pepeiborra closed 6 years ago
The reason for this is garbage collection. The Haskell side tries to keep track of all Element
in the DOM tree, and garbage collects them and their event handlers when they are no longer reachable. Tracking lifetimes for DOM elements is reasonably straightforward, in that they are usually only manipulated from the Haskell side, for instance by using getElementById
or by using the children
property.
This heuristic does not work for general JSObject
(e.g. a JavaScript canvas object), because they can and will be manipulated by many different functions.
Note that it is common for an event handler to keep its element alive, which in turn keeps the handler alive, i.e. it is common that we have a circular reference. The only way to handle this properly is to use the Haskell garbage collector, because JavaScript garbage collector are impoverished.
What is your particular use case? I'm open to suggestion on how to incorporate more objects besides DOM elements.
I am writing a Threepenny binding to a JS data grid for my employer. The data grid is a JS object that exposes several methods and events, and I want to use the Haskell garbage collector to manage its lifetime.
Ah, I see. A JS data grid sounds like it could be treated as part of the DOM tree, like an Element
. I haven't thought about integrating things like this yet. You will probably have to roll your own by mimicking the private API and using Foreign.JavaScript
directly.
Something to make this a bit less painful would be the ability to add reachable js objects to a threepenny Element.
Would you consider this for a 0.8.0.1 release ? I can send a pull request later today.
Sure, why not! (Though the PVP requires that adding a function increases the minor version number, so this would be a 0.8.1.0 release.)
Has this issue been resolved / worked around to your satisfaction?
Looks good. I might have more feedback when we get to integrate 0.8.1.0, but if that is the case I will follow up in a new issue.
Threepenny exposes the events of JSObjects that correspond to DOM elements only. Is there a design reason for this ?
Currently all the primitives (fromJSObject, getEvents, addEvents) are private, as is the Window event vendor, so the only way to implement this properly from user land is to bolt a StateT on top of UI to carry a new event vendor.
If I'm missing something, please point me in the right direction.