UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

131 lines 4.32 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isObjectOrArray = isObjectOrArray; exports.deepMergeObject = deepMergeObject; exports.deepMergeObjectInPlace = deepMergeObjectInPlace; exports.compactRecord = compactRecord; exports.deepClonePreserveUnclonable = deepClonePreserveUnclonable; const json_1 = require("./json"); /** * checks if `item` is an object (it may be an array, ...) */ function isObjectOrArray(item) { return typeof item === 'object'; } function deepMergeObject(base, addon) { if (!base) { return addon; } else if (!addon) { return base; } else if (typeof base !== 'object' || typeof addon !== 'object') { // this case should be guarded by type guards, but in case we do not know throw new Error('illegal types for deepMergeObject!'); } assertSameType(base, addon); const result = { ...base }; const baseIsArray = Array.isArray(base); const addonIsArray = Array.isArray(addon); if (!baseIsArray && !addonIsArray) { deepMergeObjectWithResult(addon, base, result); } else if (baseIsArray && addonIsArray) { return base.concat(addon); } else { throw new Error('cannot merge object with array!'); } return result; } function deepMergeObjectWithResult(addon, base, result) { for (const key of Object.keys(addon)) { // values that are undefined (like from a partial object) should NOT be overwritten if (addon[key] === undefined) { continue; } if (typeof addon[key] === 'object') { if (key in base) { result[key] = deepMergeObject(base[key], addon[key]); } else { result[key] = addon[key]; } } else { assertSameType(result[key], addon[key]); result[key] = addon[key]; } } } function deepMergeObjectInPlace(base, addon) { if (!base) { return addon; } else if (!addon) { return base; } else if (typeof base !== 'object' || typeof addon !== 'object') { // this case should be guarded by type guards, but in case we do not know throw new Error('illegal types for deepMergeObjectInPlace!'); } assertSameType(base, addon); const baseIsArray = Array.isArray(base); const addonIsArray = Array.isArray(addon); if (!baseIsArray && !addonIsArray) { deepMergeObjectWithResult(addon, base, base); } else if (baseIsArray && addonIsArray) { (base).push(...addon); } else { throw new Error('cannot merge object with array!'); } return base; } function assertSameType(base, addon) { if (base !== undefined && addon !== undefined && typeof base !== typeof addon) { throw new Error(`cannot merge different types! ${typeof base} (${JSON.stringify(base, json_1.jsonReplacer)}) !== ${typeof addon} (${JSON.stringify(addon, json_1.jsonReplacer)})`); } } /** from a record take only the keys that are not undefined */ function compactRecord(record) { if (record === undefined) { return undefined; } const result = {}; for (const key of Object.keys(record)) { if (record[key] !== undefined) { result[key] = record[key]; } } return result; } /** * This is a version of a deep clone that preserves unclonable values (like functions, symbols, ...) by keeping the same reference to them. */ function deepClonePreserveUnclonable(obj) { if (typeof obj !== 'object' || obj === null) { return obj; } else if (Array.isArray(obj)) { return obj.map(deepClonePreserveUnclonable); } else if (obj instanceof Date) { return new Date(obj.getTime()); } else if (obj instanceof Map) { return new Map(obj.entries().map(([k, v]) => [deepClonePreserveUnclonable(k), deepClonePreserveUnclonable(v)])); } else if (obj instanceof Set) { return new Set(obj.values().map(deepClonePreserveUnclonable)); } else { const result = {}; for (const key of Object.keys(obj)) { result[key] = deepClonePreserveUnclonable(obj[key]); } return result; } } //# sourceMappingURL=objects.js.map