|
|
@ -360,10 +360,6 @@ function setEquiv(a, b, strict, memo) { |
|
|
|
// This is a lazily initiated Set of entries which have to be compared
|
|
|
|
// pairwise.
|
|
|
|
var set = null; |
|
|
|
// When the sets contain only value types (eg, lots of numbers), and we're in
|
|
|
|
// strict mode or if all entries strictly match, we don't need to match the
|
|
|
|
// entries in a pairwise way. In that case this initialization is done lazily
|
|
|
|
// to avoid the allocation & bookkeeping cost.
|
|
|
|
for (const val of a) { |
|
|
|
// Note: Checking for the objects first improves the performance for object
|
|
|
|
// heavy sets but it is a minor slow down for primitives. As they are fast
|
|
|
@ -384,7 +380,7 @@ function setEquiv(a, b, strict, memo) { |
|
|
|
|
|
|
|
if (set !== null) { |
|
|
|
for (const val of b) { |
|
|
|
// In non-strict-mode we have to check if a primitive value is already
|
|
|
|
// We have to check if a primitive value is already
|
|
|
|
// matching and only if it's not, go hunting for it.
|
|
|
|
if (typeof val === 'object' && val !== null) { |
|
|
|
if (!setHasEqualElement(set, val, strict, memo)) |
|
|
@ -460,10 +456,13 @@ function mapHasLoosePrim(a, b, key1, memo, item1, item2) { |
|
|
|
return false; |
|
|
|
|
|
|
|
for (const val of setA) { |
|
|
|
if (typeof val === 'object' && val !== null) { |
|
|
|
if (!setHasEqualElement(setB, val, false, memo)) |
|
|
|
return false; |
|
|
|
} else if (!setB.has(val) && !setHasLoosePrim(setA, setB, val)) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return true; |
|
|
|
} |
|
|
|
|
|
|
@ -483,36 +482,28 @@ function mapHasEqualEntry(set, map, key1, item1, strict, memo) { |
|
|
|
} |
|
|
|
|
|
|
|
function mapEquiv(a, b, strict, memo) { |
|
|
|
// Caveat: In non-strict mode, this implementation does not handle cases
|
|
|
|
// where maps contain two equivalent-but-not-reference-equal keys.
|
|
|
|
if (a.size !== b.size) |
|
|
|
return false; |
|
|
|
|
|
|
|
var set = null; |
|
|
|
|
|
|
|
for (const [key, item1] of a) { |
|
|
|
// By directly retrieving the value we prevent another b.has(key) check in
|
|
|
|
// almost all possible cases.
|
|
|
|
const item2 = b.get(key); |
|
|
|
if (item2 === undefined) { |
|
|
|
// Just like setEquiv above but in addition we have to make sure the
|
|
|
|
// values are also equal.
|
|
|
|
if (typeof key === 'object' && key !== null) { |
|
|
|
if (set === null) { |
|
|
|
set = new Set(); |
|
|
|
} |
|
|
|
set.add(key); |
|
|
|
// Note: we do not have to pass memo in this case as at least one item
|
|
|
|
// is undefined.
|
|
|
|
} else if ((!innerDeepEqual(item1, item2, strict) || !b.has(key)) && |
|
|
|
(strict || !mapHasLoosePrim(a, b, key, memo, item1))) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
} else if (!innerDeepEqual(item1, item2, strict, memo) && |
|
|
|
} else { |
|
|
|
// By directly retrieving the value we prevent another b.has(key) check in
|
|
|
|
// almost all possible cases.
|
|
|
|
const item2 = b.get(key); |
|
|
|
if ((item2 === undefined && !b.has(key) || |
|
|
|
!innerDeepEqual(item1, item2, strict, memo)) && |
|
|
|
(strict || !mapHasLoosePrim(a, b, key, memo, item1, item2))) { |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (set !== null) { |
|
|
|
for (const [key, item] of b) { |
|
|
|