assert: use Same-value equality in deepStrictEqual
PR-URL: https://github.com/nodejs/node/pull/15398 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Rich Trott <rtrott@gmail.com>
This commit is contained in:
parent
ca2c73cae0
commit
b0d3bec95c
@ -142,6 +142,7 @@ Generally identical to `assert.deepEqual()` with a few exceptions:
|
|||||||
the [Strict Equality Comparison][] too.
|
the [Strict Equality Comparison][] too.
|
||||||
3. [Type tags][Object.prototype.toString()] of objects should be the same.
|
3. [Type tags][Object.prototype.toString()] of objects should be the same.
|
||||||
4. [Object wrappers][] are compared both as objects and unwrapped values.
|
4. [Object wrappers][] are compared both as objects and unwrapped values.
|
||||||
|
5. `0` and `-0` are not considered equal.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
const assert = require('assert');
|
const assert = require('assert');
|
||||||
@ -179,6 +180,11 @@ assert.deepStrictEqual(new Number(1), new Number(2));
|
|||||||
// Fails because the wrapped number is unwrapped and compared as well.
|
// Fails because the wrapped number is unwrapped and compared as well.
|
||||||
assert.deepStrictEqual(new String('foo'), Object('foo'));
|
assert.deepStrictEqual(new String('foo'), Object('foo'));
|
||||||
// OK because the object and the string are identical when unwrapped.
|
// OK because the object and the string are identical when unwrapped.
|
||||||
|
|
||||||
|
assert.deepStrictEqual(-0, -0);
|
||||||
|
// OK
|
||||||
|
assert.deepStrictEqual(0, -0);
|
||||||
|
// AssertionError: 0 deepStrictEqual -0
|
||||||
```
|
```
|
||||||
|
|
||||||
If the values are not equal, an `AssertionError` is thrown with a `message`
|
If the values are not equal, an `AssertionError` is thrown with a `message`
|
||||||
@ -438,6 +444,9 @@ parameter is an instance of an `Error` then it will be thrown instead of the
|
|||||||
<!-- YAML
|
<!-- YAML
|
||||||
added: v1.2.0
|
added: v1.2.0
|
||||||
changes:
|
changes:
|
||||||
|
- version: REPLACEME
|
||||||
|
pr-url: https://github.com/nodejs/node/pull/REPLACEME
|
||||||
|
description: -0 and +0 are not considered equal anymore.
|
||||||
- version: REPLACEME
|
- version: REPLACEME
|
||||||
pr-url: https://github.com/nodejs/node/pull/15036
|
pr-url: https://github.com/nodejs/node/pull/15036
|
||||||
description: NaN is now compared using the [SameValueZero][] comparison.
|
description: NaN is now compared using the [SameValueZero][] comparison.
|
||||||
|
@ -118,12 +118,12 @@ function areSimilarRegExps(a, b) {
|
|||||||
// For small buffers it's faster to compare the buffer in a loop. The c++
|
// For small buffers it's faster to compare the buffer in a loop. The c++
|
||||||
// barrier including the Uint8Array operation takes the advantage of the faster
|
// barrier including the Uint8Array operation takes the advantage of the faster
|
||||||
// binary compare otherwise. The break even point was at about 300 characters.
|
// binary compare otherwise. The break even point was at about 300 characters.
|
||||||
function areSimilarTypedArrays(a, b) {
|
function areSimilarTypedArrays(a, b, max) {
|
||||||
const len = a.byteLength;
|
const len = a.byteLength;
|
||||||
if (len !== b.byteLength) {
|
if (len !== b.byteLength) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (len < 300) {
|
if (len < max) {
|
||||||
for (var offset = 0; offset < len; offset++) {
|
for (var offset = 0; offset < len; offset++) {
|
||||||
if (a[offset] !== b[offset]) {
|
if (a[offset] !== b[offset]) {
|
||||||
return false;
|
return false;
|
||||||
@ -160,10 +160,7 @@ function isObjectOrArrayTag(tag) {
|
|||||||
// reasonable to interpret their underlying memory in the same way,
|
// reasonable to interpret their underlying memory in the same way,
|
||||||
// which is checked by comparing their type tags.
|
// which is checked by comparing their type tags.
|
||||||
// (e.g. a Uint8Array and a Uint16Array with the same memory content
|
// (e.g. a Uint8Array and a Uint16Array with the same memory content
|
||||||
// could still be different because they will be interpreted differently)
|
// could still be different because they will be interpreted differently).
|
||||||
// Never perform binary comparisons for Float*Arrays, though,
|
|
||||||
// since e.g. +0 === -0 is true despite the two values' bit patterns
|
|
||||||
// not being identical.
|
|
||||||
//
|
//
|
||||||
// For strict comparison, objects should have
|
// For strict comparison, objects should have
|
||||||
// a) The same built-in type tags
|
// a) The same built-in type tags
|
||||||
@ -211,8 +208,9 @@ function strictDeepEqual(actual, expected) {
|
|||||||
if (actual.message !== expected.message) {
|
if (actual.message !== expected.message) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (!isFloatTypedArrayTag(actualTag) && ArrayBuffer.isView(actual)) {
|
} else if (ArrayBuffer.isView(actual)) {
|
||||||
if (!areSimilarTypedArrays(actual, expected)) {
|
if (!areSimilarTypedArrays(actual, expected,
|
||||||
|
isFloatTypedArrayTag(actualTag) ? 0 : 300)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Buffer.compare returns true, so actual.length === expected.length
|
// Buffer.compare returns true, so actual.length === expected.length
|
||||||
@ -266,9 +264,10 @@ function looseDeepEqual(actual, expected) {
|
|||||||
const actualTag = objectToString(actual);
|
const actualTag = objectToString(actual);
|
||||||
const expectedTag = objectToString(expected);
|
const expectedTag = objectToString(expected);
|
||||||
if (actualTag === expectedTag) {
|
if (actualTag === expectedTag) {
|
||||||
if (!isObjectOrArrayTag(actualTag) && !isFloatTypedArrayTag(actualTag) &&
|
if (!isObjectOrArrayTag(actualTag) && ArrayBuffer.isView(actual)) {
|
||||||
ArrayBuffer.isView(actual)) {
|
return areSimilarTypedArrays(actual, expected,
|
||||||
return areSimilarTypedArrays(actual, expected);
|
isFloatTypedArrayTag(actualTag) ?
|
||||||
|
Infinity : 300);
|
||||||
}
|
}
|
||||||
// Ensure reflexivity of deepEqual with `arguments` objects.
|
// Ensure reflexivity of deepEqual with `arguments` objects.
|
||||||
// See https://github.com/nodejs/node-v0.x-archive/pull/7178
|
// See https://github.com/nodejs/node-v0.x-archive/pull/7178
|
||||||
@ -280,7 +279,9 @@ function looseDeepEqual(actual, expected) {
|
|||||||
function innerDeepEqual(actual, expected, strict, memos) {
|
function innerDeepEqual(actual, expected, strict, memos) {
|
||||||
// All identical values are equivalent, as determined by ===.
|
// All identical values are equivalent, as determined by ===.
|
||||||
if (actual === expected) {
|
if (actual === expected) {
|
||||||
|
if (actual !== 0)
|
||||||
return true;
|
return true;
|
||||||
|
return strict ? Object.is(actual, expected) : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a boolean if (not) equal and undefined in case we have to check
|
// Returns a boolean if (not) equal and undefined in case we have to check
|
||||||
|
@ -507,5 +507,8 @@ assert.doesNotThrow(
|
|||||||
boxedSymbol.slow = true;
|
boxedSymbol.slow = true;
|
||||||
assertNotDeepOrStrict(boxedSymbol, {});
|
assertNotDeepOrStrict(boxedSymbol, {});
|
||||||
}
|
}
|
||||||
|
// Minus zero
|
||||||
|
assertOnlyDeepEqual(0, -0);
|
||||||
|
assertDeepAndStrictEqual(-0, -0);
|
||||||
|
|
||||||
/* eslint-enable */
|
/* eslint-enable */
|
||||||
|
@ -20,16 +20,20 @@ const equalArrayPairs = [
|
|||||||
[new Int32Array(1e5), new Int32Array(1e5)],
|
[new Int32Array(1e5), new Int32Array(1e5)],
|
||||||
[new Float32Array(1e5), new Float32Array(1e5)],
|
[new Float32Array(1e5), new Float32Array(1e5)],
|
||||||
[new Float64Array(1e5), new Float64Array(1e5)],
|
[new Float64Array(1e5), new Float64Array(1e5)],
|
||||||
[new Int16Array(256), new Uint16Array(256)],
|
[new Float32Array([+0.0]), new Float32Array([+0.0])],
|
||||||
[new Int16Array([256]), new Uint16Array([256])],
|
|
||||||
[new Float32Array([+0.0]), new Float32Array([-0.0])],
|
|
||||||
[new Float64Array([+0.0]), new Float32Array([-0.0])],
|
|
||||||
[new Float64Array([+0.0]), new Float64Array([-0.0])],
|
|
||||||
[new Uint8Array([1, 2, 3, 4]).subarray(1), new Uint8Array([2, 3, 4])],
|
[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 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])]
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const looseEqualArrayPairs = [
|
||||||
|
[new Float64Array([+0.0]), new Float32Array([-0.0])],
|
||||||
|
[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])]
|
||||||
|
];
|
||||||
|
|
||||||
const notEqualArrayPairs = [
|
const notEqualArrayPairs = [
|
||||||
[new Uint8Array(2), new Uint8Array(3)],
|
[new Uint8Array(2), new Uint8Array(3)],
|
||||||
[new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])],
|
[new Uint8Array([1, 2, 3]), new Uint8Array([4, 5, 6])],
|
||||||
@ -46,6 +50,16 @@ const notEqualArrayPairs = [
|
|||||||
equalArrayPairs.forEach((arrayPair) => {
|
equalArrayPairs.forEach((arrayPair) => {
|
||||||
// eslint-disable-next-line no-restricted-properties
|
// eslint-disable-next-line no-restricted-properties
|
||||||
assert.deepEqual(arrayPair[0], arrayPair[1]);
|
assert.deepEqual(arrayPair[0], arrayPair[1]);
|
||||||
|
assert.deepStrictEqual(arrayPair[0], arrayPair[1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
looseEqualArrayPairs.forEach((arrayPair) => {
|
||||||
|
// eslint-disable-next-line no-restricted-properties
|
||||||
|
assert.deepEqual(arrayPair[0], arrayPair[1]);
|
||||||
|
assert.throws(
|
||||||
|
makeBlock(assert.deepStrictEqual, arrayPair[0], arrayPair[1]),
|
||||||
|
assert.AssertionError
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
notEqualArrayPairs.forEach((arrayPair) => {
|
notEqualArrayPairs.forEach((arrayPair) => {
|
||||||
@ -54,4 +68,8 @@ notEqualArrayPairs.forEach((arrayPair) => {
|
|||||||
makeBlock(assert.deepEqual, arrayPair[0], arrayPair[1]),
|
makeBlock(assert.deepEqual, arrayPair[0], arrayPair[1]),
|
||||||
assert.AssertionError
|
assert.AssertionError
|
||||||
);
|
);
|
||||||
|
assert.throws(
|
||||||
|
makeBlock(assert.deepStrictEqual, arrayPair[0], arrayPair[1]),
|
||||||
|
assert.AssertionError
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user