Skip to content
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 shared instance fields #79

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

betalb
Copy link

@betalb betalb commented Nov 20, 2018

This PR makes pretty big changes

Some of them will have performance impact, like binding every time when we call getter on super (see comment in code)

Both: setter and getter of original descriptor may now create instance-bound property: though actual binding will happen on real get (callGetter argument of reDefineProperty)

@@ -68,6 +68,36 @@ describe('autobind method decorator: @boundMethod', () => {
assert(value === 50);
});

test('should not share instance methods between instances', () => {
const a = new A('foo');
const b = new A('bar');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test seems too much. Why can't we just change a method on a and see if that method is the same on b?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we also need a test:
Once instance method is changed, it shouldn't be bound.

Copy link
Author

@betalb betalb Nov 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the first point: don't think that this will work, methods won't be equal, they will be bound instances of the same underlying function. So theoretically we need to check underlying method. Though I think that test case may be made cleaner. And just realised that

const aOriginalGetValue = a.getValue;
a.getValue = function () {
  return 'foo' + '-' + aOriginalGetValue();
};

And

a.getValue = function () {
  return 'fake-foo';
};

Will hit different code paths, will need to cover this too

For the second point: this one is interesting. Are you saing that if we run setter with new function it shouldn't be auto-bound? If yes, this is not how existing code works (before my change), so I've mimicked this behaviour

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the second point: this one is interesting. Are you saing that if we run setter with new function it shouldn't be auto-bound?

What do you think? I feel like autobind is bound on the method not the property. Let's also take performance into consideration.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, we should not continue auto-binding if somebody changes method, or more interesting - plays with prototype chain of parents

But this will be breaking change and should be done as separate PR

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But this will be breaking change and should be done as separate PR

Since this change is quite big I'd release a major for this anyways...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should not continue auto-binding if somebody changes method, or more interesting - plays with prototype chain of parents

Will this improve the performance?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In certain use-cases, most likely, but this needs to be proved

@stevemao
Copy link
Collaborator

Thanks for the PR!

@betalb
Copy link
Author

betalb commented Nov 21, 2018

Updated PR, simplified tests

Removed code that auto-binds super method. Correct solution seems to be more complicated and tends to be over-engineered.

Will live my thoughts on this here:

  1. Caching is not straightforward, because method is defined on prototype chain and we should not shadow instance level method, which may potentially happen, i.e. we have class hierarchy A -> B -> C all having method with name getValue annotated with @boundMethod, if it is called on C instance how should we cache bound methods on A & B, how to construct cache key? Options may be some integer counter, or depth of parent in chain
  2. Changing method on parent’s prototype should or should not work? Should we reset cached bound version? (I think that yes, we should)

@stevemao
Copy link
Collaborator

  • Caching is not straightforward, because method is defined on prototype chain and we should not shadow instance level method, which may potentially happen, i.e. we have class hierarchy A -> B -> C all having method with name getValue annotated with @boundMethod, if it is called on C instance how should we cache bound methods on A & B, how to construct cache key? Options may be some integer counter, or depth of parent in chain
  • Changing method on parent’s prototype should or should not work? Should we reset cached bound version? (I think that yes, we should)

What about the performance? How hard is it to implement?

@betalb
Copy link
Author

betalb commented Nov 23, 2018

This will impact performance for classes that have boundMethods on parents

@stevemao

This comment has been minimized.

@stevemao
Copy link
Collaborator

Hi @betalb , could you please add the caveats of new behaviours in README? And then we'll merge this :)

@betalb
Copy link
Author

betalb commented Dec 20, 2018

Sorry, was caught with other things, will try to finish everything by the end of the year

@mr-pinzhang
Copy link

Thanks for your works, when will this be merged?

@stevemao
Copy link
Collaborator

As long as docs is added I'll merge this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants