Skip to content

Commit

Permalink
assert: allow circular references
Browse files Browse the repository at this point in the history
assert.deepEqual() and assert.deepStrictEqual() will no longer throw a
RangeError if passed objects with circular references.

Refs: strager/node@56dbd80
Fixes: nodejs#6416
  • Loading branch information
Trott committed Apr 27, 2016
1 parent 3cdb506 commit 70a889b
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 12 deletions.
16 changes: 12 additions & 4 deletions lib/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) {
}
};

function _deepEqual(actual, expected, strict) {
function _deepEqual(actual, expected, strict, actualVisitedObjects) {
// 7.1. All identical values are equivalent, as determined by ===.
if (actual === expected) {
return true;
Expand Down Expand Up @@ -191,15 +191,22 @@ function _deepEqual(actual, expected, strict) {
// corresponding key, and an identical 'prototype' property. Note: this
// accounts for both named and indexed properties on Arrays.
} else {
return objEquiv(actual, expected, strict);
actualVisitedObjects = actualVisitedObjects || [];

if (actualVisitedObjects.includes(actual))
return true;

actualVisitedObjects.push(actual);

return objEquiv(actual, expected, strict, actualVisitedObjects);
}
}

function isArguments(object) {
return Object.prototype.toString.call(object) == '[object Arguments]';
}

function objEquiv(a, b, strict) {
function objEquiv(a, b, strict, actualVisitedObjects) {
if (a === null || a === undefined || b === null || b === undefined)
return false;
// if one is a primitive, the other must be same
Expand Down Expand Up @@ -235,7 +242,8 @@ function objEquiv(a, b, strict) {
//~~~possibly expensive deep test
for (i = ka.length - 1; i >= 0; i--) {
key = ka[i];
if (!_deepEqual(a[key], b[key], strict)) return false;
if (!_deepEqual(a[key], b[key], strict, actualVisitedObjects))
return false;
}
return true;
}
Expand Down
13 changes: 5 additions & 8 deletions test/parallel/test-assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,25 +381,22 @@ try {

assert.ok(threw);

// GH-207. Make sure deepEqual doesn't loop forever on circular refs
// https://github.com/nodejs/node/issues/6416
// Make sure circular refs don't throw.
var b = {};
b.b = b;

var c = {};
c.b = c;

var gotError = false;
try {
assert.deepEqual(b, c);
} catch (e) {
gotError = true;
}
a.doesNotThrow(makeBlock(a.deepEqual, b, c));
a.doesNotThrow(makeBlock(a.deepStrictEqual, b, c));


// GH-7178. Ensure reflexivity of deepEqual with `arguments` objects.
var args = (function() { return arguments; })();
a.throws(makeBlock(a.deepEqual, [], args));
a.throws(makeBlock(a.deepEqual, args, []));
assert.ok(gotError);


var circular = {y: 1};
Expand Down

0 comments on commit 70a889b

Please sign in to comment.