From bf13d2683d5880b18db00087e80ee0fd5e1f429a Mon Sep 17 00:00:00 2001
From: Shahar Talmi <shahar.talmi@gmail.com>
Date: Sat, 21 Jun 2014 19:17:25 +0300
Subject: [PATCH] fix($rootScope): $watchCollection should handle NaN in
 objects

This fixes a potential infinite digest in $watchCollection when one of the values is NaN. This was previously fixed for arrays, but needs to be handled for objects as well.

Closes #7930
---
 src/ng/rootScope.js      | 8 +++++---
 test/ng/rootScopeSpec.js | 8 ++++++++
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/src/ng/rootScope.js b/src/ng/rootScope.js
index 179983ca7cc0..4114a6501ba8 100644
--- a/src/ng/rootScope.js
+++ b/src/ng/rootScope.js
@@ -443,7 +443,7 @@ function $RootScopeProvider(){
 
         function $watchCollectionWatch() {
           newValue = objGetter(self);
-          var newLength, key;
+          var newLength, key, bothNaN;
 
           if (!isObject(newValue)) { // if primitive
             if (oldValue !== newValue) {
@@ -467,7 +467,7 @@ function $RootScopeProvider(){
             }
             // copy the items to oldValue and look for changes.
             for (var i = 0; i < newLength; i++) {
-              var bothNaN = (oldValue[i] !== oldValue[i]) &&
+              bothNaN = (oldValue[i] !== oldValue[i]) &&
                   (newValue[i] !== newValue[i]);
               if (!bothNaN && (oldValue[i] !== newValue[i])) {
                 changeDetected++;
@@ -487,7 +487,9 @@ function $RootScopeProvider(){
               if (newValue.hasOwnProperty(key)) {
                 newLength++;
                 if (oldValue.hasOwnProperty(key)) {
-                  if (oldValue[key] !== newValue[key]) {
+                  bothNaN = (oldValue[key] !== oldValue[key]) &&
+                      (newValue[key] !== newValue[key]);
+                  if (!bothNaN && (oldValue[key] !== newValue[key])) {
                     changeDetected++;
                     oldValue[key] = newValue[key];
                   }
diff --git a/test/ng/rootScopeSpec.js b/test/ng/rootScopeSpec.js
index dc2dda2554af..cd86c71d329a 100644
--- a/test/ng/rootScopeSpec.js
+++ b/test/ng/rootScopeSpec.js
@@ -698,6 +698,14 @@ describe('Scope', function() {
           $rootScope.$digest();
           expect(log.empty()).toEqual([{newVal: {b: {}, c: 'B'}, oldVal: {a: [], b: {}, c: 'B'}}]);
         });
+
+        it('should not infinitely digest when current value is NaN', function() {
+          $rootScope.obj = {a: NaN};
+          expect(function() {
+            $rootScope.$digest();
+          }).not.toThrow();
+        });
+
       });
     });