diff --git a/lib/assert.js b/lib/assert.js index 6f340d8ef4e46b..73c4a1c444e2df 100644 --- a/lib/assert.js +++ b/lib/assert.js @@ -279,8 +279,15 @@ function innerDeepEqual(actual, expected, strict, memos) { position: 0 }; } else { - if (memos.actual.has(actual)) { - return memos.actual.get(actual) === memos.expected.get(expected); + // We prevent up to two map.has(x) calls by directly retrieving the value + // and checking for undefined. The map can only contain numbers, so it is + // safe to check for undefined only. + const expectedMemoA = memos.actual.get(actual); + if (expectedMemoA !== undefined) { + const expectedMemoB = memos.expected.get(expected); + if (expectedMemoB !== undefined) { + return expectedMemoA === expectedMemoB; + } } memos.position++; } diff --git a/test/parallel/test-assert-deep.js b/test/parallel/test-assert-deep.js index 74c4eb44ffc7b4..25e94b0f2fd187 100644 --- a/test/parallel/test-assert-deep.js +++ b/test/parallel/test-assert-deep.js @@ -303,6 +303,26 @@ assertOnlyDeepEqual( new Set([undefined]) ); +// Circular structures +{ + const a = {}; + const b = {}; + a.a = a; + b.a = {}; + b.a.a = a; + assertDeepAndStrictEqual(a, b); +} + +{ + const a = new Set(); + const b = new Set(); + const c = new Set(); + a.add(a); + b.add(b); + c.add(a); + assertDeepAndStrictEqual(b, c); +} + { const values = [ 123, diff --git a/test/parallel/test-assert.js b/test/parallel/test-assert.js index ab45aa6c4b63c4..98c0f9eef2994f 100644 --- a/test/parallel/test-assert.js +++ b/test/parallel/test-assert.js @@ -550,8 +550,8 @@ a.throws(makeBlock(thrower, TypeError), function(err) { const h = {ref: g}; - a.throws(makeBlock(a.deepEqual, f, h), /AssertionError/); - a.throws(makeBlock(a.deepStrictEqual, f, h), /AssertionError/); + a.doesNotThrow(makeBlock(a.deepEqual, f, h)); + a.doesNotThrow(makeBlock(a.deepStrictEqual, f, h)); } // GH-7178. Ensure reflexivity of deepEqual with `arguments` objects. const args = (function() { return arguments; })();