Skip to content

Commit d3cb2ab

Browse files
authoredMar 30, 2024··
Merge pull request #14468 from Automattic/vkarpov15/gh-14446
fix(document): handle virtuals that are stored as objects but getter returns string with toJSON
2 parents 759f0d4 + 69a0581 commit d3cb2ab

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed
 

‎lib/document.js

+6-1
Original file line numberDiff line numberDiff line change
@@ -4113,7 +4113,12 @@ function applyGetters(self, json, options) {
41134113
for (let ii = 0; ii < plen; ++ii) {
41144114
part = parts[ii];
41154115
v = cur[part];
4116-
if (ii === last) {
4116+
// If we've reached a non-object part of the branch, continuing would
4117+
// cause "Cannot create property 'foo' on string 'bar'" error.
4118+
// Necessary for mongoose-intl plugin re: gh-14446
4119+
if (branch != null && typeof branch !== 'object') {
4120+
break;
4121+
} else if (ii === last) {
41174122
const val = self.$get(path);
41184123
branch[part] = clone(val, options);
41194124
} else if (v == null) {

‎test/document.test.js

+32
Original file line numberDiff line numberDiff line change
@@ -12538,6 +12538,38 @@ describe('document', function() {
1253812538
assert.equal(purchaseFromDbCart.products[0].product.name, 'Bug');
1253912539
assert.equal(purchaseFromDbCart.singleProduct.name, 'Bug');
1254012540
});
12541+
12542+
it('handles virtuals that are stored as objects but getter returns string with toJSON (gh-14446)', async function() {
12543+
const childSchema = new mongoose.Schema();
12544+
12545+
childSchema.virtual('name')
12546+
.set(function(values) {
12547+
for (const [lang, val] of Object.entries(values)) {
12548+
this.set(`name.${lang}`, val);
12549+
}
12550+
})
12551+
.get(function() {
12552+
return this.$__getValue(`name.${this.lang}`);
12553+
});
12554+
12555+
childSchema.add({ name: { en: { type: String }, de: { type: String } } });
12556+
12557+
const ChildModel = db.model('Child', childSchema);
12558+
const ParentModel = db.model('Parent', new mongoose.Schema({
12559+
children: [childSchema]
12560+
}));
12561+
12562+
const child = await ChildModel.create({ name: { en: 'Stephen', de: 'Stefan' } });
12563+
child.lang = 'en';
12564+
assert.equal(child.name, 'Stephen');
12565+
12566+
const parent = await ParentModel.create({
12567+
children: [{ name: { en: 'Stephen', de: 'Stefan' } }]
12568+
});
12569+
parent.children[0].lang = 'de';
12570+
const obj = parent.toJSON({ getters: true });
12571+
assert.equal(obj.children[0].name, 'Stefan');
12572+
});
1254112573
});
1254212574

1254312575
describe('Check if instance function that is supplied in schema option is availabe', function() {

0 commit comments

Comments
 (0)
Please sign in to comment.