Node: util.isDeepStrictEqual would be better to return false to compare WeakMap/WeakSet

Created on 18 Jan 2018  路  11Comments  路  Source: nodejs/node

  • Version:
    v9.4.0

  • Platform:
    OSX, Linux, Windows

  • Subsystem:
    N/A

util.isDeepStrictEqual always returns true when WeakMap/WeakSet comparison.

const util = require('util');
const wm1 = new WeakMap();
const wm2 = new WeakMap();
const key = {};
wm1.set(key, 1);
wm2.set(key, 2);
console.log(util.isDeepStrictEqual(wm1, wm2)); // true

this is because WeakMap|WeakSet.prototype.valueOf always returns empty object.
I know WeakMap / WeakSet do not have an API to show the full content, and they depends on GC so those collection comparison is very difficult.

However, this behavior (always return true) seems to be curious for me. I think it would be better to always return false.

help wanted util

Most helpful comment

Without reading the discussion (so I stay with intuition) - I'd expect deepEqual to return true if and only if the two WeakMap or WeakSets are to the same reference.

All 11 comments

I thought about this before and I feel like the current way is the more correct one.

The comparison always relies on what is possible to detect. Since Weap(Map|Set) entries do not provide a way to compare them, they should just be ignored.

The suggested change will also make it impossible to distinguish differences like these:

const a = new WeakMap();
const b = new WeakMap();
const c = new WeakMap();
c.isClearlyDifferent = true;

util.isDeepStrictEqual(a, b); // => false even though they are indeed equal
util.isDeepStrictEqual(a, c); // => false without distinguishing this from the former check

hm, but I think WeakMap / WeakSet are not suitable to compare the equivalence, so we would be better to return false than true.

Any WeakMap and WeakSet comparison always return true is very confusing. false is also confusing but it has the reason (WeakMap and WeakSet is not suitable to compare).

Anyway, we would be better to add a note on documentation.

@yosuke-furukawa I am definitely +1 for updating the docs! That should also apply to assert.deepStrictEqual.

About being right or wrong: I think there is no _definite_ right approach. Only one way we want to decide on. So far it was the one in place right now (maybe by chance) and I personally feel it is the better one.

I feel returning true is not so confusing anymore after checking the documentation how weak entries are saved and after thinking about how it is possible to compare things in JS.

+1 for updating the docs

Thank you, I will send another PR.

@nodejs/collaborators
I would like to hear other members' opinion.
My opinion is "WeakMap/Set are not comparable, so util.isDeepStrictEqual would be better to return false than return true".

Without reading the discussion (so I stay with intuition) - I'd expect deepEqual to return true if and only if the two WeakMap or WeakSets are to the same reference.

I ask everyone to continue discussing this in #18248. Thanks :-)

@benjamingr that would be a special handling of those and not be aligned with any other object.

/cc @nodejs/tsc

I'm +1 to what @benjamingr proposed above.

I am 馃憤 to:

  1. return true if the two objects are the same instance and return false otherwise
  2. throw consistently because two Weak* are not really comparable

We should also document the current behvior in our current/lts release lines.

I agree with @mcollina.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sandeepks1 picture sandeepks1  路  3Comments

danielstaleiny picture danielstaleiny  路  3Comments

fanjunzhi picture fanjunzhi  路  3Comments

akdor1154 picture akdor1154  路  3Comments

dfahlander picture dfahlander  路  3Comments