From d1072deafb5f0f9a7fcf94a0b2eec8570bf541f5 Mon Sep 17 00:00:00 2001
From: Giovanni <github@puskin.it>
Date: Thu, 12 Dec 2024 11:54:48 +0100
Subject: [PATCH] assert: make partialDeepStrictEqual throw when comparing [0]
 with [-0]

Fixes: https://github.com/nodejs/node/issues/56230
---
 lib/assert.js                        | 49 ++++++++++++++++++++--------
 test/parallel/test-assert-objects.js | 20 ++++++++++++
 2 files changed, 55 insertions(+), 14 deletions(-)

diff --git a/lib/assert.js b/lib/assert.js
index a2991a096ac0816..9226c6b4c741a8f 100644
--- a/lib/assert.js
+++ b/lib/assert.js
@@ -507,16 +507,23 @@ function partiallyCompareArrays(actual, expected, comparedObjects) {
   // Create a map to count occurrences of each element in the expected array
   const expectedCounts = new SafeMap();
   for (const expectedItem of expected) {
-    let found = false;
-    for (const { 0: key, 1: count } of expectedCounts) {
-      if (isDeepStrictEqual(key, expectedItem)) {
-        expectedCounts.set(key, count + 1);
-        found = true;
-        break;
+    const expectedIsMinusZero = ObjectIs(expectedItem, -0);
+    if (ObjectIs(expectedItem, 0) || expectedIsMinusZero) {
+      // Handle 0 and -0 separately to avoid map key collisions
+      const zeroKey = expectedIsMinusZero ? '-0' : '0';
+      expectedCounts.set(zeroKey, (expectedCounts.get(zeroKey) || 0) + 1);
+    } else {
+      let found = false;
+      for (const { 0: key, 1: count } of expectedCounts) {
+        if (isDeepStrictEqual(key, expectedItem)) {
+          expectedCounts.set(key, count + 1);
+          found = true;
+          break;
+        }
+      }
+      if (!found) {
+        expectedCounts.set(expectedItem, 1);
       }
-    }
-    if (!found) {
-      expectedCounts.set(expectedItem, 1);
     }
   }
 
@@ -524,14 +531,28 @@ function partiallyCompareArrays(actual, expected, comparedObjects) {
 
   // Create a map to count occurrences of relevant elements in the actual array
   for (const actualItem of safeActual) {
-    for (const { 0: key, 1: count } of expectedCounts) {
-      if (isDeepStrictEqual(key, actualItem)) {
+    const actualIsMinusZero = ObjectIs(actualItem, -0);
+    const zeroKey = actualIsMinusZero ? '-0' : '0';
+
+    if (ObjectIs(actualItem, 0) || actualIsMinusZero) {
+      if (expectedCounts.has(zeroKey)) {
+        const count = expectedCounts.get(zeroKey);
         if (count === 1) {
-          expectedCounts.delete(key);
+          expectedCounts.delete(zeroKey);
         } else {
-          expectedCounts.set(key, count - 1);
+          expectedCounts.set(zeroKey, count - 1);
+        }
+      }
+    } else {
+      for (const { 0: expectedItem, 1: count } of expectedCounts) {
+        if (isDeepStrictEqual(expectedItem, actualItem)) {
+          if (count === 1) {
+            expectedCounts.delete(expectedItem);
+          } else {
+            expectedCounts.set(expectedItem, count - 1);
+          }
+          break;
         }
-        break;
       }
     }
   }
diff --git a/test/parallel/test-assert-objects.js b/test/parallel/test-assert-objects.js
index 3f02ff3c274daa3..3404ff4f6f5e25f 100644
--- a/test/parallel/test-assert-objects.js
+++ b/test/parallel/test-assert-objects.js
@@ -97,6 +97,16 @@ describe('Object Comparison Tests', () => {
           actual: [1, 'two', true],
           expected: [1, 'two', false],
         },
+        {
+          description: 'throws when comparing [0] with [-0]',
+          actual: [0],
+          expected: [-0],
+        },
+        {
+          description: 'throws when comparing [-0] with [0]',
+          actual: [0],
+          expected: [-0],
+        },
         {
           description:
             'throws when comparing two Date objects with different times',
@@ -385,6 +395,16 @@ describe('Object Comparison Tests', () => {
         actual: [1, 'two', true],
         expected: [1, 'two', true],
       },
+      {
+        description: 'compares [0] with [0]',
+        actual: [0],
+        expected: [0],
+      },
+      {
+        description: 'compares [-0] with [-0]',
+        actual: [-0],
+        expected: [-0],
+      },
       {
         description: 'compares two Date objects with the same time',
         actual: new Date(0),