(actual, expected, comparator, anyPropertyKey, matchAgainstAnyProp, dontMatchWholeObject)
| 21611 | } |
| 21612 | |
| 21613 | function deepCompare(actual, expected, comparator, anyPropertyKey, matchAgainstAnyProp, dontMatchWholeObject) { |
| 21614 | var actualType = getTypeForFilter(actual); |
| 21615 | var expectedType = getTypeForFilter(expected); |
| 21616 | |
| 21617 | if ((expectedType === 'string') && (expected.charAt(0) === '!')) { |
| 21618 | return !deepCompare(actual, expected.substring(1), comparator, anyPropertyKey, matchAgainstAnyProp); |
| 21619 | } else if (isArray(actual)) { |
| 21620 | // In case `actual` is an array, consider it a match |
| 21621 | // if ANY of it's items matches `expected` |
| 21622 | return actual.some(function(item) { |
| 21623 | return deepCompare(item, expected, comparator, anyPropertyKey, matchAgainstAnyProp); |
| 21624 | }); |
| 21625 | } |
| 21626 | |
| 21627 | switch (actualType) { |
| 21628 | case 'object': |
| 21629 | var key; |
| 21630 | if (matchAgainstAnyProp) { |
| 21631 | for (key in actual) { |
| 21632 | // Under certain, rare, circumstances, key may not be a string and `charAt` will be undefined |
| 21633 | // See: https://github.com/angular/angular.js/issues/15644 |
| 21634 | if (key.charAt && (key.charAt(0) !== '$') && |
| 21635 | deepCompare(actual[key], expected, comparator, anyPropertyKey, true)) { |
| 21636 | return true; |
| 21637 | } |
| 21638 | } |
| 21639 | return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, anyPropertyKey, false); |
| 21640 | } else if (expectedType === 'object') { |
| 21641 | for (key in expected) { |
| 21642 | var expectedVal = expected[key]; |
| 21643 | if (isFunction(expectedVal) || isUndefined(expectedVal)) { |
| 21644 | continue; |
| 21645 | } |
| 21646 | |
| 21647 | var matchAnyProperty = key === anyPropertyKey; |
| 21648 | var actualVal = matchAnyProperty ? actual : actual[key]; |
| 21649 | if (!deepCompare(actualVal, expectedVal, comparator, anyPropertyKey, matchAnyProperty, matchAnyProperty)) { |
| 21650 | return false; |
| 21651 | } |
| 21652 | } |
| 21653 | return true; |
| 21654 | } else { |
| 21655 | return comparator(actual, expected); |
| 21656 | } |
| 21657 | case 'function': |
| 21658 | return false; |
| 21659 | default: |
| 21660 | return comparator(actual, expected); |
| 21661 | } |
| 21662 | } |
| 21663 | |
| 21664 | // Used for easily differentiating between `null` and actual `object` |
| 21665 | function getTypeForFilter(val) { |
no test coverage detected