Skip to content

Commit

Permalink
fix(document): avoid infinite recursion when calling toObject() on …
Browse files Browse the repository at this point in the history
…self-referencing document

Fix #11756
  • Loading branch information
vkarpov15 committed May 22, 2022
1 parent 2b922d5 commit 8325e56
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 4 deletions.
9 changes: 5 additions & 4 deletions lib/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -3464,9 +3464,9 @@ Document.prototype.$toObject = function(options, json) {

const path = json ? 'toJSON' : 'toObject';
const baseOptions = this.constructor &&
this.constructor.base &&
this.constructor.base.options &&
get(this.constructor.base.options, path) || {};
this.constructor.base &&
this.constructor.base.options &&
get(this.constructor.base.options, path) || {};
const schemaOptions = this.$__schema && this.$__schema.options || {};
// merge base default options with Schema's set default options if available.
// `clone` is necessary here because `utils.options` directly modifies the second input.
Expand Down Expand Up @@ -3503,7 +3503,8 @@ Document.prototype.$toObject = function(options, json) {
_isNested: true,
json: json,
minimize: _minimize,
flattenMaps: flattenMaps
flattenMaps: flattenMaps,
_seen: (options && options._seen) || new Map()
});

if (utils.hasUserDefinedProperty(options, 'getters')) {
Expand Down
6 changes: 6 additions & 0 deletions lib/helpers/clone.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,15 @@ module.exports = clone;
function cloneObject(obj, options, isArrayChild) {
const minimize = options && options.minimize;
const omitUndefined = options && options.omitUndefined;
const seen = options && options._seen;
const ret = {};
let hasKeys;

if (seen && seen.has(obj)) {
return seen.get(obj);
} else if (seen) {
seen.set(obj, ret);
}
if (trustedSymbol in obj) {
ret[trustedSymbol] = obj[trustedSymbol];
}
Expand Down
19 changes: 19 additions & 0 deletions test/document.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1035,6 +1035,25 @@ describe('document', function() {
assert.ok(posts[0].postedBy._id);
});

it('handles infinite recursion (gh-11756)', function() {
const User = db.model('User', Schema({
name: { type: String, required: true },
posts: [{ type: mongoose.Types.ObjectId, ref: 'Post' }]
}));

const Post = db.model('Post', Schema({
creator: { type: Schema.Types.ObjectId, ref: 'User' }
}));

const user = new User({ name: 'Test', posts: [] });
const post = new Post({ creator: user });
user.posts.push(post);

const inspected = post.inspect();
assert.ok(inspected);
assert.equal(inspected.creator.posts[0].creator.name, 'Test');
});

it('populate on nested path (gh-5703)', function() {
const toySchema = new mongoose.Schema({ color: String });
const Toy = db.model('Cat', toySchema);
Expand Down

0 comments on commit 8325e56

Please sign in to comment.