Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

assert: improve deep equal map #14501

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 18 additions & 27 deletions lib/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -353,10 +353,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
Expand All @@ -377,7 +373,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))
Expand Down Expand Up @@ -453,10 +449,13 @@ function mapHasLoosePrim(a, b, key1, memo, item1, item2) {
return false;

for (const val of setA) {
if (!setHasEqualElement(setB, val, false, memo))
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;
}

Expand All @@ -476,34 +475,26 @@ 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))) {
if (typeof key === 'object' && key !== null) {
if (set === null) {
set = new Set();
}
set.add(key);
} 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;
}
} else if (!innerDeepEqual(item1, item2, strict, memo) &&
(strict || !mapHasLoosePrim(a, b, key, memo, item1, item2))) {
return false;
}
}

Expand Down