Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 2cd09c9

Browse files
sinelawjeffbcross
authored andcommitted
fix($rootScope): prevent infinite $digest by checking if asyncQueue is empty when decrementing ttl
An infinite $digest loop can be caused by expressions that invoke a promise. The problem is that $digest does not decrement ttl unless it finds dirty changes; it should check also if asyncQueue is empty. Generally the condition for decrementing ttl should be the same as the condition for terminating the $digest loop. Fixes #2622
1 parent 34fee06 commit 2cd09c9

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

src/ng/rootScope.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ function $RootScopeProvider(){
632632

633633
// `break traverseScopesLoop;` takes us to here
634634

635-
if(dirty && !(ttl--)) {
635+
if((dirty || asyncQueue.length) && !(ttl--)) {
636636
clearPhase();
637637
throw $rootScopeMinErr('infdig',
638638
'{0} $digest() iterations reached. Aborting!\n' +

test/ng/rootScopeSpec.js

+25
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,31 @@ describe('Scope', function() {
258258
}));
259259

260260

261+
it('should prevent infinite loop when creating and resolving a promise in a watched expression', function() {
262+
module(function($rootScopeProvider) {
263+
$rootScopeProvider.digestTtl(10);
264+
});
265+
inject(function($rootScope, $q) {
266+
var d = $q.defer();
267+
268+
d.resolve('Hello, world.');
269+
$rootScope.$watch(function () {
270+
var $d2 = $q.defer();
271+
$d2.resolve('Goodbye.');
272+
$d2.promise.then(function () { });
273+
return d.promise;
274+
}, function () { return 0; });
275+
276+
expect(function() {
277+
$rootScope.$digest();
278+
}).toThrowMinErr('$rootScope', 'infdig', '10 $digest() iterations reached. Aborting!\n'+
279+
'Watchers fired in the last 5 iterations: []');
280+
281+
expect($rootScope.$$phase).toBeNull();
282+
});
283+
});
284+
285+
261286
it('should not fire upon $watch registration on initial $digest', inject(function($rootScope) {
262287
var log = '';
263288
$rootScope.a = 1;

0 commit comments

Comments
 (0)