Skip to content

Commit f949c27

Browse files
addaleaxMyles Borins
authored andcommitted
assert: Check typed array view type in deepEqual
Do not convert typed arrays to `Buffer` for deepEqual since their values may not be accurately represented by 8-bit ints. Instead perform binary comparison of underlying `ArrayBuffer`s, but only when the array types match. Never apply any kind of optimization for floating-point typed arrays since bit pattern equality is not the right kind of check for them. PR-URL: #5910 Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Fixes: #5907
1 parent a39051f commit f949c27

2 files changed

Lines changed: 27 additions & 6 deletions

File tree

‎lib/assert.js‎

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const compare = process.binding('buffer').compare;
2929
constutil=require('util');
3030
constBuffer=require('buffer').Buffer;
3131
constpSlice=Array.prototype.slice;
32+
constpToString=(obj)=>Object.prototype.toString.call(obj);
3233

3334
// 1. The assert module provides functions that throw
3435
// AssertionError's when particular conditions are not met. The
@@ -170,10 +171,18 @@ function _deepEqual(actual, expected, strict) {
170171
(expected===null||typeofexpected!=='object')){
171172
returnstrict ? actual===expected : actual==expected;
172173

173-
// If both values are instances of typed arrays, wrap them in
174-
// a Buffer each to increase performance
175-
}elseif(ArrayBuffer.isView(actual)&&ArrayBuffer.isView(expected)){
176-
returncompare(newBuffer(actual),newBuffer(expected))===0;
174+
// If both values are instances of typed arrays, wrap their underlying
175+
// ArrayBuffers in a Buffer each to increase performance
176+
// This optimization requires the arrays to have the same type as checked by
177+
// Object.prototype.toString (aka pToString). Never perform binary
178+
// comparisons for Float*Arrays, though, since e.g. +0 === -0 but their
179+
// bit patterns are not identical.
180+
}elseif(ArrayBuffer.isView(actual)&&ArrayBuffer.isView(expected)&&
181+
pToString(actual)===pToString(expected)&&
182+
!(actualinstanceofFloat32Array||
183+
actualinstanceofFloat64Array)){
184+
returncompare(newBuffer(actual.buffer),
185+
newBuffer(expected.buffer))===0;
177186

178187
// 7.5 For all other Object pairs, including Array objects, equivalence is
179188
// determined by having the same number of owned properties (as verified

‎test/parallel/test-assert-typedarray-deepequal.js‎

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,25 @@ const equalArrayPairs = [
2020
[newInt16Array(1e5),newInt16Array(1e5)],
2121
[newInt32Array(1e5),newInt32Array(1e5)],
2222
[newFloat32Array(1e5),newFloat32Array(1e5)],
23-
[newFloat64Array(1e5),newFloat64Array(1e5)]
23+
[newFloat64Array(1e5),newFloat64Array(1e5)],
24+
[newInt16Array(256),newUint16Array(256)],
25+
[newInt16Array([256]),newUint16Array([256])],
26+
[newFloat32Array([+0.0]),newFloat32Array([-0.0])],
27+
[newFloat64Array([+0.0]),newFloat32Array([-0.0])],
28+
[newFloat64Array([+0.0]),newFloat64Array([-0.0])]
2429
];
2530

2631
constnotEqualArrayPairs=[
2732
[newUint8Array(2),newUint8Array(3)],
2833
[newUint8Array([1,2,3]),newUint8Array([4,5,6])],
29-
[newUint8ClampedArray([300,2,3]),newUint8Array([300,2,3])]
34+
[newUint8ClampedArray([300,2,3]),newUint8Array([300,2,3])],
35+
[newUint16Array([2]),newUint16Array([3])],
36+
[newUint16Array([0]),newUint16Array([256])],
37+
[newInt16Array([0]),newUint16Array([256])],
38+
[newInt16Array([-256]),newUint16Array([0xff00])],// same bits
39+
[newInt32Array([-256]),newUint32Array([0xffffff00])],// ditto
40+
[newFloat32Array([0.1]),newFloat32Array([0.0])],
41+
[newFloat64Array([0.1]),newFloat64Array([0.0])]
3042
];
3143

3244
equalArrayPairs.forEach((arrayPair)=>{

0 commit comments

Comments
 (0)