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

util.isDeepStrictEqual would be better to return false to compare WeakMap/WeakSet #18227

Closed
yosuke-furukawa opened this issue Jan 18, 2018 · 14 comments
Labels
help wanted Issues that need assistance from volunteers or PRs that need help to proceed. util Issues and PRs related to the built-in util module.

Comments

@yosuke-furukawa
Copy link
Member

  • 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.

@BridgeAR
Copy link
Member

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

@yosuke-furukawa
Copy link
Member Author

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.

@BridgeAR
Copy link
Member

@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.

@yosuke-furukawa
Copy link
Member Author

yosuke-furukawa commented Jan 18, 2018

+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".

@benjamingr
Copy link
Member

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.

@BridgeAR
Copy link
Member

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.

@addaleax addaleax added util Issues and PRs related to the built-in util module. tsc-review labels Feb 7, 2018
@addaleax
Copy link
Member

addaleax commented Feb 7, 2018

/cc @nodejs/tsc

@ofrobots
Copy link
Contributor

ofrobots commented Feb 7, 2018

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

@mcollina
Copy link
Member

mcollina commented Feb 8, 2018

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.

@cjihrig
Copy link
Contributor

cjihrig commented Feb 8, 2018

I agree with @mcollina.

@wza62692371
Copy link

@jasnell jasnell added the help wanted Issues that need assistance from volunteers or PRs that need help to proceed. label Jun 26, 2020
@BridgeAR
Copy link
Member

After looking into this again, I changed my mind / I agree with the suggested behavior change.

@yosuke-furukawa
Copy link
Member Author

wow. I am surprised this issue is still open.
#53495 this PR pushed this discussion. I don't change my mind. if the PR is merged, this issue will be closed.

@benjamingr
Copy link
Member

The PR landed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Issues that need assistance from volunteers or PRs that need help to proceed. util Issues and PRs related to the built-in util module.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants