/*--------------------------------------------------------------------------------------------- * Licensed under the MIT License. * * @Author: fantasticsoul *--------------------------------------------------------------------------------------------*/ import type { ObjectLike } from '../inner-types'; import { isMap, isObject, isPrimitive, isSet } from '../support/util'; export function deepCopy(obj: T): T { const innerDeep = (obj: any) => { if (isPrimitive(obj)) { return obj; } // TODO: 或许这里通过 metaVer 能够解决多引用问题 ( see 3.4.2 ) // TODO: 传入参数 reuse,确定是否走逻辑查看 meta.modified,并复用 meta.copy or meta.self let newNode = obj; if (Array.isArray(obj)) { newNode = obj.slice(); newNode.forEach((item: any, idx: number) => { newNode[idx] = innerDeep(item); }); } if (isSet(obj)) { const tmpArr = Array.from(obj); tmpArr.forEach((item, idx) => { tmpArr[idx] = innerDeep(item); }); newNode = new Set(tmpArr); } if (isMap(obj)) { newNode = new Map(obj) as Map; (newNode as Map).forEach((value, key) => { newNode.set(key, innerDeep(value)); }); } if (isObject(obj)) { newNode = {}; Object.keys(obj).forEach((key) => { newNode[key] = innerDeep(obj[key]); }); } return newNode; }; return innerDeep(obj); } export function makeCopy(val: any) { if (Array.isArray(val)) { return val.slice(); } if (isObject(val)) { return { ...val }; } if (isMap(val)) { return new Map(val); } if (isSet(val)) { return new Set(val); } return val; } /** * 尝试生成copy * @param val * @returns */ export function tryMakeCopy(val: any, readOnly?: boolean) { if (readOnly) { return val; } if (Array.isArray(val)) { return val.slice(); } let copy = val; if (val && isObject(val)) { copy = { ...val }; } if (isMap(val)) { copy = new Map(val); } if (isSet(val)) { copy = new Set(val); } return copy; } // 调用处已保证 meta 不为空 export function mayMakeCopy( ori: any, options: { immutBase: boolean; readOnly: boolean; }, ) { // LABEL: SEE IF IMMUT HAS MEM LEAK if (options.immutBase) { return ori; } const copy = tryMakeCopy(ori, options.readOnly); return copy; }