-
-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Don't use object pool for initialOldData, and properly recycle tempObject #5459
Conversation
src/core/component.js
Outdated
@@ -203,6 +204,7 @@ Component.prototype = { | |||
// If value is an object, copy it to our pooled newAttrValue object to use to update | |||
// the attrValue. | |||
tempObject = this.objectPool.use(); | |||
utils.objectPool.clearObject(tempObject); |
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.
So I understand. use
function should already calls clearObject. Is not this redundant?
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.
Oops, seems when cleaning up the PR I got clearObject
and removeUnusedKeys
mixed up in this place. The object pool does indeed "clear" the object, but the keys remains. Looking at the code again in more detail, it is actually safe here to have superfluous keys on tempObject
in the subsequent utils.extend
and extendProperties
calls.
@@ -324,9 +326,8 @@ Component.prototype = { | |||
|
|||
// For oldData, pass empty object to multiple-prop schemas or object single-prop schema. | |||
// Pass undefined to rest of types. | |||
initialOldData = this.isObjectBased ? this.objectPool.use() : undefined; | |||
initialOldData = this.isObjectBased ? emptyInitialOldData : undefined; |
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.
Same here. My understanding is that the use
function calls clearObject
. You mention
The pool however makes no guarantees about the state of the object. It might very well not be an empty object
What Am I missing?
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.
The problem is that clearObject
only sets the keys to undefined. As a result the initialOldData
can have zero or more keys present. This means that any update code doing things like Object.keys(oldData)
or "someProp" in oldData
ends up getting incorrect results.
Before there was enough leakage that you'd generally always get a fresh empty object from the pool.
4308889
to
a565ab3
Compare
Thanks! |
Description:
A temporary object was never released to the objectPool, causing a leak. After fixing this leak, some unit tests regressed. It turns out that the
initialOldData
provided to a component'supdate(oldData)
is also leased from this pool. The pool however makes no guarantees about the state of the object. It might very well not be an empty object. (And due to the various leaks, it likely was an empty object)This PR correctly clears and returns the
tempObject
to the pool and uses a constant frozen empty object for theinitialOldData
. This is a slight change in behaviour in case users mutate this object, but that was never correct and will now give an error.Changes proposed:
tempObject
in Component update logic (updateCachedAttrValue
)initialOldData
for a Component's firstupdate
call