Skip to content

Commit 05c981a

Browse files
authored
Merge pull request #15374 from Automattic/vkarpov15/gh-15350
fix: correct change tracking with maps of arrays of primitives and maps of maps
2 parents 7cab712 + 3bfa762 commit 05c981a

File tree

3 files changed

+63
-3
lines changed

3 files changed

+63
-3
lines changed

lib/schema/map.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ class SchemaMap extends SchemaType {
2323
return SchemaType.set(option, value);
2424
}
2525

26-
cast(val, doc, init) {
26+
cast(val, doc, init, prev, options) {
2727
if (val instanceof MongooseMap) {
2828
return val;
2929
}
3030

31-
const path = this.path;
31+
const path = options?.path ?? this.path;
3232

3333
if (init) {
3434
const map = new MongooseMap({}, path, doc, this.$__schemaType);

lib/types/map.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ class MongooseMap extends Map {
136136
}
137137
} else {
138138
try {
139-
const options = this.$__schemaType.$isMongooseDocumentArray || this.$__schemaType.$isSingleNested ?
139+
const options = this.$__schemaType.$isMongooseDocumentArray || this.$__schemaType.$isSingleNested || this.$__schemaType.$isMongooseArray || this.$__schemaType.$isSchemaMap ?
140140
{ path: fullPath.call(this) } :
141141
null;
142142
value = this.$__schemaType.applySetters(

test/types.map.test.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,4 +1179,64 @@ describe('Map', function() {
11791179
doc1 = await Test.findOne({ _id: doc1._id }).lean();
11801180
assert.deepStrictEqual(doc1.test_map, { key1: [] });
11811181
});
1182+
1183+
it('handles modifying array in map of primitives (gh-15350)', async function() {
1184+
const DocSchema = new mongoose.Schema({
1185+
map: {
1186+
type: Map,
1187+
of: [{ type: Number }],
1188+
default: new Map()
1189+
}
1190+
});
1191+
const Doc = db.model('Test', DocSchema);
1192+
1193+
const doc = await Doc.create({});
1194+
assert.ok(doc.map instanceof Map);
1195+
assert.equal(doc.map.size, 0);
1196+
1197+
doc.map.set('key', [1, 2]);
1198+
await doc.save();
1199+
assert.deepEqual(Array.from(doc.map.get('key')), [1, 2]);
1200+
1201+
const list = doc.map.get('key');
1202+
list.push(3);
1203+
assert.deepStrictEqual(doc.getChanges().$push, { 'map.key': { $each: [3] } });
1204+
await doc.save();
1205+
1206+
const fromDb = await Doc.findById(doc._id);
1207+
assert.deepEqual(Array.from(fromDb.map.get('key')), [1, 2, 3]);
1208+
});
1209+
1210+
it('handles maps of maps of numbers (gh-15350)', async function() {
1211+
const DocSchema = new mongoose.Schema({
1212+
map: {
1213+
type: Map,
1214+
of: {
1215+
type: Map,
1216+
of: Number
1217+
},
1218+
default: new Map()
1219+
}
1220+
});
1221+
const Doc = db.model('Test', DocSchema);
1222+
1223+
const doc = await Doc.create({});
1224+
assert.ok(doc.map instanceof Map);
1225+
assert.equal(doc.map.size, 0);
1226+
1227+
const innerMap = new Map();
1228+
innerMap.set('inner', 42);
1229+
doc.map.set('outer', innerMap);
1230+
await doc.save();
1231+
1232+
assert.equal(doc.map.get('outer').get('inner'), 42);
1233+
1234+
doc.map.get('outer').set('inner2', 43);
1235+
assert.deepStrictEqual(doc.getChanges(), { $set: { 'map.outer.inner2': 43 } });
1236+
await doc.save();
1237+
1238+
const fromDb = await Doc.findById(doc._id);
1239+
assert.equal(fromDb.map.get('outer').get('inner'), 42);
1240+
assert.equal(fromDb.map.get('outer').get('inner2'), 43);
1241+
});
11821242
});

0 commit comments

Comments
 (0)