Skip to content

Commit 5360dd1

Browse files
committed
assert: handle (deep) equal(NaN, NaN) as being identical
This aligns the `equal` and `deepEqual()` implementations with the strict versions by accepting `NaN` as being identical in case both sides are NaN. Refs: #30350 (comment) PR-URL: #30766 Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Denys Otrishko <shishugi@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: David Carlier <devnexen@gmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
1 parent b5f2942 commit 5360dd1

File tree

5 files changed

+39
-10
lines changed

5 files changed

+39
-10
lines changed

doc/api/assert.md

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,10 @@ An alias of [`assert.ok()`][].
160160
<!-- YAML
161161
added: v0.1.21
162162
changes:
163+
- version: REPLACEME
164+
pr-url: https://github.com/nodejs/node/pull/30766
165+
description: NaN is now treated as being identical in case both sides are
166+
NaN.
163167
- version: v12.0.0
164168
pr-url: https://github.com/nodejs/node/pull/25008
165169
description: The type tags are now properly compared and there are a couple
@@ -203,7 +207,8 @@ are also recursively evaluated by the following rules.
203207
### Comparison details
204208

205209
* Primitive values are compared with the [Abstract Equality Comparison][]
206-
( `==` ).
210+
( `==` ) with the exception of `NaN`. It is treated as being identical in case
211+
both sides are `NaN`.
207212
* [Type tags][Object.prototype.toString()] of objects should be the same.
208213
* Only [enumerable "own" properties][] are considered.
209214
* [`Error`][] names and messages are always compared, even if these are not
@@ -554,6 +559,11 @@ assert.doesNotThrow(
554559
## assert.equal(actual, expected\[, message\])
555560
<!-- YAML
556561
added: v0.1.21
562+
changes:
563+
- version: REPLACEME
564+
pr-url: https://github.com/nodejs/node/pull/30766
565+
description: NaN is now treated as being identical in case both sides are
566+
NaN.
557567
-->
558568

559569
* `actual` {any}
@@ -569,7 +579,8 @@ An alias of [`assert.strictEqual()`][].
569579
> Stability: 0 - Deprecated: Use [`assert.strictEqual()`][] instead.
570580
571581
Tests shallow, coercive equality between the `actual` and `expected` parameters
572-
using the [Abstract Equality Comparison][] ( `==` ).
582+
using the [Abstract Equality Comparison][] ( `==` ). `NaN` is special handled
583+
and treated as being identical in case both sides are `NaN`.
573584

574585
```js
575586
const assert = require('assert');
@@ -578,6 +589,8 @@ assert.equal(1, 1);
578589
// OK, 1 == 1
579590
assert.equal(1, '1');
580591
// OK, 1 == '1'
592+
assert.equal(NaN, NaN);
593+
// OK
581594

582595
assert.equal(1, 2);
583596
// AssertionError: 1 == 2
@@ -732,6 +745,10 @@ let err;
732745
<!-- YAML
733746
added: v0.1.21
734747
changes:
748+
- version: REPLACEME
749+
pr-url: https://github.com/nodejs/node/pull/30766
750+
description: NaN is now treated as being identical in case both sides are
751+
NaN.
735752
- version: v9.0.0
736753
pr-url: https://github.com/nodejs/node/pull/15001
737754
description: The `Error` names and messages are now properly compared
@@ -853,6 +870,11 @@ instead of the [`AssertionError`][].
853870
## assert.notEqual(actual, expected\[, message\])
854871
<!-- YAML
855872
added: v0.1.21
873+
changes:
874+
- version: REPLACEME
875+
pr-url: https://github.com/nodejs/node/pull/30766
876+
description: NaN is now treated as being identical in case both sides are
877+
NaN.
856878
-->
857879

858880
* `actual` {any}
@@ -868,7 +890,8 @@ An alias of [`assert.notStrictEqual()`][].
868890
> Stability: 0 - Deprecated: Use [`assert.notStrictEqual()`][] instead.
869891
870892
Tests shallow, coercive inequality with the [Abstract Equality Comparison][]
871-
( `!=` ).
893+
(`!=` ). `NaN` is special handled and treated as being identical in case both
894+
sides are `NaN`.
872895

873896
```js
874897
const assert = require('assert');

lib/assert.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const {
2525
ObjectIs,
2626
ObjectKeys,
2727
ObjectPrototypeIsPrototypeOf,
28+
NumberIsNaN
2829
} = primordials;
2930

3031
const { Buffer } = require('buffer');
@@ -398,7 +399,7 @@ assert.equal = function equal(actual, expected, message) {
398399
throw new ERR_MISSING_ARGS('actual', 'expected');
399400
}
400401
// eslint-disable-next-line eqeqeq
401-
if (actual != expected) {
402+
if (actual != expected && (!NumberIsNaN(actual) || !NumberIsNaN(expected))) {
402403
innerFail({
403404
actual,
404405
expected,
@@ -416,7 +417,7 @@ assert.notEqual = function notEqual(actual, expected, message) {
416417
throw new ERR_MISSING_ARGS('actual', 'expected');
417418
}
418419
// eslint-disable-next-line eqeqeq
419-
if (actual == expected) {
420+
if (actual == expected || (NumberIsNaN(actual) && NumberIsNaN(expected))) {
420421
innerFail({
421422
actual,
422423
expected,

lib/internal/util/comparisons.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ function innerDeepEqual(val1, val2, strict, memos) {
180180
if (val1 === null || typeof val1 !== 'object') {
181181
if (val2 === null || typeof val2 !== 'object') {
182182
// eslint-disable-next-line eqeqeq
183-
return val1 == val2;
183+
return val1 == val2 || (NumberIsNaN(val1) && NumberIsNaN(val2));
184184
}
185185
return false;
186186
}

test/parallel/test-assert-deep.js

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -590,10 +590,9 @@ assertNotDeepOrStrict(
590590
}
591591

592592
// Handle NaN
593-
assert.notDeepEqual(NaN, NaN);
594-
assert.deepStrictEqual(NaN, NaN);
595-
assert.deepStrictEqual({ a: NaN }, { a: NaN });
596-
assert.deepStrictEqual([ 1, 2, NaN, 4 ], [ 1, 2, NaN, 4 ]);
593+
assertDeepAndStrictEqual(NaN, NaN);
594+
assertDeepAndStrictEqual({ a: NaN }, { a: NaN });
595+
assertDeepAndStrictEqual([ 1, 2, NaN, 4 ], [ 1, 2, NaN, 4 ]);
597596

598597
// Handle boxed primitives
599598
{

test/parallel/test-assert.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -501,6 +501,12 @@ assert.throws(
501501
}
502502
);
503503

504+
a.equal(NaN, NaN);
505+
a.throws(
506+
() => a.notEqual(NaN, NaN),
507+
a.AssertionError
508+
);
509+
504510
// Test strict assert.
505511
{
506512
const a = require('assert');

0 commit comments

Comments
 (0)