mirror of
https://github.com/Hopiu/angular.js.git
synced 2026-03-17 07:40:22 +00:00
feat(scope): better logging of infinite digest error
Feedback team has often problems debugging inifinite digest errors, this change should reveal info about what watchers are causing the infinite loop
This commit is contained in:
parent
615841a5d3
commit
ef875ad0cf
2 changed files with 38 additions and 7 deletions
17
src/Scope.js
17
src/Scope.js
|
|
@ -260,7 +260,8 @@ Scope.prototype = {
|
|||
watcher = {
|
||||
fn: listenFn,
|
||||
last: Number.NaN, // NaN !== NaN. We used this to force $watch to fire on first run.
|
||||
get: get
|
||||
get: get,
|
||||
exp: watchExp
|
||||
};
|
||||
|
||||
if (!array) {
|
||||
|
|
@ -325,7 +326,8 @@ Scope.prototype = {
|
|||
asyncQueue,
|
||||
length,
|
||||
dirty, ttl = 100,
|
||||
next, current, target = this;
|
||||
next, current, target = this,
|
||||
watchLog = [];
|
||||
|
||||
if (target.$$phase) {
|
||||
throw Error(target.$$phase + ' already in progress');
|
||||
|
|
@ -356,6 +358,14 @@ Scope.prototype = {
|
|||
dirty = true;
|
||||
watch.last = copy(value);
|
||||
watch.fn(current, value, last);
|
||||
if (ttl < 5) {
|
||||
if (!watchLog[4-ttl]) watchLog[4-ttl] = [];
|
||||
if (isFunction(watch.exp)) {
|
||||
watchLog[4-ttl].push('fn: ' + (watch.exp.name || watch.exp.toString()));
|
||||
} else {
|
||||
watchLog[4-ttl].push(watch.exp);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
current.$service('$exceptionHandler')(e);
|
||||
|
|
@ -376,7 +386,8 @@ Scope.prototype = {
|
|||
} while ((current = next));
|
||||
|
||||
if(!(ttl--)) {
|
||||
throw Error('100 $digest() iterations reached. Aborting!');
|
||||
throw Error('100 $digest() iterations reached. Aborting!\n' +
|
||||
'Watchers fired in the last 5 iterations: ' + toJson(watchLog));
|
||||
}
|
||||
} while (dirty);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -218,14 +218,34 @@ describe('Scope', function() {
|
|||
});
|
||||
|
||||
|
||||
it('should prevent infinite recursion', function() {
|
||||
root.$watch('a', function(self, v){self.b++;});
|
||||
root.$watch('b', function(self, v){self.a++;});
|
||||
it('should prevent infinite recursion and print watcher expression', function() {
|
||||
root.$watch('a', function(self){self.b++;});
|
||||
root.$watch('b', function(self){self.a++;});
|
||||
root.a = root.b = 0;
|
||||
|
||||
expect(function() {
|
||||
root.$digest();
|
||||
}).toThrow('100 $digest() iterations reached. Aborting!');
|
||||
}).toThrow('100 $digest() iterations reached. Aborting!\n'+
|
||||
'Watchers fired in the last 5 iterations: ' +
|
||||
'[["a","b"],["a","b"],["a","b"],["a","b"],["a","b"]]');
|
||||
});
|
||||
|
||||
|
||||
it('should prevent infinite recurcion and print print watcher function name or body',
|
||||
function() {
|
||||
root.$watch(function watcherA() {return root.a;}, function(self){self.b++;});
|
||||
root.$watch(function() {return root.b;}, function(self){self.a++;});
|
||||
root.a = root.b = 0;
|
||||
|
||||
expect(function() {
|
||||
root.$digest();
|
||||
}).toThrow('100 $digest() iterations reached. Aborting!\n'+
|
||||
'Watchers fired in the last 5 iterations: ' +
|
||||
'[["fn: watcherA","fn: function () {return root.b;}"],'+
|
||||
'["fn: watcherA","fn: function () {return root.b;}"],'+
|
||||
'["fn: watcherA","fn: function () {return root.b;}"],'+
|
||||
'["fn: watcherA","fn: function () {return root.b;}"],'+
|
||||
'["fn: watcherA","fn: function () {return root.b;}"]]');
|
||||
});
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue