UNPKG

froebel

Version:
85 lines (68 loc) 2.49 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _clone = _interopRequireDefault(require("./clone")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const merge_ = (a, b) => { const visited = new Map(); return mergeItems(a, b, visited); }; const mergeItems = (a, b, visited) => { if (isPrimitive(a) || isPrimitive(b)) return (0, _clone.default)(b); if (!visited.has(a)) visited.set(a, new Map()); if (visited.get(a).has(b)) return visited.get(a).get(b); let result; if (Array.isArray(b)) { const clonedA = Array.isArray(a) ? (0, _clone.default)(a) : []; const clonedB = (0, _clone.default)(b); result = [...clonedA, ...clonedB]; for (let i = 0; i < result.length; i++) { if (result[i] === clonedA || result[i] === clonedB) result[i] = result; } } else if (b instanceof Set) { result = new Set([...(a instanceof Set ? a : []), ...b]); if (result.has(a) || result.has(b)) { result.delete(a); result.delete(b); result.add(result); } } else if (b instanceof Map) { result = new Map([...(a instanceof Map ? a : []), ...b]); const keys = [...result.keys()]; if (keys.includes(a)) { result.set(result, result.get(a)); result.delete(a); } if (keys.includes(b)) { result.set(result, result.get(b)); result.delete(b); } for (const [k, v] of result) { if (v === a || v === b) result.set(k, result); } } else { const keys = [...new Set([...Object.keys(a), ...Object.keys(b)])]; result = {}; visited.get(a).set(b, result); for (const key of keys) { result[key] = !(key in b) ? (0, _clone.default)(a[key]) : !(key in a) ? (0, _clone.default)(b[key]) : mergeItems(a[key], b[key], visited); } } visited.get(a).set(b, result); return result; }; /** * Recursively merges `A` and `B`. If a property in `A` and `B` is of a * different type (i.e. it's not an array, Set, Map, or plain object in both, * the value from `B` will be used in the result). * * If there are self-references in the cloned values, array / Set items, or Map * keys or values, they will also be self-referencing in the result. */ const merge = merge_; var _default = merge; exports.default = _default; const isPrimitive = value => typeof value !== "object" || value === null; module.exports = Object.assign(exports.default || {}, exports);