deep-eql icon indicating copy to clipboard operation
deep-eql copied to clipboard

fix: check array's custom properties

Open lucasfcosta opened this issue 8 years ago • 6 comments

Hi, folks!

While working on sinonjs/sinon#1322 I've found out that we're not checking for custom properties in arrays when doing deep equality on them.

While this might be considered a bad practice, it is indeed possible and more common that we'd like it to be, so this fix may come in handy.

Before this commit, two different arrays, like these ones, would yield false positives:

var arrOne = [1, 2, 3]
arrOne.foo = 'bar'

var arrTwo = [1, 2, 3]
arrTwo.foo = 'baz'

deepEqual(arrOne, arrTwo) // true

Also, I didn't use getEnumerableKeys when getting the Array's properties because we don't want to check the Array prototype, because when dealing with Buffers or TypedArrays, they might have different offsets due to the fact of being binary data and this could cause problems. Especially when using Buffer itself.

If you don't mind I could add a check to avoid comparing the offset property on TypedArrays only so that we can compare the other properties in the array prototype, but I don't that would be productive.

I also added tests for this behavior.

lucasfcosta avatar Jun 01 '17 00:06 lucasfcosta

I'm on the fence about this, but regardless of those opinions, I would say this is probably a feat and I feel like its a BREAKING CHANGE as there is no documentation to suggest this would work but doesn't.

The code itself is fine, again regardless of my fence-sitting. But I would also say that if this is true:

Also, I didn't use getEnumerableKeys when getting the Array's properties because we don't want to check the Array prototype, because when dealing with Buffers or TypedArrays, they might have different offsets due to the fact of being binary data and this could cause problems. Especially when using Buffer itself.

Then we should write tests that validate against these cases to ensure that later on a PR is not made to optimise this path and use getEnumerableKeys


Sidebar: Also, looks like node 0.12 is failing, but as it is EOL maybe this PR (especially if it is a breaking change) could drop Node 0.12 support?

keithamus avatar Jun 01 '17 10:06 keithamus

Hey @lucasfcosta, great job!

The most common case of having to deal with non-index keys is result of RegExp#exec.

Please, consider

/a/.exec("a").should.eql(["a"])

If I read correctly, PR makes that throw. Is this something we are OK with? It is impossible to special-case exec's result without patching it (pretty neat in ES6, though).

shvaikalesh avatar Jun 01 '17 11:06 shvaikalesh

@keithamus Thanks for your feedback 😄.

We already have tests that deal with this. The Buffer one is an example. Even though two buffers are equal, they have different offset properties and thus this will cause this test to fail.

IMO we should indeed drop v0.12. I've just ammended a change to my commit for that.

@shvaikalesh that's a good question. I'd like it to pass, but I think it's more adequate to let people deal with this by adding the missing properties to the expected result than to throw incorrectly on the other cases, after all, this is how the real result of running exec looks like.

lucasfcosta avatar Jun 01 '17 22:06 lucasfcosta

@lucasfcosta I'm late to the party but this change makes sense to me. Were you able to compare the performance of .every vs for in?

meeber avatar Aug 05 '17 12:08 meeber

Hi @meeber, unfortunately I didn't. I've been very busy in the last few weeks because I'll be moving to London in the next two months so I'm kind of getting things done around here in Brazil so that I can be ready to move ASAP. So I'd like to say sorry for not being able to be as present as I've been before. Hopefully I'll have some free time this weekend so that I can check this and finish this PR and get back to contributing more frequently as soon as things are set up.

Btw, thanks everyone for keeping things going, I've seen you've done some amazing work recently.

lucasfcosta avatar Aug 07 '17 19:08 lucasfcosta

@lucasfcosta Sounds exciting! Congrats on the big move! Take your time with things, Chai will still be here when you're ready.

meeber avatar Aug 08 '17 01:08 meeber