mongoose 6.2.0 → 6.2.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.
Files changed (41) hide show
  1. package/.eslintrc.json +150 -0
  2. package/CHANGELOG.md +21 -0
  3. package/dist/browser.umd.js +113 -112
  4. package/lib/aggregate.js +1 -1
  5. package/lib/document.js +83 -64
  6. package/lib/helpers/clone.js +40 -27
  7. package/lib/helpers/common.js +2 -2
  8. package/lib/helpers/getFunctionName.js +6 -4
  9. package/lib/helpers/isMongooseObject.js +9 -8
  10. package/lib/helpers/isObject.js +4 -4
  11. package/lib/helpers/path/parentPaths.js +10 -5
  12. package/lib/helpers/populate/assignRawDocsToIdStructure.js +4 -2
  13. package/lib/helpers/populate/assignVals.js +8 -4
  14. package/lib/helpers/populate/getModelsMapForPopulate.js +4 -4
  15. package/lib/helpers/populate/markArraySubdocsPopulated.js +3 -1
  16. package/lib/helpers/populate/modelNamesFromRefPath.js +4 -3
  17. package/lib/helpers/query/castUpdate.js +6 -2
  18. package/lib/helpers/schema/getPath.js +4 -2
  19. package/lib/helpers/timestamps/setupTimestamps.js +3 -8
  20. package/lib/index.js +2 -0
  21. package/lib/internal.js +1 -1
  22. package/lib/model.js +22 -8
  23. package/lib/plugins/trackTransaction.js +4 -3
  24. package/lib/query.js +3 -2
  25. package/lib/queryhelpers.js +1 -1
  26. package/lib/schema/array.js +17 -15
  27. package/lib/schema/documentarray.js +5 -8
  28. package/lib/schema/objectid.js +1 -1
  29. package/lib/schematype.js +29 -26
  30. package/lib/types/ArraySubdocument.js +2 -1
  31. package/lib/types/DocumentArray/index.js +9 -26
  32. package/lib/types/DocumentArray/isMongooseDocumentArray.js +5 -0
  33. package/lib/types/DocumentArray/methods/index.js +15 -3
  34. package/lib/types/array/index.js +21 -20
  35. package/lib/types/array/isMongooseArray.js +5 -0
  36. package/lib/types/array/methods/index.js +12 -12
  37. package/lib/utils.js +7 -0
  38. package/package.json +18 -147
  39. package/tools/repl.js +1 -1
  40. package/tsconfig.json +10 -0
  41. package/{index.d.ts → types/index.d.ts} +84 -75
package/lib/aggregate.js CHANGED
@@ -39,7 +39,7 @@ const readConcern = Query.prototype.readConcern;
39
39
  * ```javascript
40
40
  * new Aggregate([{ $match: { _id: '00000000000000000000000a' } }]);
41
41
  * // Do this instead to cast to an ObjectId
42
- * new Aggregate([{ $match: { _id: mongoose.Types.ObjectId('00000000000000000000000a') } }]);
42
+ * new Aggregate([{ $match: { _id: new mongoose.Types.ObjectId('00000000000000000000000a') } }]);
43
43
  * ```
44
44
  *
45
45
  * @see MongoDB http://docs.mongodb.org/manual/applications/aggregation/
package/lib/document.js CHANGED
@@ -90,7 +90,7 @@ function Document(obj, fields, skipId, options) {
90
90
  options = arguments[4] || {};
91
91
  }
92
92
 
93
- this.$__ = new InternalCache;
93
+ this.$__ = new InternalCache();
94
94
  this.$isNew = 'isNew' in options ? options.isNew : true;
95
95
 
