-
-
Notifications
You must be signed in to change notification settings - Fork 696
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
Update deep-eql to version 1.0.0 🚀 #837
Conversation
Summary of issues:
var obja = Object.create({ tea: 'chai' })
, objb = Object.create({ tea: 'chai' });
assert.deepEqual(obja, objb); // Fails
var circularObject = {}
, secondCircularObject = {};
circularObject.field = circularObject;
secondCircularObject.field = secondCircularObject;
assert.deepEqual(circularObject, secondCircularObject); // Fails The second assertion feels like it should pass. I'm not sure how I feel about the first assertion. Should the "deepness" check extend up both objects' prototype chains? |
@meeber I totally agree that the example with circular objects should pass. |
I misinterpreted the situation regarding the first example: var obja = Object.create({ tea: 'chai' })
, objb = Object.create({ tea: 'chai' });
assert.deepEqual(obja, objb); // Fails The above test used to pass because the previous version of deep-eql checks all enumerable properties, both own and inherited, whereas the new version only checks own enumerable properties but also performs a strict equality comparison on the objects' prototypes. The new behavior is more in line with node's I think a strong argument could be made for any implementation:
Hell, you could even make an argument for any of the above implementations to also include non-enumerable properties. I don't think there's a single right answer here. Personally, I prefer the first (new deep-eql) or the third (old deep-eql) over the second (lodash and node's assert.deepEqual). But I don't currently have a preference between the first and third. Whatever we decide should be documented in deep-eql's readme and either noted or linked in chai's deep equal jsdoc. Thoughts @keithamus @lucasfcosta @vieiralucas @shvaikalesh? |
Regarding the second example: var circularObject = {}
, secondCircularObject = {};
circularObject.field = circularObject;
secondCircularObject.field = secondCircularObject;
assert.deepEqual(circularObject, secondCircularObject); // Fails There's actually a test in deep-eql demonstrating that such a comparison should indeed return false: it('returns false with recursive objects of differing values', function () {
var objectA = { foo: 1 };
var objectB = { foo: 1 };
objectA.bar = objectB;
objectB.bar = objectA;
assert(eql(objectA, objectB) === false,
'eql({ foo: 1, bar: -> }, { foo: 1, bar: <- }) === false');
}); I don't follow the logic on why this comparison should return false. @keithamus help! |
@meeber thanks for the detailed description! Regarding the circular reference, since you mentioned |
The failing tests from this PR seem to be the only real blocker currently for a 4.0 canary release. It's just a matter of coming to an understanding on the desired behavior for a couple scenarios. Pinging @keithamus @lucasfcosta @vieiralucas @shvaikalesh for feedback! |
Ah sorry, yes, forgot about this one. My opinion is that we should do the old behaviour wherever we can. The intent of the rewrite was not to break the fundamentals of how it worked like this, so these are, IMO bugs |
Regarding the first issue: The new "bugged" behavior of performing a strict equality check between the objects' prototypes is actually more in-line with how Node's Regarding the second issue: I haven't looked too closely at what's causing the failed test with circular dependencies in otherwise empty objects but I suspect it's related to these lines temporarily setting the operands to |
To me the first option describe by @meeber LGT.M
As @lucasfcosta said. |
Hmm, I have thought about it again and I'm not sure our users would like the new behavior. Also, I don't think performance will be much of a problem since we're a testing library and won't be running on production environments, our number 1 priority should be correctness. I vote with @keithamus, let's correct What do you think? Would you guys like to vote? |
We seem to be at en impasse. On one hand, it could be painful for our users - such a fundemental change. On the other hand - both @meeber and @vieiralucas agree, and I suppose I do, that if prototypes differ then those two things aren't equal. I'm not sure what the right answer is. Perhaps we can solicit @shvaikalesh's opinion? |
Both options relate to the same concept: taking both objects' prototype into consideration when performing a deep equality comparison. They just take different paths to get there. Old: Cycle through both own and inherited properties and perform a deep equal on each one. New: Cycle through own properties only but also perform a strict equal on the objects' prototypes. I lean toward the old implementation because then it wouldn't be a breaking change. And then I lean toward the new implementation because it's more in line with Node's You know what, I'm gonna change my vote to "keep the old implementation unless we can come up with a strong reason why the new implementation is not only better, but so much better that it justifies a breaking change". |
Two objects are equal if:
Every item of the list may be a requirement for implementing deep equal algo, depending on strictness and our free time 😄 . And every each of them are correct. But I think we should choose the most mainstream one (lodash) and not break compat. |
Switching to lodash's algorithm will be a pretty big breaking change though, not only on the topic of prototypes/inherited properties, but also concepts like +0/-0. |
Yeah I think picking another implementation, while saving us time, would A) deviate further from what we're already breaking and B) prevent us from doing things like changing/adding features at the cadence we would like to. I don't think it would be too significant to get these failing tests passing in deep-eql, and I think in the interests of getting 4.0 done, we should just get it working, and think about possibly breaking this later (if ever). |
Hello lovely humans,
deep-eql just published its new version 1.0.0.
This version is not covered by your current version range.
Without accepting this pull request your project will work just like it did before. There might be a bunch of new features, fixes and perf improvements that the maintainers worked on for you though.
I recommend you look into these changes and try to get onto the latest version of deep-eql.
Given that you have a decent test suite, a passing build is a strong indicator that you can take advantage of these changes by merging the proposed change into your project. Otherwise this branch is a great starting point for you to work on the update.
Do you have any ideas how I could improve these pull requests? Did I report anything you think isn’t right?
Are you unsure about how things are supposed to work?
There is a collection of frequently asked questions and while I’m just a bot, there is a group of people who are happy to teach me new things. Let them know.
Good luck with your project ✨
You rock!
🌴