mongoose 6.0.13 → 6.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -214,14 +214,11 @@ function iter(i) {
214
214
  } catch (error) {
215
215
  // Collection operation may throw because of max bson size, catch it here
216
216
  // See gh-3906
217
- if (typeof callback === 'function') {
218
- callback(error);
219
- } else {
220
- this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, error: error });
221
- }
222
217
  if (typeof lastArg === 'function') {
223
- lastArg(error);
218
+ return lastArg(error);
224
219
  } else {
220
+ this.conn.emit('operation-end', { _id: opId, modelName: _this.modelName, collectionName: this.name, method: i, error: error });
221
+
225
222
  throw error;
226
223
  }
227
224
  }
@@ -146,6 +146,7 @@ NativeConnection.prototype.doClose = function(force, fn) {
146
146
  return this;
147
147
  };
148
148
 
149
+
149
150
  /*!
150
151
  * Module exports.
151
152
  */
@@ -73,9 +73,6 @@ module.exports = function assignVals(o) {
73
73
 
74
74
  return valueFilter(val[0], options, populateOptions, _allIds);
75
75
  } else if (o.justOne === false && !Array.isArray(val)) {
76
- if (val === null && o.isVirtual) {
77
- return void 0;
78
- }
79
76
  return valueFilter([val], options, populateOptions, _allIds);
80
77
  }
81
78
  return valueFilter(val, options, populateOptions, _allIds);
@@ -133,6 +130,9 @@ module.exports = function assignVals(o) {
133
130
  docs[i].$populated(_path, o.justOne ? originalIds[0] : originalIds, o.allOptions);
134
131
  // If virtual populate and doc is already init-ed, need to walk through
135
132
  // the actual doc to set rather than setting `_doc` directly
133
+ if (Array.isArray(valueToSet)) {
134
+ valueToSet = valueToSet.map(v => v == null ? void 0 : v);
135
+ }
136
136
  mpath.set(_path, valueToSet, docs[i], void 0, setValue, false);
137
137
  continue;
138
138
  }
@@ -170,7 +170,7 @@ module.exports = function assignVals(o) {
170
170
  }
