diff --git a/lib/core/scope.dart b/lib/core/scope.dart index 827ba851a..6381c638d 100644 --- a/lib/core/scope.dart +++ b/lib/core/scope.dart @@ -433,6 +433,11 @@ class Scope implements Map { watcherCount = 0; scopeCount = 0; + var firedExpressions; + if (_ttl - _ttlLeft > 2) { + firedExpressions = []; + watchLog.add(firedExpressions); + } assert((timerId = _perf.startTimer('ng.dirty_check', _ttl-_ttlLeft)) != false); digestLoop: do { // "traverse the scopes" loop @@ -448,6 +453,9 @@ class Scope implements Map { var value = watch.get(current); var last = watch.last; if (!_identical(value, last)) { + if (_ttlLeft < 3) { + firedExpressions.add(watch.exp == null ? '[unknown]' : watch.exp); + } lastDirtyWatch = watch; lastLoopLastDirtyWatch = null; watch.last = value; @@ -488,7 +496,7 @@ class Scope implements Map { assert(_perf.stopTimer(timerId) != false); if(lastDirtyWatch != null && (_ttlLeft--) == 0) { throw '$_ttl \$digest() iterations reached. Aborting!\n' + - 'Watchers fired in the last 5 iterations: ${_toJson(watchLog)}'; + 'Watchers fired in the last ${_ttl - 2} iterations: ${_toJson(watchLog)}'; } } while (lastDirtyWatch != null || innerAsyncQueue.length > 0); _perf.counters['ng.scope.watchers'] = watcherCount; diff --git a/test/core/scope_spec.dart b/test/core/scope_spec.dart index 23fa79f2d..cea2a2a07 100644 --- a/test/core/scope_spec.dart +++ b/test/core/scope_spec.dart @@ -327,6 +327,22 @@ main() { })); + it(r'should prevent infinite digest and should log firing expressions', inject((Scope $rootScope) { + $rootScope['a'] = 0; + $rootScope['b'] = 0; + $rootScope.$watch('a = a + 1'); + $rootScope.$watch('b = b + 1'); + + expect(() { + $rootScope.$digest(); + }).toThrow('Watchers fired in the last 3 iterations: [' + '["a = a + 1","b = b + 1"],' + '["a = a + 1","b = b + 1"],' + '["a = a + 1","b = b + 1"]' + ']'); + })); + + it(r'should always call the watchr with newVal and oldVal equal on the first run', inject((Scope $rootScope) { var log = [];