Skip to content

Commit

Permalink
fix(document): handle validation with triply nested document arrays
Browse files Browse the repository at this point in the history
Fix #11564
  • Loading branch information
vkarpov15 committed Apr 10, 2022
1 parent dd4fe2c commit 8ae4a4a
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 4 deletions.
5 changes: 1 addition & 4 deletions lib/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -2485,10 +2485,7 @@ function _getPathsToValidate(doc) {
if (subdoc.$basePath) {
// Remove child paths for now, because we'll be validating the whole
// subdoc
if (!subdoc.$__.fullPath) {
subdoc.ownerDocument();
}
const fullPathToSubdoc = subdoc.$__.fullPath;
const fullPathToSubdoc = subdoc.$__fullPathWithIndexes();

for (const p of paths) {
if (p === null || p.startsWith(fullPathToSubdoc + '.')) {
Expand Down
29 changes: 29 additions & 0 deletions lib/types/subdocument.js
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,35 @@ Subdocument.prototype.ownerDocument = function() {
return this.$__.ownerDocument;
};

/*!
* ignore
*/

Subdocument.prototype.$__fullPathWithIndexes = function() {
let parent = this; // eslint-disable-line consistent-this
const paths = [];
const seenDocs = new Set([parent]);

while (true) {
if (typeof parent.$__pathRelativeToParent !== 'function') {
break;
}
paths.unshift(parent.$__pathRelativeToParent(void 0, false));
const _parent = parent.$parent();
if (_parent == null) {
break;
}
parent = _parent;
if (seenDocs.has(parent)) {
throw new Error('Infinite subdocument loop: subdoc with _id ' + parent._id + ' is a parent of itself');
}

seenDocs.add(parent);
}

return paths.join('.');
};

/**
* Returns this sub-documents parent document.
*
Expand Down
45 changes: 45 additions & 0 deletions test/document.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11238,4 +11238,49 @@ describe('document', function() {
assert.equal(doc.name, 'test');
assert.equal(doc.mix.val, 'foo');
});

it('correctly validates deeply nested document arrays (gh-11564)', async function() {
const testSchemaSub3 = new mongoose.Schema({
name: {
type: String,
required: true
}
});

const testSchemaSub2 = new mongoose.Schema({
name: {
type: String,
required: true
},
list: [testSchemaSub3]
});

const testSchemaSub1 = new mongoose.Schema({
name: {
type: String,
required: true
},
list: [testSchemaSub2]
});

const testSchema = new mongoose.Schema({
name: String,
list: [testSchemaSub1]
});

const testModel = db.model('Test', testSchema);

await testModel.create({
name: 'lvl1',
list: [{
name: 'lvl2',
list: [{
name: 'lvl3'
// list: [{
// name: 'lvl4'
// }]
}]
}]
});
});
});

0 comments on commit 8ae4a4a

Please sign in to comment.