Shopify/batman — pull request #729 by jamesmacaulay (2013-05-23 15:16:52+00:00)
Title: Clear sources and handlers from unobserved properties when sources change

@hornairs and @matthelm please review.

TL;DR: this fixes #646.

It happens that `observeAndFire` [assumes that the cached @value is correct and up-to-date](https://github.com/Shopify/batman/blob/467cd95f2987b700bf5aabaf506e129dc438895e/src/observable/property.coffee#L198) after calling `observe`. Most of the time this is the case, but it is possible to have a property in a state where its `@value` is stale even after calling `observe`.

As @TheJeff correctly pointed out, part of the problem had to do with avoiding an unnecessary `getValue()` when `@sources` [was already populated](https://github.com/Shopify/batman/blob/467cd95f2987b700bf5aabaf506e129dc438895e/src/observable/property.coffee#L201).

The other part of the problem is that when one of an _unobserved_ property's sources is changed, [the only thing that happens is that we mark the property as "uncached"](https://github.com/Shopify/batman/blob/467cd95f2987b700bf5aabaf506e129dc438895e/src/observable/property.coffee#L166-L167). This is enough to keep subsequent `getValue()`s fresh, but the (possibly stale) `@sources` still remain. Even if the `@sources` were still correct, the `@value` would be stale and `observeAndFire` would use it anyway. If the change event from `observeAndFire` happened to be the last thing that updated a view binding, then you'd see stale data.

This patch adds a call to `@_removeHandlers()` when an unobserved property's source changes. This deletes the property's `@sources` array and has the added benefit of cleaning up unneeded and possibly invalid source handlers. When `observeAndFire` is then called, the necessary `@getValue()` will occur because the `@sources` aren't there.