Skip to content

Commit

Permalink
feat: match JSON.stringify() behavior
Browse files Browse the repository at this point in the history
The library will now match the behavior of the JSON.stringify() method:

- undefined is now encoded as nil (0xc0)
- undefined values in objects are now ignored
  • Loading branch information
darrachequesne committed May 21, 2022
1 parent f570e46 commit 21c6592
Show file tree
Hide file tree
Showing 7 changed files with 25 additions and 21 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ A fast [Node.js](http://nodejs.org) implementation of the latest [MessagePack](h
## Notes

* This implementation is not backwards compatible with those that use the older spec. It is recommended that this library is only used in isolated systems.
* `undefined` is encoded as `fixext 1 [0, 0]`, i.e. `<Buffer d4 00 00>`
* `undefined` is encoded as `nil`
* `Date` objects are encoded as `fixext 8 [0, ms]`, e.g. `new Date('2000-06-13T00:00:00.000Z')` => `<Buffer d7 00 00 00 00 df b7 62 9c 00>`
* `ArrayBuffer` are encoded as `ext 8/16/32 [0, data]`, e.g. `Uint8Array.of(1, 2, 3, 4)` => `<Buffer c7 04 00 01 02 03 04>`

Expand Down
4 changes: 0 additions & 4 deletions browser/decode.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,10 +203,6 @@ Decoder.prototype._parse = function () {
case 0xd4:
type = this._view.getInt8(this._offset);
this._offset += 1;
if (type === 0x00) {
this._offset += 1;
return void 0;
}
return [type, this._bin(1)];
case 0xd5:
type = this._view.getInt8(this._offset);
Expand Down
7 changes: 3 additions & 4 deletions browser/encode.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ function _encode(bytes, defers, value) {
var allKeys = Object.keys(value);
for (i = 0, l = allKeys.length; i < l; i++) {
key = allKeys[i];
if (typeof value[key] !== 'function') {
if (value[key] !== undefined && typeof value[key] !== 'function') {
keys.push(key);
}
}
Expand Down Expand Up @@ -254,10 +254,9 @@ function _encode(bytes, defers, value) {
bytes.push(value ? 0xc3 : 0xc2);
return 1;
}
// fixext 1 / undefined
if (type === 'undefined') {
bytes.push(0xd4, 0, 0);
return 3;
bytes.push(0xc0);
return 1;
}
// custom types like BigInt (typeof value === 'bigint')
if (typeof value.toJSON === 'function') {
Expand Down
4 changes: 0 additions & 4 deletions lib/decode.js
Original file line number Diff line number Diff line change
Expand Up @@ -189,10 +189,6 @@ Decoder.prototype.parse = function () {
case 0xd4:
type = this.buffer.readInt8(this.offset);
this.offset += 1;
if (type === 0x00) {
this.offset += 1;
return void 0;
}
return [type, this.bin(1)];
case 0xd5:
type = this.buffer.readInt8(this.offset);
Expand Down
8 changes: 4 additions & 4 deletions lib/encode.js
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ function _encode(bytes, defers, value) {

for (let i = 0, l = allKeys.length; i < l; i++) {
key = allKeys[i];
if (typeof value[key] !== 'function') {
if (value[key] !== undefined && typeof value[key] !== 'function') {
keys.push(key);
}
}
Expand Down Expand Up @@ -274,9 +274,9 @@ function _encode(bytes, defers, value) {
case 'boolean': // false/true
bytes.push(value ? 0xc3 : 0xc2);
return 1;
case 'undefined': // fixext 1 / undefined
bytes.push(0xd4, 0, 0);
return 3;
case 'undefined':
bytes.push(0xc0);
return 1;
default:
// custom types like BigInt (typeof value === 'bigint')
if (typeof value.toJSON === 'function') {
Expand Down
2 changes: 1 addition & 1 deletion test/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ describe('notepack (browser build)', function() {
map: {},
nil: null,
bool: { 'true': true, 'false': false, both: [true, false, false, false, true] },
fixext: [undefined, new Date('2140-01-01T13:14:15.678Z'), undefined, new Date('2005-12-31T23:59:59.999Z')],
fixext: [null, new Date('2140-01-01T13:14:15.678Z'), null, new Date('2005-12-31T23:59:59.999Z')],
utf8: ['α', '亜', '\uD83D\uDC26'],
float: [1.1, 1234567891234567.5, Infinity, -Infinity, NaN]
};
Expand Down
19 changes: 16 additions & 3 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ describe('notepack', function () {

it('nil', function () {
check(null, 'c0');
checkEncode(undefined, 'c0');
});

it('false', function () {
Expand Down Expand Up @@ -208,8 +209,7 @@ describe('notepack', function () {
check(-Math.pow(2, 63) - 1024, 'd38000000000000000');
});

it('fixext 1 / undefined', function () {
check(undefined, 'd40000');
it('fixext 1', function () {
checkDecode([127, Buffer.from('a')], 'd4' + '7f' + '61');
});

Expand Down Expand Up @@ -311,7 +311,7 @@ describe('notepack', function () {
map: {},
nil: null,
bool: { 'true': true, 'false': false, both: [true, false, false, false, true] },
fixext: [undefined, new Date('2140-01-01T13:14:15.678Z'), undefined, new Date('2005-12-31T23:59:59.999Z')]
fixext: [null, new Date('2140-01-01T13:14:15.678Z'), null, new Date('2005-12-31T23:59:59.999Z')]
};
expected.map['a'.repeat(32)] = { a: 'a', b: 'b', c: 'c' };
expected.map['b'.repeat(256)] = { a: { b: 1, c: 1, d: 1, e: { f: { g: 2, h: 2 } } } };
Expand All @@ -322,6 +322,19 @@ describe('notepack', function () {
expect(notepack.decode(notepack.encode(expected))).to.deep.equal(expected);
});

it('undefined as array elem or map value', function () {
const value = {
a: undefined,
b: null,
c: [undefined, null]
};
const expected = {
b: null,
c: [null, null]
};
expect(notepack.decode(notepack.encode(value))).to.deep.equal(expected);
});

it('10000', function () {
const fixture = require('./fixtures/10000.json');

Expand Down

0 comments on commit 21c6592

Please sign in to comment.