From 197f1698a3c8335becd9548d7589a3f601514463 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Mon, 7 Aug 2023 16:38:31 -0400 Subject: [PATCH 1/3] fix: avoid applying map property getters when saving Fix #13657 --- lib/utils.js | 16 +++++++++++++++- test/schema.uuid.test.js | 31 +++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/lib/utils.js b/lib/utils.js index 1a013d610d9..5ff64a6ccca 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -630,9 +630,23 @@ function _populateObj(obj) { */ exports.getValue = function(path, obj, map) { - return mpath.get(path, obj, '_doc', map); + return mpath.get(path, obj, getValueLookup, map); }; +/*! + * ignore + */ + +const mapGetterOptions = Object.freeze({ getters: false }); + +function getValueLookup(obj, part) { + const _from = obj && obj._doc ? obj._doc : obj; + obj = _from instanceof Map ? + _from.get(part, mapGetterOptions) : + _from[part]; + return obj; +} + /** * Sets the value of `obj` at the given `path`. * diff --git a/test/schema.uuid.test.js b/test/schema.uuid.test.js index b17da15a431..77b7b2300fa 100644 --- a/test/schema.uuid.test.js +++ b/test/schema.uuid.test.js @@ -172,6 +172,37 @@ describe('SchemaUUID', function() { assert.equal(_id, uuid.toString()); }); + it('avoids converting maps of uuids to strings (gh-13657)', async function() { + const schema = new mongoose.Schema( + { + doc_map: { + type: mongoose.Schema.Types.Map, + of: mongoose.Schema.Types.UUID + } + } + ); + db.deleteModel(/Test/); + const Test = db.model('Test', schema); + await Test.deleteMany({}); + + const user = new Test({ + doc_map: new Map([ + ['role_1', new mongoose.Types.UUID()], + ['role_2', new mongoose.Types.UUID()] + ]) + }); + + await user.save(); + + user.doc_map.set('role_1', new mongoose.Types.UUID()); + await user.save(); + + const exists = await Test.findOne({ 'doc_map.role_1': { $type: 'binData' } }); + assert.ok(exists); + + assert.equal(typeof user.get('doc_map.role_1'), 'string'); + }); + // the following are TODOs based on SchemaUUID.prototype.$conditionalHandlers which are not tested yet it('should work with $bits* operators'); it('should work with $all operator'); From 8f4b29ecc1ed11570722523203015f56376766cb Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 8 Aug 2023 15:00:53 -0400 Subject: [PATCH 2/3] Update lib/utils.js Co-authored-by: Uzlopak --- lib/utils.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/utils.js b/lib/utils.js index 5ff64a6ccca..5c8e73f71bb 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -641,10 +641,9 @@ const mapGetterOptions = Object.freeze({ getters: false }); function getValueLookup(obj, part) { const _from = obj && obj._doc ? obj._doc : obj; - obj = _from instanceof Map ? + return _from instanceof Map ? _from.get(part, mapGetterOptions) : _from[part]; - return obj; } /** From a1a45123bde8d580d50d174a8e52853d29190f88 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Tue, 8 Aug 2023 15:12:59 -0400 Subject: [PATCH 3/3] Update lib/utils.js Co-authored-by: Hafez --- lib/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils.js b/lib/utils.js index 5c8e73f71bb..ab7563bd992 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -640,7 +640,7 @@ exports.getValue = function(path, obj, map) { const mapGetterOptions = Object.freeze({ getters: false }); function getValueLookup(obj, part) { - const _from = obj && obj._doc ? obj._doc : obj; + const _from = obj?._doc || obj; return _from instanceof Map ? _from.get(part, mapGetterOptions) : _from[part];