diff --git a/lib/document.js b/lib/document.js index ffa48ce906f..cd5c8b0c84e 100644 --- a/lib/document.js +++ b/lib/document.js @@ -1621,7 +1621,7 @@ Document.prototype.$__shouldModify = function(pathToMark, path, options, constru return false; } - if (!deepEqual(val, priorVal || utils.getValue(path, this))) { + if (!deepEqual(val, priorVal !== undefined ? priorVal : utils.getValue(path, this))) { return true; } diff --git a/test/document.test.js b/test/document.test.js index 9804b6b8c18..80380ec26a9 100644 --- a/test/document.test.js +++ b/test/document.test.js @@ -12075,6 +12075,41 @@ describe('document', function() { assert.equal(doc.list.length, 3); assert.deepStrictEqual(doc.list.map(el => el.a), [1, 2, 3]); }); + + it('should not trigger isModified when setting a nested boolean to the same value as previously (gh-12992)', async function() { + const Test = db.model('Test', new Schema({ + result: new Schema( + { + score: Number, + passed: Boolean + }, + { _id: false } + ) + })); + const newTest = await Test.create({ + result: { + score: 40, + passed: false + } + }); + + const existingTest = await Test.findById(newTest._id); + existingTest.result = { + score: 40, + passed: false + }; + + assert.equal(existingTest.isModified(), false); + assert.equal(existingTest.modifiedPaths().length, 0); + + existingTest.result = { + score: 40, + passed: true + }; + + assert.equal(existingTest.isModified(), true); + assert.equal(existingTest.modifiedPaths().length, 1); + }); }); describe('Check if instance function that is supplied in schema option is availabe', function() {