Skip to content

assert: add support for Set and Map #2315

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
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
37 changes: 37 additions & 0 deletions lib/assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,36 @@ function isArguments(object) {
return Object.prototype.toString.call(object) == '[object Arguments]';
}

function compareMaps(a, b, strict) {
// check size of the maps
if (a.size !== b.size)
return false;

// iterate over all keys and check if they exist in the other
for (let kvs of a) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let is not faster than var, if this code is hotcode, we would be better to use var instead of let.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I wouldn't consider this to be hot code, but probably should stick with var for now?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is not faster, but performs equally in this kind of situation: http://jsperf.com/let-vs-var-iteration
I believe the optimization arrived with V8 4.4.

const key = kvs[0];
const val = kvs[1];
if (!b.has(key)) {
return false;
}

if (!_deepEqual(val, b.get(key), strict))
return false;
}
return true;
}

function compareSets(a, b) {
if (a.size !== b.size)
return false;

for (let item of a) {
if (!b.has(item))
return false;
}
return true;
}

function objEquiv(a, b, strict) {
if (a === null || a === undefined || b === null || b === undefined)
return false;
Expand All @@ -202,6 +232,13 @@ function objEquiv(a, b, strict) {
b = pSlice.call(b);
return _deepEqual(a, b, strict);
}
const aStr = Object.prototype.toString.call(a);
const bStr = Object.prototype.toString.call(b);
if (aStr === '[object Map]' && bStr === '[object Map]') {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We does not support WeakMap and WeakSet ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, not yet. Was going to knock that out next.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do plan on supporting them ? They do not expose iterators.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we cannot measure the equality of WeakMap and WeakSet...
If so, we cannot support WeakMap and WeakSet. would we be better to note the supported types in document?

return compareMaps(a, b, strict);
} else if (aStr === '[object Set]' && bStr === '[object Set]') {
return compareSets(a, b);
}
var ka = Object.keys(a),
kb = Object.keys(b),
key, i;
Expand Down
59 changes: 59 additions & 0 deletions test/parallel/test-assert.js
Original file line number Diff line number Diff line change
Expand Up @@ -465,4 +465,63 @@ testBlockTypeError(assert.doesNotThrow, null);
testBlockTypeError(assert.throws, undefined);
testBlockTypeError(assert.doesNotThrow, undefined);

// Map deep equal, deep strict equal
const map1 = new Map();
const map2 = new Map();
map1.set('1', '2');
map2.set('1', '2');
assert.deepEqual(map1, map2);
map1.set('2', '2');
assert.throws(function() {
assert.deepEqual(map1, map2);
});
map1.delete('2');
map2.set('1', 2);
assert.deepEqual(map1, map2);
assert.throws(function() {
assert.deepStrictEqual(map1, map2);
});
map1.clear();
map2.clear();
map1.set(NaN, 'not a number');
map2.set(NaN, 'not a number');
assert.deepEqual(map1, map2);
map1.clear();
map2.clear();
map1.set('1', { name: 'test' });
map2.set('1', { name: 'test' });
assert.deepStrictEqual(map1, map2);
map1.clear();
map2.clear();
// verify that insertion order doesn't matter
map1.set('1', '1');
map1.set('2', '2');
map2.set('2', '2');
map2.set('1', '1');
assert.deepEqual(map1, map2);

// Set deep equal, deep strict equal
var set1 = new Set();
var set2 = new Set();
set1.add(1);
set2.add(1);
assert.deepEqual(set1, set2);
set1.add(2);
assert.throws(function() {
assert.deepEqual(set1, set2);
});
set1.delete(2);
set2.delete(1);
set2.add('1');
// throws because we can't really check without being strict
assert.throws(function() {
assert.deepEqual(set1, set2);
});

assert.deepEqual(new Set([NaN]), new Set([NaN]));
// verify that insertion order doesn't matter
set1 = new Set([1, 2]);
set2 = new Set([2, 1]);
assert.deepEqual(set1, set2);

console.log('All OK');