{"ScriptPreparationCode":"function generateDeepObject(levels, breadth, currentLevel = 0) {\r\n if (currentLevel \u003E= levels) {\r\n return {\r\n value: \u0060leaf_${Math.random()}\u0060,\r\n number: Math.random() * 1000,\r\n nullValue: Math.random() \u003E 0.7 ? null : \u0060value_${Math.random()}\u0060,\r\n array: Array.from({length: 5}, (_, i) =\u003E i)\r\n };\r\n }\r\n \r\n const obj = {};\r\n for (let i = 0; i \u003C breadth; i\u002B\u002B) {\r\n obj[\u0060key_${currentLevel}_${i}\u0060] = generateDeepObject(levels, breadth, currentLevel \u002B 1);\r\n // Add some null values\r\n if (Math.random() \u003E 0.8) {\r\n obj[\u0060null_key_${currentLevel}_${i}\u0060] = null;\r\n }\r\n }\r\n return obj;\r\n}","TestCases":[{"Name":"Onyx fastMerge","Code":"const ONYX_INTERNALS__REPLACE_OBJECT_MARK = \u0027ONYX_INTERNALS__REPLACE_OBJECT_MARK\u0027;\r\n\r\nfunction fastMergeOriginal(target, source, options, metadata, basePath = []) {\r\n if (!metadata) {\r\n metadata = {\r\n replaceNullPatches: [],\r\n };\r\n }\r\n\r\n if (Array.isArray(source) || source === null || source === undefined) {\r\n return {result: source, replaceNullPatches: metadata.replaceNullPatches};\r\n }\r\n\r\n const optionsWithDefaults = {\r\n shouldRemoveNestedNulls: options?.shouldRemoveNestedNulls ?? false,\r\n objectRemovalMode: options?.objectRemovalMode ?? \u0027none\u0027,\r\n };\r\n\r\n const mergedValue = mergeObjectOriginal(target, source, optionsWithDefaults, metadata, basePath);\r\n return {result: mergedValue, replaceNullPatches: metadata.replaceNullPatches};\r\n}\r\n\r\nfunction mergeObjectOriginal(target, source, options, metadata, basePath) {\r\n const destination = {};\r\n const targetObject = isMergeableObjectOriginal(target) ? target : undefined;\r\n\r\n if (targetObject) {\r\n Object.keys(targetObject).forEach((key) =\u003E {\r\n const targetProperty = targetObject?.[key];\r\n const sourceProperty = source?.[key];\r\n\r\n const shouldOmitNullishProperty = options.shouldRemoveNestedNulls \u0026\u0026 (targetProperty === null || sourceProperty === null);\r\n\r\n if (targetProperty === undefined || shouldOmitNullishProperty) {\r\n return;\r\n }\r\n\r\n destination[key] = targetProperty;\r\n });\r\n }\r\n\r\n Object.keys(source).forEach((key) =\u003E {\r\n let targetProperty = targetObject?.[key];\r\n const sourceProperty = source[key];\r\n\r\n const shouldOmitNullishProperty = options.shouldRemoveNestedNulls \u0026\u0026 sourceProperty === null;\r\n\r\n if (sourceProperty === undefined || shouldOmitNullishProperty) {\r\n return;\r\n }\r\n\r\n if (!isMergeableObjectOriginal(sourceProperty)) {\r\n destination[key] = sourceProperty;\r\n return;\r\n }\r\n\r\n if (options.objectRemovalMode === \u0027mark\u0027 \u0026\u0026 targetProperty === null) {\r\n targetProperty = {[ONYX_INTERNALS__REPLACE_OBJECT_MARK]: true};\r\n metadata.replaceNullPatches.push([[...basePath, key], {...sourceProperty}]);\r\n }\r\n\r\n if (options.objectRemovalMode === \u0027replace\u0027 \u0026\u0026 sourceProperty[ONYX_INTERNALS__REPLACE_OBJECT_MARK]) {\r\n const sourcePropertyWithoutMark = {...sourceProperty};\r\n delete sourcePropertyWithoutMark.ONYX_INTERNALS__REPLACE_OBJECT_MARK;\r\n destination[key] = sourcePropertyWithoutMark;\r\n return;\r\n }\r\n\r\n destination[key] = fastMergeOriginal(targetProperty, sourceProperty, options, metadata, [...basePath, key]).result;\r\n });\r\n\r\n return destination;\r\n}\r\n\r\nfunction isMergeableObjectOriginal(value) {\r\n const isNonNullObject = value != null ? typeof value === \u0027object\u0027 : false;\r\n return isNonNullObject \u0026\u0026 !(value instanceof RegExp) \u0026\u0026 !(value instanceof Date) \u0026\u0026 !Array.isArray(value);\r\n}\r\n\r\nconst data1 = generateDeepObject(5, 3);\r\nconst data2 = generateDeepObject(5, 3);\r\nconst arrayData1 = Array.from({length: 1000}, (_, i) =\u003E ({\r\n id: i,\r\n nested: generateDeepObject(3, 2),\r\n tags: Array.from({length: 10}, (_, j) =\u003E \u0060tag_${j}\u0060),\r\n metadata: {\r\n created: new Date(),\r\n updated: Math.random() \u003E 0.5 ? null : new Date(),\r\n author: Math.random() \u003E 0.3 ? \u0060user_${i}\u0060 : null\r\n }\r\n}));\r\n\r\nconst arrayData2 = Array.from({length: 1000}, (_, i) =\u003E ({\r\n id: i,\r\n nested: generateDeepObject(3, 2),\r\n tags: Array.from({length: 8}, (_, j) =\u003E \u0060new_tag_${j}\u0060),\r\n metadata: {\r\n created: new Date(),\r\n updated: new Date(),\r\n author: \u0060new_user_${i}\u0060,\r\n deleted: Math.random() \u003E 0.7 ? null : \u0060reason_${i}\u0060\r\n }\r\n}));\r\n// Test\r\nfastMergeOriginal(data1, data2, { shouldRemoveNestedNulls: true });\r\nfastMergeOriginal(arrayData1, arrayData2, { shouldRemoveNestedNulls: true });\r\n","IsDeferred":false},{"Name":"Optimized fastMerge","Code":"function fastMergeOptimized(target, source, options, metadata = { replaceNullPatches: [] }, basePath = []) {\r\n if (source === null || source === undefined || Array.isArray(source)) {\r\n return { result: source, replaceNullPatches: metadata.replaceNullPatches };\r\n }\r\n\r\n const optionsWithDefaults = {\r\n shouldRemoveNestedNulls: options?.shouldRemoveNestedNulls ?? false,\r\n objectRemovalMode: options?.objectRemovalMode ?? \u0027none\u0027,\r\n };\r\n\r\n const mergedValue = mergeObjectOptimized(target, source, optionsWithDefaults, metadata, basePath);\r\n return { result: mergedValue, replaceNullPatches: metadata.replaceNullPatches };\r\n}\r\n\r\nfunction mergeObjectOptimized(target, source, options, metadata, basePath) {\r\n const destination = Object.create(null);\r\n const targetObject = isMergeableObjectOptimized(target) ? target : undefined;\r\n const { shouldRemoveNestedNulls, objectRemovalMode } = options;\r\n\r\n if (targetObject) {\r\n const targetKeys = Object.keys(targetObject);\r\n for (let i = 0; i \u003C targetKeys.length; i\u002B\u002B) {\r\n const key = targetKeys[i];\r\n const targetProperty = targetObject[key];\r\n const sourceProperty = source[key];\r\n\r\n const shouldOmit = shouldRemoveNestedNulls \u0026\u0026 (targetProperty === null || sourceProperty === null);\r\n\r\n if (targetProperty !== undefined \u0026\u0026 !shouldOmit) {\r\n destination[key] = targetProperty;\r\n }\r\n }\r\n }\r\n\r\n const sourceKeys = Object.keys(source);\r\n for (let i = 0; i \u003C sourceKeys.length; i\u002B\u002B) {\r\n const key = sourceKeys[i];\r\n let targetProperty = targetObject?.[key];\r\n const sourceProperty = source[key];\r\n\r\n if (sourceProperty === undefined) continue;\r\n \r\n const shouldOmitNullish = shouldRemoveNestedNulls \u0026\u0026 sourceProperty === null;\r\n if (shouldOmitNullish) continue;\r\n\r\n if (!isMergeableObjectOptimized(sourceProperty)) {\r\n destination[key] = sourceProperty;\r\n continue;\r\n }\r\n\r\n if (objectRemovalMode === \u0027mark\u0027 \u0026\u0026 targetProperty === null) {\r\n targetProperty = { [ONYX_INTERNALS__REPLACE_OBJECT_MARK]: true };\r\n metadata.replaceNullPatches.push([basePath.concat(key), { ...sourceProperty }]);\r\n }\r\n\r\n if (objectRemovalMode === \u0027replace\u0027 \u0026\u0026 sourceProperty[ONYX_INTERNALS__REPLACE_OBJECT_MARK]) {\r\n const { [ONYX_INTERNALS__REPLACE_OBJECT_MARK]: _, ...cleanSource } = sourceProperty;\r\n destination[key] = cleanSource;\r\n continue;\r\n }\r\n\r\n const newPath = basePath.length === 0 ? [key] : basePath.concat(key);\r\n destination[key] = fastMergeOptimized(targetProperty, sourceProperty, options, metadata, newPath).result;\r\n }\r\n\r\n return destination;\r\n}\r\n\r\nconst objectCtorString = Object.prototype.constructor.toString();\r\nfunction isMergeableObjectOptimized(value) {\r\n if (value === null || typeof value !== \u0027object\u0027) return false;\r\n \r\n const proto = Object.getPrototypeOf(value);\r\n if (proto === null) return true;\r\n \r\n return proto.constructor \u0026\u0026 proto.constructor.toString() === objectCtorString;\r\n}\r\n\r\nconst data1 = generateDeepObject(5, 3);\r\nconst data2 = generateDeepObject(5, 3);\r\nconst arrayData1 = Array.from({length: 1000}, (_, i) =\u003E ({\r\n id: i,\r\n nested: generateDeepObject(3, 2),\r\n tags: Array.from({length: 10}, (_, j) =\u003E \u0060tag_${j}\u0060),\r\n metadata: {\r\n created: new Date(),\r\n updated: Math.random() \u003E 0.5 ? null : new Date(),\r\n author: Math.random() \u003E 0.3 ? \u0060user_${i}\u0060 : null\r\n }\r\n}));\r\n\r\nconst arrayData2 = Array.from({length: 1000}, (_, i) =\u003E ({\r\n id: i,\r\n nested: generateDeepObject(3, 2),\r\n tags: Array.from({length: 8}, (_, j) =\u003E \u0060new_tag_${j}\u0060),\r\n metadata: {\r\n created: new Date(),\r\n updated: new Date(),\r\n author: \u0060new_user_${i}\u0060,\r\n deleted: Math.random() \u003E 0.7 ? null : \u0060reason_${i}\u0060\r\n }\r\n}));\r\n\r\n// Test\r\nfastMergeOptimized(data1, data2, { shouldRemoveNestedNulls: true });\r\nfastMergeOptimized(arrayData1, arrayData2, { shouldRemoveNestedNulls: true });\r\n","IsDeferred":false},{"Name":"Mutative","Code":"\r\nfunction mutativeDeepMerge(base, updates) {\r\n return Mutative.create(base, draft =\u003E {\r\n function applyUpdates(target, source) {\r\n for (const key in source) {\r\n if (source.hasOwnProperty(key)) {\r\n const sourceVal = source[key];\r\n const targetVal = target[key];\r\n \r\n if (isMergeableObject(sourceVal) \u0026\u0026 isMergeableObject(targetVal)) {\r\n applyUpdates(targetVal, sourceVal);\r\n } else {\r\n target[key] = sourceVal;\r\n }\r\n }\r\n }\r\n }\r\n applyUpdates(draft, updates);\r\n });\r\n}\r\n\r\nfunction isMergeableObject(value) {\r\n const isNonNullObject = value != null ? typeof value === \u0027object\u0027 : false;\r\n return isNonNullObject \u0026\u0026 !(value instanceof RegExp) \u0026\u0026 !(value instanceof Date) \u0026\u0026 !Array.isArray(value);\r\n}\r\n\r\nconst data1 = generateDeepObject(5, 3);\r\nconst data2 = generateDeepObject(5, 3);\r\nconst arrayData1 = Array.from({length: 1000}, (_, i) =\u003E ({\r\n id: i,\r\n nested: generateDeepObject(3, 2),\r\n tags: Array.from({length: 10}, (_, j) =\u003E \u0060tag_${j}\u0060),\r\n metadata: {\r\n created: new Date(),\r\n updated: Math.random() \u003E 0.5 ? null : new Date(),\r\n author: Math.random() \u003E 0.3 ? \u0060user_${i}\u0060 : null\r\n }\r\n}));\r\n\r\nconst arrayData2 = Array.from({length: 1000}, (_, i) =\u003E ({\r\n id: i,\r\n nested: generateDeepObject(3, 2),\r\n tags: Array.from({length: 8}, (_, j) =\u003E \u0060new_tag_${j}\u0060),\r\n metadata: {\r\n created: new Date(),\r\n updated: new Date(),\r\n author: \u0060new_user_${i}\u0060,\r\n deleted: Math.random() \u003E 0.7 ? null : \u0060reason_${i}\u0060\r\n }\r\n}));\r\n\r\nmutativeDeepMerge(data1, data2);\r\nmutativeDeepMerge(arrayData1, arrayData2);\r\n","IsDeferred":false},{"Name":"Immutable-js","Code":"function immutableDeepMerge(base, updates) {\r\n const baseImmutable = Immutable.fromJS(base);\r\n const updatesImmutable = Immutable.fromJS(updates);\r\n const merged = Immutable.mergeDeep(baseImmutable, updatesImmutable);\r\n return merged.toJS();\r\n}\r\n\r\nconst data1 = generateDeepObject(5, 3);\r\nconst data2 = generateDeepObject(5, 3);\r\nconst arrayData1 = Array.from({length: 1000}, (_, i) =\u003E ({\r\n id: i,\r\n nested: generateDeepObject(3, 2),\r\n tags: Array.from({length: 10}, (_, j) =\u003E \u0060tag_${j}\u0060),\r\n metadata: {\r\n created: new Date(),\r\n updated: Math.random() \u003E 0.5 ? null : new Date(),\r\n author: Math.random() \u003E 0.3 ? \u0060user_${i}\u0060 : null\r\n }\r\n}));\r\n\r\nconst arrayData2 = Array.from({length: 1000}, (_, i) =\u003E ({\r\n id: i,\r\n nested: generateDeepObject(3, 2),\r\n tags: Array.from({length: 8}, (_, j) =\u003E \u0060new_tag_${j}\u0060),\r\n metadata: {\r\n created: new Date(),\r\n updated: new Date(),\r\n author: \u0060new_user_${i}\u0060,\r\n deleted: Math.random() \u003E 0.7 ? null : \u0060reason_${i}\u0060\r\n }\r\n}));\r\n\r\nimmutableDeepMerge(data1, data2);\r\nimmutableDeepMerge(arrayData1, arrayData2);\r\n","IsDeferred":false},{"Name":"ImmerJS","Code":"function immerDeepMerge(base, updates) {\r\n return immer.produce(base, draft =\u003E {\r\n function applyUpdates(target, source) {\r\n for (const key in source) {\r\n if (source.hasOwnProperty(key)) {\r\n const sourceVal = source[key];\r\n const targetVal = target[key];\r\n \r\n // If both are objects (not arrays, null, or special objects), merge recursively\r\n if (isMergeableObject(sourceVal) \u0026\u0026 isMergeableObject(targetVal)) {\r\n applyUpdates(targetVal, sourceVal);\r\n } else {\r\n // Otherwise replace the value\r\n target[key] = sourceVal;\r\n }\r\n }\r\n }\r\n }\r\n applyUpdates(draft, updates);\r\n });\r\n}\r\n\r\nfunction isMergeableObject(value) {\r\n const isNonNullObject = value != null ? typeof value === \u0027object\u0027 : false;\r\n return isNonNullObject \u0026\u0026 !(value instanceof RegExp) \u0026\u0026 !(value instanceof Date) \u0026\u0026 !Array.isArray(value);\r\n}\r\n\r\nconst data1 = generateDeepObject(5, 3);\r\nconst data2 = generateDeepObject(5, 3);\r\nconst arrayData1 = Array.from({length: 1000}, (_, i) =\u003E ({\r\n id: i,\r\n nested: generateDeepObject(3, 2),\r\n tags: Array.from({length: 10}, (_, j) =\u003E \u0060tag_${j}\u0060),\r\n metadata: {\r\n created: new Date(),\r\n updated: Math.random() \u003E 0.5 ? null : new Date(),\r\n author: Math.random() \u003E 0.3 ? \u0060user_${i}\u0060 : null\r\n }\r\n}));\r\n\r\nconst arrayData2 = Array.from({length: 1000}, (_, i) =\u003E ({\r\n id: i,\r\n nested: generateDeepObject(3, 2),\r\n tags: Array.from({length: 8}, (_, j) =\u003E \u0060new_tag_${j}\u0060),\r\n metadata: {\r\n created: new Date(),\r\n updated: new Date(),\r\n author: \u0060new_user_${i}\u0060,\r\n deleted: Math.random() \u003E 0.7 ? null : \u0060reason_${i}\u0060\r\n }\r\n}));\r\n\r\nimmerDeepMerge(data1, data2);\r\nimmerDeepMerge(arrayData1, arrayData2);","IsDeferred":false}]}