(actual, expected, comparator, anyPropertyKey, matchAgainstAnyProp, dontMatchWholeObject)
| 21176 | } |
| 21177 | |
| 21178 | function deepCompare(actual, expected, comparator, anyPropertyKey, matchAgainstAnyProp, dontMatchWholeObject) { |
| 21179 | var actualType = getTypeForFilter(actual); |
| 21180 | var expectedType = getTypeForFilter(expected); |
| 21181 | |
| 21182 | if ((expectedType === 'string') && (expected.charAt(0) === '!')) { |
| 21183 | return !deepCompare(actual, expected.substring(1), comparator, anyPropertyKey, matchAgainstAnyProp); |
| 21184 | } else if (isArray(actual)) { |
| 21185 | // In case `actual` is an array, consider it a match |
| 21186 | // if ANY of it's items matches `expected` |
| 21187 | return actual.some(function(item) { |
| 21188 | return deepCompare(item, expected, comparator, anyPropertyKey, matchAgainstAnyProp); |
| 21189 | }); |
| 21190 | } |
| 21191 | |
| 21192 | switch (actualType) { |
| 21193 | case 'object': |
| 21194 | var key; |
| 21195 | if (matchAgainstAnyProp) { |
| 21196 | for (key in actual) { |
| 21197 | // Under certain, rare, circumstances, key may not be a string and `charAt` will be undefined |
| 21198 | // See: https://github.com/angular/angular.js/issues/15644 |
| 21199 | if (key.charAt && (key.charAt(0) !== '$') && |
| 21200 | deepCompare(actual[key], expected, comparator, anyPropertyKey, true)) { |
| 21201 | return true; |
| 21202 | } |
| 21203 | } |
| 21204 | return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, anyPropertyKey, false); |
| 21205 | } else if (expectedType === 'object') { |
| 21206 | for (key in expected) { |
| 21207 | var expectedVal = expected[key]; |
| 21208 | if (isFunction(expectedVal) || isUndefined(expectedVal)) { |
| 21209 | continue; |
| 21210 | } |
| 21211 | |
| 21212 | var matchAnyProperty = key === anyPropertyKey; |
| 21213 | var actualVal = matchAnyProperty ? actual : actual[key]; |
| 21214 | if (!deepCompare(actualVal, expectedVal, comparator, anyPropertyKey, matchAnyProperty, matchAnyProperty)) { |
| 21215 | return false; |
| 21216 | } |
| 21217 | } |
| 21218 | return true; |
| 21219 | } else { |
| 21220 | return comparator(actual, expected); |
| 21221 | } |
| 21222 | case 'function': |
| 21223 | return false; |
| 21224 | default: |
| 21225 | return comparator(actual, expected); |
| 21226 | } |
| 21227 | } |
| 21228 | |
| 21229 | // Used for easily differentiating between `null` and actual `object` |
| 21230 | function getTypeForFilter(val) { |
no test coverage detected