HeinrichApfelmus / threepenny-gui

GUI framework that uses the web browser as a display.
https://heinrichapfelmus.github.io/threepenny-gui/
Other
439 stars 77 forks source link

Function don't get garbaged collected #122

Closed massudaw closed 7 years ago

massudaw commented 8 years ago

When i run the code in the gist, i get some strange behavior. The function traceShow is never garbaged collected. For each time the checkbox changes to true, a trace is printed one more time for each button click.

https://gist.github.com/massudaw/ebcf69dc49f9465f5afc

To reproduce just click some times in the checkbox then click on the button.

Is this expected behavior?

HeinrichApfelmus commented 8 years ago

With your combination of items and sink, you create a new <div> element every time when the event facts (triding bt) occurs. The old <div> elements are removed from the viewport, but they still listen to the UI.click btr event. Whenever that event occurs, the Behavior bh has to be updated, like it or not — its effect may no longer be visible in the browser window, but the <div> is still in the browser's memory, and its properties might still have an influence on visible elements.

In short, I don't think that the garbage collector may remove the <div> element and corresponding Behavior. I think you have to remove the old <div> elements by hand, e.g. using delete.

massudaw commented 8 years ago

I've ended up with a different workaround. Implementing a finalizer for Prim.addHandler to unregister the sink handler from the event graph and register the behavior finalizer to the element . So when the element is deleted i just call the handler finalizer.

I think my problem is more about removing the behavior from the graph when the div it was updating is not used anymore

jvdp commented 8 years ago

I've been wondering about that; is there more to event unregistering than just removing the handler from the map? (Sounds like a simple fix if not.)

massudaw commented 8 years ago

In the Reactive.Threepenny part removing a event is basically that. But using it gets anoying, because you need to explicitly call the finalizer between two behavior changes. The only way i found was associating it with the element and calling when destructing it. But has some limitations you don't have access to handler in the context you want to unregister automatically. So you need to add the handlers to the element. Seems like we need some kind of region delimiting the resources to properly remove all handlers.