assert: allow circular references
assert.deepEqual() and assert.deepStrictEqual() will no longer throw a RangeError if passed objects with circular references. PR-URL: https://github.com/nodejs/node/pull/6432 Fixes: https://github.com/nodejs/node/issues/6416 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net>
This commit is contained in:
parent
c2bbfe2a5c
commit
d3aafd02ef
@ -143,7 +143,7 @@ assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) {
|
||||
}
|
||||
};
|
||||
|
||||
function _deepEqual(actual, expected, strict) {
|
||||
function _deepEqual(actual, expected, strict, memos) {
|
||||
// 7.1. All identical values are equivalent, as determined by ===.
|
||||
if (actual === expected) {
|
||||
return true;
|
||||
@ -191,7 +191,19 @@ 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);
|
||||
memos = memos || {actual: [], expected: []};
|
||||
|
||||
const actualIndex = memos.actual.indexOf(actual);
|
||||
if (actualIndex !== -1) {
|
||||
if (actualIndex === memos.expected.indexOf(expected)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
memos.actual.push(actual);
|
||||
memos.expected.push(expected);
|
||||
|
||||
return objEquiv(actual, expected, strict, memos);
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,7 +211,7 @@ 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
|
||||
@ -235,7 +247,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;
|
||||
}
|
||||
|
@ -381,25 +381,33 @@ try {
|
||||
|
||||
assert.ok(threw);
|
||||
|
||||
// GH-207. Make sure deepEqual doesn't loop forever on circular refs
|
||||
var b = {};
|
||||
b.b = b;
|
||||
// https://github.com/nodejs/node/issues/6416
|
||||
// Make sure circular refs don't throw.
|
||||
{
|
||||
const b = {};
|
||||
b.b = b;
|
||||
|
||||
var c = {};
|
||||
c.b = c;
|
||||
const 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));
|
||||
|
||||
const d = {};
|
||||
d.a = 1;
|
||||
d.b = d;
|
||||
|
||||
const e = {};
|
||||
e.a = 1;
|
||||
e.b = e.a;
|
||||
|
||||
a.throws(makeBlock(a.deepEqual, d, e), /AssertionError/);
|
||||
a.throws(makeBlock(a.deepStrictEqual, d, e), /AssertionError/);
|
||||
}
|
||||
|
||||
// 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};
|
||||
|
Loading…
x
Reference in New Issue
Block a user