Skip to content
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

Memory leak when executing toTextarea after entering characters #6411

Open
RyuDoizaki opened this issue Sep 13, 2020 · 2 comments
Open

Memory leak when executing toTextarea after entering characters #6411

RyuDoizaki opened this issue Sep 13, 2020 · 2 comments

Comments

@RyuDoizaki
Copy link

#6409
I am very grateful for the immediate response to the issue I posted last time.

#6410
However, the problem of memory leak when I entered the characters I posted the last time still occurs.
If you run toTextarea after typing characters in CodeMirror, that instance of CodeMirror will remain in memory. It will not be released by garbage collection.

I tried to reproduce this memory leak automatically with just a script, but it didn't work.
Instead, I made it possible to reproduce this by manually executing the script while holding down the key.

memory_leak3

<html>
    <head>
        <!-- CodeMirror master branch Sep 12 15:00:00 2020 -->
        <link rel="stylesheet" href="./CodeMirror/lib/codemirror.css">
        <script src="./CodeMirror/lib/codemirror.js"></script>
    </head>
    <body>
        <textarea id="targetTextarea" cols="30" rows="10"></textarea>
        <div>
            <br>
            <div id="loopMessage"></div>
            <button id="add">
                add and remove 100
            </button>
            <div>keydown</div>
            <div id="keydownMessage"></div>
        </div>
        <script>
            let codemirror = undefined;
            let addEl = undefined;
            let loopMessageEl = undefined;
            let keydownMessageEl = undefined;

            function sleepMills(mill){
                return new Promise(resolve => setTimeout(resolve, mill));
            }

            window.onload = function(){
                addEl = document.querySelector('#add');
                loopMessageEl = document.querySelector('#loopMessage');
                addEl.addEventListener('click', async () => {
                    loopMessageEl.textContent = 'looping';
                    for (let i = 0; i < 100; i++) {
                        codemirror = CodeMirror.fromTextArea(document.querySelector('#targetTextarea'), { autofocus: true });
                        // Set the time that you can enter one or more characters by holding down the key
                        await sleepMills(35);
                        codemirror.toTextArea();
                        codemirror = null;
                    }
                    loopMessageEl.textContent = '';
                });

                keydownMessageEl = document.querySelector('#keydownMessage');
                window.addEventListener('keydown', (e) => {
                    const key = `[${e.key}]`
                    if(!keydownMessageEl.textContent.includes(key)) {
                        keydownMessageEl.textContent += key;
                    }
                })
                window.addEventListener('keyup', (e) => {
                    const key = `[${e.key}]`
                    if(keydownMessageEl.textContent.includes(key)) {
                        keydownMessageEl.textContent = keydownMessageEl.textContent.replace(key, '');
                    }
                })
            }
        </script>
    </body>
</html>

In this video, I held down A on my keyboard and clicked add and remove 100.
And, The number of garbage instances of CodeMirror has increased by 100 each.
I have the exact same problem with Chrome on both Windows 10 and Mac Catalina

@marijnh
Copy link
Member

marijnh commented Sep 14, 2020

I can confirm the leak, but debugging it with Chrome devtools shows entirely inexplicable elements in the retainer chain for the CodeMirror objects. Specifically, it claims the textarea element is being retained by a ShadowRoot (CodeMirror does not use shadow roots), which, in turn, is being retained by a sequence of InternalNode objects, which could be anything and doesn't appear to be documented anywhere.

Interestingly, I can produce a similar effect if I just add a number of raw textareas to the document, focus them, wait a bit to let the held key type something into them, and remove them again. When profiling memory after that, even though the textarea elements have all been removed from the document, I'm seeing a bunch of them retained by ShadowRoot objects. So I think this is more of a Chrome issue than a CodeMirror issue.

@RyuDoizaki
Copy link
Author

Thank you for looking into this right away.
Sorry, I didn't realize it was a problem with Chrome.
Thank you so much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants