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 ===.
|
// 7.1. All identical values are equivalent, as determined by ===.
|
||||||
if (actual === expected) {
|
if (actual === expected) {
|
||||||
return true;
|
return true;
|
||||||
@ -191,7 +191,19 @@ function _deepEqual(actual, expected, strict) {
|
|||||||
// corresponding key, and an identical 'prototype' property. Note: this
|
// corresponding key, and an identical 'prototype' property. Note: this
|
||||||
// accounts for both named and indexed properties on Arrays.
|
// accounts for both named and indexed properties on Arrays.
|
||||||
} else {
|
} 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]';
|
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)
|
if (a === null || a === undefined || b === null || b === undefined)
|
||||||
return false;
|
return false;
|
||||||
// if one is a primitive, the other must be same
|
// if one is a primitive, the other must be same
|
||||||
@ -235,7 +247,8 @@ function objEquiv(a, b, strict) {
|
|||||||
//~~~possibly expensive deep test
|
//~~~possibly expensive deep test
|
||||||
for (i = ka.length - 1; i >= 0; i--) {
|
for (i = ka.length - 1; i >= 0; i--) {
|
||||||
key = ka[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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -381,25 +381,33 @@ try {
|
|||||||
|
|
||||||
assert.ok(threw);
|
assert.ok(threw);
|
||||||
|
|
||||||
// GH-207. Make sure deepEqual doesn't loop forever on circular refs
|
// https://github.com/nodejs/node/issues/6416
|
||||||
var b = {};
|
// Make sure circular refs don't throw.
|
||||||
b.b = b;
|
{
|
||||||
|
const b = {};
|
||||||
|
b.b = b;
|
||||||
|
|
||||||
var c = {};
|
const c = {};
|
||||||
c.b = c;
|
c.b = c;
|
||||||
|
|
||||||
var gotError = false;
|
a.doesNotThrow(makeBlock(a.deepEqual, b, c));
|
||||||
try {
|
a.doesNotThrow(makeBlock(a.deepStrictEqual, b, c));
|
||||||
assert.deepEqual(b, c);
|
|
||||||
} catch (e) {
|
const d = {};
|
||||||
gotError = true;
|
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.
|
// GH-7178. Ensure reflexivity of deepEqual with `arguments` objects.
|
||||||
var args = (function() { return arguments; })();
|
var args = (function() { return arguments; })();
|
||||||
a.throws(makeBlock(a.deepEqual, [], args));
|
a.throws(makeBlock(a.deepEqual, [], args));
|
||||||
a.throws(makeBlock(a.deepEqual, args, []));
|
a.throws(makeBlock(a.deepEqual, args, []));
|
||||||
assert.ok(gotError);
|
|
||||||
|
|
||||||
|
|
||||||
var circular = {y: 1};
|
var circular = {y: 1};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user