You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
89 lines
3.5 KiB
89 lines
3.5 KiB
import { __assign, __spreadArray } from "tslib"; |
|
import { isNonNullObject } from "./objects.js"; |
|
var hasOwnProperty = Object.prototype.hasOwnProperty; |
|
export function mergeDeep() { |
|
var sources = []; |
|
for (var _i = 0; _i < arguments.length; _i++) { |
|
sources[_i] = arguments[_i]; |
|
} |
|
return mergeDeepArray(sources); |
|
} |
|
// In almost any situation where you could succeed in getting the |
|
// TypeScript compiler to infer a tuple type for the sources array, you |
|
// could just use mergeDeep instead of mergeDeepArray, so instead of |
|
// trying to convert T[] to an intersection type we just infer the array |
|
// element type, which works perfectly when the sources array has a |
|
// consistent element type. |
|
export function mergeDeepArray(sources) { |
|
var target = sources[0] || {}; |
|
var count = sources.length; |
|
if (count > 1) { |
|
var merger = new DeepMerger(); |
|
for (var i = 1; i < count; ++i) { |
|
target = merger.merge(target, sources[i]); |
|
} |
|
} |
|
return target; |
|
} |
|
var defaultReconciler = function (target, source, property) { |
|
return this.merge(target[property], source[property]); |
|
}; |
|
var DeepMerger = /** @class */ (function () { |
|
function DeepMerger(reconciler) { |
|
if (reconciler === void 0) { reconciler = defaultReconciler; } |
|
this.reconciler = reconciler; |
|
this.isObject = isNonNullObject; |
|
this.pastCopies = new Set(); |
|
} |
|
DeepMerger.prototype.merge = function (target, source) { |
|
var _this = this; |
|
var context = []; |
|
for (var _i = 2; _i < arguments.length; _i++) { |
|
context[_i - 2] = arguments[_i]; |
|
} |
|
if (isNonNullObject(source) && isNonNullObject(target)) { |
|
Object.keys(source).forEach(function (sourceKey) { |
|
if (hasOwnProperty.call(target, sourceKey)) { |
|
var targetValue = target[sourceKey]; |
|
if (source[sourceKey] !== targetValue) { |
|
var result = _this.reconciler.apply(_this, __spreadArray([target, |
|
source, |
|
sourceKey], context, false)); |
|
// A well-implemented reconciler may return targetValue to indicate |
|
// the merge changed nothing about the structure of the target. |
|
if (result !== targetValue) { |
|
target = _this.shallowCopyForMerge(target); |
|
target[sourceKey] = result; |
|
} |
|
} |
|
} |
|
else { |
|
// If there is no collision, the target can safely share memory with |
|
// the source, and the recursion can terminate here. |
|
target = _this.shallowCopyForMerge(target); |
|
target[sourceKey] = source[sourceKey]; |
|
} |
|
}); |
|
return target; |
|
} |
|
// If source (or target) is not an object, let source replace target. |
|
return source; |
|
}; |
|
DeepMerger.prototype.shallowCopyForMerge = function (value) { |
|
if (isNonNullObject(value)) { |
|
if (!this.pastCopies.has(value)) { |
|
if (Array.isArray(value)) { |
|
value = value.slice(0); |
|
} |
|
else { |
|
value = __assign({ __proto__: Object.getPrototypeOf(value) }, value); |
|
} |
|
this.pastCopies.add(value); |
|
} |
|
} |
|
return value; |
|
}; |
|
return DeepMerger; |
|
}()); |
|
export { DeepMerger }; |
|
//# sourceMappingURL=mergeDeep.js.map
|