155 lines
4.6 KiB
JavaScript
155 lines
4.6 KiB
JavaScript
'use strict';
|
|
|
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
|
|
const isObject = require('./isObject.js');
|
|
const isPrimitive = require('../../predicate/isPrimitive.js');
|
|
const isEqualsSameValueZero = require('../../_internal/isEqualsSameValueZero.js');
|
|
|
|
function isMatchWith(target, source, compare) {
|
|
if (typeof compare !== 'function') {
|
|
return isMatchWith(target, source, () => undefined);
|
|
}
|
|
return isMatchWithInternal(target, source, function doesMatch(objValue, srcValue, key, object, source, stack) {
|
|
const isEqual = compare(objValue, srcValue, key, object, source, stack);
|
|
if (isEqual !== undefined) {
|
|
return Boolean(isEqual);
|
|
}
|
|
return isMatchWithInternal(objValue, srcValue, doesMatch, stack);
|
|
}, new Map());
|
|
}
|
|
function isMatchWithInternal(target, source, compare, stack) {
|
|
if (source === target) {
|
|
return true;
|
|
}
|
|
switch (typeof source) {
|
|
case 'object': {
|
|
return isObjectMatch(target, source, compare, stack);
|
|
}
|
|
case 'function': {
|
|
const sourceKeys = Object.keys(source);
|
|
if (sourceKeys.length > 0) {
|
|
return isMatchWithInternal(target, { ...source }, compare, stack);
|
|
}
|
|
return isEqualsSameValueZero.isEqualsSameValueZero(target, source);
|
|
}
|
|
default: {
|
|
if (!isObject.isObject(target)) {
|
|
return isEqualsSameValueZero.isEqualsSameValueZero(target, source);
|
|
}
|
|
if (typeof source === 'string') {
|
|
return source === '';
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
function isObjectMatch(target, source, compare, stack) {
|
|
if (source == null) {
|
|
return true;
|
|
}
|
|
if (Array.isArray(source)) {
|
|
return isArrayMatch(target, source, compare, stack);
|
|
}
|
|
if (source instanceof Map) {
|
|
return isMapMatch(target, source, compare, stack);
|
|
}
|
|
if (source instanceof Set) {
|
|
return isSetMatch(target, source, compare, stack);
|
|
}
|
|
const keys = Object.keys(source);
|
|
if (target == null || isPrimitive.isPrimitive(target)) {
|
|
return keys.length === 0;
|
|
}
|
|
if (keys.length === 0) {
|
|
return true;
|
|
}
|
|
if (stack?.has(source)) {
|
|
return stack.get(source) === target;
|
|
}
|
|
stack?.set(source, target);
|
|
try {
|
|
for (let i = 0; i < keys.length; i++) {
|
|
const key = keys[i];
|
|
if (!isPrimitive.isPrimitive(target) && !(key in target)) {
|
|
return false;
|
|
}
|
|
if (source[key] === undefined && target[key] !== undefined) {
|
|
return false;
|
|
}
|
|
if (source[key] === null && target[key] !== null) {
|
|
return false;
|
|
}
|
|
const isEqual = compare(target[key], source[key], key, target, source, stack);
|
|
if (!isEqual) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
finally {
|
|
stack?.delete(source);
|
|
}
|
|
}
|
|
function isMapMatch(target, source, compare, stack) {
|
|
if (source.size === 0) {
|
|
return true;
|
|
}
|
|
if (!(target instanceof Map)) {
|
|
return false;
|
|
}
|
|
for (const [key, sourceValue] of source.entries()) {
|
|
const targetValue = target.get(key);
|
|
const isEqual = compare(targetValue, sourceValue, key, target, source, stack);
|
|
if (isEqual === false) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
function isArrayMatch(target, source, compare, stack) {
|
|
if (source.length === 0) {
|
|
return true;
|
|
}
|
|
if (!Array.isArray(target)) {
|
|
return false;
|
|
}
|
|
const countedIndex = new Set();
|
|
for (let i = 0; i < source.length; i++) {
|
|
const sourceItem = source[i];
|
|
let found = false;
|
|
for (let j = 0; j < target.length; j++) {
|
|
if (countedIndex.has(j)) {
|
|
continue;
|
|
}
|
|
const targetItem = target[j];
|
|
let matches = false;
|
|
const isEqual = compare(targetItem, sourceItem, i, target, source, stack);
|
|
if (isEqual) {
|
|
matches = true;
|
|
}
|
|
if (matches) {
|
|
countedIndex.add(j);
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!found) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
function isSetMatch(target, source, compare, stack) {
|
|
if (source.size === 0) {
|
|
return true;
|
|
}
|
|
if (!(target instanceof Set)) {
|
|
return false;
|
|
}
|
|
return isArrayMatch([...target], [...source], compare, stack);
|
|
}
|
|
|
|
exports.isMatchWith = isMatchWith;
|
|
exports.isSetMatch = isSetMatch;
|