96
96
  if ('priorDoc' in options) {
@@ -479,7 +479,7 @@ function $__applyDefaults(doc, fields, exclude, hasIncludedChildren, isBeforeSet
479
479
  break;
480
480
  }
481
481
  } else if (exclude === false && fields && !included) {
482
- if (curPath in fields) {
482
+ if (curPath in fields || type.$isSingleNested && hasIncludedChildren[curPath]) {
483
483
  included = true;
484
484
  } else if (!hasIncludedChildren[curPath]) {
485
485
  break;
@@ -795,11 +795,12 @@ function init(self, obj, doc, opts, prefix) {
795
795
 
796
796
  const keys = Object.keys(obj);
797
797
  const len = keys.length;
798
- let schema;
798
+ let schemaType;
799
799
  let path;
800
800
  let i;
801
801
  let index = 0;
802
802
  const strict = self.$__.strictMode;
803
+ const docSchema = self.$__schema;
803
804
 
804
805
  while (index < len) {
805
806
  _init(index++);
@@ -808,25 +809,27 @@ function init(self, obj, doc, opts, prefix) {
808
809
  function _init(index) {
809
810
  i = keys[index];
810
811
  path = prefix + i;
811
- schema = self.$__schema.path(path);
812
+ schemaType = docSchema.path(path);
812
813
 
813
814
  // Should still work if not a model-level discriminator, but should not be
814
815
  // necessary. This is *only* to catch the case where we queried using the
815
816
  // base model and the discriminated model has a projection
816
- if (self.$__schema.$isRootDiscriminator && !self.$__isSelected(path)) {
817
+ if (docSchema.$isRootDiscriminator && !self.$__isSelected(path)) {
817
818
  return;
818
819
  }
819
820
 
820
- if (!schema && utils.isPOJO(obj[i])) {
821
+ if (!schemaType && utils.isPOJO(obj[i])) {
821
822
  // assume nested object
822
823
  if (!doc[i]) {
823
824
  doc[i] = {};
825
+ if (!strict && !(i in docSchema.tree) && !(i in docSchema.methods) && !(i in docSchema.virtuals)) {
826
+ self[i] = doc[i];
827
+ }
824
828
  }
825
829
  init(self, obj[i], doc[i], opts, path + '.');
826
- } else if (!schema) {
830
+ } else if (!schemaType) {
827
831
  doc[i] = obj[i];
828
- if (!strict && !prefix) {
829
- // Set top-level properties that aren't in the schema if strict is false
832
+ if (!strict) {
830
833
  self[i] = obj[i];
831
834
  }
832
835
  } else {
@@ -835,13 +838,13 @@ function init(self, obj, doc, opts, prefix) {
835
838
  delete doc[i];
836
839
  }
837
840
  if (obj[i] === null) {
838
- doc[i] = schema._castNullish(null);
841
+ doc[i] = schemaType._castNullish(null);
839
842
  } else if (obj[i] !== undefined) {
840
843
  const wasPopulated = obj[i].$__ == null ? null : obj[i].$__.wasPopulated;
841
844
 
842
- if (schema && !wasPopulated) {
845
+ if (schemaType && !wasPopulated) {
843
846
  try {
844
- doc[i] = schema.cast(obj[i], self, true);
847
+ doc[i] = schemaType.cast(obj[i], self, true);
845
848
  } catch (e) {
846
849
  self.invalidate(e.path, new ValidatorError({
847
850
  path: e.path,
@@ -1135,7 +1138,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
1135
1138
  // them to ensure we keep the user's key order.
1136
1139
  if (type === true &&
1137
1140
  !prefix &&
1138
- path[key] != null &&
1141
+ valForKey != null &&
1139
1142
  pathtype === 'nested' &&
1140
1143
  this._doc[key] != null) {
1141
1144
  delete this._doc[key];
@@ -1313,7 +1316,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
1313
1316
  let curPath = '';
1314
1317
  for (i = 0; i < parts.length - 1; ++i) {
1315
1318
  cur = cur[parts[i]];
1316
- curPath += (curPath.length > 0 ? '.' : '') + parts[i];
1319
+ curPath += (curPath.length !== 0 ? '.' : '') + parts[i];
1317
1320
  if (!cur) {
1318
1321
  this.$set(curPath, {});
1319
1322
  // Hack re: gh-5800. If nested field is not selected, it probably exists
@@ -1336,7 +1339,8 @@ Document.prototype.$set = function $set(path, val, type, options) {
1336
1339
  if (parts.length <= 1) {
1337
1340
  pathToMark = path;
1338
1341
  } else {
1339
- for (i = 0; i < parts.length; ++i) {
1342
+ const len = parts.length;
1343
+ for (i = 0; i < len; ++i) {
1340
1344
  const subpath = parts.slice(0, i + 1).join('.');
1341
1345
  if (this.$get(subpath, null, { getters: false }) === null) {
1342
1346
  pathToMark = subpath;
@@ -1361,7 +1365,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
1361
1365
  _markValidSubpaths(this, path);
1362
1366
  }
1363
1367
 
1364
- if (schema.$isSingleNested && val != null && merge) {
1368
+ if (val != null && merge && schema.$isSingleNested) {
1365
1369
  if (val instanceof Document) {
1366
1370
  val = val.toObject({ virtuals: false, transform: false });
1367
1371
  }
@@ -1431,9 +1435,10 @@ Document.prototype.$set = function $set(path, val, type, options) {
1431
1435
  val = schema.applySetters(val, this, false, priorVal);
1432
1436
  }
1433
1437
 
1434
- if (schema.$isMongooseDocumentArray &&
1435
- Array.isArray(val) &&
1436
- val.length > 0 &&
1438
+ if (Array.isArray(val) &&
1439
+ !Array.isArray(schema) &&
1440
+ schema.$isMongooseDocumentArray &&
1441
+ val.length !== 0 &&
1437
1442
  val[0] != null &&
1438
1443
  val[0].$__ != null &&
1439
1444
  val[0].$__.populated != null) {
@@ -1459,7 +1464,7 @@ Document.prototype.$set = function $set(path, val, type, options) {
1459
1464
  delete this.$__.populated[path];
1460
1465
  }
1461
1466
 
1462
- if (schema.$isSingleNested && val != null) {
1467
+ if (val != null && schema.$isSingleNested) {
1463
1468
  _checkImmutableSubpaths(val, schema, priorVal);
1464
1469
  }
1465
1470
 
@@ -1652,11 +1657,11 @@ Document.prototype.$__set = function(pathToMark, path, options, constructing, pa
1652
1657
 
1653
1658
  // handle directly setting arrays (gh-1126)
1654
1659
  MongooseArray || (MongooseArray = require('./types/array'));
1655
- if (val && val.isMongooseArray) {
1660
+ if (val && utils.isMongooseArray(val)) {
1656
1661
  val._registerAtomic('$set', val);
1657
1662
 
1658
1663
  // Update embedded document parent references (gh-5189)
1659
- if (val.isMongooseDocumentArray) {
1664
+ if (utils.isMongooseDocumentArray(val)) {
1660
1665
  val.forEach(function(item) {
1661
1666
  item && item.__parentArray && (item.__parentArray = val);
1662
1667
  });
@@ -1670,10 +1675,10 @@ Document.prototype.$__set = function(pathToMark, path, options, constructing, pa
1670
1675
  }
1671
1676
  });
1672
1677
  }
1673
- } else if (Array.isArray(val) && val.isMongooseArray && Array.isArray(priorVal) && priorVal.isMongooseArray) {
1678
+ } else if (Array.isArray(val) && Array.isArray(priorVal) && utils.isMongooseArray(val) && utils.isMongooseArray(priorVal)) {
1674
1679
  val[arrayAtomicsSymbol] = priorVal[arrayAtomicsSymbol];
1675
1680
  val[arrayAtomicsBackupSymbol] = priorVal[arrayAtomicsBackupSymbol];
1676
- if (val.isMongooseDocumentArray) {
1681
+ if (utils.isMongooseDocumentArray(val)) {
1677
1682
  val.forEach(doc => { doc.isNew = false; });
1678
1683
  }
1679
1684
  }
@@ -1702,7 +1707,7 @@ Document.prototype.$__set = function(pathToMark, path, options, constructing, pa
1702
1707
  obj = obj[parts[i]];
1703
1708
  } else if (obj[parts[i]] && obj[parts[i]] instanceof Embedded) {
1704
1709
  obj = obj[parts[i]];
1705
- } else if (obj[parts[i]] && obj[parts[i]].$isSingleNested) {
1710
+ } else if (obj[parts[i]] && !Array.isArray(obj[parts[i]]) && obj[parts[i]].$isSingleNested) {
1706
1711
  obj = obj[parts[i]];
1707
1712
  } else if (obj[parts[i]] && Array.isArray(obj[parts[i]])) {
1708
1713
  obj = obj[parts[i]];
@@ -1963,7 +1968,7 @@ Document.prototype.$isEmpty = function(path) {
1963
1968
  transform: false
1964
1969
  };
1965
1970
 
1966
- if (arguments.length > 0) {
1971
+ if (arguments.length !== 0) {
1967
1972
  const v = this.$get(path);
1968
1973
  if (v == null) {
1969
1974
  return true;
@@ -2006,51 +2011,60 @@ function _isEmpty(v) {
2006
2011
 
2007
2012
  Document.prototype.modifiedPaths = function(options) {
2008
2013
  options = options || {};
2014
+
2009
2015
  const directModifiedPaths = Object.keys(this.$__.activePaths.states.modify);
2010
- const _this = this;
2011
- return directModifiedPaths.reduce(function(list, path) {
2012
- const parts = path.split('.');
2013
- list = list.concat(parts.reduce(function(chains, part, i) {
2014
- return chains.concat(parts.slice(0, i).concat(part).join('.'));
2015
- }, []).filter(function(chain) {
2016
- return (list.indexOf(chain) === -1);
2017
- }));
2016
+ const result = new Set();
2017
+
2018
+ let i = 0;
2019
+ let j = 0;
2020
+ const len = directModifiedPaths.length;
2021
+
2022
+ for (i = 0; i < len; ++i) {
2023
+ const path = directModifiedPaths[i];
2024
+ const parts = parentPaths(path);
2025
+ const pLen = parts.length;
2026
+
2027
+ for (j = 0; j < pLen; ++j) {
2028
+ result.add(parts[j]);
2029
+ }
2018
2030
 
2019
2031
  if (!options.includeChildren) {
2020
- return list;
2032
+ continue;
2021
2033
  }
2022
2034
 
2023
- let cur = _this.$get(path);
2024
- if (cur != null && typeof cur === 'object') {
2035
+ let ii = 0;
2036
+ let cur = this.$get(path);
2037
+ if (typeof cur === 'object' && cur !== null) {
2025
2038
  if (cur._doc) {
2026
2039
  cur = cur._doc;
2027
2040
  }
2041
+ const len = cur.length;
2028
2042
  if (Array.isArray(cur)) {
2029
- const len = cur.length;
2030
- for (let i = 0; i < len; ++i) {
2031
- if (list.indexOf(path + '.' + i) === -1) {
2032
- list.push(path + '.' + i);
2033
- if (cur[i] != null && cur[i].$__) {
2034
- const modified = cur[i].modifiedPaths();
2035
- for (const childPath of modified) {
2036
- list.push(path + '.' + i + '.' + childPath);
2043
+ for (ii = 0; ii < len; ++ii) {
2044
+ const subPath = path + '.' + ii;
2045
+ if (!result.has(subPath)) {
2046
+ result.add(subPath);
2047
+ if (cur[ii] != null && cur[ii].$__) {
2048
+ const modified = cur[ii].modifiedPaths();
2049
+ let iii = 0;
2050
+ const iiiLen = modified.length;
2051
+ for (iii = 0; iii < iiiLen; ++iii) {
2052
+ result.add(subPath + '.' + modified[iii]);
2037
2053
  }
2038
2054
  }
2039
2055
  }
2040
2056
  }
2041
2057
  } else {
2042
- Object.keys(cur).
2043
- filter(function(key) {
2044
- return list.indexOf(path + '.' + key) === -1;
2045
- }).
2046
- forEach(function(key) {
2047
- list.push(path + '.' + key);
2048
- });
2058
+ const keys = Object.keys(cur);
2059
+ let ii = 0;
2060
+ const len = keys.length;
2061
+ for (ii = 0; ii < len; ++ii) {
2062
+ result.add(path + '.' + keys[ii]);
2063
+ }
2049
2064
  }
2050
2065
  }
2051
-
2052
- return list;
2053
- }, []);
2066
+ }
2067
+ return Array.from(result);
2054
2068
  };
2055
2069
 
2056
2070
  Document.prototype[documentModifiedPaths] = Document.prototype.modifiedPaths;
@@ -2448,7 +2462,12 @@ Document.prototype.$validate = Document.prototype.validate;
2448
2462
  */
2449
2463
 
2450
2464
  function _evaluateRequiredFunctions(doc) {
2451
- Object.keys(doc.$__.activePaths.states.require).forEach(path => {
2465
+ const requiredFields = Object.keys(doc.$__.activePaths.states.require);
2466
+ let i = 0;
2467
+ const len = requiredFields.length;
2468
+ for (i = 0; i < len; ++i) {
2469
+ const path = requiredFields[i];
2470
+
2452
2471
  const p = doc.$__schema.path(path);
2453
2472
 
2454
2473
  if (p != null && typeof p.originalRequiredValue === 'function') {
@@ -2459,7 +2478,7 @@ function _evaluateRequiredFunctions(doc) {
2459
2478
  doc.invalidate(path, err);
2460
2479
  }
2461
2480
  }
2462
- });
2481
+ }
2463
2482
  }
2464
2483
 
2465
2484
  /*!
@@ -2520,7 +2539,7 @@ function _getPathsToValidate(doc) {
2520
2539
  // To avoid potential performance issues, skip doc arrays whose children
2521
2540
  // are not required. `getPositionalPathType()` may be slow, so avoid
2522
2541
  // it unless we have a case of #6364
2523
- (_pathType.$isMongooseDocumentArray && !get(_pathType, 'schemaOptions.required'))) {
2542
+ (!Array.isArray(_pathType) && _pathType.$isMongooseDocumentArray && !get(_pathType, 'schemaOptions.required'))) {
2524
2543
  continue;
2525
2544
  }
2526
2545
 
@@ -3112,7 +3131,7 @@ Document.prototype.$__reset = function reset() {
3112
3131
  return _this.$__getValue(i);
3113
3132
  })
3114
3133
  .filter(function(val) {
3115
- return val && val instanceof Array && val.isMongooseDocumentArray && val.length;
3134
+ return val && val instanceof Array && utils.isMongooseDocumentArray(val) && val.length;
3116
3135
  })
3117
3136
  .forEach(function(array) {
3118
3137
  let i = array.length;
@@ -3135,7 +3154,7 @@ Document.prototype.$__reset = function reset() {
3135
3154
  return _this.$__getValue(i);
3136
3155
  }).
3137
3156
  filter(function(val) {
3138
- return val && val.$isSingleNested;
3157
+ return val && !Array.isArray(val) && val.$isSingleNested;
3139
3158
  }).
3140
3159
  forEach(function(doc) {
3141
3160
  doc.$__reset();
@@ -3315,7 +3334,7 @@ Document.prototype.$__getArrayPathsToValidate = function() {
3315
3334
  return this.$__getValue(i);
3316
3335
  }.bind(this))
3317
3336
  .filter(function(val) {
3318
- return val && val instanceof Array && val.isMongooseDocumentArray && val.length;
3337
+ return val && val instanceof Array && utils.isMongooseDocumentArray(val) && val.length;
3319
3338
  }).reduce(function(seed, array) {
3320
3339
  return seed.concat(array);
3321
3340
  }, [])
@@ -3357,12 +3376,12 @@ Document.prototype.$getAllSubdocs = function() {
3357
3376
  seed = Array.from(val.keys()).reduce(function(seed, path) {
3358
3377
  return docReducer(val.get(path), seed, null);
3359
3378
  }, seed);
3360
- } else if (val && val.$isSingleNested) {
3379
+ } else if (val && !Array.isArray(val) && val.$isSingleNested) {
3361
3380
  seed = Object.keys(val._doc).reduce(function(seed, path) {
3362
3381
  return docReducer(val._doc, seed, path);
3363
3382
  }, seed);
3364
3383
  seed.push(val);
3365
- } else if (val && val.isMongooseDocumentArray) {
3384
+ } else if (val && utils.isMongooseDocumentArray(val)) {
3366
3385
  val.forEach(function _docReduce(doc) {
3367
3386
  if (!doc || !doc._doc) {
3368
3387
  return;
@@ -4139,7 +4158,7 @@ Document.prototype.populate = function populate() {
4139
4158
  const args = [...arguments];
4140
4159
  let fn;
4141
4160
 
4142
- if (args.length > 0) {
4161
+ if (args.length !== 0) {
4143
4162
  if (typeof args[args.length - 1] === 'function') {
4144
4163
  fn = args.pop();
4145
4164
  }
@@ -1,7 +1,5 @@
1
1
  'use strict';
2
2
 
3
-
4
- const cloneRegExp = require('regexp-clone');
5
3
  const Decimal = require('../types/decimal128');
6
4
  const ObjectId = require('../types/objectid');
7
5
  const specialProperties = require('./specialProperties');
@@ -34,7 +32,7 @@ function clone(obj, options, isArrayChild) {
34
32
  }
35
33
 
36
34
  if (Array.isArray(obj)) {
37
- return cloneArray(obj, options);
35
+ return cloneArray(utils.isMongooseArray(obj) ? obj.__array : obj, options);
38
36
  }
39
37
 
40
38
  if (isMongooseObject(obj)) {
@@ -54,12 +52,14 @@ function clone(obj, options, isArrayChild) {
54
52
  return obj.toObject(options);
55
53
  }
56
54
 
57
- if (obj.constructor) {
58
- switch (getFunctionName(obj.constructor)) {
55
+ const objConstructor = obj.constructor;
56
+
57
+ if (objConstructor) {
58
+ switch (getFunctionName(objConstructor)) {
59
59
  case 'Object':
60
60
  return cloneObject(obj, options, isArrayChild);
61
61
  case 'Date':
62
- return new obj.constructor(+obj);
62
+ return new objConstructor(+obj);
63
63
  case 'RegExp':
64
64
  return cloneRegExp(obj);
65
65
  default:
@@ -79,12 +79,12 @@ function clone(obj, options, isArrayChild) {
79
79
  return Decimal.fromString(obj.toString());
80
80
  }
81
81
 
82
- if (!obj.constructor && isObject(obj)) {
83
- // object created with Object.create(null)
82
+ // object created with Object.create(null)
83
+ if (!objConstructor && isObject(obj)) {
84
84
  return cloneObject(obj, options, isArrayChild);
85
85
  }
86
86
 
87
- if (obj[symbols.schemaTypeSymbol]) {
87
+ if (typeof obj === 'object' && obj[symbols.schemaTypeSymbol]) {
88
88
  return obj.clone();
89
89
  }
90
90
 
@@ -95,7 +95,7 @@ function clone(obj, options, isArrayChild) {
95
95
  return obj;
96
96
  }
97
97
 
98
- if (obj.valueOf != null) {
98
+ if (typeof obj.valueOf === 'function') {
99
99
  return obj.valueOf();
100
100
  }
101
101
 
@@ -112,25 +112,28 @@ function cloneObject(obj, options, isArrayChild) {
112
112
  const ret = {};
113
113
  let hasKeys;
114
114
 
115
- if (obj[trustedSymbol]) {
115
+ if (trustedSymbol in obj) {
116
116
  ret[trustedSymbol] = obj[trustedSymbol];
117
117
  }
118
118
 
119
- for (const k of Object.keys(obj)) {
120
- if (specialProperties.has(k)) {
119
+ let i = 0;
120
+ let key = '';
121
+ const keys = Object.keys(obj);
122
+ const len = keys.length;
123
+
124
+ for (i = 0; i < len; ++i) {
125
+ if (specialProperties.has(key = keys[i])) {
121
126
  continue;
122
127
  }
123
128
 
124
129
  // Don't pass `isArrayChild` down
125
- const val = clone(obj[k], options);
126
-
127
- if (!minimize || (typeof val !== 'undefined')) {
128
- if (minimize === false && typeof val === 'undefined') {
129
- delete ret[k];
130
- } else {
131
- hasKeys || (hasKeys = true);
132
- ret[k] = val;
133
- }
130
+ const val = clone(obj[key], options, false);
131
+
132
+ if (minimize === false && typeof val === 'undefined') {
133
+ delete ret[key];
134
+ } else if (minimize !== true || (typeof val !== 'undefined')) {
135
+ hasKeys || (hasKeys = true);
136
+ ret[key] = val;
134
137
  }
135
138
  }
136
139
 
@@ -138,11 +141,21 @@ function cloneObject(obj, options, isArrayChild) {
138
141
  }
139
142
 
140
143
  function cloneArray(arr, options) {
141
- const ret = [];
142
-
143
- for (const item of arr) {
144
- ret.push(clone(item, options, true));
144
+ let i = 0;
145
+ const len = arr.length;
146
+ const ret = new Array(len);
147
+ for (i = 0; i < len; ++i) {
148
+ ret[i] = clone(arr[i], options, true);
145
149
  }
146
150
 
147
151
  return ret;
148
- }
152
+ }
153
+
154
+ function cloneRegExp(regexp) {
155
+ const ret = new RegExp(regexp.source, regexp.flags);
156
+
157
+ if (ret.lastIndex !== regexp.lastIndex) {
158
+ ret.lastIndex = regexp.lastIndex;
159
+ }
160
+ return ret;
161
+ }
@@ -88,7 +88,7 @@ function modifiedPaths(update, path, result) {
88
88
  cur += '.' + sp[i];
89
89
  }
90
90
  }
91
- if (isMongooseObject(val) && !Buffer.isBuffer(val)) {
91
+ if (!Buffer.isBuffer(val) && isMongooseObject(val)) {
92
92
  val = val.toObject({ transform: false, virtuals: false });
93
93
  }
94
94
  if (shouldFlatten(val)) {
@@ -108,7 +108,7 @@ function shouldFlatten(val) {
108
108
  typeof val === 'object' &&
109
109
  !(val instanceof Date) &&
110
110
  !(val instanceof ObjectId) &&
111
- (!Array.isArray(val) || val.length > 0) &&
111
+ (!Array.isArray(val) || val.length !== 0) &&
112
112
  !(val instanceof Buffer) &&
113
113
  !(val instanceof Decimal128) &&
114
114
  !(val instanceof Binary);
@@ -1,8 +1,10 @@
1
1
  'use strict';
2
2
 
3
+ const functionNameRE = /^function\s*([^\s(]+)/;
4
+
3
5
  module.exports = function(fn) {
4
- if (fn.name) {
5
- return fn.name;
6
- }
7
- return (fn.toString().trim().match(/^function\s*([^\s(]+)/) || [])[1];
6
+ return (
7
+ fn.name ||
8
+ (fn.toString().trim().match(functionNameRE) || [])[1]
9
+ );
8
10
  };
@@ -1,5 +1,6 @@
1
1
  'use strict';
2
2
 
3
+ const isMongooseArray = require('../types/array/isMongooseArray').isMongooseArray;
3
4
  /*!
4
5
  * Returns if `v` is a mongoose object that has a `toObject()` method we can use.
5
6
  *
@@ -10,12 +11,12 @@
10
11
  */
11
12
 
12
13
  module.exports = function(v) {
13
- if (v == null) {
14
- return false;
15
- }
16
-
17
- return v.$__ != null || // Document
18
- v.isMongooseArray || // Array or Document Array
19
- v.isMongooseBuffer || // Buffer
20
- v.$isMongooseMap; // Map
14
+ return (
15
+ v != null && (
16
+ isMongooseArray(v) || // Array or Document Array
17
+ v.$__ != null || // Document
18
+ v.isMongooseBuffer || // Buffer
19
+ v.$isMongooseMap // Map
20
+ )
21
+ );
21
22
  };
@@ -9,8 +9,8 @@
9
9
  */
10
10
 
11
11
  module.exports = function(arg) {
12
- if (Buffer.isBuffer(arg)) {
13
- return true;
14
- }
15
- return Object.prototype.toString.call(arg) === '[object Object]';
12
+ return (
13
+ Buffer.isBuffer(arg) ||
14
+ Object.prototype.toString.call(arg) === '[object Object]'
15
+ );
16
16
  };
@@ -1,12 +1,17 @@
1
1
  'use strict';
2
2
 
3
+ const dotRE = /\./g;
3
4
  module.exports = function parentPaths(path) {
4
- const pieces = path.split('.');
5
+ if (path.indexOf('.') === -1) {
6
+ return [path];
7
+ }
8
+ const pieces = path.split(dotRE);
9
+ const len = pieces.length;
10
+ const ret = new Array(len);
5
11
  let cur = '';
6
- const ret = [];
7
- for (let i = 0; i < pieces.length; ++i) {
8
- cur += (cur.length > 0 ? '.' : '') + pieces[i];
9
- ret.push(cur);
12
+ for (let i = 0; i < len; ++i) {
13
+ cur += (cur.length !== 0) ? '.' + pieces[i] : pieces[i];
14
+ ret[i] = cur;
10
15
  }
11
16
 
12
17
  return ret;
@@ -35,11 +35,13 @@ function assignRawDocsToIdStructure(rawIds, resultDocs, resultOrder, options, re
35
35
  let sid;
36
36
  let id;
37
37
 
38
- if (rawIds.isMongooseArrayProxy) {
38
+ if (utils.isMongooseArray(rawIds)) {
39
39
  rawIds = rawIds.__array;
40
40
  }
41
41
 
42
- for (let i = 0; i < rawIds.length; ++i) {
42
+ let i = 0;
43
+ const len = rawIds.length;
44
+ for (i = 0; i < len; ++i) {
43
45
  id = rawIds[i];
44
46
 
45
47
  if (Array.isArray(id)) {
@@ -241,15 +241,19 @@ function valueFilter(val, assignmentOpts, populateOptions, allIds) {
241
241
  }
242
242
  }
243
243
 
244
+ const rLen = ret.length;
244
245
  // Since we don't want to have to create a new mongoosearray, make sure to
245
246
  // modify the array in place
246
- while (val.length > ret.length) {
247
+ while (val.length > rLen) {
247
248
  Array.prototype.pop.apply(val, []);
248
249
  }
249
- for (let i = 0; i < ret.length; ++i) {
250
- if (val.isMongooseArrayProxy) {
250
+ let i = 0;
251
+ if (utils.isMongooseArray(val)) {
252
+ for (i = 0; i < rLen; ++i) {
251
253
  val.set(i, ret[i], true);
252
- } else {
254
+ }
255
+ } else {
256
+ for (i = 0; i < rLen; ++i) {
253
257
  val[i] = ret[i];
254
258
  }
255
259
  }
@@ -43,7 +43,7 @@ module.exports = function getModelsMapForPopulate(model, docs, options) {
43
43
  let allSchemaTypes = getSchemaTypes(model, modelSchema, null, options.path);
44
44
  allSchemaTypes = Array.isArray(allSchemaTypes) ? allSchemaTypes : [allSchemaTypes].filter(v => v != null);
45
45
 
46
- if (allSchemaTypes.length <= 0 && options.strictPopulate !== false && options._localModel != null) {
46
+ if (allSchemaTypes.length === 0 && options.strictPopulate !== false && options._localModel != null) {
47
47
  return new MongooseError('Cannot populate path `' + (options._fullPath || options.path) +
48
48
  '` because it is not in your schema. Set the `strictPopulate` option ' +
49
49
  'to false to override.');
@@ -607,7 +607,7 @@ function _getLocalFieldValues(doc, localField, model, options, virtual, schema)
607
607
  const getters = 'getters' in _populateOptions ?
608
608
  _populateOptions.getters :
609
609
  get(virtual, 'options.getters', false);
610
- if (localFieldGetters.length > 0 && getters) {
610
+ if (localFieldGetters.length !== 0 && getters) {
611
611
  const hydratedDoc = (doc.$__ != null) ? doc : model.hydrate(doc);
612
612
  const localFieldValue = utils.getValue(localField, doc);
613
613
  if (Array.isArray(localFieldValue)) {
@@ -644,7 +644,7 @@ function convertTo_id(val, schema) {
644
644
  rawVal[i] = rawVal[i]._id;
645
645
  }
646
646
  }
647
- if (val.isMongooseArray && val.$schema()) {
647
+ if (utils.isMongooseArray(val) && val.$schema()) {
648
648
  return val.$schema()._castForPopulate(val, val.$parent());
649
649
  }
650
650
 
@@ -694,7 +694,7 @@ function _findRefPathForDiscriminators(doc, modelSchema, data, options, normaliz
694
694
  if (schematype != null &&
695
695
  schematype.$isMongooseArray &&
696
696
  schematype.caster.discriminators != null &&
697
- Object.keys(schematype.caster.discriminators).length > 0) {
697
+ Object.keys(schematype.caster.discriminators).length !== 0) {
698
698
  const subdocs = utils.getValue(cur, doc);
699
699
  const remnant = options.path.substring(cur.length + 1);
700
700
  const discriminatorKey = schematype.caster.schema.options.discriminatorKey;