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

Fix(filter): Filter objects with circular references #6319

16 changes: 12 additions & 4 deletions src/ng/filter/filter.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ function filterFilter() {
if (!isArray(array)) return array;

var comparatorType = typeof(comparator),
predicates = [];
predicates = [],
evaluatedObjects = [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to use the hashKey api from src/api.js for this, rather than an array (this would work for 1.2.x as well)


predicates.check = function(value) {
for (var j = 0; j < predicates.length; j++) {
Expand Down Expand Up @@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

indexOf(evaluatedObjects, value) if we want to make this backportable to 1.2.x

evaluatedObjects.push(value);
}
if (search(value, text)) {
return true;
}
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

free up references with evaluatedObjects.length = 0

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nevermind, that won't do anything. ignore :)

break;
Expand Down
12 changes: 12 additions & 0 deletions test/ng/filter/filterSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down