@oscarpalmer/atoms 0.168.0 → 0.170.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 +70 -64
- package/dist/internal/function/timer.mjs +8 -5
- 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 +18 -15
- package/dist/value/diff.mjs +10 -9
- package/package.json +2 -2
- package/src/internal/function/timer.ts +13 -6
- 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 +40 -24
- 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
|
|
@@ -1137,24 +1146,25 @@ function getInterval(value) {
|
|
|
1137
1146
|
}
|
|
1138
1147
|
function getTimer(type, callback, time) {
|
|
1139
1148
|
const interval = getInterval(time);
|
|
1140
|
-
function run(
|
|
1149
|
+
function run() {
|
|
1150
|
+
const now = performance.now();
|
|
1141
1151
|
start ??= now;
|
|
1142
1152
|
if (interval === 0 || now - start >= interval - OFFSET) {
|
|
1143
1153
|
start = throttle ? now : void 0;
|
|
1144
1154
|
callback(...args);
|
|
1145
|
-
} else
|
|
1155
|
+
} else id = startTimer(run);
|
|
1146
1156
|
}
|
|
1147
1157
|
const throttle = type === TIMER_THROTTLE;
|
|
1148
1158
|
let args;
|
|
1149
|
-
let
|
|
1159
|
+
let id;
|
|
1150
1160
|
let start;
|
|
1151
1161
|
const timer = (...parameters) => {
|
|
1152
1162
|
timer.cancel();
|
|
1153
1163
|
args = parameters;
|
|
1154
|
-
|
|
1164
|
+
id = startTimer(run);
|
|
1155
1165
|
};
|
|
1156
1166
|
timer.cancel = () => {
|
|
1157
|
-
|
|
1167
|
+
clearTimer(id);
|
|
1158
1168
|
};
|
|
1159
1169
|
return timer;
|
|
1160
1170
|
}
|
|
@@ -1162,6 +1172,8 @@ const OFFSET = 5;
|
|
|
1162
1172
|
const TIMER_DEBOUNCE = "debounce";
|
|
1163
1173
|
const TIMER_THROTTLE = "throttle";
|
|
1164
1174
|
const TIMER_WAIT = "wait";
|
|
1175
|
+
const clearTimer = typeof cancelAnimationFrame === "function" ? cancelAnimationFrame : clearTimeout;
|
|
1176
|
+
const startTimer = typeof requestAnimationFrame === "function" ? requestAnimationFrame : setTimeout;
|
|
1165
1177
|
//#endregion
|
|
1166
1178
|
//#region src/internal/function/misc.ts
|
|
1167
1179
|
/**
|
|
@@ -1255,7 +1267,7 @@ var SizedMap = class extends Map {
|
|
|
1255
1267
|
* Is the Map full?
|
|
1256
1268
|
*/
|
|
1257
1269
|
get full() {
|
|
1258
|
-
return
|
|
1270
|
+
return super.size >= this.#maximumSize;
|
|
1259
1271
|
}
|
|
1260
1272
|
get maximum() {
|
|
1261
1273
|
return this.#maximumSize;
|
|
@@ -1274,17 +1286,23 @@ var SizedMap = class extends Map {
|
|
|
1274
1286
|
* @inheritdoc
|
|
1275
1287
|
*/
|
|
1276
1288
|
get(key) {
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1289
|
+
if (super.has(key)) {
|
|
1290
|
+
const value = super.get(key);
|
|
1291
|
+
this.#setValue(key, value, true);
|
|
1292
|
+
return value;
|
|
1293
|
+
}
|
|
1280
1294
|
}
|
|
1281
1295
|
/**
|
|
1282
1296
|
* @inheritdoc
|
|
1283
1297
|
*/
|
|
1284
1298
|
set(key, value) {
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1299
|
+
return this.#setValue(key, value, super.has(key));
|
|
1300
|
+
}
|
|
1301
|
+
#setValue(key, value, has) {
|
|
1302
|
+
if (has) super.delete(key);
|
|
1303
|
+
else if (super.size >= this.#maximumSize) super.delete(super.keys().next().value);
|
|
1304
|
+
super.set(key, value);
|
|
1305
|
+
return this;
|
|
1288
1306
|
}
|
|
1289
1307
|
};
|
|
1290
1308
|
//#endregion
|
|
@@ -1685,15 +1703,8 @@ function equalArray(first, second, options) {
|
|
|
1685
1703
|
offset = offset > ARRAY_THRESHOLD ? ARRAY_THRESHOLD : offset;
|
|
1686
1704
|
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
1705
|
}
|
|
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
|
-
}
|
|
1706
|
+
const end = length - offset;
|
|
1707
|
+
for (let index = offset; index < end; index += 1) if (!equalValue(first[index], second[index], options)) return false;
|
|
1697
1708
|
return true;
|
|
1698
1709
|
}
|
|
1699
1710
|
function equalArrayBuffer(first, second, options) {
|
|
@@ -1706,11 +1717,9 @@ function equalMap(first, second, options) {
|
|
|
1706
1717
|
const { size } = first;
|
|
1707
1718
|
if (size !== second.size) return false;
|
|
1708
1719
|
const firstKeys = [...first.keys()];
|
|
1709
|
-
const secondKeys = [...second.keys()];
|
|
1710
|
-
if (firstKeys.some((key) => !secondKeys.includes(key))) return false;
|
|
1711
1720
|
for (let index = 0; index < size; index += 1) {
|
|
1712
1721
|
const key = firstKeys[index];
|
|
1713
|
-
if (!equalValue(first.get(key), second.get(key), options)) return false;
|
|
1722
|
+
if (!second.has(key) || !equalValue(first.get(key), second.get(key), options)) return false;
|
|
1714
1723
|
}
|
|
1715
1724
|
return true;
|
|
1716
1725
|
}
|
|
@@ -1721,11 +1730,12 @@ function equalPlainObject(first, second, options) {
|
|
|
1721
1730
|
firstKeys = firstKeys.filter((key) => filterKey(key, options));
|
|
1722
1731
|
secondKeys = secondKeys.filter((key) => filterKey(key, options));
|
|
1723
1732
|
}
|
|
1733
|
+
const secondSet = secondKeys.length >= MINIMUM_LENGTH_FOR_SET ? new Set(secondKeys) : void 0;
|
|
1724
1734
|
const { length } = firstKeys;
|
|
1725
|
-
if (length !== secondKeys.length
|
|
1735
|
+
if (length !== secondKeys.length) return false;
|
|
1726
1736
|
for (let index = 0; index < length; index += 1) {
|
|
1727
1737
|
const key = firstKeys[index];
|
|
1728
|
-
if (!equalValue(first[key], second[key], options)) return false;
|
|
1738
|
+
if (!(secondSet?.has(key) ?? secondKeys.includes(key)) || !equalValue(first[key], second[key], options)) return false;
|
|
1729
1739
|
}
|
|
1730
1740
|
return true;
|
|
1731
1741
|
}
|
|
@@ -1744,7 +1754,7 @@ function equalSet(first, second, options) {
|
|
|
1744
1754
|
const secondValues = [...second];
|
|
1745
1755
|
for (let index = 0; index < size; index += 1) {
|
|
1746
1756
|
const firstValue = firstValues[index];
|
|
1747
|
-
if (!secondValues.some((secondValue) => equalValue(firstValue, secondValue, options))) return false;
|
|
1757
|
+
if (isPrimitive(firstValue) ? !second.has(firstValue) : !secondValues.some((secondValue) => equalValue(firstValue, secondValue, options))) return false;
|
|
1748
1758
|
}
|
|
1749
1759
|
return true;
|
|
1750
1760
|
}
|
|
@@ -1838,6 +1848,7 @@ const ARRAY_PEEK_PERCENTAGE = 10;
|
|
|
1838
1848
|
const ARRAY_THRESHOLD = 100;
|
|
1839
1849
|
const ERROR_PROPERTIES = ["name", "message"];
|
|
1840
1850
|
const EXPRESSION_PROPERTIES = ["source", "flags"];
|
|
1851
|
+
const MINIMUM_LENGTH_FOR_SET = 16;
|
|
1841
1852
|
//#endregion
|
|
1842
1853
|
//#region src/internal/value/misc.ts
|
|
1843
1854
|
function findKey(needle, haystack) {
|
|
@@ -2242,18 +2253,12 @@ function cloneDataView(value, depth, references) {
|
|
|
2242
2253
|
references.set(value, cloned);
|
|
2243
2254
|
return cloned;
|
|
2244
2255
|
}
|
|
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);
|
|
2256
|
+
function cloneMap(map, depth, references) {
|
|
2257
|
+
if (depth >= MAX_CLONE_DEPTH) return map;
|
|
2258
|
+
const cloned = /* @__PURE__ */ new Map();
|
|
2259
|
+
const entries = map.entries();
|
|
2260
|
+
for (const entry of entries) cloned.set(cloneValue(entry[0], depth + 1, references), cloneValue(entry[1], depth + 1, references));
|
|
2261
|
+
references.set(map, cloned);
|
|
2257
2262
|
return cloned;
|
|
2258
2263
|
}
|
|
2259
2264
|
function cloneNode(node, depth, references) {
|
|
@@ -2281,6 +2286,15 @@ function cloneRegularExpression(value, depth, references) {
|
|
|
2281
2286
|
references.set(value, cloned);
|
|
2282
2287
|
return cloned;
|
|
2283
2288
|
}
|
|
2289
|
+
function cloneSet(set, depth, references) {
|
|
2290
|
+
if (depth >= MAX_CLONE_DEPTH) return set;
|
|
2291
|
+
const cloned = /* @__PURE__ */ new Set();
|
|
2292
|
+
const values = [...set.values()];
|
|
2293
|
+
const { length } = values;
|
|
2294
|
+
for (let index = 0; index < length; index += 1) cloned.add(cloneValue(values[index], depth + 1, references));
|
|
2295
|
+
references.set(set, cloned);
|
|
2296
|
+
return cloned;
|
|
2297
|
+
}
|
|
2284
2298
|
function cloneTypedArray(value, depth, references) {
|
|
2285
2299
|
if (depth >= MAX_CLONE_DEPTH) return value;
|
|
2286
2300
|
const cloned = new value.constructor(value);
|
|
@@ -2301,9 +2315,9 @@ function cloneValue(value, depth, references) {
|
|
|
2301
2315
|
case value instanceof DataView: return cloneDataView(value, depth, references);
|
|
2302
2316
|
case value instanceof Date: return new Date(value.getTime());
|
|
2303
2317
|
case value instanceof RegExp: return cloneRegularExpression(value, depth, references);
|
|
2304
|
-
case value instanceof Map:
|
|
2305
|
-
case value instanceof
|
|
2306
|
-
case value instanceof
|
|
2318
|
+
case value instanceof Map: return cloneMap(value, depth, references);
|
|
2319
|
+
case typeof Node !== "undefined" && value instanceof Node: return cloneNode(value, depth, references);
|
|
2320
|
+
case value instanceof Set: return cloneSet(value, depth, references);
|
|
2307
2321
|
case isArrayOrPlainObject(value): return clonePlainObject(value, depth, references);
|
|
2308
2322
|
case isTypedArray(value): return cloneTypedArray(value, depth, references);
|
|
2309
2323
|
default: return clone.handlers.handle(value, depth, references);
|
|
@@ -2351,7 +2365,7 @@ function diff(first, second, options) {
|
|
|
2351
2365
|
diffResult.type = DIFF_FULL;
|
|
2352
2366
|
return diffResult;
|
|
2353
2367
|
}
|
|
2354
|
-
const diffs = getDiffs(first, second, relaxedNullish);
|
|
2368
|
+
const diffs = getDiffs(first, second, { relaxedNullish });
|
|
2355
2369
|
const { length } = diffs;
|
|
2356
2370
|
if (length === 0) diffResult.type = DIFF_NONE;
|
|
2357
2371
|
for (let index = 0; index < length; index += 1) {
|
|
@@ -2363,7 +2377,7 @@ function diff(first, second, options) {
|
|
|
2363
2377
|
}
|
|
2364
2378
|
return diffResult;
|
|
2365
2379
|
}
|
|
2366
|
-
function getChanges(changes, first, second,
|
|
2380
|
+
function getChanges(changes, first, second, options, prefix) {
|
|
2367
2381
|
const checked = /* @__PURE__ */ new Set();
|
|
2368
2382
|
for (let outerIndex = 0; outerIndex < 2; outerIndex += 1) {
|
|
2369
2383
|
const value = (outerIndex === 0 ? first : second) ?? {};
|
|
@@ -2376,7 +2390,7 @@ function getChanges(changes, first, second, relaxedNullish, prefix) {
|
|
|
2376
2390
|
setChanges({
|
|
2377
2391
|
changes,
|
|
2378
2392
|
key,
|
|
2379
|
-
|
|
2393
|
+
options,
|
|
2380
2394
|
prefix,
|
|
2381
2395
|
values: {
|
|
2382
2396
|
first,
|
|
@@ -2387,7 +2401,7 @@ function getChanges(changes, first, second, relaxedNullish, prefix) {
|
|
|
2387
2401
|
}
|
|
2388
2402
|
return changes;
|
|
2389
2403
|
}
|
|
2390
|
-
function getDiffs(first, second,
|
|
2404
|
+
function getDiffs(first, second, options, prefix) {
|
|
2391
2405
|
const changes = [];
|
|
2392
2406
|
if (Array.isArray(first) && Array.isArray(second)) {
|
|
2393
2407
|
const maximumLength = Math.max(first.length, second.length);
|
|
@@ -2401,20 +2415,21 @@ function getDiffs(first, second, relaxedNullish, prefix) {
|
|
|
2401
2415
|
});
|
|
2402
2416
|
}
|
|
2403
2417
|
}
|
|
2404
|
-
return getChanges(changes, first, second,
|
|
2418
|
+
return getChanges(changes, first, second, options, prefix);
|
|
2405
2419
|
}
|
|
2406
2420
|
function setChanges(parameters) {
|
|
2407
|
-
const { changes, key, prefix,
|
|
2421
|
+
const { changes, key, prefix, options, values } = parameters;
|
|
2422
|
+
const prefixed = join([prefix, key], ".");
|
|
2408
2423
|
const from = values.first?.[key];
|
|
2409
2424
|
const to = values.second?.[key];
|
|
2410
|
-
|
|
2411
|
-
const
|
|
2425
|
+
const nested = isArrayOrPlainObject(from) || isArrayOrPlainObject(to);
|
|
2426
|
+
const diffs = nested ? getDiffs(from, to, options, prefixed) : [];
|
|
2427
|
+
if (nested ? diffs.length === 0 : equal(from, to, options)) return;
|
|
2412
2428
|
const change = {
|
|
2413
2429
|
from,
|
|
2414
2430
|
to,
|
|
2415
2431
|
key: prefixed
|
|
2416
2432
|
};
|
|
2417
|
-
const diffs = isArrayOrPlainObject(from) || isArrayOrPlainObject(to) ? getDiffs(from, to, relaxedNullish, prefixed) : [];
|
|
2418
2433
|
changes.push(change);
|
|
2419
2434
|
const diffsLength = diffs.length;
|
|
2420
2435
|
for (let diffIndex = 0; diffIndex < diffsLength; diffIndex += 1) changes.push(diffs[diffIndex]);
|
|
@@ -3484,15 +3499,6 @@ function isNumerical(value) {
|
|
|
3484
3499
|
function isObject(value) {
|
|
3485
3500
|
return typeof value === "object" && value !== null || typeof value === "function";
|
|
3486
3501
|
}
|
|
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
3502
|
const EXPRESSION_WHITESPACE = /^\s*$/;
|
|
3497
3503
|
//#endregion
|
|
3498
3504
|
//#region src/logger.ts
|
|
@@ -4427,8 +4433,8 @@ var SizedSet = class extends Set {
|
|
|
4427
4433
|
* @inheritdoc
|
|
4428
4434
|
*/
|
|
4429
4435
|
add(value) {
|
|
4430
|
-
if (
|
|
4431
|
-
else if (this.size >= this.#maximumSize)
|
|
4436
|
+
if (super.has(value)) super.delete(value);
|
|
4437
|
+
else if (this.size >= this.#maximumSize) super.delete(this.values().next().value);
|
|
4432
4438
|
return super.add(value);
|
|
4433
4439
|
}
|
|
4434
4440
|
/**
|
|
@@ -4438,9 +4444,9 @@ var SizedSet = class extends Set {
|
|
|
4438
4444
|
* @returns Found value if it exists, otherwise `undefined`
|
|
4439
4445
|
*/
|
|
4440
4446
|
get(value, update) {
|
|
4441
|
-
if (
|
|
4447
|
+
if (super.has(value)) {
|
|
4442
4448
|
if (update ?? false) {
|
|
4443
|
-
|
|
4449
|
+
super.delete(value);
|
|
4444
4450
|
this.add(value);
|
|
4445
4451
|
}
|
|
4446
4452
|
return value;
|
|
@@ -4,24 +4,25 @@ function getInterval(value) {
|
|
|
4
4
|
}
|
|
5
5
|
function getTimer(type, callback, time) {
|
|
6
6
|
const interval = getInterval(time);
|
|
7
|
-
function run(
|
|
7
|
+
function run() {
|
|
8
|
+
const now = performance.now();
|
|
8
9
|
start ??= now;
|
|
9
10
|
if (interval === 0 || now - start >= interval - OFFSET) {
|
|
10
11
|
start = throttle ? now : void 0;
|
|
11
12
|
callback(...args);
|
|
12
|
-
} else
|
|
13
|
+
} else id = startTimer(run);
|
|
13
14
|
}
|
|
14
15
|
const throttle = type === TIMER_THROTTLE;
|
|
15
16
|
let args;
|
|
16
|
-
let
|
|
17
|
+
let id;
|
|
17
18
|
let start;
|
|
18
19
|
const timer = (...parameters) => {
|
|
19
20
|
timer.cancel();
|
|
20
21
|
args = parameters;
|
|
21
|
-
|
|
22
|
+
id = startTimer(run);
|
|
22
23
|
};
|
|
23
24
|
timer.cancel = () => {
|
|
24
|
-
|
|
25
|
+
clearTimer(id);
|
|
25
26
|
};
|
|
26
27
|
return timer;
|
|
27
28
|
}
|
|
@@ -29,5 +30,7 @@ const OFFSET = 5;
|
|
|
29
30
|
const TIMER_DEBOUNCE = "debounce";
|
|
30
31
|
const TIMER_THROTTLE = "throttle";
|
|
31
32
|
const TIMER_WAIT = "wait";
|
|
33
|
+
const clearTimer = typeof cancelAnimationFrame === "function" ? cancelAnimationFrame : clearTimeout;
|
|
34
|
+
const startTimer = typeof requestAnimationFrame === "function" ? requestAnimationFrame : setTimeout;
|
|
32
35
|
//#endregion
|
|
33
36
|
export { TIMER_DEBOUNCE, TIMER_THROTTLE, TIMER_WAIT, getTimer };
|
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
|
|
104
|
-
case value instanceof
|
|
105
|
+
case value instanceof Map: return cloneMap(value, depth, references);
|
|
106
|
+
case typeof Node !== "undefined" && 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.170.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
|
+
}
|
|
@@ -19,7 +19,9 @@ export function getTimer<Callback extends GenericCallback>(
|
|
|
19
19
|
): CancelableCallback<Callback> {
|
|
20
20
|
const interval = getInterval(time);
|
|
21
21
|
|
|
22
|
-
function run(
|
|
22
|
+
function run(): void {
|
|
23
|
+
const now = performance.now();
|
|
24
|
+
|
|
23
25
|
start ??= now;
|
|
24
26
|
|
|
25
27
|
if (interval === 0 || now - start >= interval - OFFSET) {
|
|
@@ -27,25 +29,26 @@ export function getTimer<Callback extends GenericCallback>(
|
|
|
27
29
|
|
|
28
30
|
callback(...args);
|
|
29
31
|
} else {
|
|
30
|
-
|
|
32
|
+
id = startTimer(run);
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
35
|
|
|
34
36
|
const throttle = type === TIMER_THROTTLE;
|
|
35
37
|
|
|
36
38
|
let args: Parameters<Callback>;
|
|
37
|
-
let
|
|
38
|
-
let start:
|
|
39
|
+
let id: number;
|
|
40
|
+
let start: number | undefined;
|
|
39
41
|
|
|
40
42
|
const timer = (...parameters: Parameters<Callback>): void => {
|
|
41
43
|
timer.cancel();
|
|
42
44
|
|
|
43
45
|
args = parameters;
|
|
44
|
-
|
|
46
|
+
|
|
47
|
+
id = startTimer(run);
|
|
45
48
|
};
|
|
46
49
|
|
|
47
50
|
timer.cancel = (): void => {
|
|
48
|
-
|
|
51
|
+
clearTimer(id);
|
|
49
52
|
};
|
|
50
53
|
|
|
51
54
|
return timer as CancelableCallback<Callback>;
|
|
@@ -63,4 +66,8 @@ export const TIMER_THROTTLE: TimerType = 'throttle';
|
|
|
63
66
|
|
|
64
67
|
export const TIMER_WAIT: TimerType = 'wait';
|
|
65
68
|
|
|
69
|
+
const clearTimer = typeof cancelAnimationFrame === 'function' ? cancelAnimationFrame : clearTimeout;
|
|
70
|
+
|
|
71
|
+
const startTimer = typeof requestAnimationFrame === 'function' ? requestAnimationFrame : setTimeout;
|
|
72
|
+
|
|
66
73
|
// #endregion
|
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
|
-
case value instanceof Node:
|
|
246
|
+
case typeof Node !== 'undefined' && 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;
|