@oscarpalmer/atoms 0.167.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.
@@ -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;