diff --git a/src/ng/filter/filter.js b/src/ng/filter/filter.js index 5c6bf2d79e7e..158c848bb737 100644 --- a/src/ng/filter/filter.js +++ b/src/ng/filter/filter.js @@ -118,7 +118,8 @@ function filterFilter() { if (!isArray(array)) return array; var comparatorType = typeof(comparator), - predicates = []; + predicates = [], + evaluatedObjects = []; predicates.check = function(value) { for (var j = 0; j < predicates.length; j++) { @@ -165,9 +166,16 @@ function filterFilter() { case "object": return comparator(obj, text); default: - for ( var objKey in obj) { - if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) { - return true; + for (var objKey in obj) { + if (objKey.charAt(0) !== '$') { + var value = obj[objKey]; + if (isObject(value) || isFunction(value)) { + if (evaluatedObjects.indexOf(value) >= 0) continue; + evaluatedObjects.push(value); + } + if (search(value, text)) { + return true; + } } } break; diff --git a/test/ng/filter/filterSpec.js b/test/ng/filter/filterSpec.js index 7679136ac9f9..8f01f0f4f04b 100644 --- a/test/ng/filter/filterSpec.js +++ b/test/ng/filter/filterSpec.js @@ -34,6 +34,18 @@ describe('Filter: filter', function() { expect(filter(items, 'misko').length).toBe(0); }); + it('should not re-evaluate circular references', function() { + var originalItem = {name: 'misko'}; + var referencedItem = {originalItem: originalItem}; + originalItem.referencedItem = referencedItem; + + var items = [originalItem]; + expect(function() { filter(items, 'not misko') }) + .not.toThrow(); + + expect(filter(items, 'misko')).toEqual([originalItem]); + }); + it('should filter on specific property', function() { var items = [{ignore: 'a', name: 'a'}, {ignore: 'a', name: 'abc'}]; expect(filter(items, {}).length).toBe(2);