UNPKG

@rslike/cmp

Version:

JavaScript Comparison package without undefined behavior!

177 lines (175 loc) 5.03 kB
// src/symbols.ts var kCompare = Symbol.for("Symbol.compare"); var kEquals = Symbol.for("Symbol.equals"); var kPartialEquals = Symbol.for("Symbol.partialEquals"); // src/utils.ts import { UndefinedBehaviorError } from "@rslike/std"; function compare(a, b, compareFn) { if (typeof a[kCompare] === "function") { return a[kCompare](b); } if (typeof b[kCompare] === "function") { return b[kCompare](a); } if (compareFn) { if (typeof compareFn !== "function") { throw new UndefinedBehaviorError( `compareFn argument should be a function. Got "${typeof compareFn}"`, { cause: { value: compareFn, type: typeof compareFn } } ); } const res = compareFn(a, b); if (typeof res !== "number") { throw new UndefinedBehaviorError( `"compareFn" function should return number. Got "${typeof res}"`, { cause: { value: res, type: typeof res } } ); } } throw new UndefinedBehaviorError( 'At least 1 argument should implement "Symbol.compare" trait' ); } function partialEquals(a, b, equalityFn) { if (typeof a[kPartialEquals] === "function") { const res = Reflect.apply(a[kPartialEquals], a, [b]); if (typeof res === "boolean") { return res; } throw new UndefinedBehaviorError( `Cannot call partialCompare for imcoming first argument. "Symbol.partialEquals" trait should returns boolean result. Got "${typeof res}"`, { cause: { first: a, typeFirst: typeof a, ctorFirst: a?.constructor, result: res, typeResult: typeof res, second: b, typeSecond: typeof b, ctorSecond: b?.constructor } } ); } if (typeof b[kPartialEquals] === "function") { const res = Reflect.apply(b[kPartialEquals], b, [a]); if (typeof res === "boolean") { return res; } throw new UndefinedBehaviorError( `Cannot call partialCompare for imcoming second argument. "Symbol.partialEquals" trait should returns boolean result. Got "${typeof res}"`, { cause: { first: a, typeFirst: typeof a, ctorFirst: a?.constructor, result: res, typeResult: typeof res, second: b, typeSecond: typeof b, ctorSecond: b?.constructor } } ); } if (equalityFn) { if (typeof equalityFn === "function") { const res = equalityFn(a, b); if (typeof res === "boolean") { return res; } throw new UndefinedBehaviorError( `equalityFn should returns boolean. Got "${typeof res}"`, { cause: { value: res, type: typeof res } } ); } throw new UndefinedBehaviorError( `equalityFn argument should be a function. Got "${typeof equalityFn}"`, { cause: { value: equalityFn, type: typeof equalityFn } } ); } return a == b; } function equals(a, b, equalityFn) { if (typeof a === "object" && a !== null && kEquals in a && typeof a[kEquals] === "function") { const res = Reflect.apply(a[kEquals], a, [b]); if (typeof res === "boolean") { return res; } throw new UndefinedBehaviorError( `Cannot call equals for imcoming first argument. "Symbol.equals" trait should returns boolean result. Got "${typeof res}"`, { cause: { first: a, typeFirst: typeof a, ctorFirst: a?.constructor, result: res, typeResult: typeof res, second: b, typeSecond: typeof b, ctorSecond: b?.constructor } } ); } if (typeof b === "object" && b !== null && kEquals in b && typeof b[kEquals] === "function") { const res = Reflect.apply(b[kEquals], b, [a]); if (typeof res === "boolean") { return res; } throw new UndefinedBehaviorError( `Cannot call equals for imcoming second argument. "Symbol.equals" trait should returns boolean result. Got "${typeof res}"`, { cause: { first: a, typeFirst: typeof a, ctorFirst: a?.constructor, result: res, typeResult: typeof res, second: b, typeSecond: typeof b, ctorSecond: b?.constructor } } ); } if (equalityFn) { if (typeof equalityFn === "function") { const res = equalityFn(a, b); if (typeof res === "boolean") { return res; } throw new UndefinedBehaviorError( `equalityFn should returns boolean. Got "${typeof res}"`, { cause: { value: res, type: typeof res } } ); } throw new UndefinedBehaviorError( `equalityFn argument should be a function. Got "${typeof equalityFn}"`, { cause: { value: equalityFn, type: typeof equalityFn } } ); } return a === b; } export { compare, equals, kCompare, kEquals, kPartialEquals, partialEquals };