You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					143 lines
				
				3.6 KiB
			
		
		
			
		
	
	
					143 lines
				
				3.6 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const cloneRegExp = require('regexp-clone');
							 | 
						||
| 
								 | 
							
								const Decimal = require('../types/decimal128');
							 | 
						||
| 
								 | 
							
								const ObjectId = require('../types/objectid');
							 | 
						||
| 
								 | 
							
								const specialProperties = require('./specialProperties');
							 | 
						||
| 
								 | 
							
								const isMongooseObject = require('./isMongooseObject');
							 | 
						||
| 
								 | 
							
								const getFunctionName = require('./getFunctionName');
							 | 
						||
| 
								 | 
							
								const isBsonType = require('./isBsonType');
							 | 
						||
| 
								 | 
							
								const isObject = require('./isObject');
							 | 
						||
| 
								 | 
							
								const symbols = require('./symbols');
							 | 
						||
| 
								 | 
							
								const utils = require('../utils');
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*!
							 | 
						||
| 
								 | 
							
								 * Object clone with Mongoose natives support.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * If options.minimize is true, creates a minimal data object. Empty objects and undefined values will not be cloned. This makes the data payload sent to MongoDB as small as possible.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Functions are never cloned.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param {Object} obj the object to clone
							 | 
						||
| 
								 | 
							
								 * @param {Object} options
							 | 
						||
| 
								 | 
							
								 * @param {Boolean} isArrayChild true if cloning immediately underneath an array. Special case for minimize.
							 | 
						||
| 
								 | 
							
								 * @return {Object} the cloned object
							 | 
						||
| 
								 | 
							
								 * @api private
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function clone(obj, options, isArrayChild) {
							 | 
						||
| 
								 | 
							
								  if (obj == null) {
							 | 
						||
| 
								 | 
							
								    return obj;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (Array.isArray(obj)) {
							 | 
						||
| 
								 | 
							
								    return cloneArray(obj, options);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (isMongooseObject(obj)) {
							 | 
						||
| 
								 | 
							
								    // Single nested subdocs should apply getters later in `applyGetters()`
							 | 
						||
| 
								 | 
							
								    // when calling `toObject()`. See gh-7442, gh-8295
							 | 
						||
| 
								 | 
							
								    if (options && options._skipSingleNestedGetters && obj.$isSingleNested) {
							 | 
						||
| 
								 | 
							
								      options = Object.assign({}, options, { getters: false });
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (utils.isPOJO(obj) && obj.$__ != null && obj._doc != null) {
							 | 
						||
| 
								 | 
							
								      return obj._doc;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (options && options.json && typeof obj.toJSON === 'function') {
							 | 
						||
| 
								 | 
							
								      return obj.toJSON(options);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return obj.toObject(options);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (obj.constructor) {
							 | 
						||
| 
								 | 
							
								    switch (getFunctionName(obj.constructor)) {
							 | 
						||
| 
								 | 
							
								      case 'Object':
							 | 
						||
| 
								 | 
							
								        return cloneObject(obj, options, isArrayChild);
							 | 
						||
| 
								 | 
							
								      case 'Date':
							 | 
						||
| 
								 | 
							
								        return new obj.constructor(+obj);
							 | 
						||
| 
								 | 
							
								      case 'RegExp':
							 | 
						||
| 
								 | 
							
								        return cloneRegExp(obj);
							 | 
						||
| 
								 | 
							
								      default:
							 | 
						||
| 
								 | 
							
								        // ignore
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (obj instanceof ObjectId) {
							 | 
						||
| 
								 | 
							
								    return new ObjectId(obj.id);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (isBsonType(obj, 'Decimal128')) {
							 | 
						||
| 
								 | 
							
								    if (options && options.flattenDecimals) {
							 | 
						||
| 
								 | 
							
								      return obj.toJSON();
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return Decimal.fromString(obj.toString());
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (!obj.constructor && isObject(obj)) {
							 | 
						||
| 
								 | 
							
								    // object created with Object.create(null)
							 | 
						||
| 
								 | 
							
								    return cloneObject(obj, options, isArrayChild);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (obj[symbols.schemaTypeSymbol]) {
							 | 
						||
| 
								 | 
							
								    return obj.clone();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // If we're cloning this object to go into a MongoDB command,
							 | 
						||
| 
								 | 
							
								  // and there's a `toBSON()` function, assume this object will be
							 | 
						||
| 
								 | 
							
								  // stored as a primitive in MongoDB and doesn't need to be cloned.
							 | 
						||
| 
								 | 
							
								  if (options && options.bson && typeof obj.toBSON === 'function') {
							 | 
						||
| 
								 | 
							
								    return obj;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (obj.valueOf != null) {
							 | 
						||
| 
								 | 
							
								    return obj.valueOf();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return cloneObject(obj, options, isArrayChild);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								module.exports = clone;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/*!
							 | 
						||
| 
								 | 
							
								 * ignore
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function cloneObject(obj, options, isArrayChild) {
							 | 
						||
| 
								 | 
							
								  const minimize = options && options.minimize;
							 | 
						||
| 
								 | 
							
								  const ret = {};
							 | 
						||
| 
								 | 
							
								  let hasKeys;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (const k of Object.keys(obj)) {
							 | 
						||
| 
								 | 
							
								    if (specialProperties.has(k)) {
							 | 
						||
| 
								 | 
							
								      continue;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Don't pass `isArrayChild` down
							 | 
						||
| 
								 | 
							
								    const val = clone(obj[k], options);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (!minimize || (typeof val !== 'undefined')) {
							 | 
						||
| 
								 | 
							
								      if (minimize === false && typeof val === 'undefined') {
							 | 
						||
| 
								 | 
							
								        delete ret[k];
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        hasKeys || (hasKeys = true);
							 | 
						||
| 
								 | 
							
								        ret[k] = val;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return minimize && !isArrayChild ? hasKeys && ret : ret;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function cloneArray(arr, options) {
							 | 
						||
| 
								 | 
							
								  const ret = [];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  for (const item of arr) {
							 | 
						||
| 
								 | 
							
								    ret.push(clone(item, options, true));
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return ret;
							 | 
						||
| 
								 | 
							
								}
							 |