-
Notifications
You must be signed in to change notification settings - Fork 27.4k
fix(equals): handle objects with circular references #11653
Conversation
Make `angular.equals` handle circular references. Closes angular#11372
|
||
function equalsCacheContains(cache, o1, o2) { | ||
for (var i = 0, ii = cache.length; i < ii; i += 2) { | ||
if (cache[i] === o1 && cache[i + 1] === o2) return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be faster (not tested):
var index = 0, length = cache.length;
while (index < length) {
index = cache.indexOf(o1, index);
if (index == -1) break;
if (cache[index + 1] === o2) return true;
}
return false;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not safe as is (e.g. index
has to be an even number).
@gkalpak If we were talking about only making This PR is just to open the discussion if this is the approach to fix #11372 |
#11372 has been fixed (as long as you don't use If it turns out we do want to support |
A simple option would be to use `cache` only if present and send it in this
specific case from ngOptions
|
This will effect performance, similar to Using an ES6 |
@jbedard I am not happy with this solution. This may have performance implications just as with |
Yes it will have noticeable performance implications. I think you're right that it would have to be optional just to avoid effecting performance of existing calls (like in the digest loop!). What don't you like about the |
It would make Angular execution less predictable. The reason being that if the user uses a library that provides a polyfill (say they use babel), then Angular would use it if this is defined before Angular. This is, Angular behavior would depend on the order libraries are loaded. |
I thought that extra uncertainty might be worth it since most browsers (all the latest versions) have |
@jbedard if you are ok, I think that a new issue would be a better place to discuss about a potential With the entire discussion, I am leaning towards wont fix, but would like to know what others think |
(Shim considerations aside) I would be OK with an "opt-in" mode supporting circular references (e.g. as @lgalfaso suggested, only when explicitly passing a cache). And using this mode for But it would be interesting to hear what others think. |
@petebacondarwin WDYT?
|
I am nervous about supporting cyclic equality checks. I wonder if the real fix is to use |
@petebacondarwin you are not the only one unease about this. BTW, I would be ok in leaving this as a known issue for 1.4.0 |
How about this instead: #11743 |
I think that my original unit test was too strong and not real life |
I think that #11743 is a lot cleaner, I just do not know if this would break other use cases and expectations. It somehow feels like we are moving the issue from one place to another (that, too would imply a known issue in the release notes). Note: I see #11743 as a POC that would also need to change the comments as what we are doing and what we claim we are doing, and what the test claim to check and what it test, do not match. |
#11743 is more inline with what happens in I think if we made this very clear, i.e. that we only watch the file level of the model and that people cannot change levels below and expect the model to update accordingly, we should be fine. |
@petebacondarwin SGTM, but this needs to be documented. Will close this PR in favor of #11743 |
I am working to improve that PR now |
Using a deep watch caused Angular to enter an infinite recursion in the case that the model contains a circular reference. Using `$watchCollection` instead prevents this from happening. This change means that we will not re-render the directive when there is a change below the first level of properties on the model object. Making such a change is a strange corner case that is unlikely to occur in practice and the directive was not documented as supporting such a situation. The documentation has been updated to clarify this behaviour. Closes angular#11372 Closes angular#11653
Using a deep watch caused Angular to enter an infinite recursion in the case that the model contains a circular reference. Using `$watchCollection` instead prevents this from happening. This change means that we will not re-render the directive when there is a change below the first level of properties on the model object. Making such a change is a strange corner case that is unlikely to occur in practice and the directive is not designed to support such a situation. The documentation has been updated to clarify this behaviour. This is not a breaking change since in 1.3.x this scenario did not work at all. Compare 1.3.15: http://plnkr.co/edit/zsgnhflQ3M1ClUSrsne0?p=preview to snapshot: http://plnkr.co/edit/hI48vBc0GscyYTYucJ0U?p=preview Closes angular#11372 Closes angular#11653 Closes angular#11743
Using a deep watch caused Angular to enter an infinite recursion in the case that the model contains a circular reference. Using `$watchCollection` instead prevents this from happening. This change means that we will not re-render the directive when there is a change below the first level of properties on the model object. Making such a change is a strange corner case that is unlikely to occur in practice and the directive is not designed to support such a situation. The documentation has been updated to clarify this behaviour. This is not a breaking change since in 1.3.x this scenario did not work at all. Compare 1.3.15: http://plnkr.co/edit/zsgnhflQ3M1ClUSrsne0?p=preview to snapshot: http://plnkr.co/edit/hI48vBc0GscyYTYucJ0U?p=preview Closes #11372 Closes #11653 Closes #11743
Using a deep watch caused Angular to enter an infinite recursion in the case that the model contains a circular reference. Using `$watchCollection` instead prevents this from happening. This change means that we will not re-render the directive when there is a change below the first level of properties on the model object. Making such a change is a strange corner case that is unlikely to occur in practice and the directive is not designed to support such a situation. The documentation has been updated to clarify this behaviour. This is not a breaking change since in 1.3.x this scenario did not work at all. Compare 1.3.15: http://plnkr.co/edit/zsgnhflQ3M1ClUSrsne0?p=preview to snapshot: http://plnkr.co/edit/hI48vBc0GscyYTYucJ0U?p=preview Closes angular#11372 Closes angular#11653 Closes angular#11743
Make
angular.equals
handle circular references.Closes #11372