UNPKG

@mikro-orm/core

Version:

TypeScript ORM for Node.js based on Data Mapper, Unit of Work and Identity Map patterns. Supports MongoDB, MySQL, PostgreSQL and SQLite databases as well as usage with vanilla JavaScript.

132 lines (131 loc) 4.35 kB
/** * Inspired by https://github.com/pvorb/clone but simplified and never tries to * clone `EventEmitter`s to get around https://github.com/mikro-orm/mikro-orm/issues/2748 * @internal */ /** * Get the property descriptor of a property on an object or its prototype chain. * * @param obj - The object to get the property descriptor from. * @param prop - The property to get the descriptor for. */ function getPropertyDescriptor(obj, prop) { const descriptor = Object.getOwnPropertyDescriptor(obj, prop); if (descriptor) { return descriptor; } const proto = Object.getPrototypeOf(obj); if (proto) { return getPropertyDescriptor(proto, prop); } return null; } const TypedArray = Object.getPrototypeOf(Uint8Array); export function clone(parent, respectCustomCloneMethod = true) { const allParents = []; const allChildren = []; function _clone(parent) { // cloning null always returns null if (parent === null) { return null; } if (typeof parent !== 'object') { return parent; } if (respectCustomCloneMethod && 'clone' in parent && typeof parent.clone === 'function') { return parent.clone(); } let child; let proto; if (parent instanceof Map) { child = new Map(); } else if (parent instanceof Set) { child = new Set(); } else if (parent instanceof Promise) { child = new Promise((resolve, reject) => { parent.then(resolve.bind(null, _clone), reject.bind(null, _clone)); }); } else if (Array.isArray(parent)) { child = []; } else if (parent instanceof RegExp) { let flags = ''; if (parent.global) { flags += 'g'; } if (parent.ignoreCase) { flags += 'i'; } if (parent.multiline) { flags += 'm'; } child = new RegExp(parent.source, flags); if (parent.lastIndex) { child.lastIndex = parent.lastIndex; } } else if (parent instanceof Date) { child = new Date(parent.getTime()); } else if (Buffer.isBuffer(parent)) { child = Buffer.allocUnsafe(parent.length); parent.copy(child); return child; } else if (parent instanceof TypedArray) { child = parent.slice(); return child; } else if (parent instanceof Error) { child = new parent.constructor(parent.message); } else { proto = Object.getPrototypeOf(parent); child = Object.create(proto); } const index = allParents.indexOf(parent); if (index !== -1) { return allChildren[index]; } allParents.push(parent); allChildren.push(child); if (parent instanceof Map) { parent.forEach((value, key) => { const keyChild = _clone(key); const valueChild = _clone(value); child.set(keyChild, valueChild); }); } if (parent instanceof Set) { parent.forEach((value) => { const entryChild = _clone(value); child.add(entryChild); }); } for (const i in parent) { let attrs; if (proto) { attrs = getPropertyDescriptor(proto, i); } if (attrs && typeof attrs.get === 'function' && attrs.set == null) { continue; } child[i] = _clone(parent[i]); } const symbols = Object.getOwnPropertySymbols(parent); for (let i = 0; i < symbols.length; i++) { const symbol = symbols[i]; const descriptor = Object.getOwnPropertyDescriptor(parent, symbol); if (descriptor && !descriptor.enumerable) { Object.defineProperty(child, symbol, { ...descriptor, value: _clone(descriptor.value) }); continue; } child[symbol] = _clone(parent[symbol]); } return child; } return _clone(parent); }