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

Commit b5002ab

Browse files
committed
fix(filterFilter): fix matching against null/undefined
Included fixes: * Do not convert `null`/`undefined` to strings for substring matching in non-strict comparison mode. Prevents `null`/`undefined` from being matched against e.g. 'u'. * Let `null` (as a top-level filter expression) match "deeply" (as do booleans, numbers and strings). E.g. let `filterFilter(arr, null)` match an item like `{someProp: null}`. Closes #11432 Closes #11445
1 parent 393f503 commit b5002ab

File tree

2 files changed

+62
-1
lines changed

2 files changed

+62
-1
lines changed

src/ng/filter/filter.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -135,14 +135,16 @@ function filterFilter() {
135135
}
136136
}
137137

138+
var expressionType = (expression !== null) ? typeof expression : 'null';
138139
var predicateFn;
139140
var matchAgainstAnyProp;
140141

141-
switch (typeof expression) {
142+
switch (expressionType) {
142143
case 'function':
143144
predicateFn = expression;
144145
break;
145146
case 'boolean':
147+
case 'null':
146148
case 'number':
147149
case 'string':
148150
matchAgainstAnyProp = true;
@@ -172,6 +174,14 @@ function createPredicateFn(expression, comparator, matchAgainstAnyProp) {
172174
comparator = equals;
173175
} else if (!isFunction(comparator)) {
174176
comparator = function(actual, expected) {
177+
if (isUndefined(actual)) {
178+
// No substring matching against `undefined`
179+
return false;
180+
}
181+
if ((actual === null) || (expected === null)) {
182+
// No substring matching against `null`; only match against `null`
183+
return actual === expected;
184+
}
175185
if (isObject(expected) || (isObject(actual) && !hasCustomToString(actual))) {
176186
// Should not compare primitives against objects, unless they have custom `toString` method
177187
return false;

test/ng/filter/filterSpec.js

+51
Original file line numberDiff line numberDiff line change
@@ -463,8 +463,59 @@ describe('Filter: filter', function() {
463463
});
464464

465465

466+
it('should match `null` against `null` only', function() {
467+
var items = [
468+
{value: null},
469+
{value: undefined},
470+
{value: true},
471+
{value: false},
472+
{value: NaN},
473+
{value: 42},
474+
{value: 'null'},
475+
{value: 'test'},
476+
{value: {}},
477+
{value: new Date()}
478+
];
479+
var flt;
480+
481+
flt = null;
482+
expect(filter(items, flt).length).toBe(1);
483+
expect(filter(items, flt)[0]).toBe(items[0]);
484+
485+
flt = {value: null};
486+
expect(filter(items, flt).length).toBe(1);
487+
expect(filter(items, flt)[0]).toBe(items[0]);
488+
489+
flt = {value: undefined};
490+
expect(filter(items, flt).length).toBe(items.length);
491+
492+
flt = {value: NaN};
493+
expect(includes(filter(items, flt), items[0])).toBeFalsy();
494+
495+
flt = {value: false};
496+
expect(includes(filter(items, flt), items[0])).toBeFalsy();
497+
498+
flt = '';
499+
expect(includes(filter(items, flt), items[0])).toBeFalsy();
500+
501+
flt = {value: 'null'};
502+
expect(includes(filter(items, flt), items[0])).toBeFalsy();
503+
});
504+
505+
466506
describe('should support comparator', function() {
467507

508+
it('not convert `null` or `undefined` to string in non-strict comparison', function() {
509+
var items = [
510+
{value: null},
511+
{value: undefined}
512+
];
513+
var flt = {value: 'u'};
514+
515+
expect(filter(items, flt).length).toBe(0);
516+
});
517+
518+
468519
it('not consider objects without a custom `toString` in non-strict comparison', function() {
469520
var items = [{test: {}}];
470521
var expr = '[object';

0 commit comments

Comments
 (0)