@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 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 this.size >= this.#maximumSize;
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
- const value = super.get(key);
1278
- if (value !== void 0 || this.has(key)) this.set(key, value);
1279
- return value;
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
- if (this.has(key)) this.delete(key);
1286
- else if (this.size >= this.#maximumSize) this.delete(this.keys().next().value);
1287
- return super.set(key, value);
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 firstChunks = chunk(first.slice(offset, length - offset), ARRAY_THRESHOLD);
1689
- const secondChunks = chunk(second.slice(offset, length - offset), ARRAY_THRESHOLD);
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 || firstKeys.some((key) => !secondKeys.includes(key))) return false;
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 cloneMapOrSet(value, depth, references) {
2246
- if (depth >= MAX_CLONE_DEPTH) return value;
2247
- const isMap = value instanceof Map;
2248
- const cloned = isMap ? /* @__PURE__ */ new Map() : /* @__PURE__ */ new Set();
2249
- const entries = [...value.entries()];
2250
- const { length } = entries;
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, relaxedNullish, prefix) {
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
- relaxedNullish,
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, relaxedNullish, prefix) {
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, relaxedNullish, prefix);
2415
+ return getChanges(changes, first, second, options, prefix);
2405
2416
  }
2406
2417
  function setChanges(parameters) {
2407
- const { changes, key, prefix, relaxedNullish, values } = parameters;
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
- if (equal(from, to, { relaxedNullish })) return;
2411
- const prefixed = join([prefix, key], ".");
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 (this.has(value)) this.delete(value);
4431
- else if (this.size >= this.#maximumSize) this.delete(this.values().next().value);
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 (this.has(value)) {
4444
+ if (super.has(value)) {
4442
4445
  if (update ?? false) {
4443
- this.delete(value);
4446
+ super.delete(value);
4444
4447
  this.add(value);
4445
4448
  }
4446
4449
  return value;
@@ -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 };
@@ -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 firstChunks = chunk(first.slice(offset, length - offset), ARRAY_THRESHOLD);
22
- const secondChunks = chunk(second.slice(offset, length - offset), ARRAY_THRESHOLD);
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 || firstKeys.some((key) => !secondKeys.includes(key))) return false;
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 { Primitive } from "./models.mjs";
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 };
@@ -14,7 +14,7 @@ var SizedMap = class extends Map {
14
14
  * Is the Map full?
15
15
  */
16
16
  get full() {
17
- return this.size >= this.#maximumSize;
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
- const value = super.get(key);
37
- if (value !== void 0 || this.has(key)) this.set(key, value);
38
- return value;
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
- if (this.has(key)) this.delete(key);
45
- else if (this.size >= this.#maximumSize) this.delete(this.keys().next().value);
46
- return super.set(key, value);
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
@@ -32,8 +32,8 @@ var SizedSet = class extends Set {
32
32
  * @inheritdoc
33
33
  */
34
34
  add(value) {
35
- if (this.has(value)) this.delete(value);
36
- else if (this.size >= this.#maximumSize) this.delete(this.values().next().value);
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 (this.has(value)) {
46
+ if (super.has(value)) {
47
47
  if (update ?? false) {
48
- this.delete(value);
48
+ super.delete(value);
49
49
  this.add(value);
50
50
  }
51
51
  return value;
@@ -40,18 +40,12 @@ function cloneDataView(value, depth, references) {
40
40
  references.set(value, cloned);
41
41
  return cloned;
42
42
  }
43
- function cloneMapOrSet(value, depth, references) {
44
- if (depth >= MAX_CLONE_DEPTH) return value;
45
- const isMap = value instanceof Map;
46
- const cloned = isMap ? /* @__PURE__ */ new Map() : /* @__PURE__ */ new Set();
47
- const entries = [...value.entries()];
48
- const { length } = entries;
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);
@@ -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, relaxedNullish, prefix) {
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
- relaxedNullish,
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, relaxedNullish, prefix) {
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, relaxedNullish, prefix);
83
+ return getChanges(changes, first, second, options, prefix);
84
84
  }
85
85
  function setChanges(parameters) {
86
- const { changes, key, prefix, relaxedNullish, values } = parameters;
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
- if (equal(from, to, { relaxedNullish })) return;
90
- const prefixed = join([prefix, key], ".");
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.168.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
+ }
@@ -1,4 +1,11 @@
1
- import type {ArrayOrPlainObject, Constructor, Key, PlainObject, TypedArray} from '../models';
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 firstChunks = chunk(first.slice(offset, length - offset), ARRAY_THRESHOLD);
125
+ const end = length - offset;
126
126
 
127
- const secondChunks = chunk(second.slice(offset, length - offset), ARRAY_THRESHOLD);
128
-
129
- const chunksLength = firstChunks.length;
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 || firstKeys.some(key => !secondKeys.includes(key))) {
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 (!equalValue(first[key as never], second[key as never], options)) {
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 (!secondValues.some(secondValue => equalValue(firstValue, secondValue, options))) {
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 this.size >= this.#maximumSize;
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
- const value = super.get(key);
78
+ if (super.has(key)) {
79
+ const value = super.get(key) as SizedValue;
79
80
 
80
- if (value !== undefined || this.has(key)) {
81
- this.set(key, value as SizedValue);
82
- }
81
+ this.#setValue(key, value, true);
83
82
 
84
- return value;
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
- if (this.has(key)) {
92
- this.delete(key);
93
- } else if (this.size >= this.#maximumSize) {
94
- this.delete(this.keys().next().value as SizedKey);
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
- return super.set(key, value);
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 (this.has(value)) {
75
- this.delete(value);
74
+ if (super.has(value)) {
75
+ super.delete(value);
76
76
  } else if (this.size >= this.#maximumSize) {
77
- this.delete(this.values().next().value as Value);
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 (this.has(value)) {
90
+ if (super.has(value)) {
91
91
  if (update ?? false) {
92
- this.delete(value);
92
+ super.delete(value);
93
+
93
94
  this.add(value);
94
95
  }
95
96
 
@@ -86,36 +86,28 @@ function cloneDataView(
86
86
  return cloned;
87
87
  }
88
88
 
89
- function cloneMapOrSet<Value extends Map<unknown, unknown> | Set<unknown>>(
90
- value: Value,
89
+ function cloneMap(
90
+ map: Map<unknown, unknown>,
91
91
  depth: number,
92
92
  references: WeakMap<WeakKey, unknown>,
93
- ): Value {
93
+ ): Map<unknown, unknown> {
94
94
  if (depth >= MAX_CLONE_DEPTH) {
95
- return value;
95
+ return map;
96
96
  }
97
97
 
98
- const isMap = value instanceof Map;
99
- const cloned = isMap ? new Map<unknown, unknown>() : new Set<unknown>();
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 (let index = 0; index < length; index += 1) {
104
- const entry = entries[index];
105
-
106
- if (isMap) {
107
- (cloned as Map<unknown, unknown>).set(
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(value, cloned);
108
+ references.set(map, cloned);
117
109
 
118
- return cloned as Value;
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
- case value instanceof Set:
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
- relaxedNullish: boolean,
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
- relaxedNullish,
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
- relaxedNullish: boolean,
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, relaxedNullish, prefix);
187
+ return getChanges(changes, first, second, options, prefix);
188
188
  }
189
189
 
190
190
  function setChanges(parameters: Parameters): void {
191
- const {changes, key, prefix, relaxedNullish, values} = parameters;
191
+ const {changes, key, prefix, options, values} = parameters;
192
192
 
193
- const from = values.first?.[key as never];
194
- const to = values.second?.[key as never];
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
- if (equal(from, to, {relaxedNullish})) {
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;