(actual, expected, comparator, anyPropertyKey, matchAgainstAnyProp, dontMatchWholeObject)
| 22397 | } |
| 22398 | |
| 22399 | function deepCompare(actual, expected, comparator, anyPropertyKey, matchAgainstAnyProp, dontMatchWholeObject) { |
| 22400 | var actualType = getTypeForFilter(actual); |
| 22401 | var expectedType = getTypeForFilter(expected); |
| 22402 | |
| 22403 | if ((expectedType === 'string') && (expected.charAt(0) === '!')) { |
| 22404 | return !deepCompare(actual, expected.substring(1), comparator, anyPropertyKey, matchAgainstAnyProp); |
| 22405 | } else if (isArray(actual)) { |
| 22406 | // In case `actual` is an array, consider it a match |
| 22407 | // if ANY of it's items matches `expected` |
| 22408 | return actual.some(function(item) { |
| 22409 | return deepCompare(item, expected, comparator, anyPropertyKey, matchAgainstAnyProp); |
| 22410 | }); |
| 22411 | } |
| 22412 | |
| 22413 | switch (actualType) { |
| 22414 | case 'object': |
| 22415 | var key; |
| 22416 | if (matchAgainstAnyProp) { |
| 22417 | for (key in actual) { |
| 22418 | // Under certain, rare, circumstances, key may not be a string and `charAt` will be undefined |
| 22419 | // See: https://github.com/angular/angular.js/issues/15644 |
| 22420 | if (key.charAt && (key.charAt(0) !== '$') && |
| 22421 | deepCompare(actual[key], expected, comparator, anyPropertyKey, true)) { |
| 22422 | return true; |
| 22423 | } |
| 22424 | } |
| 22425 | return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, anyPropertyKey, false); |
| 22426 | } else if (expectedType === 'object') { |
| 22427 | for (key in expected) { |
| 22428 | var expectedVal = expected[key]; |
| 22429 | if (isFunction(expectedVal) || isUndefined(expectedVal)) { |
| 22430 | continue; |
| 22431 | } |
| 22432 | |
| 22433 | var matchAnyProperty = key === anyPropertyKey; |
| 22434 | var actualVal = matchAnyProperty ? actual : actual[key]; |
| 22435 | if (!deepCompare(actualVal, expectedVal, comparator, anyPropertyKey, matchAnyProperty, matchAnyProperty)) { |
| 22436 | return false; |
| 22437 | } |
| 22438 | } |
| 22439 | return true; |
| 22440 | } else { |
| 22441 | return comparator(actual, expected); |
| 22442 | } |
| 22443 | case 'function': |
| 22444 | return false; |
| 22445 | default: |
| 22446 | return comparator(actual, expected); |
| 22447 | } |
| 22448 | } |
| 22449 | |
| 22450 | // Used for easily differentiating between `null` and actual `object` |
| 22451 | function getTypeForFilter(val) { |
no test coverage detected