Skip to content

Commit

Permalink
fix(ejson-serialize): prevent double serialization for nested documents
Browse files Browse the repository at this point in the history
* don't require mongodb on browser tests

(part of the fix to #303)

* Revert "don't require mongodb on browser tests"

This reverts commit 3dc2cc1.

* Remove double serialization of nested docs

* combined two lines per code review
  • Loading branch information
justingrant authored and mbroadst committed Feb 12, 2019
1 parent 9f43809 commit ab790c9
Showing 1 changed file with 27 additions and 36 deletions.
63 changes: 27 additions & 36 deletions lib/extended_json.js
Original file line number Diff line number Diff line change
Expand Up @@ -251,53 +251,44 @@ function serializeValue(value, options) {
return { $numberDouble: value.toString() };
}

if (value instanceof RegExp) {
let flags = value.flags;
if (flags === undefined) {
flags = value.toString().match(/[gimuy]*$/)[0];
}

const rx = new BSONRegExp(value.source, flags);
return rx.toExtendedJSON();
}

if (value != null && typeof value === 'object') return serializeDocument(value, options);
return value;
}

function serializeDocument(doc, options) {
if (doc == null || typeof doc !== 'object') throw new Error('not an object instance');

// the document itself is a BSON type
if (doc._bsontype && typeof doc.toExtendedJSON === 'function') {
if (doc._bsontype === 'Code' && doc.scope) {
doc.scope = serializeDocument(doc.scope, options);
} else if (doc._bsontype === 'DBRef' && doc.oid) {
doc.oid = serializeDocument(doc.oid, options);
}

return doc.toExtendedJSON(options);
}

// the document is an object with nested BSON types
const _doc = {};
for (let name in doc) {
let val = doc[name];
if (Array.isArray(val)) {
_doc[name] = serializeArray(val, options);
} else if (val != null && typeof val.toExtendedJSON === 'function') {
if (val._bsontype === 'Code' && val.scope) {
val.scope = serializeDocument(val.scope, options);
} else if (val._bsontype === 'DBRef' && val.oid) {
val.oid = serializeDocument(val.oid, options);
// the "document" is a BSON type
if (doc._bsontype) {
if (typeof doc.toExtendedJSON === 'function') {
// TODO: the two cases below mutate the original document! Bad. I don't know
// enough about these two BSON types to know how to safely clone these objects, but
// someone who knows MongoDB better should fix this to clone instead of mutating input objects.
if (doc._bsontype === 'Code' && doc.scope) {
doc.scope = serializeDocument(doc.scope, options);
} else if (doc._bsontype === 'DBRef' && doc.oid) {
doc.oid = serializeDocument(doc.oid, options);
}

_doc[name] = val.toExtendedJSON(options);
} else if (val instanceof Date) {
_doc[name] = serializeValue(val, options);
} else if (val != null && typeof val === 'object') {
_doc[name] = serializeDocument(val, options);
return doc.toExtendedJSON(options);
}
_doc[name] = serializeValue(val, options);
if (val instanceof RegExp) {
let flags = val.flags;
if (flags === undefined) {
flags = val.toString().match(/[gimuy]*$/)[0];
}
// TODO: should we throw an exception if there's a BSON type that has no toExtendedJSON method?
}

const rx = new BSONRegExp(val.source, flags);
_doc[name] = rx.toExtendedJSON();
}
// Recursively serialize this document's property values.
const _doc = {};
for (let name in doc) {
_doc[name] = serializeValue(doc[name], options);
}

return _doc;
Expand Down

0 comments on commit ab790c9

Please sign in to comment.