Skip to content

Commit dfd3b80

Browse files
committed
assert,util: fix deep comparison for sets and maps with mixed types
When comparing a Set or a Map and they contain primitives as keys as well as objects, the primitives would always be skipped. That is not correct, since that may only be skipped in case all keys are objects. Fixes: #61386
1 parent 95852d7 commit dfd3b80

File tree

2 files changed

+28
-6
lines changed

2 files changed

+28
-6
lines changed

lib/internal/util/comparisons.js

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -669,8 +669,10 @@ function setObjectEquiv(array, a, b, mode, memo) {
669669
if (b.has(val1)) {
670670
continue;
671671
}
672-
} else if (mode !== kLoose || b.has(val1)) {
672+
} else if (b.has(val1)) {
673673
continue;
674+
} else if (mode !== kLoose) {
675+
return false;
674676
}
675677
}
676678

@@ -816,11 +818,16 @@ function mapObjectEquiv(array, a, b, mode, memo) {
816818
const extraChecks = mode === kLoose || array.length !== a.size;
817819

818820
for (const { 0: key1, 1: item1 } of a) {
819-
if (extraChecks &&
820-
(typeof key1 !== 'object' || key1 === null) &&
821-
(mode !== kLoose ||
822-
(b.has(key1) && innerDeepEqual(item1, b.get(key1), mode, memo)))) { // Mixed mode
823-
continue;
821+
if (extraChecks && (typeof key1 !== 'object' || key1 === null)) {
822+
if (mode !== kLoose) {
823+
if (!b.has(key1)) {
824+
return false;
825+
}
826+
continue;
827+
}
828+
if (b.has(key1) && innerDeepEqual(item1, b.get(key1), mode, memo)) { // Mixed mode
829+
continue;
830+
}
824831
}
825832

826833
let innerStart = start;

test/parallel/test-assert-deep.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,21 @@ test('Handle sparse arrays', () => {
634634
assertNotDeepOrStrict(a, b, AssertionError, { partial: 'pass' });
635635
});
636636

637+
test('Handle sets and maps with mixed keys', () => {
638+
// https://github.com/nodejs/node/issues/61386
639+
const aSet = new Set([0, new Set([1, 2, 3]), new Set([4, 5, 6])]);
640+
const bSet = new Set([
641+
0,
642+
new Set([1, new Set([2, 3]), new Set([20, 30])]),
643+
new Set([4, new Set([5, 6]), new Set([50, 60])]),
644+
]);
645+
assertNotDeepOrStrict(aSet, bSet);
646+
647+
const aMap = new Map([[0, 'zero'], [1, 'one'], [new Set([1, 2, 3]), 'A']]);
648+
const bMap = new Map([[0, 'zero'], [new Set([1, 2, 3]), 'A'], [new Set([9]), 'B']]);
649+
assertNotDeepOrStrict(aMap, bMap);
650+
});
651+
637652
test('Handle different error messages', () => {
638653
const err1 = new Error('foo1');
639654
assertNotDeepOrStrict(err1, new Error('foo2'), assert.AssertionError);

0 commit comments

Comments
 (0)