Skip to content

Commit ab790c9

Browse files
justingrantmbroadst
authored andcommitted
fix(ejson-serialize): prevent double serialization for nested documents
* 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
1 parent 9f43809 commit ab790c9

File tree

1 file changed

+27
-36
lines changed

1 file changed

+27
-36
lines changed

Diff for: lib/extended_json.js

+27-36
Original file line numberDiff line numberDiff line change
@@ -251,53 +251,44 @@ function serializeValue(value, options) {
251251
return { $numberDouble: value.toString() };
252252
}
253253

254+
if (value instanceof RegExp) {
255+
let flags = value.flags;
256+
if (flags === undefined) {
257+
flags = value.toString().match(/[gimuy]*$/)[0];
258+
}
259+
260+
const rx = new BSONRegExp(value.source, flags);
261+
return rx.toExtendedJSON();
262+
}
263+
254264
if (value != null && typeof value === 'object') return serializeDocument(value, options);
255265
return value;
256266
}
257267

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

261-
// the document itself is a BSON type
262-
if (doc._bsontype && typeof doc.toExtendedJSON === 'function') {
263-
if (doc._bsontype === 'Code' && doc.scope) {
264-
doc.scope = serializeDocument(doc.scope, options);
265-
} else if (doc._bsontype === 'DBRef' && doc.oid) {
266-
doc.oid = serializeDocument(doc.oid, options);
267-
}
268-
269-
return doc.toExtendedJSON(options);
270-
}
271-
272-
// the document is an object with nested BSON types
273-
const _doc = {};
274-
for (let name in doc) {
275-
let val = doc[name];
276-
if (Array.isArray(val)) {
277-
_doc[name] = serializeArray(val, options);
278-
} else if (val != null && typeof val.toExtendedJSON === 'function') {
279-
if (val._bsontype === 'Code' && val.scope) {
280-
val.scope = serializeDocument(val.scope, options);
281-
} else if (val._bsontype === 'DBRef' && val.oid) {
282-
val.oid = serializeDocument(val.oid, options);
271+
// the "document" is a BSON type
272+
if (doc._bsontype) {
273+
if (typeof doc.toExtendedJSON === 'function') {
274+
// TODO: the two cases below mutate the original document! Bad. I don't know
275+
// enough about these two BSON types to know how to safely clone these objects, but
276+
// someone who knows MongoDB better should fix this to clone instead of mutating input objects.
277+
if (doc._bsontype === 'Code' && doc.scope) {
278+
doc.scope = serializeDocument(doc.scope, options);
279+
} else if (doc._bsontype === 'DBRef' && doc.oid) {
280+
doc.oid = serializeDocument(doc.oid, options);
283281
}
284282

285-
_doc[name] = val.toExtendedJSON(options);
286-
} else if (val instanceof Date) {
287-
_doc[name] = serializeValue(val, options);
288-
} else if (val != null && typeof val === 'object') {
289-
_doc[name] = serializeDocument(val, options);
283+
return doc.toExtendedJSON(options);
290284
}
291-
_doc[name] = serializeValue(val, options);
292-
if (val instanceof RegExp) {
293-
let flags = val.flags;
294-
if (flags === undefined) {
295-
flags = val.toString().match(/[gimuy]*$/)[0];
296-
}
285+
// TODO: should we throw an exception if there's a BSON type that has no toExtendedJSON method?
286+
}
297287

298-
const rx = new BSONRegExp(val.source, flags);
299-
_doc[name] = rx.toExtendedJSON();
300-
}
288+
// Recursively serialize this document's property values.
289+
const _doc = {};
290+
for (let name in doc) {
291+
_doc[name] = serializeValue(doc[name], options);
301292
}
302293

303294
return _doc;

0 commit comments

Comments
 (0)