From 439b75b9c07405457798c1d6acb7dc144f46ea32 Mon Sep 17 00:00:00 2001 From: Caleb Sander Date: Fri, 10 Aug 2018 23:38:21 -0700 Subject: [PATCH] assert, util: *DeepEqual() handles ArrayBuffers 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: https://github.com/nodejs/node/pull/22266 Reviewed-By: Benjamin Gruenbaum Reviewed-By: Matteo Collina Reviewed-By: Tiancheng "Timothy" Gu Reviewed-By: Ruben Bridgewater Reviewed-By: James M Snell --- lib/internal/util/comparisons.js | 22 ++++++++++++++++++- .../test-assert-typedarray-deepequal.js | 21 +++++++++++++++--- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/lib/internal/util/comparisons.js b/lib/internal/util/comparisons.js index 729bd1c31efa68..9844e9d59c0c5a 100644 --- a/lib/internal/util/comparisons.js +++ b/lib/internal/util/comparisons.js @@ -3,7 +3,13 @@ const { compare } = process.binding('buffer'); const { isArrayBufferView } = require('internal/util/types'); const { internalBinding } = require('internal/bootstrap/loaders'); -const { isDate, isMap, isRegExp, isSet } = internalBinding('types'); +const { + isAnyArrayBuffer, + isDate, + isMap, + isRegExp, + isSet +} = internalBinding('types'); const { getOwnNonIndexProperties } = process.binding('util'); const ReflectApply = Reflect.apply; @@ -55,6 +61,11 @@ function areSimilarTypedArrays(a, b) { new Uint8Array(b.buffer, b.byteOffset, b.byteLength)) === 0; } +function areEqualArrayBuffers(buf1, buf2) { + return buf1.byteLength === buf2.byteLength && + compare(new Uint8Array(buf1), new Uint8Array(buf2)) === 0; +} + function isFloatTypedArrayTag(tag) { return tag === '[object Float32Array]' || tag === '[object Float64Array]'; } @@ -154,6 +165,10 @@ function strictDeepEqual(val1, val2, memos) { return false; } return keyCheck(val1, val2, kStrict, memos, kIsMap); + } else if (isAnyArrayBuffer(val1)) { + if (!areEqualArrayBuffers(val1, val2)) { + return false; + } // TODO: Make the valueOf checks safe. } else if (typeof val1.valueOf === 'function') { const val1Value = val1.valueOf(); @@ -217,6 +232,11 @@ function looseDeepEqual(val1, val2, memos) { } else if (isSet(val2) || isMap(val2)) { return false; } + if (isAnyArrayBuffer(val1) && isAnyArrayBuffer(val2)) { + if (!areEqualArrayBuffers(val1, val2)) { + return false; + } + } return keyCheck(val1, val2, kLoose, memos, kNoIterator); } diff --git a/test/parallel/test-assert-typedarray-deepequal.js b/test/parallel/test-assert-typedarray-deepequal.js index b648f07d3297f6..78394bb91facde 100644 --- a/test/parallel/test-assert-typedarray-deepequal.js +++ b/test/parallel/test-assert-typedarray-deepequal.js @@ -23,7 +23,9 @@ const equalArrayPairs = [ [new Float32Array([+0.0]), new Float32Array([+0.0])], [new Uint8Array([1, 2, 3, 4]).subarray(1), new Uint8Array([2, 3, 4])], [new Uint16Array([1, 2, 3, 4]).subarray(1), new Uint16Array([2, 3, 4])], - [new Uint32Array([1, 2, 3, 4]).subarray(1, 3), new Uint32Array([2, 3])] + [new Uint32Array([1, 2, 3, 4]).subarray(1, 3), new Uint32Array([2, 3])], + [new ArrayBuffer(3), new ArrayBuffer(3)], + [new SharedArrayBuffer(3), new SharedArrayBuffer(3)] ]; const looseEqualArrayPairs = [ @@ -31,7 +33,8 @@ const looseEqualArrayPairs = [ [new Int16Array(256), new Uint16Array(256)], [new Int16Array([256]), new Uint16Array([256])], [new Float32Array([+0.0]), new Float32Array([-0.0])], - [new Float64Array([+0.0]), new Float64Array([-0.0])] + [new Float64Array([+0.0]), new Float64Array([-0.0])], + [new ArrayBuffer(3), new SharedArrayBuffer(3)] ]; const notEqualArrayPairs = [ @@ -44,7 +47,19 @@ const notEqualArrayPairs = [ [new Int16Array([-256]), new Uint16Array([0xff00])], // same bits [new Int32Array([-256]), new Uint32Array([0xffffff00])], // ditto [new Float32Array([0.1]), new Float32Array([0.0])], - [new Float64Array([0.1]), new Float64Array([0.0])] + [new Float64Array([0.1]), new Float64Array([0.0])], + [new Uint8Array([1, 2, 3]).buffer, new Uint8Array([4, 5, 6]).buffer], + [ + new Uint8Array(new SharedArrayBuffer(3)).fill(1).buffer, + new Uint8Array(new SharedArrayBuffer(3)).fill(2).buffer + ], + [new ArrayBuffer(2), new ArrayBuffer(3)], + [new SharedArrayBuffer(2), new SharedArrayBuffer(3)], + [new ArrayBuffer(2), new SharedArrayBuffer(3)], + [ + new Uint8Array(new ArrayBuffer(3)).fill(1).buffer, + new Uint8Array(new SharedArrayBuffer(3)).fill(2).buffer + ] ]; equalArrayPairs.forEach((arrayPair) => {