fix(testing): Compare circular objects (#2172)

The "equal" function keeps track of encountered objects by adding 
them to "seen". Encountered objects must be added to "seen" before 
the first recursive call to "compare" because otherwise the "compare"
function will infinitely recurse when comparing circular objects.
This commit is contained in:
Mathis Bullinger 2022-05-01 14:50:44 +02:00 committed by GitHub
parent 8ee4023df8
commit 3dd6843571
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 15 additions and 1 deletions

View File

@ -71,6 +71,7 @@ export function equal(c: unknown, d: unknown): boolean {
if (Object.keys(a || {}).length !== Object.keys(b || {}).length) {
return false;
}
seen.set(a, b);
if (isKeyedCollection(a) && isKeyedCollection(b)) {
if (a.size !== b.size) {
return false;
@ -108,7 +109,6 @@ export function equal(c: unknown, d: unknown): boolean {
return false;
}
}
seen.set(a, b);
if (a instanceof WeakRef || b instanceof WeakRef) {
if (!(a instanceof WeakRef && b instanceof WeakRef)) return false;
return compare(a.deref(), b.deref());

View File

@ -279,6 +279,20 @@ Deno.test("testingEqual", function (): void {
);
});
Deno.test("testingEqualCircular", () => {
const objA: { prop?: unknown } = {};
objA.prop = objA;
const objB: { prop?: unknown } = {};
objB.prop = objB;
assert(equal(objA, objB));
const mapA = new Map();
mapA.set("prop", mapA);
const mapB = new Map();
mapB.set("prop", mapB);
assert(equal(mapA, mapB));
});
Deno.test("testingNotEquals", function (): void {
const a = { foo: "bar" };
const b = { bar: "foo" };