171
171
  if (docs[i].$__) {
172
172
  o.allOptions.options[populateModelSymbol] = o.allOptions.model;
173
- docs[i].$populated(_path, o.allIds[i], o.allOptions.options);
173
+ docs[i].$populated(_path, o.unpopulatedValues[i], o.allOptions.options);
174
174
 
175
175
  if (valueToSet instanceof Map && !valueToSet.$isMongooseMap) {
176
176
  valueToSet = new MongooseMap(valueToSet, _path, docs[i], docs[i].schema.path(_path).$__schemaType);
@@ -75,6 +75,20 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
75
75
  let normalizedRefPath = null;
76
76
  let schemaOptions = null;
77
77
 
78
+ if (schema != null && schema.instance === 'Embedded' && schema.options.ref) {
79
+ const data = {
80
+ localField: options.path + '._id',
81
+ foreignField: '_id',
82
+ justOne: true
83
+ };
84
+ const res = _getModelNames(doc, schema, modelNameFromQuery, model);
85
+
86
+ const unpopulatedValue = mpath.get(options.path, doc);
87
+ const id = mpath.get('_id', unpopulatedValue);
88
+ addModelNamesToMap(model, map, available, res.modelNames, options, data, id, doc, schemaOptions, unpopulatedValue);
89
+ continue;
90
+ }
91
+
78
92
  if (Array.isArray(schema)) {
79
93
  const schemasArray = schema;
80
94
  for (const _schema of schemasArray) {
@@ -183,7 +197,7 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
183
197
  let isRefPath = false;
184
198
  let justOne = null;
185
199
 
186
- if (schema && schema.caster) {
200
+ if (schema && schema.instance === 'Array') {
187
201
  schema = schema.caster;
188
202
  }
189
203
  if (schema && schema.$isSchemaMap) {
@@ -305,7 +319,12 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
305
319
  }
306
320
 
307
321
  if (!modelNames) {
308
- return { modelNames: modelNames, justOne: justOne, isRefPath: isRefPath, refPath: refPath };
322
+ // `Model.populate()` on a POJO with no known local model. Default to using the `Model`
323
+ if (options._localModel == null) {
324
+ modelNames = [model.modelName];
325
+ } else {
326
+ return { modelNames: modelNames, justOne: justOne, isRefPath: isRefPath, refPath: refPath };
327
+ }
309
328
  }
310
329
 
311
330
  if (!Array.isArray(modelNames)) {
@@ -444,11 +463,16 @@ function _virtualPopulate(model, docs, options, _virtualRes) {
444
463
  * ignore
445
464
  */
446
465
 
447
- function addModelNamesToMap(model, map, available, modelNames, options, data, ret, doc, schemaOptions) {
466
+ function addModelNamesToMap(model, map, available, modelNames, options, data, ret, doc, schemaOptions, unpopulatedValue) {
448
467
  // `PopulateOptions#connection`: if the model is passed as a string, the
449
468
  // connection matters because different connections have different models.
450
469
  const connection = options.connection != null ? options.connection : model.db;
451
470
 
471
+ unpopulatedValue = unpopulatedValue === void 0 ? ret : unpopulatedValue;
472
+ if (Array.isArray(unpopulatedValue)) {
473
+ unpopulatedValue = utils.cloneArrays(unpopulatedValue);
474
+ }
475
+
452
476
  if (modelNames == null) {
453
477
  return;
454
478
  }
@@ -510,6 +534,7 @@ function addModelNamesToMap(model, map, available, modelNames, options, data, re
510
534
  docs: [doc],
511
535
  ids: [ids],
512
536
  allIds: [ret],
537
+ unpopulatedValues: [unpopulatedValue],
513
538
  localField: new Set([data.localField]),
514
539
  foreignField: new Set([data.foreignField]),
515
540
  justOne: data.justOne,
@@ -525,6 +550,7 @@ function addModelNamesToMap(model, map, available, modelNames, options, data, re
525
550
  available[modelName].docs.push(doc);
526
551
  available[modelName].ids.push(ids);
527
552
  available[modelName].allIds.push(ret);
553
+ available[modelName].unpopulatedValues.push(unpopulatedValue);
528
554
  if (data.hasMatchFunction) {
529
555
  available[modelName].match.push(data.match);
530
556
  }
@@ -556,6 +582,8 @@ function _getLocalFieldValues(doc, localField, model, options, virtual, schema)
556
582
  const localFieldGetters = localFieldPath && localFieldPath.getters ?
557
583
  localFieldPath.getters : [];
558
584
 
585
+ localField = localFieldPath != null && localFieldPath.instance === 'Embedded' ? localField + '._id' : localField;
586
+
559
587
  const _populateOptions = get(options, 'options', {});
560
588
 
561
589
  const getters = 'getters' in _populateOptions ?
@@ -0,0 +1,13 @@
1
+ 'use strict';
2
+
3
+ /*!
4
+ * Determines if `path2` is a subpath of or equal to `path1`
5
+ *
6
+ * @param {string} path1
7
+ * @param {string} path2
8
+ * @return {Boolean}
9
+ */
10
+
11
+ module.exports = function isSubpath(path1, path2) {
12
+ return path1 === path2 || path2.startsWith(path1 + '.');
13
+ };
@@ -46,7 +46,7 @@ module.exports = function setupTimestamps(schema, timestamps) {
46
46
 
47
47
  const defaultTimestamp = currentTime != null ?
48
48
  currentTime() :
49
- (this.ownerDocument ? this.ownerDocument() : this).constructor.base.now();
49
+ this.ownerDocument().constructor.base.now();
50
50
  const auto_id = this._id && this._id.auto;
51
51
 
52
52
  if (!skipCreatedAt && createdAt && !this.$__getValue(createdAt) && this.$__isSelected(createdAt)) {
@@ -10,7 +10,17 @@ module.exports = function castArrayFilters(query) {
10
10
  const update = query.getUpdate();
11
11
  const schema = query.schema;
12
12
  const updatedPathsByFilter = updatedPathsByArrayFilter(update);
13
- const strictQuery = schema.options.strictQuery;
13
+
14
+ let strictQuery = schema.options.strict;
15
+ if (query._mongooseOptions.strict != null) {
16
+ strictQuery = query._mongooseOptions.strict;
17
+ }
18
+ if (schema._userProvidedOptions.strictQuery != null) {
19
+ strictQuery = schema._userProvidedOptions.strictQuery;
20
+ }
21
+ if (query._mongooseOptions.strictQuery != null) {
22
+ strictQuery = query._mongooseOptions.strictQuery;
23
+ }
14
24
 
15
25
  _castArrayFilters(arrayFilters, schema, strictQuery, updatedPathsByFilter, query);
16
26
  };
package/lib/index.js CHANGED
@@ -156,7 +156,7 @@ Mongoose.prototype.driver = driver;
156
156
  * - 'toObject': `{ transform: true, flattenDecimals: true }` by default. Overwrites default objects to [`toObject()`](/docs/api.html#document_Document-toObject)
157
157
  * - 'toJSON': `{ transform: true, flattenDecimals: true }` by default. Overwrites default objects to [`toJSON()`](/docs/api.html#document_Document-toJSON), for determining how Mongoose documents get serialized by `JSON.stringify()`
158
158
  * - 'strict': true by default, may be `false`, `true`, or `'throw'`. Sets the default strict mode for schemas.
159
- * - 'strictQuery': false by default, may be `false`, `true`, or `'throw'`. Sets the default [strictQuery](/docs/guide.html#strictQuery) mode for schemas.
159
+ * - 'strictQuery': same value as 'strict' by default (`true`), may be `false`, `true`, or `'throw'`. Sets the default [strictQuery](/docs/guide.html#strictQuery) mode for schemas.
160
160
  * - 'selectPopulatedPaths': true by default. Set to false to opt out of Mongoose adding all fields that you `populate()` to your `select()`. The schema-level option `selectPopulatedPaths` overwrites this one.
161
161
  * - 'maxTimeMS': If set, attaches [maxTimeMS](https://docs.mongodb.com/manual/reference/operator/meta/maxTimeMS/) to every query
162
162
  * - 'autoIndex': true by default. Set to false to disable automatic index creation for all models associated with this Mongoose instance.
@@ -984,6 +984,11 @@ Mongoose.prototype.isValidObjectId = function(v) {
984
984
  return false;
985
985
  };
986
986
 
987
+ Mongoose.prototype.syncIndexes = function() {
988
+ const _mongoose = this instanceof Mongoose ? this : mongoose;
989
+ return _mongoose.connection.syncIndexes();
990
+ };
991
+
987
992
  /**
988
993
  * The Mongoose Decimal128 [SchemaType](/docs/schematypes.html). Used for
989
994
  * declaring paths in your schema that should be
package/lib/internal.js CHANGED
@@ -14,6 +14,7 @@ function InternalCache() {
14
14
 
15
15
  // embedded docs
16
16
  this.ownerDocument = undefined;
17
+ this.isSubDocument = undefined;
17
18
  this.fullPath = undefined;
18
19
  }
19
20
 
package/lib/model.js CHANGED
@@ -343,15 +343,17 @@ Model.prototype.$__handleSave = function(options, callback) {
343
343
  where[key] = val;
344
344
  }
345
345
  }
346
- this.constructor.exists(where, optionsWithCustomValues)
347
- .then((documentExists) => {
346
+ this.constructor.exists(where, optionsWithCustomValues).
347
+ then((documentExists) => {
348
348
  if (!documentExists) {
349
- throw new DocumentNotFoundError(this.$__where(), this.constructor.modelName);
349
+ const matchedCount = 0;
350
+ return callback(null, { $where: where, matchedCount });
350
351
  }
351
352
 
352
- callback();
353
- })
354
- .catch(callback);
353
+ const matchedCount = 1;
354
+ callback(null, { $where: where, matchedCount });
355
+ }).
356
+ catch(callback);
355
357
  return;
356
358
  }
357
359
 
@@ -379,7 +381,7 @@ Model.prototype.$__save = function(options, callback) {
379
381
  if (get(options, 'safe.w') !== 0 && get(options, 'w') !== 0) {
380
382
  // Skip checking if write succeeded if writeConcern is set to
381
383
  // unacknowledged writes, because otherwise `numAffected` will always be 0
382
- if (result) {
384
+ if (result != null) {
383
385
  if (Array.isArray(result)) {
384
386
  numAffected = result.length;
385
387
  } else if (result.matchedCount != null) {
@@ -916,7 +918,7 @@ Model.prototype.$__where = function _where(where) {
916
918
  * })
917
919
  *
918
920
  *
919
- * As an extra measure of flow control, remove will return a Promise (bound to `fn` if passed) so it could be chained, or hooked to recieve errors
921
+ * As an extra measure of flow control, remove will return a Promise (bound to `fn` if passed) so it could be chained, or hooked to receive errors
920
922
  *
921
923
  * ####Example:
922
924
  * product.remove().then(function (product) {
@@ -1336,14 +1338,18 @@ Model.createCollection = function createCollection(options, callback) {
1336
1338
  options = void 0;
1337
1339
  }
1338
1340
 
1339
- const schemaCollation = get(this, 'schema.options.collation', null);
1341
+ const schemaCollation = get(this, ['schema', 'options', 'collation'], null);
1340
1342
  if (schemaCollation != null) {
1341
1343
  options = Object.assign({ collation: schemaCollation }, options);
1342
1344
  }
1343
- const capped = get(this, 'schema.options.capped');
1345
+ const capped = get(this, ['schema', 'options', 'capped']);
1344
1346
  if (capped) {
1345
1347
  options = Object.assign({ capped: true }, capped, options);
1346
1348
  }
1349
+ const timeseries = get(this, ['schema', 'options', 'timeseries']);
1350
+ if (timeseries != null) {
1351
+ options = Object.assign({ timeseries }, options);
1352
+ }
1347
1353
 
1348
1354
  callback = this.$handleCallbackError(callback);
1349
1355
 
@@ -4410,7 +4416,6 @@ function _populate(model, docs, paths, cache, callback) {
4410
4416
  if (paths.length === 0) {
4411
4417
  return callback(null, docs);
4412
4418
  }
4413
-
4414
4419
  // each path has its own query options and must be executed separately
4415
4420
  for (const path of paths) {
4416
4421
  populate(model, docs, path, next);
@@ -4434,6 +4439,11 @@ const excludeIdReg = /\s?-_id\s?/;
4434
4439
  const excludeIdRegGlobal = /\s?-_id\s?/g;
4435
4440
 
4436
4441
  function populate(model, docs, options, callback) {
4442
+
4443
+ const populateOptions = { ...options };
4444
+ if (model.base.options.strictPopulate != null && options.strictPopulate == null) {
4445
+ populateOptions.strictPopulate = model.base.options.strictPopulate;
4446
+ }
4437
4447
  // normalize single / multiple docs passed
4438
4448
  if (!Array.isArray(docs)) {
4439
4449
  docs = [docs];
@@ -4442,7 +4452,7 @@ function populate(model, docs, options, callback) {
4442
4452
  return callback();
4443
4453
  }
4444
4454
 
4445
- const modelsMap = getModelsMapForPopulate(model, docs, options);
4455
+ const modelsMap = getModelsMapForPopulate(model, docs, populateOptions);
4446
4456
  if (modelsMap instanceof MongooseError) {
4447
4457
  return immediate(function() {
4448
4458
  callback(modelsMap);
@@ -4707,6 +4717,7 @@ function _assign(model, vals, mod, assignmentOpts) {
4707
4717
  // If virtual, make sure to not mutate original field
4708
4718
  rawIds: mod.isVirtual ? allIds : mod.allIds,
4709
4719
  allIds: allIds,
4720
+ unpopulatedValues: mod.unpopulatedValues,
4710
4721
  foreignField: mod.foreignField,
4711
4722
  rawDocs: rawDocs,
4712
4723
  rawOrder: rawOrder,
@@ -82,7 +82,7 @@ Object.defineProperty(SchemaTypeOptions.prototype, 'cast', opts);
82
82
 
83
83
  /**
84
84
  * If true, attach a required validator to this path, which ensures this path
85
- * path cannot be set to a nullish value. If a function, Mongoose calls the
85
+ * cannot be set to a nullish value. If a function, Mongoose calls the
86
86
  * function and only checks for nullish values if the function returns a truthy value.
87
87
  *
88
88
  * @api public
@@ -9,7 +9,7 @@ module.exports = function(schema) {
9
9
  // in parallel. We need to clear `this.$__.validating` before post hooks for gh-8597
10
10
  const unshift = true;
11
11
  schema.s.hooks.post('validate', false, function() {
12
- if (this.ownerDocument) {
12
+ if (this.$__.isSubDocument) {
13
13
  return;
14
14
  }
15
15
 
@@ -17,7 +17,7 @@ module.exports = function(schema) {
17
17
  }, unshift);
18
18
 
19
19
  schema.s.hooks.post('validate', false, function(error, res, next) {
20
- if (this.ownerDocument) {
20
+ if (this.$__.isSubDocument) {
21
21
  next();
22
22
  return;
23
23
  }
@@ -9,7 +9,7 @@ const each = require('../helpers/each');
9
9
  module.exports = function(schema) {
10
10
  const unshift = true;
11
11
  schema.s.hooks.pre('remove', false, function(next) {
12
- if (this.ownerDocument) {
12
+ if (this.$__.isSubDocument) {
13
13
  next();
14
14
  return;
15
15
  }
@@ -9,7 +9,7 @@ const each = require('../helpers/each');
9
9
  module.exports = function(schema) {
10
10
  const unshift = true;
11
11
  schema.s.hooks.pre('save', false, function(next) {
12
- if (this.ownerDocument) {
12
+ if (this.$__.isSubDocument) {
13
13
  next();
14
14
  return;
15
15
  }
@@ -37,7 +37,7 @@ module.exports = function(schema) {
37
37
  }, null, unshift);
38
38
 
39
39
  schema.s.hooks.post('save', function(doc, next) {
40
- if (this.ownerDocument) {
40
+ if (this.$__.isSubDocument) {
41
41
  next();
42
42
  return;
43
43
  }
@@ -9,7 +9,7 @@ module.exports = function(schema) {
9
9
  schema.pre('save', false, function validateBeforeSave(next, options) {
10
10
  const _this = this;
11
11
  // Nested docs have their own presave
12
- if (this.ownerDocument) {
12
+ if (this.$__.isSubDocument) {
13
13
  return next();
14
14
  }
15
15
 
package/lib/query.js CHANGED
@@ -25,6 +25,7 @@ const helpers = require('./queryhelpers');
25
25
  const immediate = require('./helpers/immediate');
26
26
  const isExclusive = require('./helpers/projection/isExclusive');
27
27
  const isInclusive = require('./helpers/projection/isInclusive');
28
+ const isSubpath = require('./helpers/projection/isSubpath');
28
29
  const mquery = require('mquery');
29
30
  const parseProjection = require('./helpers/projection/parseProjection');
30
31
  const removeUnusedArrayFilters = require('./helpers/update/removeUnusedArrayFilters');
@@ -995,6 +996,10 @@ Query.prototype.projection = function(arg) {
995
996
  * query.select({ a: 1, b: 1 });
996
997
  * query.select({ c: 0, d: 0 });
997
998
  *
999
+ * Additional calls to select can override the previous selection:
1000
+ * query.select({ a: 1, b: 1 }).select({ b: 0 }); // selection is now { a: 1 }
1001
+ * query.select({ a: 0, b: 0 }).select({ b: 1 }); // selection is now { a: 0 }
1002
+ *
998
1003
  *
999
1004
  * @method select
1000
1005
  * @memberOf Query
@@ -1026,17 +1031,50 @@ Query.prototype.select = function select() {
1026
1031
  sanitizeProjection = this._mongooseOptions.sanitizeProjection;
1027
1032
  }
1028
1033
 
1034
+ function sanitizeValue(value) {
1035
+ return typeof value === 'string' && sanitizeProjection ? value = 1 : value;
1036
+ }
1037
+
1029
1038
  arg = parseProjection(arg);
1030
1039
 
1031
1040
  if (utils.isObject(arg)) {
1032
- const keys = Object.keys(arg);
1033
- for (let i = 0; i < keys.length; ++i) {
1034
- let value = arg[keys[i]];
1035
- if (typeof value === 'string' && sanitizeProjection) {
1036
- value = 1;
1041
+ if (this.selectedInclusively()) {
1042
+ Object.entries(arg).forEach(([key, value]) => {
1043
+ if (value) {
1044
+ // Add the field to the projection
1045
+ fields[key] = userProvidedFields[key] = sanitizeValue(value);
1046
+ } else {
1047
+ // Remove the field from the projection
1048
+ Object.keys(userProvidedFields).forEach(field => {
1049
+ if (isSubpath(key, field)) {
1050
+ delete fields[field];
1051
+ delete userProvidedFields[field];
1052
+ }
1053
+ });
1054
+ }
1055
+ });
1056
+ } else if (this.selectedExclusively()) {
1057
+ Object.entries(arg).forEach(([key, value]) => {
1058
+ if (!value) {
1059
+ // Add the field to the projection
1060
+ fields[key] = userProvidedFields[key] = sanitizeValue(value);
1061
+ } else {
1062
+ // Remove the field from the projection
1063
+ Object.keys(userProvidedFields).forEach(field => {
1064
+ if (isSubpath(key, field)) {
1065
+ delete fields[field];
1066
+ delete userProvidedFields[field];
1067
+ }
1068
+ });
1069
+ }
1070
+ });
1071
+ } else {
1072
+ const keys = Object.keys(arg);
1073
+ for (let i = 0; i < keys.length; ++i) {
1074
+ const value = arg[keys[i]];
1075
+ fields[keys[i]] = sanitizeValue(value);
1076
+ userProvidedFields[keys[i]] = sanitizeValue(value);
1037
1077
  }
1038
- fields[keys[i]] = value;
1039
- userProvidedFields[keys[i]] = value;
1040
1078
  }
1041
1079
  return this;
1042
1080
  }
@@ -4470,6 +4508,7 @@ Query.prototype.orFail = function(err) {
4470
4508
  throw _orFailError(err, this);
4471
4509
  }
4472
4510
  break;
4511
+ case 'replaceOne':
4473
4512
  case 'update':
4474
4513
  case 'updateMany':
4475
4514
  case 'updateOne':
package/lib/schema.js CHANGED
@@ -69,6 +69,7 @@ let id = 0;
69
69
  * - [versionKey](/docs/guide.html#versionKey): string or object - defaults to "__v"
70
70
  * - [optimisticConcurrency](/docs/guide.html#optimisticConcurrency): bool - defaults to false. Set to true to enable [optimistic concurrency](https://thecodebarbarian.com/whats-new-in-mongoose-5-10-optimistic-concurrency.html).
71
71
  * - [collation](/docs/guide.html#collation): object - defaults to null (which means use no collation)
72
+ * - [timeseries](/docs/guide.html#timeseries): object - defaults to null (which means this schema's collection won't be a timeseries collection)
72
73
  * - [selectPopulatedPaths](/docs/guide.html#selectPopulatedPaths): boolean - defaults to `true`
73
74
  * - [skipVersioning](/docs/guide.html#skipVersioning): object - paths to exclude from versioning
74
75
  * - [timestamps](/docs/guide.html#timestamps): object or boolean - defaults to `false`. If true, Mongoose adds `createdAt` and `updatedAt` properties to your schema and manages those properties for you.
@@ -116,7 +117,6 @@ function Schema(obj, options) {
116
117
  this.s = {
117
118
  hooks: new Kareem()
118
119
  };
119
-
120
120
  this.options = this.defaultOptions(options);
121
121
 
122
122
  // build paths
@@ -416,11 +416,9 @@ Schema.prototype.pick = function(paths, options) {
416
416
 
417
417
  Schema.prototype.defaultOptions = function(options) {
418
418
  this._userProvidedOptions = options == null ? {} : utils.clone(options);
419
-
420
419
  const baseOptions = get(this, 'base.options', {});
421
420
 
422
421
  const strict = 'strict' in baseOptions ? baseOptions.strict : true;
423
-
424
422
  options = utils.options({
425
423
  strict: strict,
426
424
  strictQuery: 'strict' in this._userProvidedOptions ?
package/lib/schematype.js CHANGED
@@ -1398,7 +1398,7 @@ SchemaType._isRef = function(self, value, doc, init) {
1398
1398
  // - setting / pushing values after population
1399
1399
  const path = doc.$__fullPath(self.path, true);
1400
1400
 
1401
- const owner = doc.ownerDocument ? doc.ownerDocument() : doc;
1401
+ const owner = doc.ownerDocument();
1402
1402
  ref = (path != null && owner.$populated(path)) || doc.$populated(self.path);
1403
1403
  }
1404
1404
 
@@ -1445,7 +1445,7 @@ SchemaType.prototype._castRef = function _castRef(value, doc, init) {
1445
1445
  // path to a plain object; cast to the Model used in
1446
1446
  // the population query.
1447
1447
  const path = doc.$__fullPath(this.path, true);
1448
- const owner = doc.ownerDocument ? doc.ownerDocument() : doc;
1448
+ const owner = doc.ownerDocument();
1449
1449
  const pop = owner.$populated(path, true);
1450
1450
  let ret = value;
1451
1451
  if (!doc.$__.populated ||
@@ -26,6 +26,7 @@ function Subdocument(value, fields, parent, skipId, options) {
26
26
  this.$basePath = options.path;
27
27
  }
28
28
  Document.call(this, value, fields, skipId, options);
29
+ this.$__.isSubDocument = true;
29
30
 
30
31
  delete this.$__.priorDoc;
31
32
  }
@@ -234,7 +235,6 @@ Subdocument.prototype.ownerDocument = function() {
234
235
  }
235
236
 
236
237
  let parent = this; // eslint-disable-line consistent-this
237
-
238
238
  const paths = [];
239
239
  const seenDocs = new Set([parent]);
240
240
 
package/lib/utils.js CHANGED
@@ -178,6 +178,18 @@ exports.clone = clone;
178
178
 
179
179
  exports.promiseOrCallback = promiseOrCallback;
180
180
 
181
+ /*!
182
+ * ignore
183
+ */
184
+
185
+ exports.cloneArrays = function cloneArrays(arr) {
186
+ if (!Array.isArray(arr)) {
187
+ return arr;
188
+ }
189
+
190
+ return arr.map(el => exports.cloneArrays(el));
191
+ };
192
+
181
193
  /*!
182
194
  * ignore
183
195
  */
@@ -24,6 +24,7 @@ const VALID_OPTIONS = Object.freeze([
24
24
  'selectPopulatedPaths',
25
25
  'setDefaultsOnInsert',
26
26
  'strict',
27
+ 'strictPopulate',
27
28
  'strictQuery',
28
29
  'toJSON',
29
30
  'toObject'
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mongoose",
3
3
  "description": "Mongoose MongoDB ODM",
4
- "version": "6.0.13",
4
+ "version": "6.1.1",
5
5
  "author": "Guillermo Rauch <guillermo@learnboost.com>",
6
6
  "keywords": [
7
7
  "mongodb",
@@ -21,7 +21,7 @@
21
21
  "dependencies": {
22
22
  "bson": "^4.2.2",
23
23
  "kareem": "2.3.2",
24
- "mongodb": "4.1.4",
24
+ "mongodb": "4.2.1",
25
25
  "mpath": "0.8.4",
26
26
  "mquery": "4.0.0",
27
27
  "ms": "2.1.2",
@@ -61,7 +61,6 @@
61
61
  "typescript": "4.4.4",
62
62
  "uuid": "2.0.3",
63
63
  "uuid-parse": "1.0.0",
64
- "validator": "10.8.0",
65
64
  "webpack": "4.44.0"
66
65
  },
67
66
  "directories": {