Skip to content

Commit 0ce4a4a

Browse files
committed
assert: make partialDeepStrictEqual throw when comparing [0] with [-0]
Fixes: #56230
1 parent a1d980c commit 0ce4a4a

File tree

2 files changed

+60
-14
lines changed

2 files changed

+60
-14
lines changed

lib/assert.js

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -507,31 +507,52 @@ function partiallyCompareArrays(actual, expected, comparedObjects) {
507507
// Create a map to count occurrences of each element in the expected array
508508
const expectedCounts = new SafeMap();
509509
for (const expectedItem of expected) {
510-
let found = false;
511-
for (const { 0: key, 1: count } of expectedCounts) {
512-
if (isDeepStrictEqual(key, expectedItem)) {
513-
expectedCounts.set(key, count + 1);
514-
found = true;
515-
break;
510+
const expectedIsMinusZero = ObjectIs(expectedItem, -0);
511+
if (ObjectIs(expectedItem, 0) || expectedIsMinusZero) {
512+
// Handle 0 and -0 separately to avoid map key collisions
513+
const zeroKey = expectedIsMinusZero ? '-0' : '0';
514+
expectedCounts.set(zeroKey, (expectedCounts.get(zeroKey) || 0) + 1);
515+
} else {
516+
let found = false;
517+
for (const { 0: key, 1: count } of expectedCounts) {
518+
if (isDeepStrictEqual(key, expectedItem)) {
519+
expectedCounts.set(key, count + 1);
520+
found = true;
521+
break;
522+
}
523+
}
524+
if (!found) {
525+
expectedCounts.set(expectedItem, 1);
516526
}
517-
}
518-
if (!found) {
519-
expectedCounts.set(expectedItem, 1);
520527
}
521528
}
522529

523530
const safeActual = new SafeArrayIterator(actual);
524531

525532
// Create a map to count occurrences of relevant elements in the actual array
526533
for (const actualItem of safeActual) {
527-
for (const { 0: key, 1: count } of expectedCounts) {
528-
if (isDeepStrictEqual(key, actualItem)) {
534+
const actualIsMinusZero = ObjectIs(actualItem, -0);
535+
const zeroKey = actualIsMinusZero ? '-0' : '0';
536+
537+
if (ObjectIs(actualItem, 0) || actualIsMinusZero) {
538+
if (expectedCounts.has(zeroKey)) {
539+
const count = expectedCounts.get(zeroKey);
529540
if (count === 1) {
530-
expectedCounts.delete(key);
541+
expectedCounts.delete(zeroKey);
531542
} else {
532-
expectedCounts.set(key, count - 1);
543+
expectedCounts.set(zeroKey, count - 1);
544+
}
545+
}
546+
} else {
547+
for (const { 0: expectedItem, 1: count } of expectedCounts) {
548+
if (isDeepStrictEqual(expectedItem, actualItem)) {
549+
if (count === 1) {
550+
expectedCounts.delete(expectedItem);
551+
} else {
552+
expectedCounts.set(expectedItem, count - 1);
553+
}
554+
break;
533555
}
534-
break;
535556
}
536557
}
537558
}

test/parallel/test-assert-objects.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,21 @@ describe('Object Comparison Tests', () => {
9797
actual: [1, 'two', true],
9898
expected: [1, 'two', false],
9999
},
100+
{
101+
description: 'throws when comparing [0] with [-0]',
102+
actual: [0],
103+
expected: [-0],
104+
},
105+
{
106+
description: 'throws when comparing [0, 0, 0] with [0, -0]',
107+
actual: [0, 0, 0],
108+
expected: [0, -0],
109+
},
110+
{
111+
description: 'throws when comparing [-0] with [0]',
112+
actual: [0],
113+
expected: [-0],
114+
},
100115
{
101116
description:
102117
'throws when comparing two Date objects with different times',
@@ -385,6 +400,16 @@ describe('Object Comparison Tests', () => {
385400
actual: [1, 'two', true],
386401
expected: [1, 'two', true],
387402
},
403+
{
404+
description: 'compares [0] with [0]',
405+
actual: [0],
406+
expected: [0],
407+
},
408+
{
409+
description: 'compares [-0] with [-0]',
410+
actual: [-0],
411+
expected: [-0],
412+
},
388413
{
389414
description: 'compares two Date objects with the same time',
390415
actual: new Date(0),

0 commit comments

Comments
 (0)