diff --git a/src/ng/rootScope.js b/src/ng/rootScope.js index bb12362b74f6..81c9ee78deb3 100644 --- a/src/ng/rootScope.js +++ b/src/ng/rootScope.js @@ -372,7 +372,7 @@ function $RootScopeProvider(){ watchLog = [], logIdx, logMsg; - flagPhase(target, '$digest'); + beginPhase('$digest'); do { dirty = false; @@ -429,12 +429,13 @@ function $RootScopeProvider(){ } while ((current = next)); if(dirty && !(ttl--)) { + clearPhase(); throw Error(TTL + ' $digest() iterations reached. Aborting!\n' + 'Watchers fired in the last 5 iterations: ' + toJson(watchLog)); } } while (dirty || asyncQueue.length); - this.$root.$$phase = null; + clearPhase(); }, @@ -469,7 +470,7 @@ function $RootScopeProvider(){ * perform any necessary cleanup. */ $destroy: function() { - if (this.$root == this) return; // we can't remove the root node; + if ($rootScope == this) return; // we can't remove the root node; var parent = this.$parent; this.$broadcast('$destroy'); @@ -586,13 +587,18 @@ function $RootScopeProvider(){ */ $apply: function(expr) { try { - flagPhase(this, '$apply'); + beginPhase('$apply'); return this.$eval(expr); } catch (e) { $exceptionHandler(e); } finally { - this.$root.$$phase = null; - this.$root.$digest(); + clearPhase(); + try { + $rootScope.$digest(); + } catch (e) { + $exceptionHandler(e); + throw e; + } } }, @@ -754,18 +760,22 @@ function $RootScopeProvider(){ } }; + var $rootScope = new Scope(); + + return $rootScope; - function flagPhase(scope, phase) { - var root = scope.$root; - if (root.$$phase) { - throw Error(root.$$phase + ' already in progress'); + function beginPhase(phase) { + if ($rootScope.$$phase) { + throw Error($rootScope.$$phase + ' already in progress'); } - root.$$phase = phase; + $rootScope.$$phase = phase; } - return new Scope(); + function clearPhase() { + $rootScope.$$phase = null; + } function compileToFn(exp, name) { var fn = $parse(exp); diff --git a/test/ng/rootScopeSpec.js b/test/ng/rootScopeSpec.js index 9d343b0848a8..934541c1e74b 100644 --- a/test/ng/rootScopeSpec.js +++ b/test/ng/rootScopeSpec.js @@ -210,6 +210,8 @@ describe('Scope', function() { '["a; newVal: 98; oldVal: 97","b; newVal: 99; oldVal: 98"],' + '["a; newVal: 99; oldVal: 98","b; newVal: 100; oldVal: 99"],' + '["a; newVal: 100; oldVal: 99","b; newVal: 101; oldVal: 100"]]'); + + expect($rootScope.$$phase).toBeNull(); }); }); @@ -492,6 +494,27 @@ describe('Scope', function() { }); + it('should log exceptions from $digest', function() { + module(function($rootScopeProvider, $exceptionHandlerProvider) { + $rootScopeProvider.digestTtl(2); + $exceptionHandlerProvider.mode('log'); + }); + inject(function($rootScope, $exceptionHandler) { + $rootScope.$watch('a', function() {$rootScope.b++;}); + $rootScope.$watch('b', function() {$rootScope.a++;}); + $rootScope.a = $rootScope.b = 0; + + expect(function() { + $rootScope.$apply(); + }).toThrow(); + + expect($exceptionHandler.errors[0]).toBeDefined(); + + expect($rootScope.$$phase).toBeNull(); + }); + }); + + describe('exceptions', function() { var log; beforeEach(module(function($exceptionHandlerProvider) {