Skip to content

Commit 9dc2e8a

Browse files
committed
Merge branch 'master' into vkarpov15/gh-14719
2 parents b698c28 + 7d742e2 commit 9dc2e8a

File tree

3 files changed

+41
-8
lines changed

3 files changed

+41
-8
lines changed

lib/document.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,9 @@ function Document(obj, fields, skipId, options) {
164164
// By default, defaults get applied **before** setting initial values
165165
// Re: gh-6155
166166
if (defaults) {
167-
applyDefaults(this, fields, exclude, hasIncludedChildren, true, null);
167+
applyDefaults(this, fields, exclude, hasIncludedChildren, true, null, {
168+
skipParentChangeTracking: true
169+
});
168170
}
169171
}
170172
if (obj) {

lib/helpers/document/applyDefaults.js

+7-6
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
const isNestedProjection = require('../projection/isNestedProjection');
44

5-
module.exports = function applyDefaults(doc, fields, exclude, hasIncludedChildren, isBeforeSetters, pathsToSkip) {
5+
module.exports = function applyDefaults(doc, fields, exclude, hasIncludedChildren, isBeforeSetters, pathsToSkip, options) {
66
const paths = Object.keys(doc.$__schema.paths);
77
const plen = paths.length;
8+
const skipParentChangeTracking = options && options.skipParentChangeTracking;
89

910
for (let i = 0; i < plen; ++i) {
1011
let def;
@@ -80,7 +81,7 @@ module.exports = function applyDefaults(doc, fields, exclude, hasIncludedChildre
8081

8182
if (typeof def !== 'undefined') {
8283
doc_[piece] = def;
83-
applyChangeTracking(doc, p);
84+
applyChangeTracking(doc, p, skipParentChangeTracking);
8485
}
8586
} else if (included) {
8687
// selected field
@@ -93,7 +94,7 @@ module.exports = function applyDefaults(doc, fields, exclude, hasIncludedChildre
9394

9495
if (typeof def !== 'undefined') {
9596
doc_[piece] = def;
96-
applyChangeTracking(doc, p);
97+
applyChangeTracking(doc, p, skipParentChangeTracking);
9798
}
9899
}
99100
} else {
@@ -106,7 +107,7 @@ module.exports = function applyDefaults(doc, fields, exclude, hasIncludedChildre
106107

107108
if (typeof def !== 'undefined') {
108109
doc_[piece] = def;
109-
applyChangeTracking(doc, p);
110+
applyChangeTracking(doc, p, skipParentChangeTracking);
110111
}
111112
}
112113
} else {
@@ -120,9 +121,9 @@ module.exports = function applyDefaults(doc, fields, exclude, hasIncludedChildre
120121
* ignore
121122
*/
122123

123-
function applyChangeTracking(doc, fullPath) {
124+
function applyChangeTracking(doc, fullPath, skipParentChangeTracking) {
124125
doc.$__.activePaths.default(fullPath);
125-
if (doc.$isSubdocument && doc.$isSingleNested && doc.$parent() != null) {
126+
if (!skipParentChangeTracking && doc.$isSubdocument && doc.$isSingleNested && doc.$parent() != null) {
126127
doc.$parent().$__.activePaths.default(doc.$__pathRelativeToParent(fullPath));
127128
}
128129
}

test/document.test.js

+31-1
Original file line numberDiff line numberDiff line change
@@ -12805,7 +12805,7 @@ describe('document', function() {
1280512805
await user.save();
1280612806
await TestModel.deleteOne({ userId });
1280712807

12808-
assert.equal(Object.keys(TestModel.schema.subpaths).length, 3);
12808+
assert.ok(Object.keys(TestModel.schema.subpaths).length <= 3);
1280912809
});
1281012810

1281112811
it('handles embedded discriminators defined using Schema.prototype.discriminator (gh-13898)', async function() {
@@ -13552,6 +13552,36 @@ describe('document', function() {
1355213552
assert.ok(blogPost.comment.jsonField.isDirectModified('fieldA'));
1355313553
});
1355413554

13555+
it('avoids leaving subdoc _id in default state when setting subdocument to same value (gh-14722)', async function() {
13556+
const getUser = () => ({
13557+
_id: new mongoose.Types.ObjectId('66852317541ef0e22ae5214c'),
13558+
name: 'test1',
13559+
13560+
});
13561+
13562+
const updateInfoSchema = new mongoose.Schema({
13563+
name: {
13564+
type: String, required: true
13565+
},
13566+
email: {
13567+
type: String,
13568+
required: true
13569+
}
13570+
}, {
13571+
versionKey: false
13572+
});
13573+
const schema = new mongoose.Schema({ name: String, updater: updateInfoSchema });
13574+
13575+
const TestModel = db.model('Test', schema);
13576+
const { _id } = await TestModel.create({ name: 'taco', updater: getUser() });
13577+
const doc = await TestModel.findById(_id).orFail();
13578+
13579+
doc.name = 'taco-edit';
13580+
doc.updater = getUser();
13581+
assert.deepStrictEqual(doc.getChanges(), { $set: { name: 'taco-edit' } });
13582+
assert.ok(!doc.$isDefault('updater._id'));
13583+
});
13584+
1355513585
it('$clearModifiedPaths (gh-14268)', async function() {
1355613586
const schema = new Schema({
1355713587
name: String,

0 commit comments

Comments
 (0)