@rustable/utils
Version:
Essential utilities for object cloning, string manipulation, and value comparison in TypeScript, inspired by Rust's standard library.
83 lines (81 loc) • 2.32 kB
JavaScript
;
function deepClone(data, hash = /* @__PURE__ */ new WeakMap()) {
if (data === null || typeof data !== "object") {
return data;
}
if (hash.has(data)) {
return hash.get(data);
}
if (!hash.has(data) && typeof data.clone === "function") {
const copy2 = Object.create(Object.getPrototypeOf(data));
hash.set(data, copy2);
const result = data.clone(hash);
if (result !== copy2) {
return result;
}
cloneProperties(data, copy2, hash);
return copy2;
}
if (data instanceof Date) {
return new Date(data.getTime());
}
if (data instanceof RegExp) {
return new RegExp(data.source, data.flags);
}
if (data instanceof Set) {
const copy2 = /* @__PURE__ */ new Set();
hash.set(data, copy2);
data.forEach((value) => copy2.add(deepClone(value, hash)));
return copy2;
}
if (data instanceof Map) {
const copy2 = /* @__PURE__ */ new Map();
hash.set(data, copy2);
data.forEach((value, key) => copy2.set(key, deepClone(value, hash)));
return copy2;
}
if (data instanceof Error) {
const error = new Error(data.message);
error.stack = data.stack;
return error;
}
if (ArrayBuffer.isView(data)) {
if (data instanceof DataView) {
const buffer = deepClone(data.buffer);
return new DataView(buffer, data.byteOffset, data.byteLength);
}
return new data.constructor(data);
}
if (data instanceof ArrayBuffer) {
return data.slice(0);
}
if (Array.isArray(data)) {
const copy2 = [];
hash.set(data, copy2);
copy2.push(...data.map((item) => deepClone(item, hash)));
return copy2;
}
const copy = Object.create(Object.getPrototypeOf(data));
hash.set(data, copy);
cloneProperties(data, copy, hash);
return copy;
}
function cloneProperties(source, target, hash) {
for (const key of [
...Object.getOwnPropertyNames(source),
...Object.getOwnPropertySymbols(source)
]) {
const descriptor = Object.getOwnPropertyDescriptor(source, key);
if (descriptor) {
if (descriptor.get || descriptor.set) {
Object.defineProperty(target, key, descriptor);
} else {
Object.defineProperty(target, key, {
...descriptor,
value: deepClone(descriptor.value, hash)
});
}
}
}
}
export { deepClone };