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

Scope#$watchCollection oldValue == newValue fix #6736

Closed
wants to merge 2 commits into from

Conversation

IgorMinar
Copy link
Contributor

No description provided.

@mary-poppins
Copy link

Thanks for the PR! Please check the items below to help us merge this faster. See the contributing docs for more information.

  • Uses the issue template (#6736)

If you need to make changes to your pull request, you can update the commit with git commit --amend.
Then, update the pull request with git push -f.

Thanks again for your help!

} else { // if object
veryOldValue = {};
for (var key in newValue) {
if (hasOwnProperty.call(newValue, key)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why not use shallowCopy()? do we need to hang onto $$hashKey for the veryOldValue?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I looked at shallowCopy, but since it doesn't support arrays I didn't use it.

I haven't thought much about $-prefixed properties. I'm not sure why they should be excluded in this case. Do you have some opinions on that?

Copy link
Contributor

Choose a reason for hiding this comment

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

Not really, I was just thinking it would be (marginally) less code. But it's true that it doesn't support arrays (but arrays are using a different codepath anyways), and not caring about the '$' should improve perf by some negligible amount

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think it's worth it. besides the $$hashkey might actually be useful for people trying to figure out what changed.

@IgorMinar
Copy link
Contributor Author

@Narretz yes, I'll update the docs

@IgorMinar
Copy link
Contributor Author

I think this is good to be merged (after squashing). any objections?

@caitp
Copy link
Contributor

caitp commented Mar 18, 2014

lgtm, basically

@Narretz
Copy link
Contributor

Narretz commented Mar 18, 2014

Yay!

IgorMinar added a commit to IgorMinar/angular.js that referenced this pull request Mar 18, 2014
Originally we destroyed the oldValue by incrementaly copying over portions of the newValue
into the oldValue during dirty-checking, this resulted in oldValue to be equal to newValue
by the time we called the watchCollection listener.

The fix creates a copy of the newValue each time a change is detected and then uses that
copy *the next time* a change is detected.

To make `$watchCollection` behave the same way as `$watch`, during the first iteration
the listener is called with newValue and oldValue being identical.

Since many of the corner-cases are already covered by existing tests, I refactored the
test logging to include oldValue and made the tests more readable.

Closes angular#2621
Closes angular#5661
Closes angular#5688
Closes angular#6736
`log.empty()` is the same as `log.reset()`, except thati `empty()`  also returns the current array with messages

instead of:

```
// do work
expect(log).toEqual(['bar']);
log.reset();
```

do:

```
// do work
expect(log.empty()).toEqual(['bar']);
```
Originally we destroyed the oldValue by incrementaly copying over portions of the newValue
into the oldValue during dirty-checking, this resulted in oldValue to be equal to newValue
by the time we called the watchCollection listener.

The fix creates a copy of the newValue each time a change is detected and then uses that
copy *the next time* a change is detected.

To make `$watchCollection` behave the same way as `$watch`, during the first iteration
the listener is called with newValue and oldValue being identical.

Since many of the corner-cases are already covered by existing tests, I refactored the
test logging to include oldValue and made the tests more readable.

Closes angular#2621
Closes angular#5661
Closes angular#5688
Closes angular#6736
@IgorMinar IgorMinar closed this in 78057a9 Mar 18, 2014
IgorMinar added a commit that referenced this pull request Mar 18, 2014
Originally we destroyed the oldValue by incrementaly copying over portions of the newValue
into the oldValue during dirty-checking, this resulted in oldValue to be equal to newValue
by the time we called the watchCollection listener.

The fix creates a copy of the newValue each time a change is detected and then uses that
copy *the next time* a change is detected.

To make `$watchCollection` behave the same way as `$watch`, during the first iteration
the listener is called with newValue and oldValue being identical.

Since many of the corner-cases are already covered by existing tests, I refactored the
test logging to include oldValue and made the tests more readable.

Closes #2621
Closes #5661
Closes #5688
Closes #6736
@johnsoftek
Copy link

This version, 78057a9, does fix the parameter problem, but it is less efficient than #2621 because it always copies newvalue during dirty checking, even when the value has not changed.

@caitp
Copy link
Contributor

caitp commented Mar 19, 2014

johnsoftek: even with the extra write overhead, algorithmically it would be more complicated to do a set of reads and then copy if a change is detected.

This might be improved a little bit, but how about we wait and see how necessary it is? That's just my opinion, though.

@johnsoftek
Copy link

Caitlin,

Well, I had a pull request that did just that, but it seems it was not
acceptable.

John M

On 19 March 2014 10:32, Caitlin Potter notifications@github.com wrote:

johnsoftek: even with the extra write overhead, algorithmically it would
be more complicated to do a set of reads and then copy if a change is
detected.

This might be improved a little bit, but how about we wait and see how
necessary it is? That's just my opinion, though.

Reply to this email directly or view it on GitHubhttps://github.com//pull/6736#issuecomment-38005891
.

@IgorMinar
Copy link
Contributor Author

@johnsoftek your change was too complex and didn't allow the optimization for the case when old value is not needed. we need the optimization to keep ngRepeat fast.

@johnsoftek
Copy link

Igor,

No idea why you think my change complex. And it would be trivial to
incorporate the "old value required" check. Also, if you really are
concerned with performance, my change copies values only if a change is
detected.

On 19 March 2014 13:37, Igor Minar notifications@github.com wrote:

@johnsoftek https://github.com/johnsoftek your change was too complex
and didn't allow the optimization for the case when old value is not
needed. we need the optimization to keep ngRepeat fast.

Reply to this email directly or view it on GitHubhttps://github.com//pull/6736#issuecomment-38014742
.

@johnsoftek
Copy link

Igor,

No idea why you think my change complex. And it would be trivial to
incorporate the "old value required" check. Also, if you really are
concerned with performance, my change copies values only if a change is
detected..

Anyway, your decision.

John M

On 19 March 2014 13:37, Igor Minar notifications@github.com wrote:

@johnsoftek https://github.com/johnsoftek your change was too complex
and didn't allow the optimization for the case when old value is not
needed. we need the optimization to keep ngRepeat fast.

Reply to this email directly or view it on GitHubhttps://github.com//pull/6736#issuecomment-38014742
.

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

Successfully merging this pull request may close these issues.

5 participants