Skip to content

Commit

Permalink
add index
Browse files Browse the repository at this point in the history
  • Loading branch information
sasaplus1 committed Aug 21, 2020
1 parent fa9c7a3 commit e16a53a
Show file tree
Hide file tree
Showing 3 changed files with 845 additions and 0 deletions.
1 change: 1 addition & 0 deletions index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { deepcopy } from './src/index';
122 changes: 122 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { detectType } from './detector';
import {
Collection,
getKeys,
getValue,
isCollection,
setValue
} from './collection';
import { copy, Customizer } from './clone';

/**
* recursively copy
*
* @private
* @param value
* @param clone
* @param references
* @param visited
* @param customizer
*/
function recursiveCopy(
value: unknown,
clone: unknown,
references: WeakMap<Record<string, unknown>, unknown>,
visited: WeakSet<Record<string, unknown>>,
customizer: Parameters<typeof copy>[2]
): unknown {
const valueType = detectType(value);
const copiedValue = copy(value, valueType);

// return if not a collection value
if (!isCollection(valueType)) {
return copiedValue;
}

const keys = /*#__INLINE__*/ getKeys(value as Collection, valueType);

// walk within collection with iterator
for (const collectionKey of keys) {
const collectionValue = /*#__INLINE__*/ getValue(
value as Collection,
collectionKey,
valueType
) as Record<string, unknown>;

if (visited.has(collectionValue)) {
// for [Circular]
setValue(
clone as Collection,
collectionKey,
references.get(collectionValue),
valueType
);
} else {
const collectionValueType = detectType(collectionValue);
const copiedCollectionValue = copy(collectionValue, collectionValueType);

// save reference if value is collection
if (isCollection(collectionValueType)) {
references.set(collectionValue, copiedCollectionValue);
visited.add(collectionValue);
}

setValue(
clone as Collection,
collectionKey,
recursiveCopy(
collectionValue,
copiedCollectionValue,
references,
visited,
customizer
),
valueType
);
}
}

// TODO: isSealed/isFrozen/isExtensible

return clone;
}

export type Options = { customizer?: Customizer };

/**
* deep copy value
*
* @param value
* @param options
*/
export function deepcopy<T>(value: T, options?: Options): T {
const {
// TODO: before/after customizer
customizer = null
// TODO: max depth
// depth = Infinity,
} = options || {};

const valueType = detectType(value);

if (!isCollection(valueType)) {
return copy(value, valueType, customizer) as T;
}

const copiedValue = copy(value, valueType, customizer);

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const references = new WeakMap<Record<string, any>, unknown>([
[value, copiedValue]
]);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const visited = new WeakSet<Record<string, any>>([value]);

return recursiveCopy(
value,
copiedValue,
references,
visited,
customizer
) as T;
}
Loading

0 comments on commit e16a53a

Please sign in to comment.