This is related to the memory leak work fixed as part of #592.
That issue fixed cleaning up eventListeners when the controller is removed/replaced within the page. However, there are cases where the element with an action can be updated within the controller (such as an input or button changing in response to other actions in a form).
I've altered the example from that issue to reproduce the new issue:
<html>
<head>
<title>EventListenerMaps memory leak</title>
<script type="module">
import { Application, Controller } from "https://unpkg.com/@hotwired/stimulus/dist/stimulus.js"
window.Stimulus = Application.start()
Stimulus.register("boosts", class extends Controller {
doClick() { process(500) }
})
</script>
<script>
function process(count) {
let i = 0
let handler = setInterval(function () {
if (++i > count) {
clearInterval(handler)
} else {
element = document.getElementById("replace-in-controller")
element.replaceWith(element.cloneNode(true))
}
}, 1)
}
</script>
</head>
<body>
<div data-controller="boosts">
<div id="replace-in-controller">
To reproduce:
<ul>
<li>Check heap snapshot</li>
<li>Click "trigger leak" button</li>
<li>Check heap snapshot again</li>
</ul>
<button data-action="click->boosts#doClick">trigger leak</button>
</div>
</div>
</body>
</html>
Comparing the heap before and after clicking this button, you can see the detached elements relating to event listeners:
In this case it appears that we execute
|
this.delegate.bindingDisconnected(binding) |
to clean up the action, which does not specify
clearEventListeners so they are not removed.
This is related to the memory leak work fixed as part of #592.
That issue fixed cleaning up eventListeners when the controller is removed/replaced within the page. However, there are cases where the element with an action can be updated within the controller (such as an input or button changing in response to other actions in a form).
I've altered the example from that issue to reproduce the new issue:
Comparing the heap before and after clicking this button, you can see the detached elements relating to event listeners:
In this case it appears that we execute
stimulus/src/core/binding_observer.ts
Line 70 in c953af5
clearEventListenersso they are not removed.