diff options
| author | Igor Minar | 2011-10-30 15:11:25 -0700 | 
|---|---|---|
| committer | Igor Minar | 2011-10-31 11:34:25 -0700 | 
| commit | ef875ad0cf4349144cb4674e050dd160564f6dd9 (patch) | |
| tree | 77b5aaac971cb6a5b2e43504db8886b9877da89b | |
| parent | 615841a5d3cb6dae8329411c27fd938e9b413f4c (diff) | |
| download | angular.js-ef875ad0cf4349144cb4674e050dd160564f6dd9.tar.bz2 | |
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
| -rw-r--r-- | src/Scope.js | 17 | ||||
| -rw-r--r-- | test/ScopeSpec.js | 28 | 
2 files changed, 38 insertions, 7 deletions
| diff --git a/src/Scope.js b/src/Scope.js index be5030cc..c4b9513b 100644 --- a/src/Scope.js +++ b/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);    }, diff --git a/test/ScopeSpec.js b/test/ScopeSpec.js index b1942646..e1f8181e 100644 --- a/test/ScopeSpec.js +++ b/test/ScopeSpec.js @@ -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;}"]]');      }); | 
