@formily/shared
Version:
> Formily 工具函数集
208 lines • 7.22 kB
JavaScript
import { isFn, isPlainObj } from './checkers';
import { isEmpty, isValid } from './isEmpty';
function defaultIsMergeableObject(value) {
return isNonNullObject(value) && !isSpecial(value);
}
function isNonNullObject(value) {
// TODO: value !== null && typeof value === 'object'
return Boolean(value) && typeof value === 'object';
}
function isSpecial(value) {
// TODO: use isComplexObject()
if ('$$typeof' in value && '_owner' in value) {
return true;
}
if (value._isAMomentObject) {
return true;
}
if (value._isJSONSchemaObject) {
return true;
}
if (isFn(value.toJS)) {
return true;
}
if (isFn(value.toJSON)) {
return true;
}
return !isPlainObj(value);
}
function emptyTarget(val) {
return Array.isArray(val) ? [] : {};
}
// @ts-ignore
function cloneUnlessOtherwiseSpecified(value, options) {
var _a;
if (options.clone !== false && ((_a = options.isMergeableObject) === null || _a === void 0 ? void 0 : _a.call(options, value))) {
return deepmerge(emptyTarget(value), value, options);
}
return value;
}
function defaultArrayMerge(target, source, options) {
return target.concat(source).map(function (element) {
return cloneUnlessOtherwiseSpecified(element, options);
});
}
function getMergeFunction(key, options) {
if (!options.customMerge) {
return deepmerge;
}
var customMerge = options.customMerge(key);
return typeof customMerge === 'function' ? customMerge : deepmerge;
}
function getEnumerableOwnPropertySymbols(target) {
return Object.getOwnPropertySymbols
? Object.getOwnPropertySymbols(target).filter(function (symbol) {
return target.propertyIsEnumerable(symbol);
})
: [];
}
function getKeys(target) {
if (!isValid(target))
return [];
return Object.keys(target).concat(getEnumerableOwnPropertySymbols(target));
}
function propertyIsOnObject(object, property) {
/* istanbul ignore next */
try {
return property in object;
}
catch (_) {
return false;
}
}
// Protects from prototype poisoning and unexpected merging up the prototype chain.
function propertyIsUnsafe(target, key) {
return (propertyIsOnObject(target, key) && // Properties are safe to merge if they don't exist in the target yet,
!(Object.hasOwnProperty.call(target, key) && // unsafe if they exist up the prototype chain,
Object.propertyIsEnumerable.call(target, key))); // and also unsafe if they're nonenumerable.
}
function mergeObject(target, source, options) {
var destination = options.assign ? target || {} : {};
if (!options.isMergeableObject(target))
return target;
if (!options.assign) {
getKeys(target).forEach(function (key) {
destination[key] = cloneUnlessOtherwiseSpecified(target[key], options);
});
}
getKeys(source).forEach(function (key) {
/* istanbul ignore next */
if (propertyIsUnsafe(target, key)) {
return;
}
if (isEmpty(target[key])) {
destination[key] = source[key];
}
else if (propertyIsOnObject(target, key) &&
// @ts-ignore
options.isMergeableObject(source[key])) {
destination[key] = getMergeFunction(key, options)(target[key], source[key], options);
}
else {
destination[key] = cloneUnlessOtherwiseSpecified(source[key], options);
}
});
return destination;
}
// @ts-ignore
function deepmerge(target, source, options) {
options = options || {};
options.arrayMerge = options.arrayMerge || defaultArrayMerge;
options.isMergeableObject =
options.isMergeableObject || defaultIsMergeableObject;
// cloneUnlessOtherwiseSpecified is added to `options` so that custom arrayMerge()
// implementations can use it. The caller may not replace it.
options.cloneUnlessOtherwiseSpecified = cloneUnlessOtherwiseSpecified;
var sourceIsArray = Array.isArray(source);
var targetIsArray = Array.isArray(target);
var sourceAndTargetTypesMatch = sourceIsArray === targetIsArray;
if (!sourceAndTargetTypesMatch) {
return cloneUnlessOtherwiseSpecified(source, options);
}
else if (sourceIsArray) {
return options.arrayMerge(target, source, options);
}
else {
return mergeObject(target, source, options);
}
}
export var lazyMerge = function (target) {
var args = [];
for (var _i = 1; _i < arguments.length; _i++) {
args[_i - 1] = arguments[_i];
}
var _lazyMerge = function (target, source) {
if (!isValid(source))
return target;
if (!isValid(target))
return source;
var isTargetObject = typeof target === 'object';
var isSourceObject = typeof source === 'object';
var isTargetFn = typeof target === 'function';
var isSourceFn = typeof source === 'function';
if (!isTargetObject && !isTargetFn)
return source;
if (!isSourceObject && !isSourceFn)
return target;
var getTarget = function () { return (isTargetFn ? target() : target); };
var getSource = function () { return (isSourceFn ? source() : source); };
var set = function (_, key, value) {
var source = getSource();
var target = getTarget();
if (key in source) {
// @ts-ignore
source[key] = value;
}
else if (key in target) {
// @ts-ignore
target[key] = value;
}
else {
source[key] = value;
}
return true;
};
var get = function (_, key) {
var source = getSource();
// @ts-ignore
if (key in source) {
return source[key];
}
// @ts-ignore
return getTarget()[key];
};
var ownKeys = function () {
var source = getSource();
var target = getTarget();
var keys = Object.keys(target);
for (var key in source) {
if (!(key in target)) {
keys.push(key);
}
}
return keys;
};
var getOwnPropertyDescriptor = function (_, key) { return ({
value: get(_, key),
enumerable: true,
configurable: true,
}); };
var has = function (_, key) {
if (key in getSource() || key in getTarget())
return true;
return false;
};
var getPrototypeOf = function () { return Object.getPrototypeOf({}); };
return new Proxy(Object.create(null), {
set: set,
get: get,
ownKeys: ownKeys,
getPrototypeOf: getPrototypeOf,
getOwnPropertyDescriptor: getOwnPropertyDescriptor,
has: has,
});
};
return args.reduce(function (buf, arg) { return _lazyMerge(buf, arg); }, target);
};
export var merge = deepmerge;
//# sourceMappingURL=merge.js.map