Version:
codemirror: 5.65.12
Browser: Chrome 120.0.6099.217 (I believe this problem is browser-irrelevent)
Problem:
Code Analysis: As is shown in code below, when cm.display.wrapper.offsetHeight == 0 the autoRefresh addon register listeners of mouseup/keyup event on window, and continiously check the wrapper's offsetHeight. As soon as the offsetHeight check pass, these listeners will be unregistered.
Abnormal Situation: But under the situation that the offsetHeight of wrapper element is keeps 0 during the whole lifetime of a CodeMirror instance, the listener will never be released, causing the instance be referenced by listener on window, and never be gc'd.
My Case: In my circumstance, I have a dialog contains 2 CodeMirror instance, one of which is hidden by display: none. The dialog and its content is destroyed after closing, and re-create if opened again. So the hidden instance might never be rendered, and the wrapper's offsetHeight keeps 0(I'm using CodeMirror constructor to create instance, BTW).
I believe attempts to destroy instance have no use to this problem. For the stopListening function can only be called by check.
// addon/display/autorefresh.js
CodeMirror.defineOption("autoRefresh", false, function(cm, val) {
if (cm.state.autoRefresh) {
stopListening(cm, cm.state.autoRefresh)
cm.state.autoRefresh = null
}
if (val && cm.display.wrapper.offsetHeight == 0)
startListening(cm, cm.state.autoRefresh = {delay: val.delay || 250})
})
function startListening(cm, state) {
function check() {
// >>What if the offsetHeight is always 0 during the whole lifetime of CodeMirror instance?<<
if (cm.display.wrapper.offsetHeight) {
stopListening(cm, state)
if (cm.display.lastWrapHeight != cm.display.wrapper.clientHeight)
cm.refresh()
} else {
state.timeout = setTimeout(check, state.delay)
}
}
state.timeout = setTimeout(check, state.delay)
state.hurry = function() {
clearTimeout(state.timeout)
state.timeout = setTimeout(check, 50)
}
CodeMirror.on(window, "mouseup", state.hurry)
CodeMirror.on(window, "keyup", state.hurry)
}
function stopListening(_cm, state) {
clearTimeout(state.timeout)
CodeMirror.off(window, "mouseup", state.hurry)
CodeMirror.off(window, "keyup", state.hurry)
}
My problem can be resolved in some other way (for example, don't instantiate 2 CodeMirror instance). So we can focus on the possible bug itself.
I'm in hurry so can not providing a minimize reproduction demo for now. If you need one please let me know.
Version:
codemirror: 5.65.12
Browser: Chrome 120.0.6099.217 (I believe this problem is browser-irrelevent)
Problem:
Code Analysis: As is shown in code below, when
cm.display.wrapper.offsetHeight == 0the autoRefresh addon register listeners of mouseup/keyup event on window, and continiously check the wrapper's offsetHeight. As soon as the offsetHeight check pass, these listeners will be unregistered.Abnormal Situation: But under the situation that the offsetHeight of wrapper element is keeps 0 during the whole lifetime of a CodeMirror instance, the listener will never be released, causing the instance be referenced by listener on window, and never be gc'd.
My Case: In my circumstance, I have a dialog contains 2 CodeMirror instance, one of which is hidden by
display: none. The dialog and its content is destroyed after closing, and re-create if opened again. So the hidden instance might never be rendered, and the wrapper's offsetHeight keeps 0(I'm using CodeMirror constructor to create instance, BTW).I believe attempts to destroy instance have no use to this problem. For the
stopListeningfunction can only be called bycheck.My problem can be resolved in some other way (for example, don't instantiate 2 CodeMirror instance). So we can focus on the possible bug itself.
I'm in hurry so can not providing a minimize reproduction demo for now. If you need one please let me know.