{"ScriptPreparationCode":"var a = { a: \u0027oh\u0027, b: \u0027my\u0027, c: { a: \u0027a\u0027, b: { c: \u0027c\u0027 } } };\r\nvar b = { c: { b: { d: \u0027a\u0027 }, c: { d: \u0027d\u0027 } } };\r\nvar c = _.merge({}, a, b);","TestCases":[{"Name":"lodash","Code":"var a = { a: \u0027oh\u0027, b: \u0027my\u0027, c: { a: \u0027a\u0027, b: { c: \u0027c\u0027 } } };\r\nvar b = { c: { b: { d: \u0027a\u0027 }, c: { d: \u0027d\u0027 } } };\r\nvar c = _.merge({}, a, b);","IsDeferred":false},{"Name":"deepmerge","Code":"var a = { a: \u0027oh\u0027, b: \u0027my\u0027, c: { a: \u0027a\u0027, b: { c: \u0027c\u0027 } } };\r\nvar b = { c: { b: { d: \u0027a\u0027 }, c: { d: \u0027d\u0027 } } };\r\nvar c = deepmerge({}, a, b);","IsDeferred":false},{"Name":"own impl","Code":"function isMergable(property) {\r\n return Array.isArray(property) || typeof property === \u0027object\u0027\r\n}\r\n\r\nfunction propertyTypesDoMatch(propA, propB) {\r\n if (propA \u0026\u0026 propB) {\r\n return propA.constructor.name === propB.constructor.name\r\n }\r\n return false\r\n}\r\n\r\nconst basics = [\u0027string\u0027, \u0027number\u0027, \u0027boolean\u0027, \u0027bigint\u0027, \u0027undefined\u0027, \u0027symbol\u0027, \u0027function\u0027]\r\n\r\nfunction deepEqual(i1, i2) {\r\n if (basics.includes(typeof i1) \u0026\u0026 typeof i1 === typeof i2) {\r\n return i1 === i2\r\n }\r\n if (Array.isArray(i1) \u0026\u0026 Array.isArray(i2)) {\r\n return i1.every((subItem) =\u003E arrayContainsSame(i2, subItem))\r\n }\r\n if (typeof i1 === typeof i2 \u0026\u0026 typeof i1 === \u0027object\u0027) {\r\n return Object.entries(i1).every(([key, value]) =\u003E {\r\n return deepEqual(value, i2[key])\r\n })\r\n }\r\n return false\r\n}\r\n\r\nfunction arrayContainsSame(items, item) {\r\n // skippable for loop makes it 1ms faster\r\n for (let c = 0; c \u003C items.length; c\u002B\u002B) {\r\n if (deepEqual(items[c], item)) {\r\n return true\r\n }\r\n }\r\n}\r\n\r\nfunction mergeArrays(array1, array2) {\r\n const all = [...array1]\r\n array2.forEach((i) =\u003E {\r\n if (!arrayContainsSame(all, i)) {\r\n all.push(i)\r\n }\r\n })\r\n return all\r\n}\r\n\r\nfunction mergeConfigurations(rootConfig, additionalConfig) {\r\n let copiedConfig = { ...rootConfig }\r\n Object.keys(additionalConfig).forEach((key) =\u003E {\r\n const doTypesMatch = propertyTypesDoMatch(copiedConfig[key], additionalConfig[key])\r\n const propExistsInRoot = Object.hasOwnProperty.call(copiedConfig, key)\r\n\r\n if (propExistsInRoot \u0026\u0026 isMergable(copiedConfig[key]) \u0026\u0026 doTypesMatch) {\r\n if (Array.isArray(copiedConfig[key])) {\r\n copiedConfig[key] = mergeArrays(copiedConfig[key], additionalConfig[key])\r\n } else {\r\n copiedConfig[key] = mergeConfigurations(copiedConfig[key], additionalConfig[key])\r\n }\r\n } else if (propExistsInRoot \u0026\u0026 doTypesMatch) {\r\n copiedConfig[key] = additionalConfig[key]\r\n } else {\r\n copiedConfig = Object.assign(copiedConfig, { [key]: additionalConfig[key] })\r\n }\r\n })\r\n return copiedConfig\r\n}\r\n\r\nvar a = { a: \u0027oh\u0027, b: \u0027my\u0027, c: { a: \u0027a\u0027, b: { c: \u0027c\u0027 } } };\r\nvar b = { c: { b: { d: \u0027a\u0027 }, c: { d: \u0027d\u0027 } } };\r\nvar c = mergeConfigurations(a, b)","IsDeferred":false}]}