metarize
Version:
A lightweight, ESM-compatible TypeScript metadata library for creating and inspecting decorators with zero dependencies
116 lines • 3.7 kB
JavaScript
/**
* A collection of types that can be cloned
*/
export const cloneableTypes = new Set([
Object,
Array,
Set,
Map,
RegExp,
Date,
Buffer,
ArrayBuffer,
Float32Array,
Float64Array,
Int8Array,
Int16Array,
Int32Array,
Uint8Array,
Uint8ClampedArray,
Uint16Array,
Uint32Array,
]);
/**
* Deep clone a value
* @param val - The value to clone
* @param refs - Map of references to handle circular references (internal use)
* @returns A deep clone of the value
*/
export function cloneDeep(val, refs = new WeakMap()) {
if (val === null || typeof val !== 'object')
return val;
// Handle circular references
if (refs.has(val)) {
throw new Error('Circular reference detected during deep cloning');
}
// Handle special types that should not be deep cloned
if (val.constructor != null && !cloneableTypes.has(val.constructor)) {
// Do not clone instances of classes/constructors, such as custom classes
return val;
}
// Add this object to the refs map
refs.set(val, true);
// Handle arrays
if (Array.isArray(val)) {
const result = val.map(item => cloneDeep(item, refs));
refs.delete(val); // Clean up refs map
return result;
}
// Handle Set
if (val instanceof Set) {
const newSet = new Set();
val.forEach(item => newSet.add(cloneDeep(item, refs)));
refs.delete(val); // Clean up refs map
return newSet;
}
// Handle Map
if (val instanceof Map) {
const newMap = new Map();
val.forEach((value, key) => newMap.set(key, cloneDeep(value, refs)));
refs.delete(val); // Clean up refs map
return newMap;
}
// Handle RegExp
if (val instanceof RegExp) {
refs.delete(val); // Clean up refs map
return new RegExp(val.source, val.flags);
}
// Handle Date
if (val instanceof Date) {
refs.delete(val); // Clean up refs map
return new Date(val.getTime());
}
// Handle ArrayBuffer and typed arrays
if (val instanceof ArrayBuffer) {
const newBuffer = new ArrayBuffer(val.byteLength);
new Uint8Array(newBuffer).set(new Uint8Array(val));
refs.delete(val); // Clean up refs map
return newBuffer;
}
if (ArrayBuffer.isView(val) && !(val instanceof DataView)) {
// Handle typed arrays (Float32Array, Uint8Array, etc.)
// Use any typed array method that creates a copy
refs.delete(val); // Clean up refs map
if (val instanceof Float32Array)
return new Float32Array(val);
if (val instanceof Float64Array)
return new Float64Array(val);
if (val instanceof Int8Array)
return new Int8Array(val);
if (val instanceof Int16Array)
return new Int16Array(val);
if (val instanceof Int32Array)
return new Int32Array(val);
if (val instanceof Uint8Array)
return new Uint8Array(val);
if (val instanceof Uint8ClampedArray)
return new Uint8ClampedArray(val);
if (val instanceof Uint16Array)
return new Uint16Array(val);
if (val instanceof Uint32Array)
return new Uint32Array(val);
// Fallback for any other ArrayBufferView types
return val;
}
// Handle plain objects
const newObj = {};
for (const key in val) {
if (Object.hasOwn(val, key)) {
newObj[key] = cloneDeep(val[key], refs);
}
}
refs.delete(val); // Clean up refs map
return newObj;
}
// 这里可以添加其他工具函数
//# sourceMappingURL=utils.js.map