-
Notifications
You must be signed in to change notification settings - Fork 30k
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
assert, util: *DeepEqual() handles ArrayBuffers #22266
assert, util: *DeepEqual() handles ArrayBuffers #22266
Conversation
Hey, thank you so much for contributing to Node! We appreciate it. Have you seen this PR: https://github.com/nodejs/node/pull/22258/files it reworks cc @BridgeAR |
No, I actually hadn't seen that PR. Funny coincidence that I made this one the same day. Seems like they shouldn't have any conflicts. |
lib/internal/util/comparisons.js
Outdated
@@ -46,6 +46,10 @@ function isObjectOrArrayTag(tag) { | |||
return tag === '[object Array]' || tag === '[object Object]'; | |||
} | |||
|
|||
function isArrayBuffer(tag) { | |||
return tag === '[object ArrayBuffer]' || tag === '[object SharedArrayBuffer]'; | |||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use util.types.isAnyArrayBuffer
instead. This value could be manipulated by using the Symbol.toStringTag
.
lib/internal/util/comparisons.js
Outdated
@@ -116,6 +120,11 @@ function strictDeepEqual(val1, val2, memos) { | |||
// if they both only contain numeric keys, we don't need to exam further | |||
return keyCheck(val1, val2, true, memos, val1.length, | |||
val2.length); | |||
} else if (isArrayBuffer(val1Tag)) { | |||
if (!areSimilarTypedArrays(new Uint8Array(val1), | |||
new Uint8Array(val2), 300)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please change this to if (val1.byteLength !== val2.byteLength || compare(new Uint8Array(val1), new Uint8Array(val2)) !== 0) {
. Otherwise the value is converted twice.
lib/internal/util/comparisons.js
Outdated
@@ -170,6 +179,12 @@ function looseDeepEqual(val1, val2, memos) { | |||
} else if (isArguments(val1Tag) || isArguments(val2Tag)) { | |||
return false; | |||
} | |||
if (isArrayBuffer(val1Tag) && isArrayBuffer(val2Tag)) { | |||
if (!areSimilarTypedArrays(new Uint8Array(val1), | |||
new Uint8Array(val2), 300)) { |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
[new ArrayBuffer(2), new SharedArrayBuffer(3)], | ||
[ | ||
new Uint8Array(new ArrayBuffer(3)).fill(1).buffer, | ||
new Uint8Array(new SharedArrayBuffer(3)).fill(2).buffer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should already fail because of the different type in strict mode. I would therefore change the test to fill(1)
on both sides. In that case it would probably pass in loose mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is already a test for that under looseEqualArrayPairs
. Here I'm testing that buffers of different types with the same length but different contents are neither loosely nor strictly equal.
This is great! Thanks a lot for the addition. Just left a few comments. I am still uncertain how it's possible to have a better error output tough. |
Yeah, I was also wondering whether the diff message could be improved. I think it is currently inferred based on the output of |
@calebsander yes, it does use |
When passing an util.inspect(Buffer.from([1, 2, 3])) // <Buffer 01 02 03>
util.inspect(new Uint8Array([1, 2, 3]).buffer) // ArrayBuffer { byteLength: 3 } I think it would make sense for the result to look something like |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this and the technical changes. Ping @nodejs/tsc since this is a breaking change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@calebsander would you be so kind and rebase? In that case the PR should be ready. |
Previously, all ArrayBuffers were considered equal in assert.deepEqual() and assert.deepStrictEqual(). Now, ArrayBuffers and SharedArrayBuffers must have the same byte lengths and contents to be considered equal. In loose mode, an ArrayBuffer is considered equal to a SharedArrayBuffer if they have the same contents, whereas in strict mode, the buffers must be both ArrayBuffers or both SharedArrayBuffers.
Done |
Landed in 439b75b @calebsander thanks a lot for your contribution and congratulations on your first commit to Node.js! 🎉 |
Previously, all ArrayBuffers were considered equal in assert.deepEqual() and assert.deepStrictEqual(). Now, ArrayBuffers and SharedArrayBuffers must have the same byte lengths and contents to be considered equal. In loose mode, an ArrayBuffer is considered equal to a SharedArrayBuffer if they have the same contents, whereas in strict mode, the buffers must be both ArrayBuffers or both SharedArrayBuffers. PR-URL: nodejs#22266 Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Tiancheng "Timothy" Gu <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: James M Snell <[email protected]>
Previously, all
ArrayBuffer
s andSharedArrayBuffer
s were considered equal inassert.deepEqual()
,assert.deepStrictEqual()
, andutil.isDeepStrictEqual()
. Now,ArrayBuffer
s andSharedArrayBuffer
s must have the same byte lengths and contents to be considered equal. In loose mode, anArrayBuffer
is considered equal to aSharedArrayBuffer
if they have the same contents, whereas in strict mode, the buffers must be bothArrayBuffer
s or bothSharedArrayBuffer
s.Here are 2 examples, both of which succeeded before but now throw:
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes