This repository has been archived by the owner on Sep 29, 2020. It is now read-only.
Fixes method-level autobind and decorate combination #87
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I noticed some unexpected behavior when using
autobind
anddecorate
on the same method.In this example,
autobind
works as expected, that is to sayHowever,
decorate
was reapplying the decorator on every invocation. In the case of memoization, every invocation created a new function with a new cache so nothing was ever memoized properly.I added a few tests and fixed this problem by redefining the property descriptor after the first invocation. Now
getFoo()
calls the memoized function which if not cached calls the bound function.I might be missing something about why it was implemented differently before, but this approach jived with the existing tests.
Notes
I am not sure whether this problem affects anything other than
decorate
; unfortunately I don't have enough time or interest to dig further.Class-level autobinding
Class-level autobinding does not work with
decorate
after this change nor did it work beforehand. The behavior is correct from the viewpoint of the decorator, that is to say it allows proper memoization. However, the autobinding does not work - calling the methods from a different context fails. It seems there would be some work needed there to handle the getters generated by other decorators.To put that in terms of code, of the following test cases where
FooAutobound
is an@autobind
class, the second test succeeds but the first fails.Decorating getters
I took a quick look to see if this approach got us any closer to allowing getters to be decorated as requested in #65. Unfortunately it does not.
Potential solution?
Both of these seem to be particularly difficult due to the need to distinguish
core-decorators
getters from user space getters.core-decorators
getters return a function while user space getters return any value.originalGet.call(this)
gives a function if called on acore-decorators
getter but you would not want to call that on a getter not created bycore-decorators
.One approach that I quickly put together was to add a Symbol key to the descriptor to identify that a getter was generated by
core-decorators
. This allowsdescriptor[isCoreDecorator] ? originalGet.call(this) : originalGet
, passing through the normal getter rather than calling it.Applied within
decorate
this allows decoration of getters. Applied withinautobind
it allows getters generated bycore-decorators
to be distinguished and autobound. Maybe that distinction is not necessary forautobind
but you would really have to go out of your way to use a getter in an unexpected context.