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),