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

Fixed property mapping to be inheritance-based #121

Conversation

cmolodo
Copy link
Contributor

@cmolodo cmolodo commented Feb 20, 2020

Modified getClassPropertyMappingOptions() to step through the prototpe chain to find the appropriate property mapping rather than just searching by property name. That way properties with the same name on different classes won't conflict.

Also added new test classes and updated unit/integration tests.

…pe chain to find the appropriate property mapping rather than just searching by property name. That way properties with the same name on different classes won't conflict. Added new test classes and updated unit/integration tests.
…is correctly handled. (Tests already checked that unmapped duplicate property is skipped.)
/**
* Class which has a property with the same name as Cat. Used to test handling
* of prototype-based property mapping search. Property has the same name, but
* an incompatible type, and is initialized (so it's present) but purposely left
Copy link
Collaborator

@tobiasschweizer tobiasschweizer Feb 24, 2020

Choose a reason for hiding this comment

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

Property has the same name, but an incompatible type

That's I exactly how I experienced the problem: I had two sibling classes that had properties of the same name, but in one case the property was optional and in the other one it was required.

If the properties' types are compatible, the behavior is still wrong (definition is possibly taken from the wrong class), but it doesn't have any effect.

Copy link
Collaborator

Choose a reason for hiding this comment

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

So I think your test ensures that the logic works correctly now.

/* Find mapping by iterating up the prototype chain to find a matching mapping, rather than
* just searching by property name. */
let prototype = Object.getPrototypeOf(instance);
while (prototype != null) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Are you sure that your loop always terminates? Is there no such thing as a reference to self?

Following the docs, it should be fine:

The prototype of the given object. If there are no inherited properties, null is returned.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As long as the object is constructed normally, it should be fine. You're right though, it's of course possible that someone has manually set the prototype to some self-referential or circular link. I'll modify it to check for self as well.

Copy link
Contributor Author

@cmolodo cmolodo Feb 24, 2020

Choose a reason for hiding this comment

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

Actually, something I've just learned is that you can't in fact create circular prototype references. That is, you can, but it will cause an error: TypeError: Cyclic __proto__ value. So we don't need to check for self - the chain will eventually always terminate.

Copy link
Collaborator

Choose a reason for hiding this comment

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

That's good to know! Otherwise this would be a quite frustrating user experience ;-)

/* Find mapping by iterating up the prototype chain to find a matching mapping, rather than
* just searching by property name. */
let prototype = Object.getPrototypeOf(instance);
while (prototype != null) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Probably you could write while (prototype !== null) so that it doesn't do type conversions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To be honest, I did that because I was lazy and wanted to catch undefined as well as null. But it's probably safer to check for both explicitly, I'll fix that as well. Thanks!

@tobiasschweizer
Copy link
Collaborator

Have you considered setting up github-ci tests? It is fairly straight-forward.
See https://help.github.com/en/actions/language-and-framework-guides/using-nodejs-with-github-actions

@cmolodo
Copy link
Contributor Author

cmolodo commented Feb 24, 2020

The github-ci automated testing definitely sounds useful, but I wouldn't want to add that in this pull request. (Also, I had to modify my karma.conf.js to get the tests to run in my IDE, since it won't allow PhantomJS anymore.) If @andreas-aeschlimann is interested, maybe you or I could create a new pull request to add it?

…tly check for null/undefined separately, and added note on circular prototype chain error. Also fixed formatting in test file.
@tobiasschweizer
Copy link
Collaborator

I would be glad to help. I already did the setup in another project and it works well.

@andreas-aeschlimann
Copy link
Member

Thank you @cmolodo and @tobiasschweizer for digging deeper in this issue.

It is correct that the approach to handle class inheritance was not well working in some special cases. The current approach just searches for any property with the same name instead of properly going up the inheritance tree.

The approach of @cmolodo to climb up the inheritance tree is elegant and of course the correct way to do it.

I will merge this PR now.

@andreas-aeschlimann andreas-aeschlimann merged commit c2e55f7 into appvision-gmbh:master Mar 1, 2020
@cmolodo cmolodo deleted the develop/inheritance-property-mapping branch March 3, 2020 16:02
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