UNPKG

alacritty-theme-switch

Version:
96 lines (95 loc) 3.05 kB
// Copyright 2018-2025 the Deno authors. MIT license. // This module is browser compatible. import { filterInPlace } from "./_utils.js"; export function deepMerge(record, other, options) { return deepMergeInternal(record, other, new Set(), options); } function deepMergeInternal(record, other, seen, options) { const result = {}; const keys = new Set([ ...getKeys(record), ...getKeys(other), ]); // Iterate through each key of other object and use correct merging strategy for (const key of keys) { // Skip to prevent Object.prototype.__proto__ accessor property calls on non-Deno platforms if (key === "__proto__") { continue; } const a = record[key]; if (!Object.hasOwn(other, key)) { result[key] = a; continue; } const b = other[key]; if (isNonNullObject(a) && isNonNullObject(b) && !seen.has(a) && !seen.has(b)) { seen.add(a); seen.add(b); result[key] = mergeObjects(a, b, seen, options); continue; } // Override value result[key] = b; } return result; } function mergeObjects(left, right, seen, options = { arrays: "merge", sets: "merge", maps: "merge", }) { // Recursively merge mergeable objects if (isMergeable(left) && isMergeable(right)) { return deepMergeInternal(left, right, seen, options); } if (isIterable(left) && isIterable(right)) { // Handle arrays if ((Array.isArray(left)) && (Array.isArray(right))) { if (options.arrays === "merge") { return left.concat(right); } return right; } // Handle maps if ((left instanceof Map) && (right instanceof Map)) { if (options.maps === "merge") { return new Map([ ...left, ...right, ]); } return right; } // Handle sets if ((left instanceof Set) && (right instanceof Set)) { if (options.sets === "merge") { return new Set([ ...left, ...right, ]); } return right; } } return right; } /** * Test whether a value is mergeable or not * Builtins that look like objects, null and user defined classes * are not considered mergeable (it means that reference will be copied) */ function isMergeable(value) { return Object.getPrototypeOf(value) === Object.prototype; } function isIterable(value) { return typeof value[Symbol.iterator] === "function"; } function isNonNullObject(value) { return value !== null && typeof value === "object"; } function getKeys(record) { const result = Object.getOwnPropertySymbols(record); filterInPlace(result, (key) => Object.prototype.propertyIsEnumerable.call(record, key)); result.push(...Object.keys(record)); return result; }