( a: any, b: any, customTesters: Array<Tester> = [], aStack: Array<any> = [], bStack: Array<any> = [], )
| 433 | } |
| 434 | |
| 435 | export function iterableEquality( |
| 436 | a: any, |
| 437 | b: any, |
| 438 | customTesters: Array<Tester> = [], |
| 439 | aStack: Array<any> = [], |
| 440 | bStack: Array<any> = [], |
| 441 | ): boolean | undefined { |
| 442 | if ( |
| 443 | typeof a !== 'object' |
| 444 | || typeof b !== 'object' |
| 445 | || Array.isArray(a) |
| 446 | || Array.isArray(b) |
| 447 | || !hasIterator(a) |
| 448 | || !hasIterator(b) |
| 449 | ) { |
| 450 | return undefined |
| 451 | } |
| 452 | |
| 453 | if (a.constructor !== b.constructor) { |
| 454 | return false |
| 455 | } |
| 456 | |
| 457 | let length = aStack.length |
| 458 | while (length--) { |
| 459 | // Linear search. Performance is inversely proportional to the number of |
| 460 | // unique nested structures. |
| 461 | // circular references at same depth are equal |
| 462 | // circular reference is not equal to non-circular one |
| 463 | if (aStack[length] === a) { |
| 464 | return bStack[length] === b |
| 465 | } |
| 466 | } |
| 467 | aStack.push(a) |
| 468 | bStack.push(b) |
| 469 | |
| 470 | const filteredCustomTesters: Array<Tester> = [ |
| 471 | ...customTesters.filter(t => t !== iterableEquality), |
| 472 | iterableEqualityWithStack, |
| 473 | ] |
| 474 | |
| 475 | function iterableEqualityWithStack(a: any, b: any) { |
| 476 | return iterableEquality(a, b, [...customTesters], [...aStack], [...bStack]) |
| 477 | } |
| 478 | |
| 479 | if (a.size !== undefined) { |
| 480 | if (a.size !== b.size) { |
| 481 | return false |
| 482 | } |
| 483 | else if (isA('Set', a) || isImmutableUnorderedSet(a)) { |
| 484 | let allFound = true |
| 485 | for (const aValue of a) { |
| 486 | if (!b.has(aValue)) { |
| 487 | let has = false |
| 488 | for (const bValue of b) { |
| 489 | const isEqual = equals(aValue, bValue, filteredCustomTesters) |
| 490 | if (isEqual === true) { |
| 491 | has = true |
| 492 | } |
no test coverage detected