From be67d0f9242ace96cac3583e1617b4d879b86ca5 Mon Sep 17 00:00:00 2001 From: Valeri Karpov Date: Sat, 6 May 2023 21:34:34 -0400 Subject: [PATCH] fix(document): handle set() from top-level underneath a map of mixed Re: #13327 --- lib/document.js | 34 ++++++++++++++++++++++++---------- test/document.test.js | 18 ++++++++++++++++++ 2 files changed, 42 insertions(+), 10 deletions(-) diff --git a/lib/document.js b/lib/document.js index cdc6dc3212f..7ce10c71f7c 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1250,6 +1250,11 @@ Document.prototype.$set = function $set(path, val, type, options) { // allow changes to sub paths of mixed types mixed = true; break; + } else if (schema.$isSchemaMap && schema.$__schemaType instanceof MixedSchema && i < parts.length - 1) { + // Map of mixed and not the last element in the path resolves to mixed + mixed = true; + schema = schema.$__schemaType; + break; } } @@ -1688,17 +1693,26 @@ Document.prototype.$__set = function(pathToMark, path, options, constructing, pa obj[parts[i]] = val; } } else { - if (utils.isPOJO(obj[parts[i]])) { - obj = obj[parts[i]]; - } else if (obj[parts[i]] && obj[parts[i]] instanceof Embedded) { - obj = obj[parts[i]]; - } else if (obj[parts[i]] && !Array.isArray(obj[parts[i]]) && obj[parts[i]].$isSingleNested) { - obj = obj[parts[i]]._doc; - } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) { - obj = obj[parts[i]]; + const isMap = obj instanceof Map; + let value = isMap ? obj.get(parts[i]) : obj[parts[i]]; + if (utils.isPOJO(value)) { + obj = value; + } else if (value && value instanceof Embedded) { + obj = value; + } else if (value && !Array.isArray(value) && value.$isSingleNested) { + obj = value._doc; + } else if (value && Array.isArray(value)) { + obj = value; + } else if (value == null) { + value = {}; + if (isMap) { + obj.set(parts[i], value); + } else { + obj[parts[i]] = value; + } + obj = value; } else { - obj[parts[i]] = obj[parts[i]] || {}; - obj = obj[parts[i]]; + obj = value; } } } diff --git a/test/document.test.js b/test/document.test.js index c941c64b3b4..12d23812a54 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -12094,6 +12094,24 @@ describe('document', function() { const fromDb = await Test.findById(x._id).lean(); assert.equal(fromDb.d.x.y, 1); }); + + it('can set() from top-level on path underneath map of mixed (gh-13327)', async function() { + const testSchema = new Schema({ + c: { + type: Map, + of: 'Mixed' + } + }); + const Test = db.model('Test', testSchema); + + const x = new Test(); + x.set('c.x.y', 1); + assert.strictEqual(x.get('c.x.y'), 1); + await x.save(); + + const fromDb = await Test.findById(x._id).lean(); + assert.equal(fromDb.c.x.y, 1); + }); }); describe('Check if instance function that is supplied in schema option is availabe', function() {