fix(scope): rerun $digest from root, rather then per scope.

This commit is contained in:
Misko Hevery 2011-08-11 15:02:08 -07:00
parent 8bc7beacd8
commit 1c9fc1e1de
2 changed files with 16 additions and 6 deletions

View file

@ -389,14 +389,15 @@ Scope.prototype = {
watch, value, last,
watchers = this.$$watchers,
length, count = 0,
iterationCount, ttl = 100;
dirtyCount, ttl = 100,
recheck = !this.$parent || !this.$parent.$$phase;
if (this.$$phase) {
throw Error(this.$$phase + ' already in progress');
}
this.$$phase = '$digest';
do {
iterationCount = 0;
dirtyCount = 0;
if (watchers) {
// process our watches
length = watchers.length;
@ -406,7 +407,7 @@ Scope.prototype = {
// Most common watches are on primitives, in which case we can short
// circuit it with === operator, only when === fails do we use .equals
if ((value = watch.get(this)) !== (last = watch.last) && !equals(value, last)) {
iterationCount++;
dirtyCount++;
watch.fn(this, watch.last = copy(value), last);
}
} catch (e) {
@ -416,14 +417,14 @@ Scope.prototype = {
}
child = this.$$childHead;
while(child) {
iterationCount += child.$digest();
dirtyCount += child.$digest();
child = child.$$nextSibling;
}
count += iterationCount;
count += dirtyCount;
if(!(ttl--)) {
throw Error('100 $digest() iterations reached. Aborting!');
}
} while (iterationCount);
} while (recheck && dirtyCount);
this.$$phase = null;
return count;
},

View file

@ -178,6 +178,15 @@ describe('Scope', function(){
expect(log).toEqual('abc');
});
it('should repeat watch cycle from the root elemnt', function(){
var log = '';
var child = root.$new();
root.$watch(function(){ log += 'a'; });
child.$watch(function(){ log += 'b'; });
root.$digest();
expect(log).toEqual('abab');
});
it('should prevent infinite recursion', function(){
root.$watch('a', function(self, v){self.b++;});