-
Notifications
You must be signed in to change notification settings - Fork 35
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
Switch to a WeakMap to avoid memory leak #23
base: master
Are you sure you want to change the base?
Conversation
@developit My understanding could be wrong here, but are Perhaps using something like https://www.npmjs.com/package/lru-cache would be a better alternative. Or in the interest of not adding external dependencies either removing the caching or just limiting the stored cache to the last 50 items? |
@AndrewLeedham yes, Map would be totally fine here. There is very little reason to evict entries anyway. Really the original need is for a cleanup or eviction that happens immediately at the end of a rendering pass. |
@developit would a conventional |
@AndrewLeedham apologies, you're right. The problem is that raw-to-escaped mappings persist indefinitely. It's an interesting issue though, because there are performance advantages attributable to keeping these mappings around across renders when strings are repeated, however the memory consumption tradeoff is currently unbounded. The problem with something like an LRU here is that evicting a string from the map actually changes the output of vhtml() - instead of producing HTML from At its core, the issue is this: const link = vhtml('a', { href: '/' }, 'hello');
console.log(link);
// `<a href="/">hello</a>` <-- now mapped as an allowed string
const div = vhtml('div', {}, link);
console.log(div);
// `<div><a href="/">hello</a></div>` <-- `link` is in the map, doesn't get escaped
// Imagine enough time passes that `link` is evicted from the string mappings.
await sleep(60);
// we pass `link` expecting it to be HTML, but it's no longer in the mapping.
const newHtml = vhtml('p', {}, link);
console.log(newHtml);
// `<div><a href="/">hello</a></div>` <-- the value of `link` gets escaped I'd previously experimented with returning an opaque value from |
@developit that makes a lot of sense, thanks for the explanation. I would have thought at least from an SSR perspective the performance hit would be preferential over a memory leak. Given React and Preact do this already I can't see the performance being that much of an issue. Perhaps this could tie in with #6. Whereby 2 packages are provided, the current implementation is kept, but we expose a |
@developit Perhaps to keep things simple for now, a |
Tests now fail on this branch, as string primitives can't be used as keys in WeakMaps:
|
This should address the issue raised in #20.