@oscarpalmer/atoms 0.168.0 → 0.169.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +61 -58
- package/dist/internal/is.d.mts +8 -2
- package/dist/internal/is.mjs +10 -1
- package/dist/internal/value/equal.mjs +9 -17
- package/dist/is.d.mts +1 -8
- package/dist/is.mjs +1 -10
- package/dist/sized/map.mjs +13 -7
- package/dist/sized/set.mjs +4 -4
- package/dist/value/clone.mjs +17 -14
- package/dist/value/diff.mjs +10 -9
- package/package.json +2 -2
- package/src/internal/is.ts +19 -1
- package/src/internal/value/equal.ts +21 -24
- package/src/is.ts +1 -11
- package/src/sized/map.ts +17 -11
- package/src/sized/set.ts +6 -5
- package/src/value/clone.ts +39 -23
- package/src/value/diff.ts +15 -16
package/dist/index.d.mts
CHANGED
|
@@ -2980,6 +2980,12 @@ declare function isNumber(value: unknown): value is number;
|
|
|
2980
2980
|
* @returns `true` if the value is a plain object, otherwise `false`
|
|
2981
2981
|
*/
|
|
2982
2982
|
declare function isPlainObject(value: unknown): value is PlainObject;
|
|
2983
|
+
/**
|
|
2984
|
+
* - Is the value a primitive value?
|
|
2985
|
+
* @param value Value to check
|
|
2986
|
+
* @returns `true` if the value matches, otherwise `false`
|
|
2987
|
+
*/
|
|
2988
|
+
declare function isPrimitive(value: unknown): value is Primitive;
|
|
2983
2989
|
/**
|
|
2984
2990
|
* Is the value a typed array?
|
|
2985
2991
|
* @param value Value to check
|
|
@@ -3030,12 +3036,6 @@ declare function isNumerical(value: unknown): value is number | `${number}`;
|
|
|
3030
3036
|
* @returns `true` if the value matches, otherwise `false`
|
|
3031
3037
|
*/
|
|
3032
3038
|
declare function isObject(value: unknown): value is object;
|
|
3033
|
-
/**
|
|
3034
|
-
* - Is the value a primitive value?
|
|
3035
|
-
* @param value Value to check
|
|
3036
|
-
* @returns `true` if the value matches, otherwise `false`
|
|
3037
|
-
*/
|
|
3038
|
-
declare function isPrimitive(value: unknown): value is Primitive;
|
|
3039
3039
|
//#endregion
|
|
3040
3040
|
//#region src/logger.d.ts
|
|
3041
3041
|
declare class Logger {
|
package/dist/index.mjs
CHANGED
|
@@ -215,6 +215,14 @@ function isPlainObject(value) {
|
|
|
215
215
|
return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
|
|
216
216
|
}
|
|
217
217
|
/**
|
|
218
|
+
* - Is the value a primitive value?
|
|
219
|
+
* @param value Value to check
|
|
220
|
+
* @returns `true` if the value matches, otherwise `false`
|
|
221
|
+
*/
|
|
222
|
+
function isPrimitive(value) {
|
|
223
|
+
return value == null || EXPRESSION_PRIMITIVE.test(typeof value);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
218
226
|
* Is the value a typed array?
|
|
219
227
|
* @param value Value to check
|
|
220
228
|
* @returns `true` if the value is a typed array, otherwise `false`
|
|
@@ -235,6 +243,7 @@ function isTypedArray(value) {
|
|
|
235
243
|
]);
|
|
236
244
|
return TYPED_ARRAYS.has(value?.constructor);
|
|
237
245
|
}
|
|
246
|
+
const EXPRESSION_PRIMITIVE = /^(bigint|boolean|number|string|symbol)$/;
|
|
238
247
|
let TYPED_ARRAYS;
|
|
239
248
|
//#endregion
|
|
240
249
|
//#region src/internal/random.ts
|
|
@@ -1255,7 +1264,7 @@ var SizedMap = class extends Map {
|
|
|
1255
1264
|
* Is the Map full?
|
|
1256
1265
|
*/
|
|
1257
1266
|
get full() {
|
|
1258
|
-
return
|
|
1267
|
+
return super.size >= this.#maximumSize;
|
|
1259
1268
|
}
|
|
1260
1269
|
get maximum() {
|
|
1261
1270
|
return this.#maximumSize;
|
|
@@ -1274,17 +1283,23 @@ var SizedMap = class extends Map {
|
|
|
1274
1283
|
* @inheritdoc
|
|
1275
1284
|
*/
|
|
1276
1285
|
get(key) {
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1286
|
+
if (super.has(key)) {
|
|
1287
|
+
const value = super.get(key);
|
|
1288
|
+
this.#setValue(key, value, true);
|
|
1289
|
+
return value;
|
|
1290
|
+
}
|
|
1280
1291
|
}
|
|
1281
1292
|
/**
|
|
1282
1293
|
* @inheritdoc
|
|
1283
1294
|
*/
|
|
1284
1295
|
set(key, value) {
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1296
|
+
return this.#setValue(key, value, super.has(key));
|
|
1297
|
+
}
|
|
1298
|
+
#setValue(key, value, has) {
|
|
1299
|
+
if (has) super.delete(key);
|
|
1300
|
+
else if (super.size >= this.#maximumSize) super.delete(super.keys().next().value);
|
|
1301
|
+
super.set(key, value);
|
|
1302
|
+
return this;
|
|
1288
1303
|
}
|
|
1289
1304
|
};
|
|
1290
1305
|
//#endregion
|
|
@@ -1685,15 +1700,8 @@ function equalArray(first, second, options) {
|
|
|
1685
1700
|
offset = offset > ARRAY_THRESHOLD ? ARRAY_THRESHOLD : offset;
|
|
1686
1701
|
for (let index = 0; index < offset; index += 1) if (!(equalValue(first[index], second[index], options) && equalValue(first[length - index - 1], second[length - index - 1], options))) return false;
|
|
1687
1702
|
}
|
|
1688
|
-
const
|
|
1689
|
-
|
|
1690
|
-
const chunksLength = firstChunks.length;
|
|
1691
|
-
for (let chunkIndex = 0; chunkIndex < chunksLength; chunkIndex += 1) {
|
|
1692
|
-
const firstChunk = firstChunks[chunkIndex];
|
|
1693
|
-
const secondChunk = secondChunks[chunkIndex];
|
|
1694
|
-
const chunkLength = firstChunk.length;
|
|
1695
|
-
for (let index = 0; index < chunkLength; index += 1) if (!equalValue(firstChunk[index], secondChunk[index], options)) return false;
|
|
1696
|
-
}
|
|
1703
|
+
const end = length - offset;
|
|
1704
|
+
for (let index = offset; index < end; index += 1) if (!equalValue(first[index], second[index], options)) return false;
|
|
1697
1705
|
return true;
|
|
1698
1706
|
}
|
|
1699
1707
|
function equalArrayBuffer(first, second, options) {
|
|
@@ -1706,11 +1714,9 @@ function equalMap(first, second, options) {
|
|
|
1706
1714
|
const { size } = first;
|
|
1707
1715
|
if (size !== second.size) return false;
|
|
1708
1716
|
const firstKeys = [...first.keys()];
|
|
1709
|
-
const secondKeys = [...second.keys()];
|
|
1710
|
-
if (firstKeys.some((key) => !secondKeys.includes(key))) return false;
|
|
1711
1717
|
for (let index = 0; index < size; index += 1) {
|
|
1712
1718
|
const key = firstKeys[index];
|
|
1713
|
-
if (!equalValue(first.get(key), second.get(key), options)) return false;
|
|
1719
|
+
if (!second.has(key) || !equalValue(first.get(key), second.get(key), options)) return false;
|
|
1714
1720
|
}
|
|
1715
1721
|
return true;
|
|
1716
1722
|
}
|
|
@@ -1721,11 +1727,12 @@ function equalPlainObject(first, second, options) {
|
|
|
1721
1727
|
firstKeys = firstKeys.filter((key) => filterKey(key, options));
|
|
1722
1728
|
secondKeys = secondKeys.filter((key) => filterKey(key, options));
|
|
1723
1729
|
}
|
|
1730
|
+
const secondSet = secondKeys.length >= MINIMUM_LENGTH_FOR_SET ? new Set(secondKeys) : void 0;
|
|
1724
1731
|
const { length } = firstKeys;
|
|
1725
|
-
if (length !== secondKeys.length
|
|
1732
|
+
if (length !== secondKeys.length) return false;
|
|
1726
1733
|
for (let index = 0; index < length; index += 1) {
|
|
1727
1734
|
const key = firstKeys[index];
|
|
1728
|
-
if (!equalValue(first[key], second[key], options)) return false;
|
|
1735
|
+
if (!(secondSet?.has(key) ?? secondKeys.includes(key)) || !equalValue(first[key], second[key], options)) return false;
|
|
1729
1736
|
}
|
|
1730
1737
|
return true;
|
|
1731
1738
|
}
|
|
@@ -1744,7 +1751,7 @@ function equalSet(first, second, options) {
|
|
|
1744
1751
|
const secondValues = [...second];
|
|
1745
1752
|
for (let index = 0; index < size; index += 1) {
|
|
1746
1753
|
const firstValue = firstValues[index];
|
|
1747
|
-
if (!secondValues.some((secondValue) => equalValue(firstValue, secondValue, options))) return false;
|
|
1754
|
+
if (isPrimitive(firstValue) ? !second.has(firstValue) : !secondValues.some((secondValue) => equalValue(firstValue, secondValue, options))) return false;
|
|
1748
1755
|
}
|
|
1749
1756
|
return true;
|
|
1750
1757
|
}
|
|
@@ -1838,6 +1845,7 @@ const ARRAY_PEEK_PERCENTAGE = 10;
|
|
|
1838
1845
|
const ARRAY_THRESHOLD = 100;
|
|
1839
1846
|
const ERROR_PROPERTIES = ["name", "message"];
|
|
1840
1847
|
const EXPRESSION_PROPERTIES = ["source", "flags"];
|
|
1848
|
+
const MINIMUM_LENGTH_FOR_SET = 16;
|
|
1841
1849
|
//#endregion
|
|
1842
1850
|
//#region src/internal/value/misc.ts
|
|
1843
1851
|
function findKey(needle, haystack) {
|
|
@@ -2242,18 +2250,12 @@ function cloneDataView(value, depth, references) {
|
|
|
2242
2250
|
references.set(value, cloned);
|
|
2243
2251
|
return cloned;
|
|
2244
2252
|
}
|
|
2245
|
-
function
|
|
2246
|
-
if (depth >= MAX_CLONE_DEPTH) return
|
|
2247
|
-
const
|
|
2248
|
-
const
|
|
2249
|
-
const entries
|
|
2250
|
-
|
|
2251
|
-
for (let index = 0; index < length; index += 1) {
|
|
2252
|
-
const entry = entries[index];
|
|
2253
|
-
if (isMap) cloned.set(cloneValue(entry[0], depth + 1, references), cloneValue(entry[1], depth + 1, references));
|
|
2254
|
-
else cloned.add(cloneValue(entry[0], depth + 1, references));
|
|
2255
|
-
}
|
|
2256
|
-
references.set(value, cloned);
|
|
2253
|
+
function cloneMap(map, depth, references) {
|
|
2254
|
+
if (depth >= MAX_CLONE_DEPTH) return map;
|
|
2255
|
+
const cloned = /* @__PURE__ */ new Map();
|
|
2256
|
+
const entries = map.entries();
|
|
2257
|
+
for (const entry of entries) cloned.set(cloneValue(entry[0], depth + 1, references), cloneValue(entry[1], depth + 1, references));
|
|
2258
|
+
references.set(map, cloned);
|
|
2257
2259
|
return cloned;
|
|
2258
2260
|
}
|
|
2259
2261
|
function cloneNode(node, depth, references) {
|
|
@@ -2281,6 +2283,15 @@ function cloneRegularExpression(value, depth, references) {
|
|
|
2281
2283
|
references.set(value, cloned);
|
|
2282
2284
|
return cloned;
|
|
2283
2285
|
}
|
|
2286
|
+
function cloneSet(set, depth, references) {
|
|
2287
|
+
if (depth >= MAX_CLONE_DEPTH) return set;
|
|
2288
|
+
const cloned = /* @__PURE__ */ new Set();
|
|
2289
|
+
const values = [...set.values()];
|
|
2290
|
+
const { length } = values;
|
|
2291
|
+
for (let index = 0; index < length; index += 1) cloned.add(cloneValue(values[index], depth + 1, references));
|
|
2292
|
+
references.set(set, cloned);
|
|
2293
|
+
return cloned;
|
|
2294
|
+
}
|
|
2284
2295
|
function cloneTypedArray(value, depth, references) {
|
|
2285
2296
|
if (depth >= MAX_CLONE_DEPTH) return value;
|
|
2286
2297
|
const cloned = new value.constructor(value);
|
|
@@ -2301,9 +2312,9 @@ function cloneValue(value, depth, references) {
|
|
|
2301
2312
|
case value instanceof DataView: return cloneDataView(value, depth, references);
|
|
2302
2313
|
case value instanceof Date: return new Date(value.getTime());
|
|
2303
2314
|
case value instanceof RegExp: return cloneRegularExpression(value, depth, references);
|
|
2304
|
-
case value instanceof Map:
|
|
2305
|
-
case value instanceof Set: return cloneMapOrSet(value, depth, references);
|
|
2315
|
+
case value instanceof Map: return cloneMap(value, depth, references);
|
|
2306
2316
|
case value instanceof Node: return cloneNode(value, depth, references);
|
|
2317
|
+
case value instanceof Set: return cloneSet(value, depth, references);
|
|
2307
2318
|
case isArrayOrPlainObject(value): return clonePlainObject(value, depth, references);
|
|
2308
2319
|
case isTypedArray(value): return cloneTypedArray(value, depth, references);
|
|
2309
2320
|
default: return clone.handlers.handle(value, depth, references);
|
|
@@ -2351,7 +2362,7 @@ function diff(first, second, options) {
|
|
|
2351
2362
|
diffResult.type = DIFF_FULL;
|
|
2352
2363
|
return diffResult;
|
|
2353
2364
|
}
|
|
2354
|
-
const diffs = getDiffs(first, second, relaxedNullish);
|
|
2365
|
+
const diffs = getDiffs(first, second, { relaxedNullish });
|
|
2355
2366
|
const { length } = diffs;
|
|
2356
2367
|
if (length === 0) diffResult.type = DIFF_NONE;
|
|
2357
2368
|
for (let index = 0; index < length; index += 1) {
|
|
@@ -2363,7 +2374,7 @@ function diff(first, second, options) {
|
|
|
2363
2374
|
}
|
|
2364
2375
|
return diffResult;
|
|
2365
2376
|
}
|
|
2366
|
-
function getChanges(changes, first, second,
|
|
2377
|
+
function getChanges(changes, first, second, options, prefix) {
|
|
2367
2378
|
const checked = /* @__PURE__ */ new Set();
|
|
2368
2379
|
for (let outerIndex = 0; outerIndex < 2; outerIndex += 1) {
|
|
2369
2380
|
const value = (outerIndex === 0 ? first : second) ?? {};
|
|
@@ -2376,7 +2387,7 @@ function getChanges(changes, first, second, relaxedNullish, prefix) {
|
|
|
2376
2387
|
setChanges({
|
|
2377
2388
|
changes,
|
|
2378
2389
|
key,
|
|
2379
|
-
|
|
2390
|
+
options,
|
|
2380
2391
|
prefix,
|
|
2381
2392
|
values: {
|
|
2382
2393
|
first,
|
|
@@ -2387,7 +2398,7 @@ function getChanges(changes, first, second, relaxedNullish, prefix) {
|
|
|
2387
2398
|
}
|
|
2388
2399
|
return changes;
|
|
2389
2400
|
}
|
|
2390
|
-
function getDiffs(first, second,
|
|
2401
|
+
function getDiffs(first, second, options, prefix) {
|
|
2391
2402
|
const changes = [];
|
|
2392
2403
|
if (Array.isArray(first) && Array.isArray(second)) {
|
|
2393
2404
|
const maximumLength = Math.max(first.length, second.length);
|
|
@@ -2401,20 +2412,21 @@ function getDiffs(first, second, relaxedNullish, prefix) {
|
|
|
2401
2412
|
});
|
|
2402
2413
|
}
|
|
2403
2414
|
}
|
|
2404
|
-
return getChanges(changes, first, second,
|
|
2415
|
+
return getChanges(changes, first, second, options, prefix);
|
|
2405
2416
|
}
|
|
2406
2417
|
function setChanges(parameters) {
|
|
2407
|
-
const { changes, key, prefix,
|
|
2418
|
+
const { changes, key, prefix, options, values } = parameters;
|
|
2419
|
+
const prefixed = join([prefix, key], ".");
|
|
2408
2420
|
const from = values.first?.[key];
|
|
2409
2421
|
const to = values.second?.[key];
|
|
2410
|
-
|
|
2411
|
-
const
|
|
2422
|
+
const nested = isArrayOrPlainObject(from) || isArrayOrPlainObject(to);
|
|
2423
|
+
const diffs = nested ? getDiffs(from, to, options, prefixed) : [];
|
|
2424
|
+
if (nested ? diffs.length === 0 : equal(from, to, options)) return;
|
|
2412
2425
|
const change = {
|
|
2413
2426
|
from,
|
|
2414
2427
|
to,
|
|
2415
2428
|
key: prefixed
|
|
2416
2429
|
};
|
|
2417
|
-
const diffs = isArrayOrPlainObject(from) || isArrayOrPlainObject(to) ? getDiffs(from, to, relaxedNullish, prefixed) : [];
|
|
2418
2430
|
changes.push(change);
|
|
2419
2431
|
const diffsLength = diffs.length;
|
|
2420
2432
|
for (let diffIndex = 0; diffIndex < diffsLength; diffIndex += 1) changes.push(diffs[diffIndex]);
|
|
@@ -3484,15 +3496,6 @@ function isNumerical(value) {
|
|
|
3484
3496
|
function isObject(value) {
|
|
3485
3497
|
return typeof value === "object" && value !== null || typeof value === "function";
|
|
3486
3498
|
}
|
|
3487
|
-
/**
|
|
3488
|
-
* - Is the value a primitive value?
|
|
3489
|
-
* @param value Value to check
|
|
3490
|
-
* @returns `true` if the value matches, otherwise `false`
|
|
3491
|
-
*/
|
|
3492
|
-
function isPrimitive(value) {
|
|
3493
|
-
return value == null || EXPRESSION_PRIMITIVE.test(typeof value);
|
|
3494
|
-
}
|
|
3495
|
-
const EXPRESSION_PRIMITIVE = /^(bigint|boolean|number|string|symbol)$/;
|
|
3496
3499
|
const EXPRESSION_WHITESPACE = /^\s*$/;
|
|
3497
3500
|
//#endregion
|
|
3498
3501
|
//#region src/logger.ts
|
|
@@ -4427,8 +4430,8 @@ var SizedSet = class extends Set {
|
|
|
4427
4430
|
* @inheritdoc
|
|
4428
4431
|
*/
|
|
4429
4432
|
add(value) {
|
|
4430
|
-
if (
|
|
4431
|
-
else if (this.size >= this.#maximumSize)
|
|
4433
|
+
if (super.has(value)) super.delete(value);
|
|
4434
|
+
else if (this.size >= this.#maximumSize) super.delete(this.values().next().value);
|
|
4432
4435
|
return super.add(value);
|
|
4433
4436
|
}
|
|
4434
4437
|
/**
|
|
@@ -4438,9 +4441,9 @@ var SizedSet = class extends Set {
|
|
|
4438
4441
|
* @returns Found value if it exists, otherwise `undefined`
|
|
4439
4442
|
*/
|
|
4440
4443
|
get(value, update) {
|
|
4441
|
-
if (
|
|
4444
|
+
if (super.has(value)) {
|
|
4442
4445
|
if (update ?? false) {
|
|
4443
|
-
|
|
4446
|
+
super.delete(value);
|
|
4444
4447
|
this.add(value);
|
|
4445
4448
|
}
|
|
4446
4449
|
return value;
|
package/dist/internal/is.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ArrayOrPlainObject, Constructor, Key, PlainObject, TypedArray } from "../models.mjs";
|
|
1
|
+
import { ArrayOrPlainObject, Constructor, Key, PlainObject, Primitive, TypedArray } from "../models.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/internal/is.d.ts
|
|
4
4
|
/**
|
|
@@ -38,6 +38,12 @@ declare function isNumber(value: unknown): value is number;
|
|
|
38
38
|
* @returns `true` if the value is a plain object, otherwise `false`
|
|
39
39
|
*/
|
|
40
40
|
declare function isPlainObject(value: unknown): value is PlainObject;
|
|
41
|
+
/**
|
|
42
|
+
* - Is the value a primitive value?
|
|
43
|
+
* @param value Value to check
|
|
44
|
+
* @returns `true` if the value matches, otherwise `false`
|
|
45
|
+
*/
|
|
46
|
+
declare function isPrimitive(value: unknown): value is Primitive;
|
|
41
47
|
/**
|
|
42
48
|
* Is the value a typed array?
|
|
43
49
|
* @param value Value to check
|
|
@@ -45,4 +51,4 @@ declare function isPlainObject(value: unknown): value is PlainObject;
|
|
|
45
51
|
*/
|
|
46
52
|
declare function isTypedArray(value: unknown): value is TypedArray;
|
|
47
53
|
//#endregion
|
|
48
|
-
export { isArrayOrPlainObject, isConstructor, isInstanceOf, isKey, isNumber, isPlainObject, isTypedArray };
|
|
54
|
+
export { isArrayOrPlainObject, isConstructor, isInstanceOf, isKey, isNumber, isPlainObject, isPrimitive, isTypedArray };
|
package/dist/internal/is.mjs
CHANGED
|
@@ -52,6 +52,14 @@ function isPlainObject(value) {
|
|
|
52
52
|
return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
|
|
53
53
|
}
|
|
54
54
|
/**
|
|
55
|
+
* - Is the value a primitive value?
|
|
56
|
+
* @param value Value to check
|
|
57
|
+
* @returns `true` if the value matches, otherwise `false`
|
|
58
|
+
*/
|
|
59
|
+
function isPrimitive(value) {
|
|
60
|
+
return value == null || EXPRESSION_PRIMITIVE.test(typeof value);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
55
63
|
* Is the value a typed array?
|
|
56
64
|
* @param value Value to check
|
|
57
65
|
* @returns `true` if the value is a typed array, otherwise `false`
|
|
@@ -72,6 +80,7 @@ function isTypedArray(value) {
|
|
|
72
80
|
]);
|
|
73
81
|
return TYPED_ARRAYS.has(value?.constructor);
|
|
74
82
|
}
|
|
83
|
+
const EXPRESSION_PRIMITIVE = /^(bigint|boolean|number|string|symbol)$/;
|
|
75
84
|
let TYPED_ARRAYS;
|
|
76
85
|
//#endregion
|
|
77
|
-
export { isArrayOrPlainObject, isConstructor, isInstanceOf, isKey, isNumber, isPlainObject, isTypedArray };
|
|
86
|
+
export { isArrayOrPlainObject, isConstructor, isInstanceOf, isKey, isNumber, isPlainObject, isPrimitive, isTypedArray };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { isPlainObject, isTypedArray } from "../is.mjs";
|
|
2
|
-
import { chunk } from "../array/chunk.mjs";
|
|
1
|
+
import { isPlainObject, isPrimitive, isTypedArray } from "../is.mjs";
|
|
3
2
|
import { getCompareHandlers } from "./handlers.mjs";
|
|
4
3
|
//#region src/internal/value/equal.ts
|
|
5
4
|
function equal(first, second, options) {
|
|
@@ -18,15 +17,8 @@ function equalArray(first, second, options) {
|
|
|
18
17
|
offset = offset > ARRAY_THRESHOLD ? ARRAY_THRESHOLD : offset;
|
|
19
18
|
for (let index = 0; index < offset; index += 1) if (!(equalValue(first[index], second[index], options) && equalValue(first[length - index - 1], second[length - index - 1], options))) return false;
|
|
20
19
|
}
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
const chunksLength = firstChunks.length;
|
|
24
|
-
for (let chunkIndex = 0; chunkIndex < chunksLength; chunkIndex += 1) {
|
|
25
|
-
const firstChunk = firstChunks[chunkIndex];
|
|
26
|
-
const secondChunk = secondChunks[chunkIndex];
|
|
27
|
-
const chunkLength = firstChunk.length;
|
|
28
|
-
for (let index = 0; index < chunkLength; index += 1) if (!equalValue(firstChunk[index], secondChunk[index], options)) return false;
|
|
29
|
-
}
|
|
20
|
+
const end = length - offset;
|
|
21
|
+
for (let index = offset; index < end; index += 1) if (!equalValue(first[index], second[index], options)) return false;
|
|
30
22
|
return true;
|
|
31
23
|
}
|
|
32
24
|
function equalArrayBuffer(first, second, options) {
|
|
@@ -39,11 +31,9 @@ function equalMap(first, second, options) {
|
|
|
39
31
|
const { size } = first;
|
|
40
32
|
if (size !== second.size) return false;
|
|
41
33
|
const firstKeys = [...first.keys()];
|
|
42
|
-
const secondKeys = [...second.keys()];
|
|
43
|
-
if (firstKeys.some((key) => !secondKeys.includes(key))) return false;
|
|
44
34
|
for (let index = 0; index < size; index += 1) {
|
|
45
35
|
const key = firstKeys[index];
|
|
46
|
-
if (!equalValue(first.get(key), second.get(key), options)) return false;
|
|
36
|
+
if (!second.has(key) || !equalValue(first.get(key), second.get(key), options)) return false;
|
|
47
37
|
}
|
|
48
38
|
return true;
|
|
49
39
|
}
|
|
@@ -54,11 +44,12 @@ function equalPlainObject(first, second, options) {
|
|
|
54
44
|
firstKeys = firstKeys.filter((key) => filterKey(key, options));
|
|
55
45
|
secondKeys = secondKeys.filter((key) => filterKey(key, options));
|
|
56
46
|
}
|
|
47
|
+
const secondSet = secondKeys.length >= MINIMUM_LENGTH_FOR_SET ? new Set(secondKeys) : void 0;
|
|
57
48
|
const { length } = firstKeys;
|
|
58
|
-
if (length !== secondKeys.length
|
|
49
|
+
if (length !== secondKeys.length) return false;
|
|
59
50
|
for (let index = 0; index < length; index += 1) {
|
|
60
51
|
const key = firstKeys[index];
|
|
61
|
-
if (!equalValue(first[key], second[key], options)) return false;
|
|
52
|
+
if (!(secondSet?.has(key) ?? secondKeys.includes(key)) || !equalValue(first[key], second[key], options)) return false;
|
|
62
53
|
}
|
|
63
54
|
return true;
|
|
64
55
|
}
|
|
@@ -77,7 +68,7 @@ function equalSet(first, second, options) {
|
|
|
77
68
|
const secondValues = [...second];
|
|
78
69
|
for (let index = 0; index < size; index += 1) {
|
|
79
70
|
const firstValue = firstValues[index];
|
|
80
|
-
if (!secondValues.some((secondValue) => equalValue(firstValue, secondValue, options))) return false;
|
|
71
|
+
if (isPrimitive(firstValue) ? !second.has(firstValue) : !secondValues.some((secondValue) => equalValue(firstValue, secondValue, options))) return false;
|
|
81
72
|
}
|
|
82
73
|
return true;
|
|
83
74
|
}
|
|
@@ -171,5 +162,6 @@ const ARRAY_PEEK_PERCENTAGE = 10;
|
|
|
171
162
|
const ARRAY_THRESHOLD = 100;
|
|
172
163
|
const ERROR_PROPERTIES = ["name", "message"];
|
|
173
164
|
const EXPRESSION_PROPERTIES = ["source", "flags"];
|
|
165
|
+
const MINIMUM_LENGTH_FOR_SET = 16;
|
|
174
166
|
//#endregion
|
|
175
167
|
export { equal };
|
package/dist/is.d.mts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { isArrayOrPlainObject, isConstructor, isInstanceOf, isKey, isNumber, isPlainObject, isTypedArray } from "./internal/is.mjs";
|
|
1
|
+
import { isArrayOrPlainObject, isConstructor, isInstanceOf, isKey, isNumber, isPlainObject, isPrimitive, isTypedArray } from "./internal/is.mjs";
|
|
3
2
|
|
|
4
3
|
//#region src/is.d.ts
|
|
5
4
|
/**
|
|
@@ -44,11 +43,5 @@ declare function isNumerical(value: unknown): value is number | `${number}`;
|
|
|
44
43
|
* @returns `true` if the value matches, otherwise `false`
|
|
45
44
|
*/
|
|
46
45
|
declare function isObject(value: unknown): value is object;
|
|
47
|
-
/**
|
|
48
|
-
* - Is the value a primitive value?
|
|
49
|
-
* @param value Value to check
|
|
50
|
-
* @returns `true` if the value matches, otherwise `false`
|
|
51
|
-
*/
|
|
52
|
-
declare function isPrimitive(value: unknown): value is Primitive;
|
|
53
46
|
//#endregion
|
|
54
47
|
export { isArrayOrPlainObject, isConstructor, isEmpty, isInstanceOf, isKey, isNonNullable, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isPlainObject, isPrimitive, isTypedArray };
|
package/dist/is.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isArrayOrPlainObject, isConstructor, isInstanceOf, isKey, isNumber, isPlainObject, isTypedArray } from "./internal/is.mjs";
|
|
1
|
+
import { isArrayOrPlainObject, isConstructor, isInstanceOf, isKey, isNumber, isPlainObject, isPrimitive, isTypedArray } from "./internal/is.mjs";
|
|
2
2
|
import { getArray } from "./array/get.mjs";
|
|
3
3
|
import { getString } from "./internal/string.mjs";
|
|
4
4
|
//#region src/is.ts
|
|
@@ -63,15 +63,6 @@ function isNumerical(value) {
|
|
|
63
63
|
function isObject(value) {
|
|
64
64
|
return typeof value === "object" && value !== null || typeof value === "function";
|
|
65
65
|
}
|
|
66
|
-
/**
|
|
67
|
-
* - Is the value a primitive value?
|
|
68
|
-
* @param value Value to check
|
|
69
|
-
* @returns `true` if the value matches, otherwise `false`
|
|
70
|
-
*/
|
|
71
|
-
function isPrimitive(value) {
|
|
72
|
-
return value == null || EXPRESSION_PRIMITIVE.test(typeof value);
|
|
73
|
-
}
|
|
74
|
-
const EXPRESSION_PRIMITIVE = /^(bigint|boolean|number|string|symbol)$/;
|
|
75
66
|
const EXPRESSION_WHITESPACE = /^\s*$/;
|
|
76
67
|
//#endregion
|
|
77
68
|
export { isArrayOrPlainObject, isConstructor, isEmpty, isInstanceOf, isKey, isNonNullable, isNullable, isNullableOrEmpty, isNullableOrWhitespace, isNumber, isNumerical, isObject, isPlainObject, isPrimitive, isTypedArray };
|
package/dist/sized/map.mjs
CHANGED
|
@@ -14,7 +14,7 @@ var SizedMap = class extends Map {
|
|
|
14
14
|
* Is the Map full?
|
|
15
15
|
*/
|
|
16
16
|
get full() {
|
|
17
|
-
return
|
|
17
|
+
return super.size >= this.#maximumSize;
|
|
18
18
|
}
|
|
19
19
|
get maximum() {
|
|
20
20
|
return this.#maximumSize;
|
|
@@ -33,17 +33,23 @@ var SizedMap = class extends Map {
|
|
|
33
33
|
* @inheritdoc
|
|
34
34
|
*/
|
|
35
35
|
get(key) {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
if (super.has(key)) {
|
|
37
|
+
const value = super.get(key);
|
|
38
|
+
this.#setValue(key, value, true);
|
|
39
|
+
return value;
|
|
40
|
+
}
|
|
39
41
|
}
|
|
40
42
|
/**
|
|
41
43
|
* @inheritdoc
|
|
42
44
|
*/
|
|
43
45
|
set(key, value) {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
return this.#setValue(key, value, super.has(key));
|
|
47
|
+
}
|
|
48
|
+
#setValue(key, value, has) {
|
|
49
|
+
if (has) super.delete(key);
|
|
50
|
+
else if (super.size >= this.#maximumSize) super.delete(super.keys().next().value);
|
|
51
|
+
super.set(key, value);
|
|
52
|
+
return this;
|
|
47
53
|
}
|
|
48
54
|
};
|
|
49
55
|
//#endregion
|
package/dist/sized/set.mjs
CHANGED
|
@@ -32,8 +32,8 @@ var SizedSet = class extends Set {
|
|
|
32
32
|
* @inheritdoc
|
|
33
33
|
*/
|
|
34
34
|
add(value) {
|
|
35
|
-
if (
|
|
36
|
-
else if (this.size >= this.#maximumSize)
|
|
35
|
+
if (super.has(value)) super.delete(value);
|
|
36
|
+
else if (this.size >= this.#maximumSize) super.delete(this.values().next().value);
|
|
37
37
|
return super.add(value);
|
|
38
38
|
}
|
|
39
39
|
/**
|
|
@@ -43,9 +43,9 @@ var SizedSet = class extends Set {
|
|
|
43
43
|
* @returns Found value if it exists, otherwise `undefined`
|
|
44
44
|
*/
|
|
45
45
|
get(value, update) {
|
|
46
|
-
if (
|
|
46
|
+
if (super.has(value)) {
|
|
47
47
|
if (update ?? false) {
|
|
48
|
-
|
|
48
|
+
super.delete(value);
|
|
49
49
|
this.add(value);
|
|
50
50
|
}
|
|
51
51
|
return value;
|
package/dist/value/clone.mjs
CHANGED
|
@@ -40,18 +40,12 @@ function cloneDataView(value, depth, references) {
|
|
|
40
40
|
references.set(value, cloned);
|
|
41
41
|
return cloned;
|
|
42
42
|
}
|
|
43
|
-
function
|
|
44
|
-
if (depth >= MAX_CLONE_DEPTH) return
|
|
45
|
-
const
|
|
46
|
-
const
|
|
47
|
-
const entries
|
|
48
|
-
|
|
49
|
-
for (let index = 0; index < length; index += 1) {
|
|
50
|
-
const entry = entries[index];
|
|
51
|
-
if (isMap) cloned.set(cloneValue(entry[0], depth + 1, references), cloneValue(entry[1], depth + 1, references));
|
|
52
|
-
else cloned.add(cloneValue(entry[0], depth + 1, references));
|
|
53
|
-
}
|
|
54
|
-
references.set(value, cloned);
|
|
43
|
+
function cloneMap(map, depth, references) {
|
|
44
|
+
if (depth >= MAX_CLONE_DEPTH) return map;
|
|
45
|
+
const cloned = /* @__PURE__ */ new Map();
|
|
46
|
+
const entries = map.entries();
|
|
47
|
+
for (const entry of entries) cloned.set(cloneValue(entry[0], depth + 1, references), cloneValue(entry[1], depth + 1, references));
|
|
48
|
+
references.set(map, cloned);
|
|
55
49
|
return cloned;
|
|
56
50
|
}
|
|
57
51
|
function cloneNode(node, depth, references) {
|
|
@@ -79,6 +73,15 @@ function cloneRegularExpression(value, depth, references) {
|
|
|
79
73
|
references.set(value, cloned);
|
|
80
74
|
return cloned;
|
|
81
75
|
}
|
|
76
|
+
function cloneSet(set, depth, references) {
|
|
77
|
+
if (depth >= MAX_CLONE_DEPTH) return set;
|
|
78
|
+
const cloned = /* @__PURE__ */ new Set();
|
|
79
|
+
const values = [...set.values()];
|
|
80
|
+
const { length } = values;
|
|
81
|
+
for (let index = 0; index < length; index += 1) cloned.add(cloneValue(values[index], depth + 1, references));
|
|
82
|
+
references.set(set, cloned);
|
|
83
|
+
return cloned;
|
|
84
|
+
}
|
|
82
85
|
function cloneTypedArray(value, depth, references) {
|
|
83
86
|
if (depth >= MAX_CLONE_DEPTH) return value;
|
|
84
87
|
const cloned = new value.constructor(value);
|
|
@@ -99,9 +102,9 @@ function cloneValue(value, depth, references) {
|
|
|
99
102
|
case value instanceof DataView: return cloneDataView(value, depth, references);
|
|
100
103
|
case value instanceof Date: return new Date(value.getTime());
|
|
101
104
|
case value instanceof RegExp: return cloneRegularExpression(value, depth, references);
|
|
102
|
-
case value instanceof Map:
|
|
103
|
-
case value instanceof Set: return cloneMapOrSet(value, depth, references);
|
|
105
|
+
case value instanceof Map: return cloneMap(value, depth, references);
|
|
104
106
|
case value instanceof Node: return cloneNode(value, depth, references);
|
|
107
|
+
case value instanceof Set: return cloneSet(value, depth, references);
|
|
105
108
|
case isArrayOrPlainObject(value): return clonePlainObject(value, depth, references);
|
|
106
109
|
case isTypedArray(value): return cloneTypedArray(value, depth, references);
|
|
107
110
|
default: return clone.handlers.handle(value, depth, references);
|
package/dist/value/diff.mjs
CHANGED
|
@@ -30,7 +30,7 @@ function diff(first, second, options) {
|
|
|
30
30
|
diffResult.type = DIFF_FULL;
|
|
31
31
|
return diffResult;
|
|
32
32
|
}
|
|
33
|
-
const diffs = getDiffs(first, second, relaxedNullish);
|
|
33
|
+
const diffs = getDiffs(first, second, { relaxedNullish });
|
|
34
34
|
const { length } = diffs;
|
|
35
35
|
if (length === 0) diffResult.type = DIFF_NONE;
|
|
36
36
|
for (let index = 0; index < length; index += 1) {
|
|
@@ -42,7 +42,7 @@ function diff(first, second, options) {
|
|
|
42
42
|
}
|
|
43
43
|
return diffResult;
|
|
44
44
|
}
|
|
45
|
-
function getChanges(changes, first, second,
|
|
45
|
+
function getChanges(changes, first, second, options, prefix) {
|
|
46
46
|
const checked = /* @__PURE__ */ new Set();
|
|
47
47
|
for (let outerIndex = 0; outerIndex < 2; outerIndex += 1) {
|
|
48
48
|
const value = (outerIndex === 0 ? first : second) ?? {};
|
|
@@ -55,7 +55,7 @@ function getChanges(changes, first, second, relaxedNullish, prefix) {
|
|
|
55
55
|
setChanges({
|
|
56
56
|
changes,
|
|
57
57
|
key,
|
|
58
|
-
|
|
58
|
+
options,
|
|
59
59
|
prefix,
|
|
60
60
|
values: {
|
|
61
61
|
first,
|
|
@@ -66,7 +66,7 @@ function getChanges(changes, first, second, relaxedNullish, prefix) {
|
|
|
66
66
|
}
|
|
67
67
|
return changes;
|
|
68
68
|
}
|
|
69
|
-
function getDiffs(first, second,
|
|
69
|
+
function getDiffs(first, second, options, prefix) {
|
|
70
70
|
const changes = [];
|
|
71
71
|
if (Array.isArray(first) && Array.isArray(second)) {
|
|
72
72
|
const maximumLength = Math.max(first.length, second.length);
|
|
@@ -80,20 +80,21 @@ function getDiffs(first, second, relaxedNullish, prefix) {
|
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
82
|
}
|
|
83
|
-
return getChanges(changes, first, second,
|
|
83
|
+
return getChanges(changes, first, second, options, prefix);
|
|
84
84
|
}
|
|
85
85
|
function setChanges(parameters) {
|
|
86
|
-
const { changes, key, prefix,
|
|
86
|
+
const { changes, key, prefix, options, values } = parameters;
|
|
87
|
+
const prefixed = join([prefix, key], ".");
|
|
87
88
|
const from = values.first?.[key];
|
|
88
89
|
const to = values.second?.[key];
|
|
89
|
-
|
|
90
|
-
const
|
|
90
|
+
const nested = isArrayOrPlainObject(from) || isArrayOrPlainObject(to);
|
|
91
|
+
const diffs = nested ? getDiffs(from, to, options, prefixed) : [];
|
|
92
|
+
if (nested ? diffs.length === 0 : equal(from, to, options)) return;
|
|
91
93
|
const change = {
|
|
92
94
|
from,
|
|
93
95
|
to,
|
|
94
96
|
key: prefixed
|
|
95
97
|
};
|
|
96
|
-
const diffs = isArrayOrPlainObject(from) || isArrayOrPlainObject(to) ? getDiffs(from, to, relaxedNullish, prefixed) : [];
|
|
97
98
|
changes.push(change);
|
|
98
99
|
const diffsLength = diffs.length;
|
|
99
100
|
for (let diffIndex = 0; diffIndex < diffsLength; diffIndex += 1) changes.push(diffs[diffIndex]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oscarpalmer/atoms",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.169.0",
|
|
4
4
|
"description": "Atomic utilities for making your JavaScript better.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"helper",
|
|
@@ -235,4 +235,4 @@
|
|
|
235
235
|
"vitest": "npm:@voidzero-dev/vite-plus-test@latest"
|
|
236
236
|
},
|
|
237
237
|
"packageManager": "npm@11.11.1"
|
|
238
|
-
}
|
|
238
|
+
}
|
package/src/internal/is.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
ArrayOrPlainObject,
|
|
3
|
+
Constructor,
|
|
4
|
+
Key,
|
|
5
|
+
PlainObject,
|
|
6
|
+
Primitive,
|
|
7
|
+
TypedArray,
|
|
8
|
+
} from '../models';
|
|
2
9
|
|
|
3
10
|
// #region Functions
|
|
4
11
|
|
|
@@ -74,6 +81,15 @@ export function isPlainObject(value: unknown): value is PlainObject {
|
|
|
74
81
|
);
|
|
75
82
|
}
|
|
76
83
|
|
|
84
|
+
/**
|
|
85
|
+
* - Is the value a primitive value?
|
|
86
|
+
* @param value Value to check
|
|
87
|
+
* @returns `true` if the value matches, otherwise `false`
|
|
88
|
+
*/
|
|
89
|
+
export function isPrimitive(value: unknown): value is Primitive {
|
|
90
|
+
return value == null || EXPRESSION_PRIMITIVE.test(typeof value);
|
|
91
|
+
}
|
|
92
|
+
|
|
77
93
|
/**
|
|
78
94
|
* Is the value a typed array?
|
|
79
95
|
* @param value Value to check
|
|
@@ -101,6 +117,8 @@ export function isTypedArray(value: unknown): value is TypedArray {
|
|
|
101
117
|
|
|
102
118
|
// #region Variables
|
|
103
119
|
|
|
120
|
+
const EXPRESSION_PRIMITIVE = /^(bigint|boolean|number|string|symbol)$/;
|
|
121
|
+
|
|
104
122
|
let TYPED_ARRAYS: Set<unknown>;
|
|
105
123
|
|
|
106
124
|
// #endregion
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import {isPrimitive} from '../is';
|
|
1
2
|
import type {ArrayOrPlainObject, Constructor, PlainObject, TypedArray} from '../../models';
|
|
2
|
-
import {chunk} from '../array/chunk';
|
|
3
3
|
import {isPlainObject, isTypedArray} from '../is';
|
|
4
4
|
import {getCompareHandlers} from './handlers';
|
|
5
5
|
|
|
@@ -122,21 +122,11 @@ function equalArray(first: unknown[], second: unknown[], options: Options): bool
|
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
const
|
|
125
|
+
const end = length - offset;
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
for (let chunkIndex = 0; chunkIndex < chunksLength; chunkIndex += 1) {
|
|
132
|
-
const firstChunk = firstChunks[chunkIndex];
|
|
133
|
-
const secondChunk = secondChunks[chunkIndex];
|
|
134
|
-
const chunkLength = firstChunk.length;
|
|
135
|
-
|
|
136
|
-
for (let index = 0; index < chunkLength; index += 1) {
|
|
137
|
-
if (!equalValue(firstChunk[index], secondChunk[index], options)) {
|
|
138
|
-
return false;
|
|
139
|
-
}
|
|
127
|
+
for (let index = offset; index < end; index += 1) {
|
|
128
|
+
if (!equalValue(first[index], second[index], options)) {
|
|
129
|
+
return false;
|
|
140
130
|
}
|
|
141
131
|
}
|
|
142
132
|
|
|
@@ -167,16 +157,11 @@ function equalMap(
|
|
|
167
157
|
}
|
|
168
158
|
|
|
169
159
|
const firstKeys = [...first.keys()];
|
|
170
|
-
const secondKeys = [...second.keys()];
|
|
171
|
-
|
|
172
|
-
if (firstKeys.some(key => !secondKeys.includes(key))) {
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
175
160
|
|
|
176
161
|
for (let index = 0; index < size; index += 1) {
|
|
177
162
|
const key = firstKeys[index];
|
|
178
163
|
|
|
179
|
-
if (!equalValue(first.get(key), second.get(key), options)) {
|
|
164
|
+
if (!second.has(key) || !equalValue(first.get(key), second.get(key), options)) {
|
|
180
165
|
return false;
|
|
181
166
|
}
|
|
182
167
|
}
|
|
@@ -197,16 +182,22 @@ function equalPlainObject(
|
|
|
197
182
|
secondKeys = secondKeys.filter(key => filterKey(key, options));
|
|
198
183
|
}
|
|
199
184
|
|
|
185
|
+
const useSet = secondKeys.length >= MINIMUM_LENGTH_FOR_SET;
|
|
186
|
+
const secondSet = useSet ? new Set(secondKeys) : undefined;
|
|
187
|
+
|
|
200
188
|
const {length} = firstKeys;
|
|
201
189
|
|
|
202
|
-
if (length !== secondKeys.length
|
|
190
|
+
if (length !== secondKeys.length) {
|
|
203
191
|
return false;
|
|
204
192
|
}
|
|
205
193
|
|
|
206
194
|
for (let index = 0; index < length; index += 1) {
|
|
207
195
|
const key = firstKeys[index];
|
|
208
196
|
|
|
209
|
-
if (
|
|
197
|
+
if (
|
|
198
|
+
!(secondSet?.has(key) ?? secondKeys.includes(key)) ||
|
|
199
|
+
!equalValue(first[key as never], second[key as never], options)
|
|
200
|
+
) {
|
|
210
201
|
return false;
|
|
211
202
|
}
|
|
212
203
|
}
|
|
@@ -246,7 +237,11 @@ function equalSet(first: Set<unknown>, second: Set<unknown>, options: Options):
|
|
|
246
237
|
for (let index = 0; index < size; index += 1) {
|
|
247
238
|
const firstValue = firstValues[index];
|
|
248
239
|
|
|
249
|
-
if (
|
|
240
|
+
if (
|
|
241
|
+
isPrimitive(firstValue)
|
|
242
|
+
? !second.has(firstValue)
|
|
243
|
+
: !secondValues.some(secondValue => equalValue(firstValue, secondValue, options))
|
|
244
|
+
) {
|
|
250
245
|
return false;
|
|
251
246
|
}
|
|
252
247
|
}
|
|
@@ -439,4 +434,6 @@ const ERROR_PROPERTIES: string[] = ['name', 'message'];
|
|
|
439
434
|
|
|
440
435
|
const EXPRESSION_PROPERTIES: string[] = ['source', 'flags'];
|
|
441
436
|
|
|
437
|
+
const MINIMUM_LENGTH_FOR_SET = 16;
|
|
438
|
+
|
|
442
439
|
// #endregion
|
package/src/is.ts
CHANGED
|
@@ -88,21 +88,10 @@ export function isObject(value: unknown): value is object {
|
|
|
88
88
|
return (typeof value === 'object' && value !== null) || typeof value === 'function';
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
/**
|
|
92
|
-
* - Is the value a primitive value?
|
|
93
|
-
* @param value Value to check
|
|
94
|
-
* @returns `true` if the value matches, otherwise `false`
|
|
95
|
-
*/
|
|
96
|
-
export function isPrimitive(value: unknown): value is Primitive {
|
|
97
|
-
return value == null || EXPRESSION_PRIMITIVE.test(typeof value);
|
|
98
|
-
}
|
|
99
|
-
|
|
100
91
|
// #endregion
|
|
101
92
|
|
|
102
93
|
// #region Variables
|
|
103
94
|
|
|
104
|
-
const EXPRESSION_PRIMITIVE = /^(bigint|boolean|number|string|symbol)$/;
|
|
105
|
-
|
|
106
95
|
const EXPRESSION_WHITESPACE = /^\s*$/;
|
|
107
96
|
|
|
108
97
|
// #endregion
|
|
@@ -116,6 +105,7 @@ export {
|
|
|
116
105
|
isKey,
|
|
117
106
|
isNumber,
|
|
118
107
|
isPlainObject,
|
|
108
|
+
isPrimitive,
|
|
119
109
|
isTypedArray,
|
|
120
110
|
} from './internal/is';
|
|
121
111
|
|
package/src/sized/map.ts
CHANGED
|
@@ -17,7 +17,7 @@ export class SizedMap<SizedKey = unknown, SizedValue = unknown> extends Map<Size
|
|
|
17
17
|
* Is the Map full?
|
|
18
18
|
*/
|
|
19
19
|
get full(): boolean {
|
|
20
|
-
return
|
|
20
|
+
return super.size >= this.#maximumSize;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
get maximum(): number {
|
|
@@ -75,26 +75,32 @@ export class SizedMap<SizedKey = unknown, SizedValue = unknown> extends Map<Size
|
|
|
75
75
|
* @inheritdoc
|
|
76
76
|
*/
|
|
77
77
|
override get(key: SizedKey): SizedValue | undefined {
|
|
78
|
-
|
|
78
|
+
if (super.has(key)) {
|
|
79
|
+
const value = super.get(key) as SizedValue;
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
this.set(key, value as SizedValue);
|
|
82
|
-
}
|
|
81
|
+
this.#setValue(key, value, true);
|
|
83
82
|
|
|
84
|
-
|
|
83
|
+
return value;
|
|
84
|
+
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
/**
|
|
88
88
|
* @inheritdoc
|
|
89
89
|
*/
|
|
90
90
|
override set(key: SizedKey, value: SizedValue): this {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
return this.#setValue(key, value, super.has(key));
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
#setValue(key: SizedKey, value: SizedValue, has: boolean): this {
|
|
95
|
+
if (has) {
|
|
96
|
+
super.delete(key);
|
|
97
|
+
} else if (super.size >= this.#maximumSize) {
|
|
98
|
+
super.delete(super.keys().next().value as SizedKey);
|
|
95
99
|
}
|
|
96
100
|
|
|
97
|
-
|
|
101
|
+
super.set(key, value);
|
|
102
|
+
|
|
103
|
+
return this;
|
|
98
104
|
}
|
|
99
105
|
}
|
|
100
106
|
|
package/src/sized/set.ts
CHANGED
|
@@ -71,10 +71,10 @@ export class SizedSet<Value = unknown> extends Set<Value> {
|
|
|
71
71
|
* @inheritdoc
|
|
72
72
|
*/
|
|
73
73
|
override add(value: Value): this {
|
|
74
|
-
if (
|
|
75
|
-
|
|
74
|
+
if (super.has(value)) {
|
|
75
|
+
super.delete(value);
|
|
76
76
|
} else if (this.size >= this.#maximumSize) {
|
|
77
|
-
|
|
77
|
+
super.delete(this.values().next().value as Value);
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
return super.add(value);
|
|
@@ -87,9 +87,10 @@ export class SizedSet<Value = unknown> extends Set<Value> {
|
|
|
87
87
|
* @returns Found value if it exists, otherwise `undefined`
|
|
88
88
|
*/
|
|
89
89
|
get(value: Value, update?: boolean): Value | undefined {
|
|
90
|
-
if (
|
|
90
|
+
if (super.has(value)) {
|
|
91
91
|
if (update ?? false) {
|
|
92
|
-
|
|
92
|
+
super.delete(value);
|
|
93
|
+
|
|
93
94
|
this.add(value);
|
|
94
95
|
}
|
|
95
96
|
|
package/src/value/clone.ts
CHANGED
|
@@ -86,36 +86,28 @@ function cloneDataView(
|
|
|
86
86
|
return cloned;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
function
|
|
90
|
-
|
|
89
|
+
function cloneMap(
|
|
90
|
+
map: Map<unknown, unknown>,
|
|
91
91
|
depth: number,
|
|
92
92
|
references: WeakMap<WeakKey, unknown>,
|
|
93
|
-
):
|
|
93
|
+
): Map<unknown, unknown> {
|
|
94
94
|
if (depth >= MAX_CLONE_DEPTH) {
|
|
95
|
-
return
|
|
95
|
+
return map;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
const
|
|
99
|
-
const
|
|
100
|
-
const entries = [...value.entries()];
|
|
101
|
-
const {length} = entries;
|
|
98
|
+
const cloned = new Map<unknown, unknown>();
|
|
99
|
+
const entries = map.entries();
|
|
102
100
|
|
|
103
|
-
for (
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
cloneValue(entry[0], depth + 1, references),
|
|
109
|
-
cloneValue(entry[1], depth + 1, references),
|
|
110
|
-
);
|
|
111
|
-
} else {
|
|
112
|
-
(cloned as Set<unknown>).add(cloneValue(entry[0], depth + 1, references));
|
|
113
|
-
}
|
|
101
|
+
for (const entry of entries) {
|
|
102
|
+
cloned.set(
|
|
103
|
+
cloneValue(entry[0], depth + 1, references),
|
|
104
|
+
cloneValue(entry[1], depth + 1, references),
|
|
105
|
+
);
|
|
114
106
|
}
|
|
115
107
|
|
|
116
|
-
references.set(
|
|
108
|
+
references.set(map, cloned);
|
|
117
109
|
|
|
118
|
-
return cloned
|
|
110
|
+
return cloned;
|
|
119
111
|
}
|
|
120
112
|
|
|
121
113
|
function cloneNode(node: Node, depth: number, references: WeakMap<WeakKey, unknown>): Node {
|
|
@@ -172,6 +164,28 @@ function cloneRegularExpression(
|
|
|
172
164
|
return cloned;
|
|
173
165
|
}
|
|
174
166
|
|
|
167
|
+
function cloneSet(
|
|
168
|
+
set: Set<unknown>,
|
|
169
|
+
depth: number,
|
|
170
|
+
references: WeakMap<WeakKey, unknown>,
|
|
171
|
+
): Set<unknown> {
|
|
172
|
+
if (depth >= MAX_CLONE_DEPTH) {
|
|
173
|
+
return set;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const cloned = new Set<unknown>();
|
|
177
|
+
const values = [...set.values()];
|
|
178
|
+
const {length} = values;
|
|
179
|
+
|
|
180
|
+
for (let index = 0; index < length; index += 1) {
|
|
181
|
+
cloned.add(cloneValue(values[index], depth + 1, references));
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
references.set(set, cloned);
|
|
185
|
+
|
|
186
|
+
return cloned;
|
|
187
|
+
}
|
|
188
|
+
|
|
175
189
|
function cloneTypedArray(
|
|
176
190
|
value: TypedArray,
|
|
177
191
|
depth: number,
|
|
@@ -227,12 +241,14 @@ function cloneValue(value: unknown, depth: number, references: WeakMap<WeakKey,
|
|
|
227
241
|
return cloneRegularExpression(value, depth, references);
|
|
228
242
|
|
|
229
243
|
case value instanceof Map:
|
|
230
|
-
|
|
231
|
-
return cloneMapOrSet(value, depth, references);
|
|
244
|
+
return cloneMap(value, depth, references);
|
|
232
245
|
|
|
233
246
|
case value instanceof Node:
|
|
234
247
|
return cloneNode(value, depth, references);
|
|
235
248
|
|
|
249
|
+
case value instanceof Set:
|
|
250
|
+
return cloneSet(value, depth, references);
|
|
251
|
+
|
|
236
252
|
case isArrayOrPlainObject(value):
|
|
237
253
|
return clonePlainObject(value, depth, references);
|
|
238
254
|
|
package/src/value/diff.ts
CHANGED
|
@@ -57,8 +57,8 @@ type KeyedDiffValue = {
|
|
|
57
57
|
type Parameters = {
|
|
58
58
|
changes: KeyedDiffValue[];
|
|
59
59
|
key: PropertyKey;
|
|
60
|
+
options: Required<DiffOptions>;
|
|
60
61
|
values: {first: unknown; second: unknown};
|
|
61
|
-
relaxedNullish: boolean;
|
|
62
62
|
prefix?: string;
|
|
63
63
|
};
|
|
64
64
|
|
|
@@ -106,7 +106,7 @@ export function diff<First, Second = First>(
|
|
|
106
106
|
return diffResult;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
const diffs = getDiffs(first, second, relaxedNullish);
|
|
109
|
+
const diffs = getDiffs(first, second, {relaxedNullish});
|
|
110
110
|
|
|
111
111
|
const {length} = diffs;
|
|
112
112
|
|
|
@@ -127,7 +127,7 @@ function getChanges(
|
|
|
127
127
|
changes: KeyedDiffValue[],
|
|
128
128
|
first: unknown,
|
|
129
129
|
second: unknown,
|
|
130
|
-
|
|
130
|
+
options: Required<DiffOptions>,
|
|
131
131
|
prefix?: string,
|
|
132
132
|
): KeyedDiffValue[] {
|
|
133
133
|
const checked = new Set<PropertyKey>();
|
|
@@ -151,7 +151,7 @@ function getChanges(
|
|
|
151
151
|
setChanges({
|
|
152
152
|
changes,
|
|
153
153
|
key,
|
|
154
|
-
|
|
154
|
+
options,
|
|
155
155
|
prefix,
|
|
156
156
|
values: {first, second},
|
|
157
157
|
});
|
|
@@ -164,7 +164,7 @@ function getChanges(
|
|
|
164
164
|
function getDiffs(
|
|
165
165
|
first: unknown,
|
|
166
166
|
second: unknown,
|
|
167
|
-
|
|
167
|
+
options: Required<DiffOptions>,
|
|
168
168
|
prefix?: string,
|
|
169
169
|
): KeyedDiffValue[] {
|
|
170
170
|
const changes: KeyedDiffValue[] = [];
|
|
@@ -184,31 +184,30 @@ function getDiffs(
|
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
return getChanges(changes, first, second,
|
|
187
|
+
return getChanges(changes, first, second, options, prefix);
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
function setChanges(parameters: Parameters): void {
|
|
191
|
-
const {changes, key, prefix,
|
|
191
|
+
const {changes, key, prefix, options, values} = parameters;
|
|
192
192
|
|
|
193
|
-
const
|
|
194
|
-
|
|
193
|
+
const prefixed = join([prefix, key], '.');
|
|
194
|
+
|
|
195
|
+
const from: unknown = values.first?.[key as never];
|
|
196
|
+
const to: unknown = values.second?.[key as never];
|
|
195
197
|
|
|
196
|
-
|
|
198
|
+
const nested = isArrayOrPlainObject(from) || isArrayOrPlainObject(to);
|
|
199
|
+
const diffs = nested ? getDiffs(from, to, options, prefixed) : [];
|
|
200
|
+
|
|
201
|
+
if (nested ? diffs.length === 0 : equal(from, to, options)) {
|
|
197
202
|
return;
|
|
198
203
|
}
|
|
199
204
|
|
|
200
|
-
const prefixed = join([prefix, key], '.');
|
|
201
|
-
|
|
202
205
|
const change = {
|
|
203
206
|
from,
|
|
204
207
|
to,
|
|
205
208
|
key: prefixed,
|
|
206
209
|
};
|
|
207
210
|
|
|
208
|
-
const nested = isArrayOrPlainObject(from) || isArrayOrPlainObject(to);
|
|
209
|
-
|
|
210
|
-
const diffs = nested ? getDiffs(from, to, relaxedNullish, prefixed) : [];
|
|
211
|
-
|
|
212
211
|
changes.push(change);
|
|
213
212
|
|
|
214
213
|
const diffsLength = diffs.length;
|