autobind-decorator
autobind-decorator copied to clipboard
If bound methods or fields are re-assigned, they become shared between instances
If bound methods or fields are re-assigned, they become shared between instances
Found this issue while trying to debounce bound method
Below test will fail
class A {
@boundMethod
bound() {}
}
const a = new A();
const b = new A();
a.bound = {
foo: 'bar'
};
assert.notEqual(a.bound, b.bound);
Committed failing test cases and fix for @boundMethod
decorator
Does it happen if you use @autobind
(the old default exported module)?
Yes, latest version before exporting of boundMethod and boundClass separately had this issue Looks like previous commit introduced it https://github.com/andreypopp/autobind-decorator/commit/98968eea6aadce8234aa95e6560239e9e11be146
Before this commit new function will just override bound function, but it won't be re-bound later on. Above comit tried to overcome this by deleting original descriptor and letting binding to happen again, but this time binding will be done on function that might be instance-specific, because we are working with instance, not prototype in this case.
In my case I was taking already bound function and debounced it
@betalb Thanks for reporting this. PR welcome :)
Created PR, but would like to revise it further, don't like appoach for super.method
handling
Any movement on this?
@L-Yeiser see discussions in the PR
I'd like to add, that there is also a possibility of memory leak.
Minimal code to illustrate:
class Base extends React.Component {
@boundMethod
method() {}
}
class Child extends Base {
method = debounce(super.method, 100);
}
- When constructing
new Child()
, the assignmentmethod = debounce(super.method, 100)
is executed - The assignment
method = debounce(super.method, 100)
will get boundmethod
, then debounce it, and finally will call setter - The setter stores debounced bound
method
for all future instances. - When constructing
new Child()
second time, the codemethod = debounce(super.method, 100)
will receive bound debounced boundmethod
, debounce it and store again. - Each new instance will add its own level of
bind
+debounce
and store the result for future instances.
bind
and debounce
consume memory themselves, but they also retain in memory their closures with all accessible variables.
Reproduction: https://codesandbox.io/s/autobind-debounce-memory-leak-jezks?file=/src/Child.js
What it looks like in DevTools:
So, can you fix the bug and the memory leak in two years?