(actual, expected, comparator, anyPropertyKey, matchAgainstAnyProp, dontMatchWholeObject)
| 22332 | } |
| 22333 | |
| 22334 | function deepCompare(actual, expected, comparator, anyPropertyKey, matchAgainstAnyProp, dontMatchWholeObject) { |
| 22335 | var actualType = getTypeForFilter(actual); |
| 22336 | var expectedType = getTypeForFilter(expected); |
| 22337 | |
| 22338 | if ((expectedType === 'string') && (expected.charAt(0) === '!')) { |
| 22339 | return !deepCompare(actual, expected.substring(1), comparator, anyPropertyKey, matchAgainstAnyProp); |
| 22340 | } else if (isArray(actual)) { |
| 22341 | // In case `actual` is an array, consider it a match |
| 22342 | // if ANY of it's items matches `expected` |
| 22343 | return actual.some(function(item) { |
| 22344 | return deepCompare(item, expected, comparator, anyPropertyKey, matchAgainstAnyProp); |
| 22345 | }); |
| 22346 | } |
| 22347 | |
| 22348 | switch (actualType) { |
| 22349 | case 'object': |
| 22350 | var key; |
| 22351 | if (matchAgainstAnyProp) { |
| 22352 | for (key in actual) { |
| 22353 | // Under certain, rare, circumstances, key may not be a string and `charAt` will be undefined |
| 22354 | // See: https://github.com/angular/angular.js/issues/15644 |
| 22355 | if (key.charAt && (key.charAt(0) !== '$') && |
| 22356 | deepCompare(actual[key], expected, comparator, anyPropertyKey, true)) { |
| 22357 | return true; |
| 22358 | } |
| 22359 | } |
| 22360 | return dontMatchWholeObject ? false : deepCompare(actual, expected, comparator, anyPropertyKey, false); |
| 22361 | } else if (expectedType === 'object') { |
| 22362 | for (key in expected) { |
| 22363 | var expectedVal = expected[key]; |
| 22364 | if (isFunction(expectedVal) || isUndefined(expectedVal)) { |
| 22365 | continue; |
| 22366 | } |
| 22367 | |
| 22368 | var matchAnyProperty = key === anyPropertyKey; |
| 22369 | var actualVal = matchAnyProperty ? actual : actual[key]; |
| 22370 | if (!deepCompare(actualVal, expectedVal, comparator, anyPropertyKey, matchAnyProperty, matchAnyProperty)) { |
| 22371 | return false; |
| 22372 | } |
| 22373 | } |
| 22374 | return true; |
| 22375 | } else { |
| 22376 | return comparator(actual, expected); |
| 22377 | } |
| 22378 | case 'function': |
| 22379 | return false; |
| 22380 | default: |
| 22381 | return comparator(actual, expected); |
| 22382 | } |
| 22383 | } |
| 22384 | |
| 22385 | // Used for easily differentiating between `null` and actual `object` |
| 22386 | function getTypeForFilter(val) { |
no test coverage detected