Skip to content

Commit f58c6c2

Browse files
committed
Merge branch '6.x' into 7.x
2 parents c9842d3 + 6760c54 commit f58c6c2

File tree

6 files changed

+119
-3
lines changed

6 files changed

+119
-3
lines changed

CHANGELOG.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
6.12.3 / 2023-11-07
2+
===================
3+
* fix(ChangeStream): correctly handle hydrate option when using change stream as stream instead of iterator #14052
4+
* fix(schema): fix dangling reference to virtual in tree after `removeVirtual()` #14019 #13085
5+
* fix(document): avoid unmarking modified on nested path if no initial value stored and already modified #14053 #14024
6+
* fix(document): consistently avoid marking subpaths of nested paths as modified #14053 #14022
7+
18
7.6.4 / 2023-10-30
29
==================
310
* fix(connection): retain modified status for documents created outside a transaction during transaction retries #14017 #13973
@@ -7,6 +14,10 @@
714
* docs: fix differences between sample codes and documentation #13998 [suzuki](https://github.com/suzuki)
815
* docs: fix missing import and change wrong variable name #13992 [suzuki](https://github.com/suzuki)
916

17+
6.12.2 / 2023-10-25
18+
===================
19+
* fix: add fullPath to ValidatorProps #13995 [Freezystem](https://github.com/Freezystem)
20+
1021
7.6.3 / 2023-10-17
1122
==================
1223
* fix(populate): handle multiple spaces when specifying paths to populate using space-delimited paths #13984 #13951
@@ -25,6 +36,11 @@
2536
* types(models): add cleaner type definitions for insertMany() with no generics to prevent errors when using insertMany() in generic classes #13964 #13957
2637
* types(schematypes): allow defining map path using type: 'Map' in addition to type: Map #13960 #13755
2738

39+
6.12.1 / 2023-10-12
40+
===================
41+
* fix(mongoose): correctly handle global applyPluginsToChildSchemas option #13945 #13887 [hasezoey](https://github.com/hasezoey)
42+
* fix: Document.prototype.isModified support for a string of keys as first parameter #13940 #13674 [k-chop](https://github.com/k-chop)
43+
2844
7.6.1 / 2023-10-09
2945
==================
3046
* fix: bump bson to match mongodb@5.9.0 exactly #13947 [hasezoey](https://github.com/hasezoey)

lib/cursor/ChangeStream.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ class ChangeStream extends EventEmitter {
8989
if (ev === 'error' && this.closed) {
9090
return;
9191
}
92+
if (data != null && data.fullDocument != null && this.options && this.options.hydrate) {
93+
data.fullDocument = this.options.model.hydrate(data.fullDocument);
94+
}
9295
this.emit(ev, data);
9396
});
9497
});

