Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Bug: angular.equals not symmetric given objects with non-enumerable properties #14853

Closed
qc00 opened this issue Jul 1, 2016 · 6 comments
Closed

Comments

@qc00
Copy link

qc00 commented Jul 1, 2016

POC:

let o = {}; Object.defineProperty(o, 'a', {value:1});
angular.equals(o , {}); // true
angular.equals({}, o); // true
angular.equals(o, {a: 1}); // false
angular.equals({a: 1}, o); // true

What the results of these should be are debatable but the last two should be at least symmetric. (Presumbly, both should return false to retain transitivity.)

The use case of non-enumerable is I want to ignore certain deep/cyclical/non-important part of the tree from comparison when using Scope.$watch(..., ..., true).

@gkalpak
Copy link
Member

gkalpak commented Jul 1, 2016

(As mentioned several times) the angular.xyz helpers are not supposed to be general purpose utility functions that cover all use cases. In this case, the recommendation is to use a specialized library.

Is there some part of Angular that is using angular.equals that is causing you problems?

@qc00
Copy link
Author

qc00 commented Jul 1, 2016

The use case of non-enumerable is I want to ignore certain deep/cyclical/non-important part of the tree from comparison when using Scope.$watch(..., ..., true).

I am not sure this feature can still be trusted if the underlying function behaves incorrectly in this use case.

@gkalpak
Copy link
Member

gkalpak commented Jul 1, 2016

So, are you trying to deep-watch an expression which sometimes points to an object with enumerable properties and sometimes to an object with non-enumerable? It sounds confusing.
Can you you post an example of what you are trying to do - e.g. a code sample that showcases the unexpected behavior?

@qc00
Copy link
Author

qc00 commented Jul 1, 2016

There's no expected behaviour in the current implementation, but as the handling of non-enumerable properties are not guaranteed by the documentation of angular.copy, the adverse condition can arise in a future version.

Specifically, angular.copy's documentation says:

... and then all elements/properties from the source are copied to it.

In reality, non-enumerable properties are not copied right now.

If the implementation were to change to copy them, then the copies may not compare correctly with the original.

@wesleycho
Copy link
Contributor

Currently the way to ignore certain parties of a deep tree is to pass a function that returns the expression to be watched, i.e.

$scope.$watch(() => $scope.foo.bar.baz, () => { ... });

I would be wary about changing Angular's core, as this would be a breaking change with potentially significant effects on some users' apps. IMO, this is a non-standard way to try to eke out perf benefits when there are already existing tricks.

@gkalpak
Copy link
Member

gkalpak commented Jul 4, 2016

@billccn, this sounds like a documentation issue. The behavior of copy is very specific, but the documentation could be lacking.

If it were to change in the future it would be a breaking change. So, this would only happen in a minor version update, be properly documented and would be expected to break things (that's what breaking changes do 😃).

But I don't think it is likely to ever happen.

If anyone is interested in updating the docs though, they would be more than welcome! 😃

@gkalpak gkalpak modified the milestones: Backlog, Purgatory Jul 4, 2016
@gkalpak gkalpak closed this as completed in 14519f8 Jul 4, 2016
gkalpak added a commit that referenced this issue Jul 4, 2016
This also improves the example a bit:
- better code formatting
- initialization of `form` to an empty object
- avoid using `email`, which doesn't get coppied when invalid (and might confuse users)

Fixes #14853
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants