From e2788d00477bb0d775c7014fc0369bf846d73374 Mon Sep 17 00:00:00 2001 From: ninevra Date: Thu, 11 Feb 2021 04:11:57 -0800 Subject: [PATCH] Allow NaN (#94) * Test encoding and decoding NaN * Encode NaN --- lib/encoder.js | 4 +--- lib/helpers.js | 6 ----- test/15-elements-maps.js | 16 ++++++++++---- test/NaN.js | 48 +++++++++++++++++++++++++++++++++++----- 4 files changed, 56 insertions(+), 18 deletions(-) diff --git a/lib/encoder.js b/lib/encoder.js index 30727b2..ad23d36 100644 --- a/lib/encoder.js +++ b/lib/encoder.js @@ -2,13 +2,11 @@ var Buffer = require('safe-buffer').Buffer var bl = require('bl') -var isNaN = require('./helpers.js').isNaN var isFloat = require('./helpers.js').isFloat module.exports = function buildEncode (encodingTypes, options) { function encode (obj) { if (obj === undefined) throw new Error('undefined is not encodable in msgpack!') - if (isNaN(obj)) throw new Error('NaN is not encodable in msgpack!') if (obj === null) return Buffer.from([ 0xc0 ]) if (obj === true) return Buffer.from([ 0xc3 ]) @@ -133,7 +131,7 @@ const fround = Math.fround function encodeFloat (obj, forceFloat64) { var buf - if (forceFloat64 || !fround || fround(obj) !== obj) { + if (forceFloat64 || !fround || !Object.is(fround(obj), obj)) { buf = Buffer.allocUnsafe(9) buf[0] = 0xcb buf.writeDoubleBE(obj, 1) diff --git a/lib/helpers.js b/lib/helpers.js index 437427a..e6e4224 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -18,9 +18,3 @@ util.inherits(IncompleteBufferError, Error) exports.isFloat = function isFloat (n) { return n % 1 !== 0 } - -exports.isNaN = function isNaN (n) { - /* eslint-disable no-self-compare */ - return n !== n && typeof n === 'number' - /* eslint-enable no-self-compare */ -} diff --git a/test/15-elements-maps.js b/test/15-elements-maps.js index 4068efd..0c72545 100644 --- a/test/15-elements-maps.js +++ b/test/15-elements-maps.js @@ -71,13 +71,21 @@ test('do not encode undefined in a map', function (t) { t.end() }) -test('throw error on NaN in a map', function (t) { +test('encode NaN in a map', function (t) { var instance = msgpack() var toEncode = { a: NaN, hello: 'world' } - t.throws(function () { - instance.encode(toEncode) - }, Error, 'must throw Error') + const buf = instance.encode(toEncode) + + t.assert(Object.is(instance.decode(buf).a, NaN)) + + const expected = {...toEncode} + delete toEncode.a + const actual = instance.decode(buf) + delete buf.a + + t.deepEqual(actual, expected) + t.end() }) diff --git a/test/NaN.js b/test/NaN.js index 303e387..ba5054b 100644 --- a/test/NaN.js +++ b/test/NaN.js @@ -3,12 +3,50 @@ var test = require('tape').test var msgpack = require('../') -test('encode NaN', function (t) { - var encoder = msgpack() +test('encode NaN as 32-bit float', function (t) { + const encoder = msgpack() - t.throws(function () { - encoder.encode(NaN) - }, Error, 'must throw Error') + const buf = encoder.encode(NaN) + t.equal(buf[0], 0xca) + t.equal(buf.byteLength, 5) + + t.end() +}) + +test('encode NaN as 64-bit float with forceFloat64', function (t) { + const encoder = msgpack({forceFloat64: true}) + + const buf = encoder.encode(NaN) + + t.equal(buf[0], 0xcb) + t.equal(buf.byteLength, 9) + + t.end() +}) + +test('round-trip 32-bit NaN', function (t) { + const encoder = msgpack() + + t.assert(Object.is(encoder.decode(encoder.encode(NaN)), NaN)) + + t.end() +}) + +test('round-trip 64-bit NaN with forceFloat64', function (t) { + const encoder = msgpack({forceFloat64: true}) + + t.assert(Object.is(encoder.decode(encoder.encode(NaN)), NaN)) + + t.end() +}) + +test('decode 64-bit NaN', function (t) { + const encoder = msgpack() + const buf = Buffer.alloc(9) + buf.writeUInt8(0xcb, 0) + buf.writeDoubleBE(NaN, 1) + + t.assert(Object.is(encoder.decode(buf), NaN)) t.end() })