"use strict"; module.exports = function immutableDeepMerge(object1, object2) { let hasChanges = false; let changedProperties = { }; let deletedProperties = []; if (object2 != null) { for (let key of Object.keys(object2)) { let value = object2[key]; let originalValue = object1[key]; if (value === Delete) { deletedProperties.push(key); hasChanges = true; } else { let transformedValue; let normalizedValue = (typeof value === "function") ? value(originalValue) : value; if (typeof normalizedValue === "object" && normalizedValue !== null) { // NOTE: We default to an empty object for the original value because from the perspective of a deep-merge, any nested paths required by the new input that don't exist in the original input should be imagined into existence. transformedValue = immutableDeepMerge(originalValue ?? {}, normalizedValue); } else { transformedValue = normalizedValue; } changedProperties[key] = transformedValue; if (transformedValue !== originalValue) { hasChanges = true; } } } } if (hasChanges) { let merged = { ... object1, ... changedProperties }; for (let property of deletedProperties) { delete merged[property]; } return merged; } else { return object1; } };