lib/document.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1181,6 +1181,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
11811181
this.invalidate(path, new MongooseError.CastError('Object', val, path));
11821182
return this;
11831183
}
1184+
const wasModified = this.$isModified(path);
11841185
const hasInitialVal = this.$__.savedState != null && this.$__.savedState.hasOwnProperty(path);
11851186
if (this.$__.savedState != null && !this.$isNew && !this.$__.savedState.hasOwnProperty(path)) {
11861187
const initialVal = this.$__getValue(path);
@@ -1203,9 +1204,11 @@ Document.prototype.$set = function $set(path, val, type, options) {
12031204

12041205
this.$__setValue(path, {});
12051206
for (const key of keys) {
1206-
this.$set(path + '.' + key, val[key], constructing, options);
1207+
this.$set(path + '.' + key, val[key], constructing, { ...options, _skipMarkModified: true });
12071208
}
1208-
if (priorVal != null && utils.deepEqual(hasInitialVal ? this.$__.savedState[path] : priorVal, val)) {
1209+
if (priorVal != null &&
1210+
(!wasModified || hasInitialVal) &&
1211+
utils.deepEqual(hasInitialVal ? this.$__.savedState[path] : priorVal, val)) {
12091212
this.unmarkModified(path);
12101213
} else {
12111214
this.markModified(path);

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@
106106
"prepublishOnly": "npm run build-browser",
107107
"release": "git pull && git push origin master --tags && npm publish",
108108
"release-5x": "git pull origin 5.x && git push origin 5.x && git push origin 5.x --tags && npm publish --tag 5x",
109-
"release-6x": "git pull origin 6.x && git push origin 6.x && git push origin 6.x --tags && npm publish --tag legacy",
109+
"release-6x": "git pull origin 6.x && git push origin 6.x && git push origin 6.x --tags && npm publish --tag 6x",
110110
"mongo": "node ./tools/repl.js",
111111
"test": "mocha --exit ./test/*.test.js",
112112
"test-deno": "deno run --allow-env --allow-read --allow-net --allow-run --allow-sys --allow-write ./test/deno.js",

test/document.test.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3701,6 +3701,11 @@ describe('document', function() {
37013701

37023702
assert.deepEqual(
37033703
kitty.modifiedPaths(),
3704+
['surnames']
3705+
);
3706+
3707+
assert.deepEqual(
3708+
kitty.modifiedPaths({ includeChildren: true }),
37043709
['surnames', 'surnames.docarray']
37053710
);
37063711
});
@@ -9198,6 +9203,49 @@ describe('document', function() {
91989203
assert.ok(foo.isModified('subdoc.bar'));
91999204
});
92009205

9206+
it('does not unmark modified if there is no initial value (gh-9396)', async function() {
9207+
const IClientSchema = new Schema({
9208+
jwt: {
9209+
token_crypt: { type: String, template: false, maxSize: 8 * 1024 },
9210+
token_salt: { type: String, template: false }
9211+
}
9212+
});
9213+
9214+
const encrypt = function(doc, path, value) {
9215+
doc.set(path + '_crypt', value + '_crypt');
9216+
doc.set(path + '_salt', value + '_salt');
9217+
};
9218+
9219+
const decrypt = function(doc, path) {
9220+
return doc.get(path + '_crypt').replace('_crypt', '');
9221+
};
9222+
9223+
IClientSchema.virtual('jwt.token')
9224+
.get(function() {
9225+
return decrypt(this, 'jwt.token');
9226+
})
9227+
.set(function(value) {
9228+
encrypt(this, 'jwt.token', value);
9229+
});
9230+
9231+
9232+
const iclient = db.model('Test', IClientSchema);
9233+
const test = new iclient({
9234+
jwt: {
9235+
token: 'firstToken'
9236+
}
9237+
});
9238+
9239+
await test.save();
9240+
const entry = await iclient.findById(test._id).orFail();
9241+
entry.set('jwt.token', 'secondToken');
9242+
entry.set(entry.toJSON());
9243+
await entry.save();
9244+
9245+
const { jwt } = await iclient.findById(test._id).orFail();
9246+
assert.strictEqual(jwt.token, 'secondToken');
9247+
});
9248+
92019249
it('correctly tracks saved state for deeply nested objects (gh-10773) (gh-9396)', async function() {
92029250
const PaymentSchema = Schema({ status: String }, { _id: false });
92039251
const OrderSchema = new Schema({
@@ -12620,6 +12668,28 @@ describe('document', function() {
1262012668
const { collection } = await Test.findById(doc);
1262112669
assert.strictEqual(collection, 'baz');
1262212670
});
12671+
it('avoids adding nested paths to markModified() output if adding a new field (gh-14024)', async function() {
12672+
const eventSchema = new Schema({
12673+
name: { type: String },
12674+
__stateBeforeSuspension: {
12675+
field1: { type: String },
12676+
field2: { type: String },
12677+
jsonField: {
12678+
name: { type: String },
12679+
name1: { type: String }
12680+
}
12681+
}
12682+
});
12683+
const Event = db.model('Event', eventSchema);
12684+
const eventObj = new Event({ name: 'event object', __stateBeforeSuspension: { field1: 'test', jsonField: { name: 'test3' } } });
12685+
await eventObj.save();
12686+
const newObject = { field1: 'test', jsonField: { name: 'test3', name1: 'test4' } };
12687+
eventObj.set('__stateBeforeSuspension', newObject);
12688+
assert.deepEqual(
12689+
eventObj.modifiedPaths(),
12690+
['__stateBeforeSuspension', '__stateBeforeSuspension.jsonField']
12691+
);
12692+
});
1262312693
});
1262412694

1262512695
describe('Check if instance function that is supplied in schema option is availabe', function() {

test/model.test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3485,6 +3485,30 @@ describe('Model', function() {
34853485
assert.equal(changeData.fullDocument.get('name'), 'Tony Stark');
34863486
});
34873487

3488+
it('fullDocument with immediate watcher and hydrate (gh-14049)', async function() {
3489+
const MyModel = db.model('Test', new Schema({ name: String }));
3490+
3491+
const doc = await MyModel.create({ name: 'Ned Stark' });
3492+
3493+
const p = new Promise((resolve) => {
3494+
MyModel.watch([], {
3495+
fullDocument: 'updateLookup',
3496+
hydrate: true
3497+
}).on('change', change => {
3498+
resolve(change);
3499+
});
3500+
});
3501+
3502+
await MyModel.updateOne({ _id: doc._id }, { name: 'Tony Stark' });
3503+
3504+
const changeData = await p;
3505+
assert.equal(changeData.operationType, 'update');
3506+
assert.equal(changeData.fullDocument._id.toHexString(),
3507+
doc._id.toHexString());
3508+
assert.ok(changeData.fullDocument.$__);
3509+
assert.equal(changeData.fullDocument.get('name'), 'Tony Stark');
3510+
});
3511+
34883512
it('respects discriminators (gh-11007)', async function() {
34893513
const BaseModel = db.model('Test', new Schema({ name: String }));
34903514
const ChildModel = BaseModel.discriminator('Test1', new Schema({ email: String }));

0 commit comments

Comments
 (0)