@@ -70,7 +70,7 @@ function deserializeValue(self, key, value, options) {
70
70
const date = new Date ( ) ;
71
71
72
72
if ( typeof d === 'string' ) date . setTime ( Date . parse ( d ) ) ;
73
- else if ( d instanceof Long ) date . setTime ( d . toNumber ( ) ) ;
73
+ else if ( Long . isLong ( d ) ) date . setTime ( d . toNumber ( ) ) ;
74
74
else if ( typeof d === 'number' && options . relaxed ) date . setTime ( d ) ;
75
75
return date ;
76
76
}
@@ -265,38 +265,68 @@ function serializeValue(value, options) {
265
265
return value ;
266
266
}
267
267
268
+ const BSON_TYPE_MAPPINGS = {
269
+ Binary : o => new Binary ( o . value ( ) , o . subtype ) ,
270
+ Code : o => new Code ( o . code , o . scope ) ,
271
+ DBRef : o => new DBRef ( o . collection || o . namespace , o . oid , o . db , o . fields ) , // "namespace" for 1.x library backwards compat
272
+ Decimal128 : o => new Decimal128 ( o . bytes ) ,
273
+ Double : o => new Double ( o . value ) ,
274
+ Int32 : o => new Int32 ( o . value ) ,
275
+ Long : o => Long . fromBits ( // underscore variants for 1.x backwards compatibility
276
+ o . low != null ? o . low : o . low_ ,
277
+ o . low != null ? o . high : o . high_ ,
278
+ o . low != null ? o . unsigned : o . unsigned_
279
+ ) ,
280
+ MaxKey : o => new MaxKey ( ) ,
281
+ MinKey : o => new MinKey ( ) ,
282
+ ObjectID : o => new ObjectId ( o ) ,
283
+ ObjectId : o => new ObjectId ( o ) , // support 4.0.0/4.0.1 before _bsontype was reverted back to ObjectID
284
+ BSONRegExp : o => new BSONRegExp ( o . pattern , o . options ) ,
285
+ Symbol : o => new Symbol ( o . value ) ,
286
+ Timestamp : o => Timestamp . fromBits ( o . low , o . high )
287
+ } ;
288
+
268
289
function serializeDocument ( doc , options ) {
269
290
if ( doc == null || typeof doc !== 'object' ) throw new Error ( 'not an object instance' ) ;
270
291
271
- // the "document" is really just a BSON type
272
- if ( doc . _bsontype ) {
273
- if ( doc . _bsontype === 'ObjectID' ) {
274
- // Deprecated ObjectID class with capital "D" is still used (e.g. by 'mongodb' package). It has
275
- // no "toExtendedJSON" method, so convert to new ObjectId (lowercase "d") class before serializing
276
- doc = ObjectId . createFromHexString ( doc . toString ( ) ) ;
292
+ const bsontype = doc . _bsontype ;
293
+ if ( typeof bsontype === 'undefined' ) {
294
+
295
+ // It's a regular object. Recursively serialize its property values.
296
+ const _doc = { } ;
297
+ for ( let name in doc ) {
298
+ _doc [ name ] = serializeValue ( doc [ name ] , options ) ;
277
299
}
278
- if ( typeof doc . toExtendedJSON === 'function' ) {
279
- // TODO: the two cases below mutate the original document! Bad. I don't know
280
- // enough about these two BSON types to know how to safely clone these objects, but
281
- // someone who knows MongoDB better should fix this to clone instead of mutating input objects.
282
- if ( doc . _bsontype === 'Code' && doc . scope ) {
283
- doc . scope = serializeDocument ( doc . scope , options ) ;
284
- } else if ( doc . _bsontype === 'DBRef' && doc . oid ) {
285
- doc . oid = serializeDocument ( doc . oid , options ) ;
300
+ return _doc ;
301
+
302
+ } else if ( typeof bsontype === 'string' ) {
303
+
304
+ // the "document" is really just a BSON type object
305
+ let _doc = doc ;
306
+ if ( typeof _doc . toExtendedJSON !== 'function' ) {
307
+ // There's no EJSON serialization function on the object. It's probably an
308
+ // object created by a previous version of this library (or another library)
309
+ // that's duck-typing objects to look like they were generated by this library).
310
+ // Copy the object into this library's version of that type.
311
+ const mapper = BSON_TYPE_MAPPINGS [ bsontype ] ;
312
+ if ( ! mapper ) {
313
+ throw new TypeError ( 'Unrecognized or invalid _bsontype: ' + bsontype ) ;
286
314
}
315
+ _doc = mapper ( _doc ) ;
316
+ }
287
317
288
- return doc . toExtendedJSON ( options ) ;
318
+ // Two BSON types may have nested objects that may need to be serialized too
319
+ if ( bsontype === 'Code' && _doc . scope ) {
320
+ _doc = new Code ( _doc . code , serializeValue ( _doc . scope , options ) ) ;
321
+ } else if ( bsontype === 'DBRef' && _doc . oid ) {
322
+ _doc = new DBRef ( _doc . collection , serializeValue ( _doc . oid , options ) , _doc . db , _doc . fields ) ;
289
323
}
290
- // TODO: should we throw an exception if there's a BSON type that has no toExtendedJSON method?
291
- }
292
324
293
- // Recursively serialize this document's property values.
294
- const _doc = { } ;
295
- for ( let name in doc ) {
296
- _doc [ name ] = serializeValue ( doc [ name ] , options ) ;
297
- }
325
+ return _doc . toExtendedJSON ( options ) ;
298
326
299
- return _doc ;
327
+ } else {
328
+ throw new Error ( '_bsontype must be a string, but was: ' + typeof bsontype ) ;
329
+ }
300
330
}
301
331
302
332
module . exports = {
0 commit comments