diff --git a/lib/document.js b/lib/document.js index 54267d26b9e..264a94a6684 100644 --- a/lib/document.js +++ b/lib/document.js @@ -3831,16 +3831,14 @@ Document.prototype.$toObject = function(options, json) { // need the original options the user passed in, plus `_isNested` and // `_parentOptions` for checking whether we need to depopulate. const cloneOptions = { + ...options, _isNested: true, json: json, minimize: _minimize, flattenMaps: flattenMaps, flattenObjectIds: flattenObjectIds, _seen: (options && options._seen) || new Map(), - _calledWithOptions: options._calledWithOptions, - virtuals: options.virtuals, - getters: options.getters, - depopulate: options.depopulate + _calledWithOptions: options._calledWithOptions }; const depopulate = options.depopulate || diff --git a/test/document.test.js b/test/document.test.js index b8030900f9b..3ce45f384d4 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -520,6 +520,34 @@ describe('document', function() { docs.toObject({ transform: true }); }); + it('propagates toObject transform function to all subdocuments (gh-14589)', async function() { + const schema = new mongoose.Schema({ + name: String, + docArr: [{ name: String }], + subdoc: new mongoose.Schema({ name: String }) + }); + const TestModel = db.model('Test', schema); + + const doc = new TestModel({ + name: 'test', + docArr: [{ name: 'test' }], + subdoc: { name: 'test' } + }); + + // pass the transform as an inline option. Deletes `_id` property + // from both the top-level document and the subdocument. + const obj = doc.toObject({ transform: deleteId }); + + assert.equal(obj._id, undefined); + assert.equal(obj.subdoc._id, undefined); + assert.equal(obj.docArr[0]._id, undefined); + + function deleteId(doc, ret) { + delete ret._id; + return ret; + } + }); + it('disabling aliases in toObject options (gh-7548)', function() { const schema = new mongoose.Schema({ name: {