-
Notifications
You must be signed in to change notification settings - Fork 5.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
DOM and memory leaks when destroying an editor instance #2469
Comments
related to #2432 <script src="https://ajaxorg.github.io/ace-builds/src/ace.js"></script>
<p><button onclick="toggleEditor()">Toggle editor</button></p>
<div id="editor" style="height: 100px;">function foo(items) {
var x = "All this is syntax highlighted";
return x;
}</div>
<script>
var editor
function toggleEditor() {
if (!editor) {
var root = document.getElementById('editor')
root.parentNode.insertBefore(root.cloneNode(true), root)
editor = ace.edit(root);
editor.setTheme("ace/theme/monokai");
editor.session.setMode("ace/mode/javascript");
} else {
editor.destroy();
var el = editor.container;
el.parentNode.removeChild(el);
editor = null;
}
}
toggleEditor()
</script> |
You are right, ref to the first created editor was retained in a closure. #2470 fixes that. |
@nightwing
On further checking we found that, the virtualrenderer was still having reference to editor once scroll events were bonded. removing the scroll events using jquery .off() before destroying fixed this. I think while destroying the editor, we have to remove the events to lose the reference they have to the editor. |
@soundar78 could you show the code you used to add remove events, or better the code you used for testing? That would help me to understand what is causing the leak. |
For reproducing i used the same code from this comment |
this appears to be a regression in chrome, the same issue happens with the following code when typing into textarea, without typing the memory doesn't increase, and on firefox the memory doesn't increase either <script>
function Editor(element) {
this.setValue = function(v) { this.value = v.split("\n") }
this.getValue = function() { return this.value.join("\n") }
this.destroy = function() {}
var self = this;
this.container = element
this.setValue(element.textContent)
var text = document.createElement("textarea")
element.appendChild(text)
element.addEventListener("mousedown", function() {
console.log(this, self, element)
text.focus()
})
}
var ace = {
edit: function(element) {
return new Editor(element)
}
}
var editor
function toggleEditor() {
if (!editor) {
var root = document.getElementById('editor')
root.parentNode.insertBefore(root.cloneNode(true), root)
editor = ace.edit(root, {
theme: "ace/theme/monokai",
mode: "ace/mode/javascript",
});
var val = editor.getValue();
editor.setValue(
new Array(10000).join(val), -1
)
} else {
editor.destroy();
var el = editor.container;
el.parentNode.removeChild(el);
editor = null;
}
}
toggleEditor()
</script> |
@soundar78 how did you use |
I actually used something similar to the below code to fix the memory leak in our app. But it did not help in fixing the memory leak with the below example.
|
but i was actually able to remove the editor reference event after typing in the textarea using the below code.
|
Ace editor requires a better handling of object references, DOM references and event handlers in the destroy() method. Although the method partially cleans up the memory, unfortunately, it still leaves some references inside the object: circular references between the editor and internal objects and closures, references to the DOM elements and unbound events. It creates problems with using the editor in large single-page applications, where multiple editor instances can be created and removed on a page during the user session. The biggest issue is the detached DOM trees, which take much memory and slows down the application.
I created a demo here: http://jsfiddle.net/hLge6j38/3/ Run it in Google Chrome and review the heap snapshot in Profiler after removing the editor. On the Contentment tab you will find a detached DOM tree (74 entries), which root is referred by the "container" item in the editor.
The Summary tab shows circular references between the editor and env objects:
Cleaning the editor's properties from outside reveals more issues, in particular, the textarea.ace_text-input element is referenced in the context for all closures defined in TextInput class: https://github.com/ajaxorg/ace-builds/blob/master/src/ace.js#L1891
The Summary tab displays other objects belonging to Ace after deleting the editor instance.
At the moment I can't find direct indications that unbound event handlers cause issues, but I'm pretty sure they do and will be revealed after cleaning up the references contained in variables.
Related: #344
The text was updated successfully, but these errors were encountered: