Skip to content

Commit b4e3b2f

Browse files
authored
Merge pull request #14213 from Automattic/vkarpov15/gh-14024
fix: add ignoreAtomics option to isModified() for better backwards compatibility with Mongoose 5
2 parents e3c12cf + 0960fae commit b4e3b2f

File tree

4 files changed

+56
-7
lines changed

4 files changed

+56
-7
lines changed

lib/document.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2221,12 +2221,15 @@ Document.prototype[documentModifiedPaths] = Document.prototype.modifiedPaths;
22212221
* doc.isDirectModified('documents') // false
22222222
*
22232223
* @param {String} [path] optional
2224+
* @param {Object} [options]
2225+
* @param {Boolean} [options.ignoreAtomics=false] If true, doesn't return true if path is underneath an array that was modified with atomic operations like `push()`
22242226
* @return {Boolean}
22252227
* @api public
22262228
*/
22272229

2228-
Document.prototype.isModified = function(paths, modifiedPaths) {
2230+
Document.prototype.isModified = function(paths, options, modifiedPaths) {
22292231
if (paths) {
2232+
const ignoreAtomics = options && options.ignoreAtomics;
22302233
const directModifiedPathsObj = this.$__.activePaths.states.modify;
22312234
if (directModifiedPathsObj == null) {
22322235
return false;
@@ -2247,7 +2250,16 @@ Document.prototype.isModified = function(paths, modifiedPaths) {
22472250
return !!~modified.indexOf(path);
22482251
});
22492252

2250-
const directModifiedPaths = Object.keys(directModifiedPathsObj);
2253+
let directModifiedPaths = Object.keys(directModifiedPathsObj);
2254+
if (ignoreAtomics) {
2255+
directModifiedPaths = directModifiedPaths.filter(path => {
2256+
const value = this.$__getValue(path);
2257+
if (value != null && value[arrayAtomicsSymbol] != null && value[arrayAtomicsSymbol].$set === undefined) {
2258+
return false;
2259+
}
2260+
return true;
2261+
});
2262+
}
22512263
return isModifiedChild || paths.some(function(path) {
22522264
return directModifiedPaths.some(function(mod) {
22532265
return mod === path || path.startsWith(mod + '.');
@@ -2681,7 +2693,7 @@ function _getPathsToValidate(doc) {
26812693
paths.delete(fullPathToSubdoc + '.' + modifiedPath);
26822694
}
26832695

2684-
if (doc.$isModified(fullPathToSubdoc, modifiedPaths) &&
2696+
if (doc.$isModified(fullPathToSubdoc, null, modifiedPaths) &&
26852697
!doc.isDirectModified(fullPathToSubdoc) &&
26862698
!doc.$isDefault(fullPathToSubdoc)) {
26872699
paths.add(fullPathToSubdoc);

lib/types/subdocument.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ Subdocument.prototype.markModified = function(path) {
178178
* ignore
179179
*/
180180

181-
Subdocument.prototype.isModified = function(paths, modifiedPaths) {
181+
Subdocument.prototype.isModified = function(paths, options, modifiedPaths) {
182182
const parent = this.$parent();
183183
if (parent != null) {
184184
if (Array.isArray(paths) || typeof paths === 'string') {
@@ -188,10 +188,10 @@ Subdocument.prototype.isModified = function(paths, modifiedPaths) {
188188
paths = this.$__pathRelativeToParent();
189189
}
190190

191-
return parent.$isModified(paths, modifiedPaths);
191+
return parent.$isModified(paths, options, modifiedPaths);
192192
}
193193

194-
return Document.prototype.isModified.call(this, paths, modifiedPaths);
194+
return Document.prototype.isModified.call(this, paths, options, modifiedPaths);
195195
};
196196

197197
/**

test/document.modified.test.js

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,43 @@ describe('document modified', function() {
208208
assert.equal(post.isModified('comments.0.title'), true);
209209
assert.equal(post.isDirectModified('comments.0.title'), true);
210210
});
211+
it('with push (gh-14024)', async function() {
212+
const post = new BlogPost();
213+
post.init({
214+
title: 'Test',
215+
slug: 'test',
216+
comments: [{ title: 'Test', date: new Date(), body: 'Test' }]
217+
});
218+
219+
post.comments.push({ title: 'new comment', body: 'test' });
220+
221+
assert.equal(post.isModified('comments.0.title', { ignoreAtomics: true }), false);
222+
assert.equal(post.isModified('comments.0.body', { ignoreAtomics: true }), false);
223+
assert.equal(post.get('comments')[0].isModified('body', { ignoreAtomics: true }), false);
224+
});
225+
it('with push and set (gh-14024)', async function() {
226+
const post = new BlogPost();
227+
post.init({
228+
title: 'Test',
229+
slug: 'test',
230+
comments: [{ title: 'Test', date: new Date(), body: 'Test' }]
231+
});
232+
233+
post.comments.push({ title: 'new comment', body: 'test' });
234+
post.get('comments')[0].set('title', 'Woot');
235+
236+
assert.equal(post.isModified('comments', { ignoreAtomics: true }), true);
237+
assert.equal(post.isModified('comments.0.title', { ignoreAtomics: true }), true);
238+
assert.equal(post.isDirectModified('comments.0.title'), true);
239+
assert.equal(post.isDirectModified('comments.0.body'), false);
240+
assert.equal(post.isModified('comments.0.body', { ignoreAtomics: true }), false);
241+
242+
assert.equal(post.isModified('comments', { ignoreAtomics: true }), true);
243+
assert.equal(post.isModified('comments.0.title', { ignoreAtomics: true }), true);
244+
assert.equal(post.isDirectModified('comments.0.title'), true);
245+
assert.equal(post.isDirectModified('comments.0.body'), false);
246+
assert.equal(post.isModified('comments.0.body', { ignoreAtomics: true }), false);
247+
});
211248
it('with accessors', function() {
212249
const post = new BlogPost();
213250
post.init({

types/document.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ declare module 'mongoose' {
179179
* Returns true if any of the given paths are modified, else false. If no arguments, returns `true` if any path
180180
* in this document is modified.
181181
*/
182-
isModified(path?: string | Array<string>): boolean;
182+
isModified(path?: string | Array<string>, options?: { ignoreAtomics?: boolean } | null): boolean;
183183

184184
/** Boolean flag specifying if the document is new. */
185185
isNew: boolean;

0 commit comments

Comments
 (0)