Interact.js: Memory leak - Detached HTML elements

Created on 26 Apr 2019  路  6Comments  路  Source: taye/interact.js

Expected behavior

I'm using interactjs in a SPA where I need to destroy/recreate several times an interact element.
When I need to destroy an interactable element I do the following:

        interact(element).unset();
        interact.removeDocument(document);

This call should be enough for the GC to collect and garbage all the retained memory by interactjs.

Actual behavior

In the Heap Snapshots of Chrome there is a Detached HTMLElement stored and never released by interactjs every time I unset.
The HTMLElement is referenced in the object Interactable inside the this._latestPointer variable this._latestPointer.eventTarget.

Solving proposition

For the moment, here is what happens inside the unset method:

https://github.com/taye/interact.js/blob/587eb948ba6adbfdda89c54c932fc3715d5651ab/packages/core/scope.ts#L93

I think we should call a new destroy method from interaction

          if (interaction.interactable === this) {
            interaction.stop()
          }
            interaction.destroy()

Inside the destroy method of interaction, it needs to clear up the memory like so :

    this._latestPointer = {
      pointer: null,
      event: null,
      eventTarget: null
    }

I've tried this solution and its working, the GC can collect and garbage.

I'm not proposing a Pull Request because maybe unset is not the right place for cleaning the memory, and maybe a new destroy or detach method should be provided by scope.

I let you guys decide.

System configuration

interact.js version: 1.4.0-RC.13
Browser name and version: Chrome
Operating System: MacOS

Most helpful comment

Found another one here downPointer in auto-scroll

image

All 6 comments

Seems like _latestPointer is not the only variable that holds a reference to a detached element.
I've detected prevTap from PointerEvent object as well. It also needs to be cleared.

image

I've created a pull request #715 that solves this issue (at least in my test-case).

Hope it helps!

Found another one here downPointer in auto-scroll

image

@jf-m Thanks again!

Hello.

Is there any chances that this issue could have been the source of a memory problem causing crashes on Safari iOS ?

Hi @bpeab,

I would say the answer of your question highly depends on your implementation of interact.js.
This issue covers a case where some detached HTML elements were retained by interact.js in the memory, preventing the GC from collecting it.

This means that the impact of this bug on the performances within your application, (and thus, the possibility of a crash) depends on what is linked to that detached HTML element.

In my case, I've been able to detect this issue because I use interact.js on a fairly big SPA application that uses VueJS. The detached HTML element had some listeners linked to it that referenced one of my heaviest (memory-wise) vueJS component.
Therefore, I was able to see the difference in Chrome Heap snapshots easily (the vue component had a 7 to 12Mb retained size).
I've never tried on Safari, but in my case, it would not surprise me if at some point safari would crash after re-displaying a lot of times that vue component.

Also, this leak happens only when you destroy and re-create the interactable element. So if you don't do it in your application, then this issue is not linked to your crash.

The best way to know the answer would be to use Chrome Heap Snapshots on your application and find out how many memory the detached element takes in your case, and see how it stacks over the time. Even if you are not facing any crashes on Chrome, it would help you anyway I'd say.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

w3bappd3v picture w3bappd3v  路  4Comments

mateop picture mateop  路  7Comments

kongaraju picture kongaraju  路  6Comments

johannes-z picture johannes-z  路  4Comments

gossi picture gossi  路  5Comments