
Tom Ellis wrote:
Suppose that each time I make a particular threepenny-gui widget, call it a `Foo`, I register an event handler using `on` so that the `Foo` can change its appearance based on some `Event`.
Suppose I create, show, and hide a billion `Foo`s, each one never to be shown again. Can they be garbage collected? Presumably there is something storing the callback that was registered for the `Event` and the callback refers to the `Foo`. How then can the `Foo`s be freed?
`Reactive.Threepenny.register` talks about an "unregister" action but says "FIXME: Unregistering event handlers does not work yet.". But how could it be known anyway when to unregister? Is there not the possibility of a space leak regardless?
(Threepenny author here.) This is a classic example of a circular reference that occurs in every GUI program: A widget keeps a reference to an event handler, which in turn keeps a reference to the widget. Of course, GHC's has a well-designed garbage collector that can handle this, but in Threepenny, the situation is actually worse: the widget is managed by the JavaScript runtime, whereas the event handler is managed by the Haskell runtime. I don't know any garbage collector that can resolve cross-runtime circular dependencies. Still, I managed to solve this problem to some extend. :) Essentially, Threepenny mirrors dependencies between JavaScript DOM elements on the Haskell side, and thus allows the Haskell garbage collector to handle this. (I wouldn't want to touch JavaScript garbage collectors with a ten-foot pole.) For your concrete situation, this means that as long as the `Foo` widgets are not inserted into the DOM tree in the browser, and you only use DOM events on them (`UI.click` etc), they will indeed be garbage collected properly whenever their lifetime ends in your Haskell program. (At least, that's the plan. I have tested that it works, but garbage collection is a tricky business, so I wouldn't bet my life on it just yet.) Note that I do have to mirror the JavaScript memory layout, so this only works for the `Element` type at the moment. If you use the `ffiExport` function to export event handlers to the JavaScript side, then they will not be garbage collected. The `Reactive.Threepenny.register` function is totally separate from this, because it doesn't talk to the JavaScript runtime at all. You're right that there might be some issues with `unregister`, but I haven't thought about this yet. Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com