(actual, expected, comparator, anyPropertyKey, matchAgainstAnyProp, dontMatchWholeObject)
| 21500 | } |
| 21501 | |
| 21502 | function deepCompare(actual, expected, comparator, anyPropertyKey, matchAgainstAnyProp, dontMatchWholeObject) { |
| 21503 | var actualType = getTypeForFilter(actual); |
| 21504 | var expectedType = getTypeForFilter(expected); |
| 21505 | |
| 21506 | if ((expectedType === 'string') && (expected.charAt(0) === '!')) { |
| 21507 | return !deepCompare(actual, expected.substring(1), comparator, anyPropertyKey, matchAgainstAnyProp); |
| 21508 | } else if (isArray(actual)) { |
| 21509 | // In case `actual` is an array, consider it a match |
| 21510 | // if ANY of it's items matches `expected` |
| 21511 | return actual.some(function(item) { |
| 21512 | return deepCompare(item, expected, comparator, anyPropertyKey, matchAgainstAnyProp); |
| 21513 | }); |
| 21514 | } |
| 21515 | |
| 21516 | switch (actualType) { |
| 21517 | case 'object': |
| 21518 | var key; |
| 21519 | if (matchAgainstAnyProp) { |
| 21520 | for (key in actual) { |
| 21521 | // Under certain, rare, circumstances, key may not be a string and `charAt` will be undefined |
| 21522 | // See: https://github.com/angular/angular.js/issues/15644 |
| 21523 | if (key.charAt && (key.charAt(0) !== '$') && |
| 21524 | deepCompare(actual[key], expected, comparator, anyPropertyKey, true)) { |
| 21525 | return true; |
| 21526 | } |
| 21527 | } |
| 21528 | return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, anyPropertyKey, false); |
| 21529 | } else if (expectedType === 'object') { |
| 21530 | for (key in expected) { |
| 21531 | var expectedVal = expected[key]; |
| 21532 | if (isFunction(expectedVal) || isUndefined(expectedVal)) { |
| 21533 | continue; |
| 21534 | } |
| 21535 | |
| 21536 | var matchAnyProperty = key === anyPropertyKey; |
| 21537 | var actualVal = matchAnyProperty ? actual : actual[key]; |
| 21538 | if (!deepCompare(actualVal, expectedVal, comparator, anyPropertyKey, matchAnyProperty, matchAnyProperty)) { |
| 21539 | return false; |
| 21540 | } |
| 21541 | } |
| 21542 | return true; |
| 21543 | } else { |
| 21544 | return comparator(actual, expected); |
| 21545 | } |
| 21546 | case 'function': |
| 21547 | return false; |
| 21548 | default: |
| 21549 | return comparator(actual, expected); |
| 21550 | } |
| 21551 | } |
| 21552 | |
| 21553 | // Used for easily differentiating between `null` and actual `object` |
| 21554 | function getTypeForFilter(val) { |
no test coverage detected