From ad5f8a177f266b44df168ec6d02789cd21e04785 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 6 Jan 2024 18:27:03 -0500 Subject: [PATCH 1/2] test: repro #14236 --- test/query.test.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/query.test.js b/test/query.test.js index f19c0e1a6aa..17baa797400 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -2328,18 +2328,20 @@ describe('Query', function() { }); }); - it('map (gh-7142)', async function() { + it('transform (gh-14236) (gh-7142)', async function() { const Model = db.model('Test', new Schema({ name: String })); - + let called = 0; await Model.create({ name: 'test' }); const now = new Date(); const res = await Model.findOne().transform(res => { res.loadedAt = now; + ++called; return res; }); assert.equal(res.loadedAt, now); + assert.strictEqual(called, 1); }); describe('orFail (gh-6841)', function() { From 3b2a13834a8be0cf4e865b4647e9dfcf0452e38b Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 6 Jan 2024 18:27:26 -0500 Subject: [PATCH 2/2] fix(query): avoid double-calling query `transform()` with `findOne()` Fix #14236 --- lib/query.js | 38 ++++++++------------------------------ 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/lib/query.js b/lib/query.js index 290a3a198c9..f94acc7f0a6 100644 --- a/lib/query.js +++ b/lib/query.js @@ -2498,12 +2498,12 @@ Query.prototype._findOne = async function _findOne() { // don't pass in the conditions because we already merged them in const doc = await this.mongooseCollection.findOne(this._conditions, options); return new Promise((resolve, reject) => { - this._completeOne(doc, null, _wrapThunkCallback(this, (err, res) => { + this._completeOne(doc, null, (err, res) => { if (err) { return reject(err); } resolve(res); - })); + }); }); }; @@ -3303,12 +3303,12 @@ Query.prototype._findOneAndUpdate = async function _findOneAndUpdate() { const doc = !options.includeResultMetadata ? res : res.value; return new Promise((resolve, reject) => { - this._completeOne(doc, res, _wrapThunkCallback(this, (err, res) => { + this._completeOne(doc, res, (err, res) => { if (err) { return reject(err); } resolve(res); - })); + }); }); }; @@ -3399,12 +3399,12 @@ Query.prototype._findOneAndDelete = async function _findOneAndDelete() { const doc = !includeResultMetadata ? res : res.value; return new Promise((resolve, reject) => { - this._completeOne(doc, res, _wrapThunkCallback(this, (err, res) => { + this._completeOne(doc, res, (err, res) => { if (err) { return reject(err); } resolve(res); - })); + }); }); }; @@ -3553,12 +3553,12 @@ Query.prototype._findOneAndReplace = async function _findOneAndReplace() { const doc = !includeResultMetadata ? res : res.value; return new Promise((resolve, reject) => { - this._completeOne(doc, res, _wrapThunkCallback(this, (err, res) => { + this._completeOne(doc, res, (err, res) => { if (err) { return reject(err); } resolve(res); - })); + }); }); }; @@ -4382,28 +4382,6 @@ function _executePreHooks(query, op) { }); } -/*! - * ignore - */ - -function _wrapThunkCallback(query, cb) { - return function(error, res) { - if (error != null) { - return cb(error); - } - - for (const fn of query._transforms) { - try { - res = fn(res); - } catch (error) { - return cb(error); - } - } - - return cb(null, res); - }; -} - /** * Executes the query returning a `Promise` which will be * resolved with either the doc(s) or rejected with the error.