uiwjs / react-codemirror

CodeMirror 6 component for React. @codemirror https://uiwjs.github.io/react-codemirror/
https://uiwjs.github.io/react-codemirror/
MIT License
1.69k stars 134 forks source link

(fix): Memory leak in hyper-link extension #687

Closed danielericlee closed 1 month ago

danielericlee commented 1 month ago

There's a memory leak in the hyper-link extension which will reliably crash a Chrome tab. To reproduce, go to to the documentation page in Chrome and paste in https://www.npmjs.com/package/@uiw/react-codemirror 3000-4000 times. You can paste them all at once or a couple hundred at a time.

Here's a recording of the crash:

https://github.com/user-attachments/assets/9b6550a4-7a83-4a26-bad1-a17087a22ec7

The issue here is that when doc.toString() is in the while loop, a new string is created of the entire document, and Chrome creates a sliced string when running defaultRegexp.exec. That sliced string has a parent reference back to the string created by doc.toString(). That sliced string, with the giant parent reference, gets set as the url state on the HyperLinkIcon widget. The result is that Chrome has in-memory a copy of the entire document for each of the links in the document, and runs out of memory as the document gets large.

Here's what it looks like in a Chrome memory snapshot:

image

Doing the toString() once outside of the loop creates a single sliced string, and each widget will have a reference to that single string.

I was able to verify locally that this change resolves the memory leak. I was able to paste 100,000 links in my app that uses the hyperlink extension without issue.

jaywcjlove commented 1 month ago

@danielericlee thx!