Skip to content

Commit

Permalink
Merge branch '6.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
vkarpov15 committed Aug 1, 2023
2 parents 22cfb3b + be5b7d5 commit a07a4f6
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 13 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
6.11.5 / 2023-08-01
===================
* fix(schema): make Schema.prototype.clone() avoid creating different copies of subdocuments and single nested paths underneath single nested paths #13671 #13626
* fix: custom debug function not processing all args #13418

7.4.1 / 2023-07-24
==================
* fix(document): correctly clean up nested subdocs modified state on save() #13644 #13609
Expand Down
23 changes: 16 additions & 7 deletions lib/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -2619,7 +2619,7 @@ function _evaluateRequiredFunctions(doc) {
*/

function _getPathsToValidate(doc, pathsToValidate, pathsToSkip) {
const skipSchemaValidators = {};
const doValidateOptions = {};

_evaluateRequiredFunctions(doc);
// only validate required fields when necessary
Expand Down Expand Up @@ -2656,8 +2656,17 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip) {
!doc.isDirectModified(fullPathToSubdoc) &&
!doc.$isDefault(fullPathToSubdoc)) {
paths.add(fullPathToSubdoc);
if (doc.$__.pathsToScopes == null) {
doc.$__.pathsToScopes = {};
}
doc.$__.pathsToScopes[fullPathToSubdoc] = subdoc.$isDocumentArrayElement ?
subdoc.__parentArray :
subdoc.$parent();

skipSchemaValidators[fullPathToSubdoc] = true;
doValidateOptions[fullPathToSubdoc] = { skipSchemaValidators: true };
if (subdoc.$isDocumentArrayElement && subdoc.__index != null) {
doValidateOptions[fullPathToSubdoc].index = subdoc.__index;
}
}
}
}
Expand Down Expand Up @@ -2791,7 +2800,7 @@ function _getPathsToValidate(doc, pathsToValidate, pathsToSkip) {
}

paths = Array.from(paths);
return [paths, skipSchemaValidators];
return [paths, doValidateOptions];
}

/*!
Expand Down Expand Up @@ -2862,7 +2871,7 @@ Document.prototype.$__validate = function(pathsToValidate, options, callback) {
const paths = shouldValidateModifiedOnly ?
pathDetails[0].filter((path) => this.$isModified(path)) :
pathDetails[0];
const skipSchemaValidators = pathDetails[1];
const doValidateOptionsByPath = pathDetails[1];
if (typeof pathsToValidate === 'string') {
pathsToValidate = pathsToValidate.split(' ');
}
Expand Down Expand Up @@ -2930,16 +2939,16 @@ Document.prototype.$__validate = function(pathsToValidate, options, callback) {
_this;

const doValidateOptions = {
skipSchemaValidators: skipSchemaValidators[path],
...doValidateOptionsByPath[path],
path: path,
validateModifiedOnly: shouldValidateModifiedOnly
};

schemaType.doValidate(val, function(err) {
if (err) {
const isSubdoc = schemaType.$isSingleNested ||
schemaType.$isArraySubdocument ||
schemaType.$isMongooseDocumentArray;
schemaType.$isArraySubdocument ||
schemaType.$isMongooseDocumentArray;
if (isSubdoc && err instanceof ValidationError) {
return --total || complete();
}
Expand Down
20 changes: 19 additions & 1 deletion lib/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,25 @@ Schema.prototype._clone = function _clone(Constructor) {
s.paths = clone(this.paths);
s.nested = clone(this.nested);
s.subpaths = clone(this.subpaths);
s.singleNestedPaths = clone(this.singleNestedPaths);
for (const schemaType of Object.values(s.paths)) {
if (schemaType.$isSingleNested) {
const path = schemaType.path;
for (const key of Object.keys(schemaType.schema.paths)) {
s.singleNestedPaths[path + '.' + key] = schemaType.schema.paths[key];
}
for (const key of Object.keys(schemaType.schema.singleNestedPaths)) {
s.singleNestedPaths[path + '.' + key] =
schemaType.schema.singleNestedPaths[key];
}
for (const key of Object.keys(schemaType.schema.subpaths)) {
s.singleNestedPaths[path + '.' + key] =
schemaType.schema.subpaths[key];
}
for (const key of Object.keys(schemaType.schema.nested)) {
s.singleNestedPaths[path + '.' + key] = 'nested';
}
}
}
s.childSchemas = gatherChildSchemas(s);

s.virtuals = clone(this.virtuals);
Expand Down
15 changes: 15 additions & 0 deletions test/schema.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1984,6 +1984,21 @@ describe('schema', function() {
const test2 = test.clone();
assert.equal(test2.localTest(), 42);
});

it('avoids creating duplicate array constructors when cloning doc array underneath subdoc (gh-13626)', function() {
const schema = new mongoose.Schema({
config: {
type: new mongoose.Schema({
attributes: [{ value: 'Mixed' }]
})
}
}).clone();

assert.strictEqual(
schema.paths['config'].schema.paths['attributes'].Constructor,
schema.singleNestedPaths['config.attributes'].Constructor
);
});
});

it('childSchemas prop (gh-5695)', function() {
Expand Down
10 changes: 5 additions & 5 deletions test/schema.validation.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1240,7 +1240,7 @@ describe('schema', function() {
}
});

it('enums on arrays (gh-6102) (gh-8449)', function() {
it('enums on arrays (gh-6102) (gh-8449)', async function() {
assert.throws(function() {
new Schema({
array: {
Expand Down Expand Up @@ -1271,10 +1271,10 @@ describe('schema', function() {
Model = mongoose.model('gh6102', MySchema);
const doc2 = new Model({ array: [1, 2, 3] });

return doc1.validate().
then(() => assert.ok(false), err => assert.equal(err.name, 'ValidationError')).
then(() => doc2.validate()).
then(() => assert.ok(false), err => assert.equal(err.name, 'ValidationError'));
let err = await doc1.validate().then(() => null, err => err);
assert.equal(err.name, 'ValidationError');
err = await doc2.validate().then(() => null, err => err);
assert.equal(err.name, 'ValidationError', err);
});

it('skips conditional required (gh-3539)', async function() {
Expand Down

0 comments on commit a07a4f6

Please sign in to comment.