-
Notifications
You must be signed in to change notification settings - Fork 392
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
fix: mutationobserver memory leak - use weakmap for bookkeeping #1423
fix: mutationobserver memory leak - use weakmap for bookkeeping #1423
Conversation
Use a WeakMap to store all nodes watched by an observer. On disconnect(), clean up references to the observer on all the nodes. Limitation: If MutationObservers are not disconnected, this could lead to memory leak of nodes.
This comment has been minimized.
This comment has been minimized.
// maintain a list of all nodes observed by this observer | ||
if (observerToNodesMap.has(this)) { | ||
const observedNodes = observerToNodesMap.get(this)!; | ||
if (observedNodes.indexOf(target) === -1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indexOf from lang
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
if (observerToNodesMap.has(this)) { | ||
const observedNodes = observerToNodesMap.get(this)!; | ||
if (observedNodes.indexOf(target) === -1) { | ||
observedNodes.push(target); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
push from lang.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed
observedNodes.push(target); | ||
} | ||
} else { | ||
observerToNodesMap.set(this, [target]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
set from lang, although we are not doing that today... we should probably start doing it at some point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its a polyfilled feature in IE11, wasn't sure if was okay to cache these. Let me know.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, it should be ok. they all run before everything else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets open a seprate issue for this in general.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great to me! :) I just had a minor nitpick.
if (observerToNodesMap.has(this)) { | ||
const observedNodes = observerToNodesMap.get(this)!; | ||
if (observedNodes.indexOf(target) === -1) { | ||
observedNodes.push(target); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these be ArrayIndexOf.call()
and ArrayPush.call
?
|
||
// maintain a list of all nodes observed by this observer | ||
if (observerToNodesMap.has(this)) { | ||
const observedNodes = observerToNodesMap.get(this)!; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason we use ArrayPush.call()
but not WeakMapHas.call()
? I.e. we cache the Array prototype functions but not the WeakMap ones?
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Benchmark resultsBase commit: lwc-engine-benchmark
|
* fix: mutationobserver memory leak - use weakmap for bookkeeping Use a WeakMap to store all nodes watched by an observer. On disconnect(), clean up references to the observer on all the nodes. Limitation: If MutationObservers are not disconnected, this could lead to memory leak of nodes. * fix: comments fixes * fix: address PR comments
@ravijayaramappa Is this the case? I thought that if the MutationObserver (the key) has no more references, then both the key and the value (the array of nodes) should be removed from the WeakMap? |
@nolanlawson Each observed node has a hard reference to the mutation observer[the |
… (#1426) * fix: mutationobserver memory leak - use weakmap for bookkeeping Use a WeakMap to store all nodes watched by an observer. On disconnect(), clean up references to the observer on all the nodes. Limitation: If MutationObservers are not disconnected, this could lead to memory leak of nodes. * fix: comments fixes * fix: address PR comments
Details
Use a WeakMap to store all nodes watched by an observer. On disconnect(), clean up references to the observer on all the nodes.
Limitation: If MutationObservers are not disconnected, this could lead to memory leak of nodes.
Does this PR introduce breaking changes?
No, it does not introduce breaking changes.
If yes, please describe the impact and migration path for existing applications.
The PR fulfills these requirements: