Skip to content
This repository has been archived by the owner on Nov 30, 2018. It is now read-only.

Endless loop in watch #1483

Closed
thezuck opened this issue Sep 7, 2015 · 11 comments
Closed

Endless loop in watch #1483

thezuck opened this issue Sep 7, 2015 · 11 comments
Assignees
Labels
Milestone

Comments

@thezuck
Copy link

thezuck commented Sep 7, 2015

There is an infinite loop caused by a deep watch loop, as can be seen in the animated gif below, we start with a simple object which is watched by MarkerChildModel, through a call to
return _this.handleModelChanges(newValue, oldValue);
this does deep watching using getChanges method

ModelKey.prototype.getChanges = function(now, prev, whitelistedProps) {

c = this.getChanges(now[prop], (prev ? prev[prop] : null));

as can be seen in the animated gif, all properties in the object are watched, including a property called icon which has a field called scaledSize, which looks like so:
X {width: 36, height: 36, L: "px", N: "px"}
however, this object has a prototype which is has a toString function which in turn has a method called disable, which seems to references itself.
Since the getchanges method recursively dives in, it never stops until an exception is fired, repeatedly watching disable. This X type object is a google.maps.Size object, so it's not something I can control, and is probably a commonly used property.
There is no way I found to limit how deep the watch should go, and it doesn't limit itself by default.

The initial model which we create and add to the models array used by gmap markers is:

{
                _id: place._id,
                latitude: place.lat,
                longitude: place.lon,
                options: {
                    icon: {
                        url: iconUrl,
                        size: iconSmallSizeObj
                    }
                },
                titleContent: place.companyName
}

where the issue occurs for icon's property size, because iconSmallSizeObj is defined as
new google.maps.Size(32, 32)
so I assume that to reproduce you need to add this type of object to the model.

Final word: this does not happen immediately when the model is added, there is some race condition or some other unexplained process which causes this to happen, can't figure out the exact route to make this happen but it happens very frequently.

infiniteloop

@thezuck
Copy link
Author

thezuck commented Sep 7, 2015

Here's the resulting exception in case it helps

screen shot 2015-09-07 at 16 45 09

@thezuck
Copy link
Author

thezuck commented Sep 7, 2015

Happened on 2.1.5, reproduced on 2.2.0

@nmccready
Copy link
Contributor

Can you make a plnkr valid example?

@nmccready
Copy link
Contributor

Also if you continue posting more code please use github conventions by using backticks.

@nmccready
Copy link
Contributor

Well adding an attribute specifically to modify watch depth would help and it is something that should be done.

@thezuck
Copy link
Author

thezuck commented Sep 8, 2015

a plnkr is a valid requirement, however, I think that iterating over own properties (by filtering using hasOwnProperty) instead of all properties makes sense as an optimization, and adding watch depth limit also makes sense, regardless of whether or not you can reproduce this bug.

@nmccready
Copy link
Contributor

Yes hasOwnProperty is wise I can add that.

@nmccready nmccready modified the milestones: 2.1.7, 2.2.1 Sep 8, 2015
@thezuck
Copy link
Author

thezuck commented Sep 10, 2015

👍

@nmccready nmccready modified the milestones: 2.2.1, 2.2.2 Sep 11, 2015
@thezuck
Copy link
Author

thezuck commented Sep 11, 2015

amazing job on this one by the way, we are using it for my startup (mapme) and very happy with it!

@nmccready
Copy link
Contributor

cool I have plans down the pipe to make the library faster. Basically I will (probably some people out there who wont like this) add another dependency. There is iterator code in angular-leaflet-directive that is proven to be faster that using Array.forEach and lodash's iterators. So I am thinking of an angular-iterator library. But this is still up in the air. If people want other options I am open to it but leafletIterators works pretty well.

http://jsperf.com/iterators/3

https://github.com/tombatossals/angular-leaflet-directive/blob/master/src/services/leafletIterators.js

Also the _async code could be possible moved into there as well.

@nmccready nmccready self-assigned this Sep 11, 2015
nmccready added a commit to nmccready/angular-google-maps that referenced this issue Sep 15, 2015
@nmccready nmccready mentioned this issue Sep 15, 2015
@nmccready
Copy link
Contributor

see PR will close on merge

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

No branches or pull requests

2 participants