diff --git a/lib/bson/binary.js b/lib/bson/binary.js index 6d190bca..58f41dde 100644 --- a/lib/bson/binary.js +++ b/lib/bson/binary.js @@ -40,8 +40,6 @@ function Binary(buffer, subType) { throw new Error('only String, Buffer, Uint8Array or Array accepted'); } - this._bsontype = 'Binary'; - if (buffer instanceof Number) { this.sub_type = buffer; this.position = 0; @@ -81,6 +79,11 @@ function Binary(buffer, subType) { } } +Object.defineProperty(Binary.prototype, '_bsontype', { + value: 'Binary', + writable: false +}); + /** * Updates this binary with byte_value. * diff --git a/lib/bson/code.js b/lib/bson/code.js index c2984cd5..ec333da0 100644 --- a/lib/bson/code.js +++ b/lib/bson/code.js @@ -8,11 +8,15 @@ */ var Code = function Code(code, scope) { if (!(this instanceof Code)) return new Code(code, scope); - this._bsontype = 'Code'; this.code = code; this.scope = scope; }; +Object.defineProperty(Code.prototype, '_bsontype', { + value: 'Code', + writable: false +}); + /** * @ignore */ diff --git a/lib/bson/db_ref.js b/lib/bson/db_ref.js index f95795b1..342c4c96 100644 --- a/lib/bson/db_ref.js +++ b/lib/bson/db_ref.js @@ -10,12 +10,16 @@ function DBRef(namespace, oid, db) { if (!(this instanceof DBRef)) return new DBRef(namespace, oid, db); - this._bsontype = 'DBRef'; this.namespace = namespace; this.oid = oid; this.db = db; } +Object.defineProperty(DBRef.prototype, '_bsontype', { + value: 'DBRef', + writable: false +}); + /** * @ignore * @api private diff --git a/lib/bson/decimal128.js b/lib/bson/decimal128.js index 924513f4..ab82b8a9 100644 --- a/lib/bson/decimal128.js +++ b/lib/bson/decimal128.js @@ -181,10 +181,14 @@ var lessThan = function(left, right) { * @return {Double} */ var Decimal128 = function(bytes) { - this._bsontype = 'Decimal128'; this.bytes = bytes; }; +Object.defineProperty(Decimal128.prototype, '_bsontype', { + value: 'Decimal128', + writable: false +}); + /** * Create a Decimal128 instance from a string representation * diff --git a/lib/bson/double.js b/lib/bson/double.js index 523c21f8..ca529c2a 100644 --- a/lib/bson/double.js +++ b/lib/bson/double.js @@ -8,10 +8,14 @@ function Double(value) { if (!(this instanceof Double)) return new Double(value); - this._bsontype = 'Double'; this.value = value; } +Object.defineProperty(Double.prototype, '_bsontype', { + value: 'Double', + writable: false +}); + /** * Access the number value. * diff --git a/lib/bson/int_32.js b/lib/bson/int_32.js index 85dbdec6..93e0cc61 100644 --- a/lib/bson/int_32.js +++ b/lib/bson/int_32.js @@ -8,10 +8,14 @@ var Int32 = function(value) { if (!(this instanceof Int32)) return new Int32(value); - this._bsontype = 'Int32'; this.value = value; }; +Object.defineProperty(Int32.prototype, '_bsontype', { + value: 'Int32', + writable: false +}); + /** * Access the number value. * diff --git a/lib/bson/long.js b/lib/bson/long.js index 78215aa3..7f473ba8 100644 --- a/lib/bson/long.js +++ b/lib/bson/long.js @@ -43,7 +43,6 @@ function Long(low, high) { if (!(this instanceof Long)) return new Long(low, high); - this._bsontype = 'Long'; /** * @type {number} * @ignore @@ -57,6 +56,11 @@ function Long(low, high) { this.high_ = high | 0; // force into 32 signed bits. } +Object.defineProperty(Long.prototype, '_bsontype', { + value: 'Long', + writable: false +}); + /** * Return the int value. * diff --git a/lib/bson/max_key.js b/lib/bson/max_key.js index eebca7bc..1fa7f536 100644 --- a/lib/bson/max_key.js +++ b/lib/bson/max_key.js @@ -6,9 +6,12 @@ */ function MaxKey() { if (!(this instanceof MaxKey)) return new MaxKey(); - - this._bsontype = 'MaxKey'; } +Object.defineProperty(MaxKey.prototype, '_bsontype', { + value: 'MaxKey', + writable: false +}); + module.exports = MaxKey; module.exports.MaxKey = MaxKey; diff --git a/lib/bson/min_key.js b/lib/bson/min_key.js index 15f45228..6bcacd1e 100644 --- a/lib/bson/min_key.js +++ b/lib/bson/min_key.js @@ -6,9 +6,12 @@ */ function MinKey() { if (!(this instanceof MinKey)) return new MinKey(); - - this._bsontype = 'MinKey'; } +Object.defineProperty(MinKey.prototype, '_bsontype', { + value: 'MinKey', + writable: false +}); + module.exports = MinKey; module.exports.MinKey = MinKey; diff --git a/lib/bson/objectid.js b/lib/bson/objectid.js index 79de40d2..3c437536 100644 --- a/lib/bson/objectid.js +++ b/lib/bson/objectid.js @@ -39,8 +39,6 @@ var ObjectID = function ObjectID(id) { if (id instanceof ObjectID) return id; if (!(this instanceof ObjectID)) return new ObjectID(id); - this._bsontype = 'ObjectID'; - // The most common usecase (blank id, new objectId instance) if (id == null || typeof id === 'number') { // Generate a new id @@ -78,6 +76,11 @@ var ObjectID = function ObjectID(id) { if (ObjectID.cacheHexString) this.__id = this.toString('hex'); }; +Object.defineProperty(ObjectID.prototype, '_bsontype', { + value: 'ObjectID', + writable: false +}); + // Allow usage of ObjectId as well as ObjectID // var ObjectId = ObjectID; diff --git a/lib/bson/parser/calculate_size.js b/lib/bson/parser/calculate_size.js index 7e0026ca..96aebd6d 100644 --- a/lib/bson/parser/calculate_size.js +++ b/lib/bson/parser/calculate_size.js @@ -61,6 +61,7 @@ function calculateElement(name, value, serializeFunctions, isArray, ignoreUndefi if (value && value.toBSON) { value = value.toBSON(); } + var _bsontype, _objPrototype; switch (typeof value) { case 'string': @@ -84,15 +85,17 @@ function calculateElement(name, value, serializeFunctions, isArray, ignoreUndefi case 'boolean': return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (1 + 1); case 'object': + var _objPrototype = value && Object.getPrototypeOf(value) + var _bsontype = _objPrototype && _objPrototype._bsontype || undefined; if ( value == null || value instanceof MinKey || value instanceof MaxKey || - value['_bsontype'] === 'MinKey' || - value['_bsontype'] === 'MaxKey' + _bsontype === 'MinKey' || + _bsontype === 'MaxKey' ) { return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + 1; - } else if (value instanceof ObjectID || value['_bsontype'] === 'ObjectID' || value['_bsontype'] === 'ObjectId') { + } else if (value instanceof ObjectID || _bsontype === 'ObjectID' || _bsontype === 'ObjectId') { return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (12 + 1); } else if (value instanceof Date || isDate(value)) { return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (8 + 1); @@ -104,14 +107,14 @@ function calculateElement(name, value, serializeFunctions, isArray, ignoreUndefi value instanceof Long || value instanceof Double || value instanceof Timestamp || - value['_bsontype'] === 'Long' || - value['_bsontype'] === 'Double' || - value['_bsontype'] === 'Timestamp' + _bsontype === 'Long' || + _bsontype === 'Double' || + _bsontype === 'Timestamp' ) { return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (8 + 1); - } else if (value instanceof Decimal128 || value['_bsontype'] === 'Decimal128') { + } else if (value instanceof Decimal128 || _bsontype === 'Decimal128') { return (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (16 + 1); - } else if (value instanceof Code || value['_bsontype'] === 'Code') { + } else if (value instanceof Code || _bsontype === 'Code') { // Calculate size depending on the availability of a scope if (value.scope != null && Object.keys(value.scope).length > 0) { return ( @@ -132,7 +135,7 @@ function calculateElement(name, value, serializeFunctions, isArray, ignoreUndefi 1 ); } - } else if (value instanceof Binary || value['_bsontype'] === 'Binary') { + } else if (value instanceof Binary || _bsontype === 'Binary') { // Check what kind of subtype we have if (value.sub_type === Binary.SUBTYPE_BYTE_ARRAY) { return ( @@ -144,7 +147,7 @@ function calculateElement(name, value, serializeFunctions, isArray, ignoreUndefi (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + (value.position + 1 + 4 + 1) ); } - } else if (value instanceof Symbol || value['_bsontype'] === 'Symbol') { + } else if (value instanceof Symbol || _bsontype === 'Symbol') { return ( (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + Buffer.byteLength(value.value, 'utf8') + @@ -152,7 +155,7 @@ function calculateElement(name, value, serializeFunctions, isArray, ignoreUndefi 1 + 1 ); - } else if (value instanceof DBRef || value['_bsontype'] === 'DBRef') { + } else if (value instanceof DBRef || _bsontype === 'DBRef') { // Set up correct object for serialization var ordered_values = { $ref: value.namespace, @@ -183,7 +186,7 @@ function calculateElement(name, value, serializeFunctions, isArray, ignoreUndefi (value.multiline ? 1 : 0) + 1 ); - } else if (value instanceof BSONRegExp || value['_bsontype'] === 'BSONRegExp') { + } else if (value instanceof BSONRegExp || _bsontype === 'BSONRegExp') { return ( (name != null ? Buffer.byteLength(name, 'utf8') + 1 : 0) + 1 + diff --git a/lib/bson/parser/serializer.js b/lib/bson/parser/serializer.js index e4ff2bd9..803b6867 100644 --- a/lib/bson/parser/serializer.js +++ b/lib/bson/parser/serializer.js @@ -705,6 +705,9 @@ var serializeInto = function serializeInto( } var type = typeof value; + var _objPrototype = value && type === 'object' && Object.getPrototypeOf(value) + var _bsontype = _objPrototype && _objPrototype._bsontype || undefined; + if (type === 'string') { index = serializeString(buffer, key, value, index, true); } else if (type === 'number') { @@ -717,13 +720,13 @@ var serializeInto = function serializeInto( index = serializeNull(buffer, key, value, index, true); } else if (value === null) { index = serializeNull(buffer, key, value, index, true); - } else if (value['_bsontype'] === 'ObjectID' || value['_bsontype'] === 'ObjectId') { + } else if (_bsontype === 'ObjectID' || _bsontype === 'ObjectId') { index = serializeObjectId(buffer, key, value, index, true); } else if (Buffer.isBuffer(value)) { index = serializeBuffer(buffer, key, value, index, true); } else if (value instanceof RegExp || isRegExp(value)) { index = serializeRegExp(buffer, key, value, index, true); - } else if (type === 'object' && value['_bsontype'] == null) { + } else if (type === 'object' && _bsontype == null) { index = serializeObject( buffer, key, @@ -736,11 +739,11 @@ var serializeInto = function serializeInto( true, path ); - } else if (type === 'object' && value['_bsontype'] === 'Decimal128') { + } else if (type === 'object' && _bsontype === 'Decimal128') { index = serializeDecimal128(buffer, key, value, index, true); - } else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') { + } else if (_bsontype === 'Long' || _bsontype === 'Timestamp') { index = serializeLong(buffer, key, value, index, true); - } else if (value['_bsontype'] === 'Double') { + } else if (_bsontype === 'Double') { index = serializeDouble(buffer, key, value, index, true); } else if (typeof value === 'function' && serializeFunctions) { index = serializeFunction( @@ -753,7 +756,7 @@ var serializeInto = function serializeInto( serializeFunctions, true ); - } else if (value['_bsontype'] === 'Code') { + } else if (_bsontype === 'Code') { index = serializeCode( buffer, key, @@ -765,18 +768,20 @@ var serializeInto = function serializeInto( ignoreUndefined, true ); - } else if (value['_bsontype'] === 'Binary') { + } else if (_bsontype === 'Binary') { index = serializeBinary(buffer, key, value, index, true); - } else if (value['_bsontype'] === 'Symbol') { + } else if (_bsontype === 'Symbol') { index = serializeSymbol(buffer, key, value, index, true); - } else if (value['_bsontype'] === 'DBRef') { + } else if (_bsontype === 'DBRef') { index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions, true); - } else if (value['_bsontype'] === 'BSONRegExp') { + } else if (_bsontype === 'BSONRegExp') { index = serializeBSONRegExp(buffer, key, value, index, true); - } else if (value['_bsontype'] === 'Int32') { + } else if (_bsontype === 'Int32') { index = serializeInt32(buffer, key, value, index, true); - } else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') { + } else if (_bsontype === 'MinKey' || _bsontype === 'MaxKey') { index = serializeMinMax(buffer, key, value, index, true); + } else if (typeof value['_bsontype'] !== 'undefined') { + throw new TypeError('Unrecognized or invalid _bsontype: ' + value['_bsontype']); } } } else if (object instanceof Map) { @@ -797,6 +802,9 @@ var serializeInto = function serializeInto( // Check the type of the value type = typeof value; + var _objPrototype = value && type === 'object' && Object.getPrototypeOf(value) + var _bsontype = _objPrototype && _objPrototype._bsontype || undefined; + // Check the key and throw error if it's illegal if (typeof key === 'string' && ignoreKeys.indexOf(key) === -1) { if (key.match(regexp) != null) { @@ -825,13 +833,13 @@ var serializeInto = function serializeInto( // } else if (value === undefined && ignoreUndefined === true) { } else if (value === null || (value === undefined && ignoreUndefined === false)) { index = serializeNull(buffer, key, value, index); - } else if (value['_bsontype'] === 'ObjectID' || value['_bsontype'] === 'ObjectId') { + } else if (_bsontype === 'ObjectID' || _bsontype === 'ObjectId') { index = serializeObjectId(buffer, key, value, index); } else if (Buffer.isBuffer(value)) { index = serializeBuffer(buffer, key, value, index); } else if (value instanceof RegExp || isRegExp(value)) { index = serializeRegExp(buffer, key, value, index); - } else if (type === 'object' && value['_bsontype'] == null) { + } else if (type === 'object' && _bsontype == null) { index = serializeObject( buffer, key, @@ -844,13 +852,13 @@ var serializeInto = function serializeInto( false, path ); - } else if (type === 'object' && value['_bsontype'] === 'Decimal128') { + } else if (type === 'object' && _bsontype === 'Decimal128') { index = serializeDecimal128(buffer, key, value, index); - } else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') { + } else if (_bsontype === 'Long' || _bsontype === 'Timestamp') { index = serializeLong(buffer, key, value, index); - } else if (value['_bsontype'] === 'Double') { + } else if (_bsontype === 'Double') { index = serializeDouble(buffer, key, value, index); - } else if (value['_bsontype'] === 'Code') { + } else if (_bsontype === 'Code') { index = serializeCode( buffer, key, @@ -863,18 +871,20 @@ var serializeInto = function serializeInto( ); } else if (typeof value === 'function' && serializeFunctions) { index = serializeFunction(buffer, key, value, index, checkKeys, depth, serializeFunctions); - } else if (value['_bsontype'] === 'Binary') { + } else if (_bsontype === 'Binary') { index = serializeBinary(buffer, key, value, index); - } else if (value['_bsontype'] === 'Symbol') { + } else if (_bsontype === 'Symbol') { index = serializeSymbol(buffer, key, value, index); - } else if (value['_bsontype'] === 'DBRef') { + } else if (_bsontype === 'DBRef') { index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions); - } else if (value['_bsontype'] === 'BSONRegExp') { + } else if (_bsontype === 'BSONRegExp') { index = serializeBSONRegExp(buffer, key, value, index); - } else if (value['_bsontype'] === 'Int32') { + } else if (_bsontype === 'Int32') { index = serializeInt32(buffer, key, value, index); - } else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') { + } else if (_bsontype === 'MinKey' || _bsontype === 'MaxKey') { index = serializeMinMax(buffer, key, value, index); + } else if (typeof value['_bsontype'] !== 'undefined') { + throw new TypeError('Unrecognized or invalid _bsontype: ' + value['_bsontype']); } } } else { @@ -898,6 +908,9 @@ var serializeInto = function serializeInto( // Check the type of the value type = typeof value; + var _objPrototype = value && type === 'object' && Object.getPrototypeOf(value) + var _bsontype = _objPrototype && _objPrototype._bsontype || undefined; + // Check the key and throw error if it's illegal if (typeof key === 'string' && ignoreKeys.indexOf(key) === -1) { if (key.match(regexp) != null) { @@ -927,13 +940,13 @@ var serializeInto = function serializeInto( if (ignoreUndefined === false) index = serializeNull(buffer, key, value, index); } else if (value === null) { index = serializeNull(buffer, key, value, index); - } else if (value['_bsontype'] === 'ObjectID' || value['_bsontype'] === 'ObjectId') { + } else if (_bsontype === 'ObjectID' || _bsontype === 'ObjectId') { index = serializeObjectId(buffer, key, value, index); } else if (Buffer.isBuffer(value)) { index = serializeBuffer(buffer, key, value, index); } else if (value instanceof RegExp || isRegExp(value)) { index = serializeRegExp(buffer, key, value, index); - } else if (type === 'object' && value['_bsontype'] == null) { + } else if (type === 'object' && _bsontype == null) { index = serializeObject( buffer, key, @@ -946,13 +959,13 @@ var serializeInto = function serializeInto( false, path ); - } else if (type === 'object' && value['_bsontype'] === 'Decimal128') { + } else if (type === 'object' && _bsontype === 'Decimal128') { index = serializeDecimal128(buffer, key, value, index); - } else if (value['_bsontype'] === 'Long' || value['_bsontype'] === 'Timestamp') { + } else if (_bsontype === 'Long' || _bsontype === 'Timestamp') { index = serializeLong(buffer, key, value, index); - } else if (value['_bsontype'] === 'Double') { + } else if (_bsontype === 'Double') { index = serializeDouble(buffer, key, value, index); - } else if (value['_bsontype'] === 'Code') { + } else if (_bsontype === 'Code') { index = serializeCode( buffer, key, @@ -965,18 +978,20 @@ var serializeInto = function serializeInto( ); } else if (typeof value === 'function' && serializeFunctions) { index = serializeFunction(buffer, key, value, index, checkKeys, depth, serializeFunctions); - } else if (value['_bsontype'] === 'Binary') { + } else if (_bsontype === 'Binary') { index = serializeBinary(buffer, key, value, index); - } else if (value['_bsontype'] === 'Symbol') { + } else if (_bsontype === 'Symbol') { index = serializeSymbol(buffer, key, value, index); - } else if (value['_bsontype'] === 'DBRef') { + } else if (_bsontype === 'DBRef') { index = serializeDBRef(buffer, key, value, index, depth, serializeFunctions); - } else if (value['_bsontype'] === 'BSONRegExp') { + } else if (_bsontype === 'BSONRegExp') { index = serializeBSONRegExp(buffer, key, value, index); - } else if (value['_bsontype'] === 'Int32') { + } else if (_bsontype === 'Int32') { index = serializeInt32(buffer, key, value, index); - } else if (value['_bsontype'] === 'MinKey' || value['_bsontype'] === 'MaxKey') { + } else if (_bsontype === 'MinKey' || _bsontype === 'MaxKey') { index = serializeMinMax(buffer, key, value, index); + } else if (typeof value['_bsontype'] !== 'undefined') { + throw new TypeError('Unrecognized or invalid _bsontype: ' + value['_bsontype']); } } } diff --git a/lib/bson/regexp.js b/lib/bson/regexp.js index 108f0166..8a4b18e6 100644 --- a/lib/bson/regexp.js +++ b/lib/bson/regexp.js @@ -8,7 +8,6 @@ function BSONRegExp(pattern, options) { if (!(this instanceof BSONRegExp)) return new BSONRegExp(); // Execute - this._bsontype = 'BSONRegExp'; this.pattern = pattern || ''; this.options = options || ''; @@ -29,5 +28,10 @@ function BSONRegExp(pattern, options) { } } +Object.defineProperty(BSONRegExp.prototype, '_bsontype', { + value: 'BSONRegExp', + writable: false +}); + module.exports = BSONRegExp; module.exports.BSONRegExp = BSONRegExp; diff --git a/lib/bson/symbol.js b/lib/bson/symbol.js index ba20cabe..f0ba5af4 100644 --- a/lib/bson/symbol.js +++ b/lib/bson/symbol.js @@ -11,10 +11,14 @@ var inspect = Buffer ? require('util').inspect.custom || 'inspect' : 'inspect'; */ function Symbol(value) { if (!(this instanceof Symbol)) return new Symbol(value); - this._bsontype = 'Symbol'; this.value = value; } +Object.defineProperty(Symbol.prototype, '_bsontype', { + value: 'Symbol', + writable: false +}); + /** * Access the wrapped string value. * diff --git a/lib/bson/timestamp.js b/lib/bson/timestamp.js index dc61a6cc..3c711715 100644 --- a/lib/bson/timestamp.js +++ b/lib/bson/timestamp.js @@ -44,7 +44,6 @@ */ function Timestamp(low, high) { if (!(this instanceof Timestamp)) return new Timestamp(low, high); - this._bsontype = 'Timestamp'; /** * @type {number} * @ignore @@ -58,6 +57,11 @@ function Timestamp(low, high) { this.high_ = high | 0; // force into 32 signed bits. } +Object.defineProperty(Timestamp.prototype, '_bsontype', { + value: 'Timestamp', + writable: false +}); + /** * Return the int value. * diff --git a/test/node/bsontype_test.js b/test/node/bsontype_test.js new file mode 100644 index 00000000..80ef7f90 --- /dev/null +++ b/test/node/bsontype_test.js @@ -0,0 +1,102 @@ +'use strict'; + +var createBSON = require('../utils'); +var M = require('../../lib/bson/map'); + +function testSerializeAndDeserialize(test, expected) { + var result; + test.doesNotThrow(function() { + var bson = createBSON(); + result = bson.deserialize(bson.serialize(expected)); + }); + test.deepEqual(result, expected); +} + +exports['Should throw on an unknown _bsontype'] = function(test) { + function myBsonType () { + this.x = 12; + } + myBsonType.prototype._bsontype = 'myBsonType'; + + test.throws(function() { + createBSON().serialize({ a: new myBsonType() }); + }); + test.done(); +} + +exports['Should ignore _bsontype that is not on the prototype'] = function(test) { + testSerializeAndDeserialize(test, { a: { _bsontype: 'foo' } }); + test.done(); +} + +exports['Should be able to handle serializing null and Object.create(null)'] = function(test) { + testSerializeAndDeserialize(test, { + a: null, + b: Object.create(null) + }); + test.done(); +} + +exports['Should throw on an unknown _bsontype in an array'] = function(test) { + function myBsonType () { + this.x = 12; + } + myBsonType.prototype._bsontype = 'myBsonType'; + + test.throws(function() { + createBSON().serialize({ a: [ new myBsonType() ] }); + }); + test.done(); +} + +exports['Should ingore _bsontype that is not on the prototype in an array'] = function(test) { + testSerializeAndDeserialize(test, { a: [{ _bsontype: 'foo' }] }); + test.done(); +} + +exports['Should be able to handle serializing null and Object.create(null) in an array'] = function(test) { + testSerializeAndDeserialize(test, { + a: [ + null, + Object.create(null) + ] + }); + test.done(); +} + +exports['Should throw on an unknown _bsontype in a Map'] = function(test) { + function myBsonType () { + this.x = 12; + } + myBsonType.prototype._bsontype = 'myBsonType'; + + test.throws(function() { + createBSON().serialize({ a: new M([ ['x', new myBsonType()] ]) }); + }); + test.done(); +} + +exports['Should ingore _bsontype that is not on the prototype in a Map'] = function(test) { + var result; + test.doesNotThrow(function() { + var bson = createBSON(); + result = bson.deserialize(bson.serialize({ a: new M([[ '_bsontype', 'foo' ]]) })); + }); + test.deepEqual(result, { a: { _bsontype: 'foo' } }); + test.done(); +} + +exports['Should be able to handle serializing null and Object.create(null) in a Map'] = function(test) { + var result; + test.doesNotThrow(function() { + var bson = createBSON(); + result = bson.deserialize(bson.serialize({ + a: new M([ + ['a', null], + ['b', Object.create(null)] + ]) + })); + }); + test.deepEqual(result, { a: { a: null, b: {} } }); + test.done(); +}