@shirudo/ddd-kit 1.0.0 → 1.1.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/utils.d.ts CHANGED
@@ -45,11 +45,23 @@ interface DeepOmitOptions {
45
45
  * provided rules.
46
46
  *
47
47
  * Walks the object tree and skips keys that match `ignoreKeys` /
48
- * `ignoreKeyPredicate`. Built-in atomic types (Date, RegExp, Map, Set,
49
- * TypedArrays, ArrayBuffer, DataView) are cloned by type rather than walked
50
- * — their internal structure has no key filtering to apply. Cycles are
48
+ * `ignoreKeyPredicate`. Built-in atomic types that `deepEqual` compares by
49
+ * value (Date, RegExp, Map, Set, TypedArrays, DataView) are cloned by type
50
+ * rather than walked — their internal structure has no key filtering to
51
+ * apply. Types that `deepEqual` compares by reference (Error, ArrayBuffer,
52
+ * SharedArrayBuffer, Promise, WeakMap, WeakSet) are passed through by
53
+ * reference, so `deepEqualExcept(x, x)` stays reflexive. Cycles are
51
54
  * preserved: a cycle `a → a` clones to `a' → a'`.
52
55
  *
56
+ * **Shared references.** Without `ignoreKeyPredicate`, an object reached
57
+ * via several paths dedupes to a single clone. With a predicate, each
58
+ * path gets its own clone — the predicate may decide differently per
59
+ * path, so memoising the first path's result would be wrong. This is
60
+ * inherently exponential for diamond-shaped sharing (a node reachable
61
+ * via 2^n paths is cloned 2^n times); the walk aborts with a descriptive
62
+ * error after {@link PATH_SENSITIVE_VISIT_BUDGET} node visits instead of
63
+ * hanging the process.
64
+ *
53
65
  * **Prototype-pollution safety.** `__proto__` and `constructor` keys
54
66
  * encountered as *own* properties of the input (typical of `JSON.parse`
55
67
  * output) are copied as inert data properties via `Object.defineProperty`
package/dist/utils.js CHANGED
@@ -18,10 +18,83 @@ var BUILT_IN_TAGS = /* @__PURE__ */ new Set([
18
18
  "[object SharedArrayBuffer]",
19
19
  "[object DataView]"
20
20
  ]);
21
+ function intrinsicGetter(proto, prop) {
22
+ const get = Object.getOwnPropertyDescriptor(proto, prop)?.get;
23
+ if (!get) throw new Error(`missing intrinsic getter for ${prop}`);
24
+ return get;
25
+ }
26
+ __name(intrinsicGetter, "intrinsicGetter");
27
+ var dateGetTime = Date.prototype.getTime;
28
+ var mapSizeGet = intrinsicGetter(Map.prototype, "size");
29
+ var setSizeGet = intrinsicGetter(Set.prototype, "size");
30
+ var weakMapHas = WeakMap.prototype.has;
31
+ var weakSetHas = WeakSet.prototype.has;
32
+ var dataViewByteLengthGet = intrinsicGetter(DataView.prototype, "byteLength");
33
+ var arrayBufferByteLengthGet = intrinsicGetter(
34
+ ArrayBuffer.prototype,
35
+ "byteLength"
36
+ );
37
+ var regExpSourceGet = intrinsicGetter(RegExp.prototype, "source");
38
+ var booleanValueOf = Boolean.prototype.valueOf;
39
+ var numberValueOf = Number.prototype.valueOf;
40
+ var stringValueOf = String.prototype.valueOf;
41
+ var PROBE_KEY = {};
42
+ var REFERENCE_COMPARED_TAGS = /* @__PURE__ */ new Set([
43
+ "[object Error]",
44
+ "[object ArrayBuffer]",
45
+ "[object SharedArrayBuffer]",
46
+ "[object Promise]",
47
+ "[object WeakMap]",
48
+ "[object WeakSet]"
49
+ ]);
50
+ function hasBrand(obj, tag) {
51
+ try {
52
+ switch (tag) {
53
+ case "[object Date]":
54
+ dateGetTime.call(obj);
55
+ return true;
56
+ case "[object RegExp]":
57
+ regExpSourceGet.call(obj);
58
+ return true;
59
+ case "[object Map]":
60
+ mapSizeGet.call(obj);
61
+ return true;
62
+ case "[object Set]":
63
+ setSizeGet.call(obj);
64
+ return true;
65
+ case "[object WeakMap]":
66
+ weakMapHas.call(obj, PROBE_KEY);
67
+ return true;
68
+ case "[object WeakSet]":
69
+ weakSetHas.call(obj, PROBE_KEY);
70
+ return true;
71
+ case "[object DataView]":
72
+ dataViewByteLengthGet.call(obj);
73
+ return true;
74
+ case "[object ArrayBuffer]":
75
+ arrayBufferByteLengthGet.call(obj);
76
+ return true;
77
+ case "[object Boolean]":
78
+ booleanValueOf.call(obj);
79
+ return true;
80
+ case "[object Number]":
81
+ numberValueOf.call(obj);
82
+ return true;
83
+ case "[object String]":
84
+ stringValueOf.call(obj);
85
+ return true;
86
+ default:
87
+ return true;
88
+ }
89
+ } catch {
90
+ return false;
91
+ }
92
+ }
93
+ __name(hasBrand, "hasBrand");
21
94
  function isBuiltInObject(obj, tag) {
22
- if (tag.endsWith("Array]")) return true;
23
95
  if (ArrayBuffer.isView(obj)) return true;
24
- return BUILT_IN_TAGS.has(tag);
96
+ if (tag.endsWith("Array]")) return false;
97
+ return BUILT_IN_TAGS.has(tag) && hasBrand(obj, tag);
25
98
  }
26
99
  __name(isBuiltInObject, "isBuiltInObject");
27
100
 
@@ -29,6 +102,10 @@ __name(isBuiltInObject, "isBuiltInObject");
29
102
  var objProto = Object.prototype;
30
103
  var objToString = objProto.toString;
31
104
  var objHasOwn = objProto.hasOwnProperty;
105
+ function sameValueZero(a, b) {
106
+ return a === b || Number.isNaN(a) && Number.isNaN(b);
107
+ }
108
+ __name(sameValueZero, "sameValueZero");
32
109
  function deepEqual(a, b) {
33
110
  return deepEqualInner(a, b, /* @__PURE__ */ new WeakMap());
34
111
  }
@@ -74,24 +151,31 @@ function deepEqualInner(a, b, visited) {
74
151
  const len = arrA.length;
75
152
  if (len !== arrB.length) return false;
76
153
  for (let i = 0; i < len; i++) {
77
- if (arrA[i] !== arrB[i]) return false;
154
+ if (!sameValueZero(arrA[i], arrB[i])) return false;
155
+ }
156
+ return true;
157
+ }
158
+ if (Array.isArray(objA) || Array.isArray(objB)) {
159
+ if (!Array.isArray(objA) || !Array.isArray(objB)) return false;
160
+ const arrA = objA;
161
+ const arrB = objB;
162
+ const len = arrA.length;
163
+ if (len !== arrB.length) return false;
164
+ for (let i = 0; i < len; i++) {
165
+ if (!deepEqualInner(arrA[i], arrB[i], visited)) return false;
78
166
  }
79
167
  return true;
80
168
  }
81
169
  const tagA = objToString.call(objA);
82
170
  const tagB = objToString.call(objB);
83
171
  if (tagA !== tagB) return false;
172
+ const builtInA = isBuiltInObject(objA, tagA);
173
+ const builtInB = isBuiltInObject(objB, tagB);
174
+ if (builtInA !== builtInB) return false;
175
+ if (!builtInA) {
176
+ return comparePlainObjects(objA, objB, visited);
177
+ }
84
178
  switch (tagA) {
85
- case "[object Array]": {
86
- const arrA = objA;
87
- const arrB = objB;
88
- const len = arrA.length;
89
- if (len !== arrB.length) return false;
90
- for (let i = 0; i < len; i++) {
91
- if (!deepEqualInner(arrA[i], arrB[i], visited)) return false;
92
- }
93
- return true;
94
- }
95
179
  case "[object Map]": {
96
180
  const mapA = objA;
97
181
  const mapB = objB;
@@ -113,9 +197,7 @@ function deepEqualInner(a, b, visited) {
113
197
  return true;
114
198
  }
115
199
  case "[object Date]": {
116
- const timeA = objA.getTime();
117
- const timeB = objB.getTime();
118
- return timeA === timeB;
200
+ return sameValueZero(objA.getTime(), objB.getTime());
119
201
  }
120
202
  case "[object RegExp]": {
121
203
  const regA = objA;
@@ -125,69 +207,88 @@ function deepEqualInner(a, b, visited) {
125
207
  case "[object Boolean]":
126
208
  case "[object Number]":
127
209
  case "[object String]": {
128
- return objA.valueOf() === objB.valueOf();
210
+ return sameValueZero(
211
+ objA.valueOf(),
212
+ objB.valueOf()
213
+ );
129
214
  }
130
215
  default: {
131
- if (isBuiltInObject(objA, tagA) && isBuiltInObject(objB, tagB)) {
132
- return objA === objB;
133
- }
134
- const recA = objA;
135
- const recB = objB;
136
- const stringKeysA = Object.keys(objA);
137
- const stringKeysB = Object.keys(objB);
138
- if (stringKeysA.length !== stringKeysB.length) return false;
139
- const symbolKeysA = Object.getOwnPropertySymbols(objA);
140
- const symbolKeysB = Object.getOwnPropertySymbols(objB);
141
- if (symbolKeysA.length !== symbolKeysB.length) return false;
142
- const symbolKeysBSet = new Set(symbolKeysB);
143
- for (const key of stringKeysA) {
144
- if (!objHasOwn.call(objB, key)) return false;
145
- }
146
- for (const key of symbolKeysA) {
147
- if (!symbolKeysBSet.has(key)) return false;
148
- }
149
- for (const key of stringKeysA) {
150
- if (!deepEqualInner(recA[key], recB[key], visited)) {
151
- return false;
152
- }
153
- }
154
- for (const key of symbolKeysA) {
155
- if (!deepEqualInner(recA[key], recB[key], visited)) {
156
- return false;
157
- }
158
- }
159
- return true;
216
+ return objA === objB;
160
217
  }
161
218
  }
162
219
  }
163
220
  __name(deepEqualInner, "deepEqualInner");
221
+ function comparePlainObjects(objA, objB, visited) {
222
+ const recA = objA;
223
+ const recB = objB;
224
+ const stringKeysA = Object.keys(objA);
225
+ const stringKeysB = Object.keys(objB);
226
+ if (stringKeysA.length !== stringKeysB.length) return false;
227
+ const symbolKeysA = Object.getOwnPropertySymbols(objA);
228
+ const symbolKeysB = Object.getOwnPropertySymbols(objB);
229
+ if (symbolKeysA.length !== symbolKeysB.length) return false;
230
+ const symbolKeysBSet = new Set(symbolKeysB);
231
+ for (const key of stringKeysA) {
232
+ if (!objHasOwn.call(objB, key)) return false;
233
+ }
234
+ for (const key of symbolKeysA) {
235
+ if (!symbolKeysBSet.has(key)) return false;
236
+ }
237
+ for (const key of stringKeysA) {
238
+ if (!deepEqualInner(recA[key], recB[key], visited)) {
239
+ return false;
240
+ }
241
+ }
242
+ for (const key of symbolKeysA) {
243
+ if (!deepEqualInner(recA[key], recB[key], visited)) {
244
+ return false;
245
+ }
246
+ }
247
+ return true;
248
+ }
249
+ __name(comparePlainObjects, "comparePlainObjects");
164
250
 
165
251
  // src/utils/array/deep-omit.ts
166
252
  function deepOmit(value, options) {
167
253
  const visited = /* @__PURE__ */ new WeakMap();
168
254
  const ignoreKeys = options.ignoreKeys ? new Set(options.ignoreKeys) : void 0;
169
- return omitInternal(value, options, ignoreKeys, [], visited);
255
+ const budget = options.ignoreKeyPredicate ? { visits: 0 } : void 0;
256
+ return omitInternal(value, options, ignoreKeys, [], visited, budget);
170
257
  }
171
258
  __name(deepOmit, "deepOmit");
172
- function omitInternal(value, options, ignoreKeys, path, visited) {
259
+ var PATH_SENSITIVE_VISIT_BUDGET = 1e6;
260
+ function omitInternal(value, options, ignoreKeys, path, visited, budget) {
173
261
  if (value === null) return value;
174
262
  if (typeof value !== "object") return value;
175
263
  const obj = value;
176
264
  if (visited.has(obj)) {
177
265
  return visited.get(obj);
178
266
  }
179
- const tag = Object.prototype.toString.call(obj);
180
- if (tag === "[object Array]") {
267
+ if (budget && ++budget.visits > PATH_SENSITIVE_VISIT_BUDGET) {
268
+ throw new Error(
269
+ `deepOmit: exceeded ${PATH_SENSITIVE_VISIT_BUDGET} node visits. With ignoreKeyPredicate, objects reached via shared references are cloned once per path (the predicate may decide differently per path), which expands exponentially on diamond-shaped sharing. Restructure the input to a tree, or use ignoreKeys for path-independent filtering.`
270
+ );
271
+ }
272
+ if (Array.isArray(obj)) {
181
273
  const arr = obj;
182
274
  const clone2 = new Array(arr.length);
183
275
  visited.set(obj, clone2);
184
276
  for (let i = 0; i < arr.length; i++) {
185
277
  path.push(i);
186
- clone2[i] = omitInternal(arr[i], options, ignoreKeys, path, visited);
278
+ clone2[i] = omitInternal(
279
+ arr[i],
280
+ options,
281
+ ignoreKeys,
282
+ path,
283
+ visited,
284
+ budget
285
+ );
187
286
  path.pop();
188
287
  }
288
+ if (budget) visited.delete(obj);
189
289
  return clone2;
190
290
  }
291
+ const tag = Object.prototype.toString.call(obj);
191
292
  if (isBuiltInObject(obj, tag)) {
192
293
  const builtInClone = cloneBuiltIn(obj, tag);
193
294
  visited.set(obj, builtInClone);
@@ -208,7 +309,8 @@ function omitInternal(value, options, ignoreKeys, path, visited) {
208
309
  options,
209
310
  ignoreKeys,
210
311
  path,
211
- visited
312
+ visited,
313
+ budget
212
314
  )
213
315
  );
214
316
  path.pop();
@@ -224,11 +326,13 @@ function omitInternal(value, options, ignoreKeys, path, visited) {
224
326
  options,
225
327
  ignoreKeys,
226
328
  path,
227
- visited
329
+ visited,
330
+ budget
228
331
  )
229
332
  );
230
333
  path.pop();
231
334
  }
335
+ if (budget) visited.delete(obj);
232
336
  return clone;
233
337
  }
234
338
  __name(omitInternal, "omitInternal");
@@ -242,6 +346,7 @@ function assignOwn(target, key, value) {
242
346
  }
243
347
  __name(assignOwn, "assignOwn");
244
348
  function cloneBuiltIn(obj, tag) {
349
+ if (REFERENCE_COMPARED_TAGS.has(tag)) return obj;
245
350
  switch (tag) {
246
351
  case "[object Date]":
247
352
  return new Date(obj.getTime());
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/array/is-built-in.ts","../src/utils/array/deep-equal.ts","../src/utils/array/deep-omit.ts","../src/utils/array/deep-equal-except.ts"],"names":["tagA","tagB","len","clone"],"mappings":"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","file":"utils.js","sourcesContent":["/**\n * Set of `Object.prototype.toString.call(x)` tags that the library treats\n * as built-in atomic types. Members of this set are compared/cloned by\n * reference (or with type-specific logic) rather than walked structurally.\n *\n * The detection is purely tag-based — `Object.prototype.toString` reads\n * `Symbol.toStringTag`, which gives the same answer across realms (an\n * iframe's `Date` has the same tag as the main window's `Date`). The\n * previous strategy also checked `globalThis[name] === constructor` and a\n * `proto !== Object.prototype` heuristic; both broke for cross-realm\n * objects and the latter additionally misclassified ordinary user classes\n * as built-ins. Tag-only is the simplest robust choice.\n */\nconst BUILT_IN_TAGS: ReadonlySet<string> = new Set([\n\t\"[object Date]\",\n\t\"[object RegExp]\",\n\t\"[object Map]\",\n\t\"[object Set]\",\n\t\"[object WeakMap]\",\n\t\"[object WeakSet]\",\n\t\"[object Promise]\",\n\t\"[object Error]\",\n\t\"[object Boolean]\",\n\t\"[object Number]\",\n\t\"[object String]\",\n\t\"[object ArrayBuffer]\",\n\t\"[object SharedArrayBuffer]\",\n\t\"[object DataView]\",\n]);\n\n/**\n * Returns `true` when `obj` is a built-in JavaScript type that should be\n * treated atomically (compared/cloned as a unit, not walked structurally).\n * Cross-realm safe.\n *\n * @param obj - The object to classify\n * @param tag - The result of `Object.prototype.toString.call(obj)` — passed\n * in so callers that already computed it don't pay twice\n */\nexport function isBuiltInObject(obj: object, tag: string): boolean {\n\t// All TypedArrays produce tags ending in \"Array]\" — future-proof match.\n\tif (tag.endsWith(\"Array]\")) return true;\n\t// ArrayBuffer view covers DataView + all TypedArrays as a belt-and-braces.\n\tif (ArrayBuffer.isView(obj)) return true;\n\treturn BUILT_IN_TAGS.has(tag);\n}\n","import { isBuiltInObject } from \"./is-built-in\";\n\nconst objProto = Object.prototype;\nconst objToString = objProto.toString;\nconst objHasOwn = objProto.hasOwnProperty;\n\n/**\n * Performs a deep equality check between two values.\n *\n * This function compares values recursively, handling:\n * - Primitives (with special handling for NaN)\n * - Arrays (nested arrays supported)\n * - Objects (plain objects and class instances)\n * - TypedArrays (Uint8Array, Int32Array, etc.)\n * - DataView\n * - Maps and Sets\n * - Dates and RegExp\n * - Wrapper objects (Boolean, Number, String)\n * - Circular references (detected and handled)\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if the values are deeply equal, `false` otherwise\n *\n * @example\n * ```ts\n * deepEqual([1, 2, 3], [1, 2, 3]); // true\n * deepEqual({ a: 1, b: [2, 3] }, { a: 1, b: [2, 3] }); // true\n * deepEqual(NaN, NaN); // true\n * deepEqual([1, 2], [1, 2, 3]); // false\n * ```\n */\nexport function deepEqual(a: unknown, b: unknown): boolean {\n\treturn deepEqualInner(a, b, new WeakMap<object, WeakSet<object>>());\n}\n\n/**\n * Visited pair tracker for cycle detection. The cache is a pair-set:\n * for every left-hand object we keep the set of right-hand objects we\n * have already paired it with. Encountering an already-known pair returns\n * the cycle hypothesis (assume equal); a new (a, b') pair with b' ≠ any\n * previously cached b for that a is walked normally — the previous shape\n * (`WeakMap<object, object>`) could only remember one B per A, which\n * could short-circuit unrelated comparisons that happened to revisit the\n * same A with a different B.\n */\ntype VisitedPairs = WeakMap<object, WeakSet<object>>;\n\n/**\n * Internal recursive function for deep equality comparison.\n *\n * @internal\n */\nfunction deepEqualInner(\n\ta: unknown,\n\tb: unknown,\n\tvisited: VisitedPairs,\n): boolean {\n\t// 1. Fast path: reference equality\n\tif (a === b) return true;\n\n\tconst typeA = typeof a;\n\tconst typeB = typeof b;\n\n\t// 2. If one is not an object → primitive / function\n\tif (typeA !== \"object\" || a === null || typeB !== \"object\" || b === null) {\n\t\t// Special case: NaN should be equal\n\t\tif (typeA === \"number\" && typeB === \"number\") {\n\t\t\treturn Number.isNaN(a as number) && Number.isNaN(b as number);\n\t\t}\n\t\t// Everything else is directly unequal with !== (including functions)\n\t\treturn false;\n\t}\n\n\t// From here on: both are non-null objects\n\n\tconst objA = a as object;\n\tconst objB = b as object;\n\n\t// 3. Cycles: already seen this exact (a, b) pair?\n\tlet cachedBs = visited.get(objA);\n\tif (cachedBs?.has(objB)) {\n\t\t// Cycle hypothesis: pretend equal so the walk can terminate. If the\n\t\t// structure is actually unequal elsewhere, a different recursive\n\t\t// branch will surface the mismatch.\n\t\treturn true;\n\t}\n\tif (!cachedBs) {\n\t\tcachedBs = new WeakSet();\n\t\tvisited.set(objA, cachedBs);\n\t}\n\tcachedBs.add(objB);\n\n\t// 4. Handle Typed Arrays / DataView first\n\tif (ArrayBuffer.isView(objA) || ArrayBuffer.isView(objB)) {\n\t\tif (!ArrayBuffer.isView(objA) || !ArrayBuffer.isView(objB)) return false;\n\n\t\tconst tagA = objToString.call(objA);\n\t\tconst tagB = objToString.call(objB);\n\t\tif (tagA !== tagB) return false;\n\n\t\t// DataView: compare byte by byte\n\t\tif (tagA === \"[object DataView]\") {\n\t\t\tconst viewA = objA as DataView;\n\t\t\tconst viewB = objB as DataView;\n\t\t\tif (viewA.byteLength !== viewB.byteLength) return false;\n\n\t\t\tconst len = viewA.byteLength;\n\t\t\tfor (let i = 0; i < len; i++) {\n\t\t\t\tif (viewA.getUint8(i) !== viewB.getUint8(i)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\t// Typed Arrays: element by element (length + numeric index access are\n\t\t// part of the TypedArray contract; the indexed read is sound).\n\t\tconst arrA = objA as unknown as Record<number, unknown> & { length: number };\n\t\tconst arrB = objB as unknown as Record<number, unknown> & { length: number };\n\n\t\tconst len = arrA.length;\n\t\tif (len !== arrB.length) return false;\n\n\t\tfor (let i = 0; i < len; i++) {\n\t\t\tif (arrA[i] !== arrB[i]) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t// 5. Tag-based type detection (robust across realms)\n\tconst tagA = objToString.call(objA);\n\tconst tagB = objToString.call(objB);\n\tif (tagA !== tagB) return false;\n\n\tswitch (tagA) {\n\t\tcase \"[object Array]\": {\n\t\t\tconst arrA = objA as unknown[];\n\t\t\tconst arrB = objB as unknown[];\n\t\t\tconst len = arrA.length;\n\t\t\tif (len !== arrB.length) return false;\n\n\t\t\tfor (let i = 0; i < len; i++) {\n\t\t\t\tif (!deepEqualInner(arrA[i], arrB[i], visited)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tcase \"[object Map]\": {\n\t\t\tconst mapA = objA as Map<unknown, unknown>;\n\t\t\tconst mapB = objB as Map<unknown, unknown>;\n\n\t\t\tif (mapA.size !== mapB.size) return false;\n\n\t\t\tfor (const [key, valA] of mapA) {\n\t\t\t\t// Map keys according to JS semantics: reference / SameValueZero\n\t\t\t\tif (!mapB.has(key)) return false;\n\t\t\t\tconst valB = mapB.get(key);\n\t\t\t\tif (!deepEqualInner(valA, valB, visited)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tcase \"[object Set]\": {\n\t\t\tconst setA = objA as Set<unknown>;\n\t\t\tconst setB = objB as Set<unknown>;\n\n\t\t\tif (setA.size !== setB.size) return false;\n\n\t\t\t// Set elements: same reference (JS semantics)\n\t\t\tfor (const value of setA) {\n\t\t\t\tif (!setB.has(value)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tcase \"[object Date]\": {\n\t\t\tconst timeA = (objA as Date).getTime();\n\t\t\tconst timeB = (objB as Date).getTime();\n\t\t\treturn timeA === timeB;\n\t\t}\n\n\t\tcase \"[object RegExp]\": {\n\t\t\tconst regA = objA as RegExp;\n\t\t\tconst regB = objB as RegExp;\n\t\t\treturn regA.source === regB.source && regA.flags === regB.flags;\n\t\t}\n\n\t\tcase \"[object Boolean]\":\n\t\tcase \"[object Number]\":\n\t\tcase \"[object String]\": {\n\t\t\t// Wrapper objects (new Boolean/Number/String)\n\t\t\treturn (objA as any).valueOf() === (objB as any).valueOf();\n\t\t}\n\n\t\tdefault: {\n\t\t\t// 6. Check if this is an unhandled built-in type (future-proof)\n\t\t\t// If both are built-ins but not handled above, they should be compared by reference\n\t\t\t// (since we don't know their internal structure)\n\t\t\tif (isBuiltInObject(objA, tagA) && isBuiltInObject(objB, tagB)) {\n\t\t\t\t// Unhandled built-in types: compare by reference as fallback\n\t\t\t\t// This ensures new built-ins don't fall through to plain object comparison\n\t\t\t\treturn objA === objB;\n\t\t\t}\n\n\t\t\t// 7. Fallback: plain / custom objects → compare own enumerable keys + values\n\t\t\tconst recA = objA as Record<string | symbol, unknown>;\n\t\t\tconst recB = objB as Record<string | symbol, unknown>;\n\n\t\t\tconst stringKeysA = Object.keys(objA as object);\n\t\t\tconst stringKeysB = Object.keys(objB as object);\n\t\t\tif (stringKeysA.length !== stringKeysB.length) return false;\n\n\t\t\tconst symbolKeysA = Object.getOwnPropertySymbols(objA as object);\n\t\t\tconst symbolKeysB = Object.getOwnPropertySymbols(objB as object);\n\t\t\tif (symbolKeysA.length !== symbolKeysB.length) return false;\n\n\t\t\t// Build the B-side symbol set once; the previous impl rebuilt the\n\t\t\t// array and ran .includes per key, which was quadratic.\n\t\t\tconst symbolKeysBSet = new Set<symbol>(symbolKeysB);\n\n\t\t\tfor (const key of stringKeysA) {\n\t\t\t\tif (!objHasOwn.call(objB, key)) return false;\n\t\t\t}\n\t\t\tfor (const key of symbolKeysA) {\n\t\t\t\tif (!symbolKeysBSet.has(key)) return false;\n\t\t\t}\n\n\t\t\tfor (const key of stringKeysA) {\n\t\t\t\tif (!deepEqualInner(recA[key], recB[key], visited)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (const key of symbolKeysA) {\n\t\t\t\tif (!deepEqualInner(recA[key], recB[key], visited)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn true;\n\t\t}\n\t}\n}\n","import { isBuiltInObject } from \"./is-built-in\";\n\nexport type Key = string | symbol;\nexport type PathSegment = string | number | symbol;\n\nexport interface DeepOmitOptions {\n\t/**\n\t * Keys to ignore everywhere in the object tree.\n\t * Only applies to object properties, not Map/Set/TypedArray contents.\n\t */\n\treadonly ignoreKeys?: readonly Key[];\n\n\t/**\n\t * Fine-grained control: Key + path (without current key).\n\t * Example path: [\"user\", \"meta\", 0, \"data\"]\n\t */\n\treadonly ignoreKeyPredicate?: (\n\t\tkey: Key,\n\t\tpath: readonly PathSegment[],\n\t) => boolean;\n}\n\n/**\n * Creates a deep copy of `value` with certain keys removed according to the\n * provided rules.\n *\n * Walks the object tree and skips keys that match `ignoreKeys` /\n * `ignoreKeyPredicate`. Built-in atomic types (Date, RegExp, Map, Set,\n * TypedArrays, ArrayBuffer, DataView) are cloned by type rather than walked\n * — their internal structure has no key filtering to apply. Cycles are\n * preserved: a cycle `a → a` clones to `a' → a'`.\n *\n * **Prototype-pollution safety.** `__proto__` and `constructor` keys\n * encountered as *own* properties of the input (typical of `JSON.parse`\n * output) are copied as inert data properties via `Object.defineProperty`\n * so the clone graph cannot bleed into `Object.prototype`.\n *\n * **Class instances.** When the input is a class instance, the clone is\n * built via `Object.create(proto)` so the prototype is preserved, but the\n * constructor is NOT re-invoked — so class invariants enforced by the\n * constructor are not re-checked. `deepOmit` is therefore best used for\n * comparison/serialisation (`voEqualsExcept`, `deepEqualExcept`), not as\n * a general-purpose clone for behaviour-carrying objects.\n *\n * @param value - The value to create a deep copy from\n * @param options - Options specifying which keys to ignore\n * @returns A deep copy of `value` with specified keys removed\n */\nexport function deepOmit<T>(value: T, options: DeepOmitOptions): T {\n\tconst visited = new WeakMap<object, unknown>();\n\t// Materialise ignoreKeys as a Set once so the inner loop probes O(1).\n\tconst ignoreKeys = options.ignoreKeys\n\t\t? new Set<Key>(options.ignoreKeys)\n\t\t: undefined;\n\treturn omitInternal(value, options, ignoreKeys, [], visited) as T;\n}\n\nfunction omitInternal(\n\tvalue: unknown,\n\toptions: DeepOmitOptions,\n\tignoreKeys: ReadonlySet<Key> | undefined,\n\tpath: PathSegment[],\n\tvisited: WeakMap<object, unknown>,\n): unknown {\n\tif (value === null) return value;\n\tif (typeof value !== \"object\") return value;\n\n\tconst obj = value as object;\n\n\t// Cycles: return cached clone if already visited. Use `has` (not\n\t// `cached !== undefined`) so a legitimately-undefined cached clone\n\t// would not be misclassified as \"never seen\".\n\tif (visited.has(obj)) {\n\t\treturn visited.get(obj);\n\t}\n\n\tconst tag = Object.prototype.toString.call(obj);\n\n\t// Arrays: recursively process elements\n\tif (tag === \"[object Array]\") {\n\t\tconst arr = obj as unknown[];\n\t\tconst clone: unknown[] = new Array(arr.length);\n\t\tvisited.set(obj, clone);\n\t\tfor (let i = 0; i < arr.length; i++) {\n\t\t\tpath.push(i);\n\t\t\tclone[i] = omitInternal(arr[i], options, ignoreKeys, path, visited);\n\t\t\tpath.pop();\n\t\t}\n\t\treturn clone;\n\t}\n\n\t// Built-in atomic types: clone by type rather than walk.\n\tif (isBuiltInObject(obj, tag)) {\n\t\tconst builtInClone = cloneBuiltIn(obj, tag);\n\t\tvisited.set(obj, builtInClone);\n\t\treturn builtInClone;\n\t}\n\n\t// Plain / Custom Objects: filter keys, recursively process values.\n\tconst clone = Object.create(Object.getPrototypeOf(obj));\n\tvisited.set(obj, clone);\n\n\tconst stringKeys = Object.keys(obj);\n\tconst symbolKeys = Object.getOwnPropertySymbols(obj);\n\n\tfor (const key of stringKeys) {\n\t\tif (shouldIgnoreKey(key, path, ignoreKeys, options)) continue;\n\t\tpath.push(key);\n\t\tassignOwn(\n\t\t\tclone,\n\t\t\tkey,\n\t\t\tomitInternal(\n\t\t\t\t(obj as Record<PropertyKey, unknown>)[key],\n\t\t\t\toptions,\n\t\t\t\tignoreKeys,\n\t\t\t\tpath,\n\t\t\t\tvisited,\n\t\t\t),\n\t\t);\n\t\tpath.pop();\n\t}\n\tfor (const key of symbolKeys) {\n\t\tif (shouldIgnoreKey(key, path, ignoreKeys, options)) continue;\n\t\tpath.push(key);\n\t\tassignOwn(\n\t\t\tclone,\n\t\t\tkey,\n\t\t\tomitInternal(\n\t\t\t\t(obj as Record<PropertyKey, unknown>)[key],\n\t\t\t\toptions,\n\t\t\t\tignoreKeys,\n\t\t\t\tpath,\n\t\t\t\tvisited,\n\t\t\t),\n\t\t);\n\t\tpath.pop();\n\t}\n\n\treturn clone;\n}\n\n/**\n * Assigns `value` as an OWN data property on `target` without going through\n * any inherited setter — critically, never invokes the `__proto__` setter\n * even when `key === \"__proto__\"`. Required to defeat prototype-pollution\n * payloads that ship `__proto__` as a parsed-JSON own key.\n */\nfunction assignOwn(target: object, key: PropertyKey, value: unknown): void {\n\tObject.defineProperty(target, key, {\n\t\tvalue,\n\t\twritable: true,\n\t\tenumerable: true,\n\t\tconfigurable: true,\n\t});\n}\n\n/**\n * Clones a built-in atomic type by case. Falls back to `structuredClone`\n * for anything not explicitly enumerated (e.g. ArrayBuffer, DataView,\n * Boolean/Number/String wrappers).\n */\nfunction cloneBuiltIn(obj: object, tag: string): unknown {\n\tswitch (tag) {\n\t\tcase \"[object Date]\":\n\t\t\treturn new Date((obj as Date).getTime());\n\t\tcase \"[object RegExp]\": {\n\t\t\tconst re = obj as RegExp;\n\t\t\tconst copy = new RegExp(re.source, re.flags);\n\t\t\tcopy.lastIndex = re.lastIndex;\n\t\t\treturn copy;\n\t\t}\n\t\tcase \"[object Map]\": {\n\t\t\tconst m = obj as Map<unknown, unknown>;\n\t\t\treturn new Map(m);\n\t\t}\n\t\tcase \"[object Set]\": {\n\t\t\tconst s = obj as Set<unknown>;\n\t\t\treturn new Set(s);\n\t\t}\n\t\tdefault:\n\t\t\treturn structuredClone(obj);\n\t}\n}\n\nfunction shouldIgnoreKey(\n\tkey: Key,\n\tpath: readonly PathSegment[],\n\tignoreKeys: ReadonlySet<Key> | undefined,\n\toptions: DeepOmitOptions,\n): boolean {\n\tif (ignoreKeys?.has(key)) return true;\n\tif (options.ignoreKeyPredicate?.(key, path)) return true;\n\treturn false;\n}\n","import { deepEqual } from \"./deep-equal\";\nimport { type DeepOmitOptions, deepOmit } from \"./deep-omit\";\n\nexport type DeepEqualExceptOptions = DeepOmitOptions;\n\n/**\n * Performs a deep equality comparison between two values after omitting specified keys.\n * \n * This function first removes the specified keys from both values using `deepOmit`,\n * then performs a deep equality check using `deepEqual`.\n * \n * @param a - The first value to compare\n * @param b - The second value to compare\n * @param options - Options specifying which keys to omit before comparison\n * @returns `true` if the values are deeply equal after omitting specified keys, `false` otherwise\n * \n * @example\n * ```ts\n * const obj1 = { id: 1, name: \"Alice\", updatedAt: \"2024-01-01\" };\n * const obj2 = { id: 2, name: \"Alice\", updatedAt: \"2024-01-02\" };\n * \n * deepEqualExcept(obj1, obj2, { ignoreKeys: [\"id\", \"updatedAt\"] }); // true\n * ```\n */\nexport function deepEqualExcept(\n\ta: unknown,\n\tb: unknown,\n\toptions: DeepEqualExceptOptions,\n): boolean {\n\tconst prunedA = deepOmit(a, options);\n\tconst prunedB = deepOmit(b, options);\n\treturn deepEqual(prunedA, prunedB);\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/array/is-built-in.ts","../src/utils/array/deep-equal.ts","../src/utils/array/deep-omit.ts","../src/utils/array/deep-equal-except.ts"],"names":["tagA","tagB","len","clone"],"mappings":"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","file":"utils.js","sourcesContent":["/**\n * Set of `Object.prototype.toString.call(x)` tags that the library treats\n * as built-in atomic types. Members of this set are compared/cloned by\n * reference (or with type-specific logic) rather than walked structurally.\n *\n * Detection is tag-based — `Object.prototype.toString` gives the same\n * answer across realms (an iframe's `Date` has the same tag as the main\n * window's `Date`) — and then brand-verified via internal-slot probes,\n * because `Symbol.toStringTag` lets any plain object claim a built-in tag.\n * The previous strategy also checked `globalThis[name] === constructor`\n * and a `proto !== Object.prototype` heuristic; both broke for cross-realm\n * objects and the latter additionally misclassified ordinary user classes\n * as built-ins.\n */\nconst BUILT_IN_TAGS: ReadonlySet<string> = new Set([\n\t\"[object Date]\",\n\t\"[object RegExp]\",\n\t\"[object Map]\",\n\t\"[object Set]\",\n\t\"[object WeakMap]\",\n\t\"[object WeakSet]\",\n\t\"[object Promise]\",\n\t\"[object Error]\",\n\t\"[object Boolean]\",\n\t\"[object Number]\",\n\t\"[object String]\",\n\t\"[object ArrayBuffer]\",\n\t\"[object SharedArrayBuffer]\",\n\t\"[object DataView]\",\n]);\n\n// Intrinsic probes for brand verification. Each one reads an internal slot\n// and throws a TypeError when `this` is not a genuine instance — the only\n// check a plain object cannot spoof via `Symbol.toStringTag`. Captured once\n// so a tampered prototype cannot redirect the probe later.\nfunction intrinsicGetter(\n\tproto: object,\n\tprop: string,\n): (this: unknown) => unknown {\n\tconst get = Object.getOwnPropertyDescriptor(proto, prop)?.get;\n\t// Spec-guaranteed accessors on intrinsic prototypes — unreachable\n\t// unless the environment itself is broken.\n\tif (!get) throw new Error(`missing intrinsic getter for ${prop}`);\n\treturn get;\n}\n\nconst dateGetTime = Date.prototype.getTime;\nconst mapSizeGet = intrinsicGetter(Map.prototype, \"size\");\nconst setSizeGet = intrinsicGetter(Set.prototype, \"size\");\nconst weakMapHas = WeakMap.prototype.has;\nconst weakSetHas = WeakSet.prototype.has;\nconst dataViewByteLengthGet = intrinsicGetter(DataView.prototype, \"byteLength\");\nconst arrayBufferByteLengthGet = intrinsicGetter(\n\tArrayBuffer.prototype,\n\t\"byteLength\",\n);\nconst regExpSourceGet = intrinsicGetter(RegExp.prototype, \"source\");\nconst booleanValueOf = Boolean.prototype.valueOf;\nconst numberValueOf = Number.prototype.valueOf;\nconst stringValueOf = String.prototype.valueOf;\nconst PROBE_KEY = {};\n\n/**\n * Tags that `deepEqual` compares BY REFERENCE (its unhandled-built-in\n * fallback) and that `deepOmit` must therefore ALIAS rather than clone —\n * a clone would break `deepEqualExcept(x, x)` reflexivity. Single source\n * of truth so the two modules cannot drift: if `deepEqual` ever learns a\n * by-value comparison for one of these, remove it here and add a clone\n * case in `deepOmit`'s `cloneBuiltIn` in the same change.\n */\nexport const REFERENCE_COMPARED_TAGS: ReadonlySet<string> = new Set([\n\t\"[object Error]\",\n\t\"[object ArrayBuffer]\",\n\t\"[object SharedArrayBuffer]\",\n\t\"[object Promise]\",\n\t\"[object WeakMap]\",\n\t\"[object WeakSet]\",\n]);\n\n/**\n * Verifies that `obj` genuinely is the type its tag claims, via an\n * internal-slot probe. Tags without a cheap probe (Promise, Error,\n * SharedArrayBuffer) are trusted — their downstream handling is\n * reference-based and cannot crash on a spoofed object.\n */\nfunction hasBrand(obj: object, tag: string): boolean {\n\ttry {\n\t\tswitch (tag) {\n\t\t\tcase \"[object Date]\":\n\t\t\t\tdateGetTime.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object RegExp]\":\n\t\t\t\tregExpSourceGet.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object Map]\":\n\t\t\t\tmapSizeGet.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object Set]\":\n\t\t\t\tsetSizeGet.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object WeakMap]\":\n\t\t\t\tweakMapHas.call(obj, PROBE_KEY);\n\t\t\t\treturn true;\n\t\t\tcase \"[object WeakSet]\":\n\t\t\t\tweakSetHas.call(obj, PROBE_KEY);\n\t\t\t\treturn true;\n\t\t\tcase \"[object DataView]\":\n\t\t\t\tdataViewByteLengthGet.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object ArrayBuffer]\":\n\t\t\t\tarrayBufferByteLengthGet.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object Boolean]\":\n\t\t\t\tbooleanValueOf.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object Number]\":\n\t\t\t\tnumberValueOf.call(obj);\n\t\t\t\treturn true;\n\t\t\tcase \"[object String]\":\n\t\t\t\tstringValueOf.call(obj);\n\t\t\t\treturn true;\n\t\t\tdefault:\n\t\t\t\treturn true;\n\t\t}\n\t} catch {\n\t\treturn false;\n\t}\n}\n\n/**\n * Returns `true` when `obj` is a built-in JavaScript type that should be\n * treated atomically (compared/cloned as a unit, not walked structurally).\n * Cross-realm safe, and brand-verified: a plain object spoofing a built-in\n * tag via `Symbol.toStringTag` returns `false` and is walked structurally\n * like any other plain object instead of crashing type-specific code.\n *\n * @param obj - The object to classify\n * @param tag - The result of `Object.prototype.toString.call(obj)` — passed\n * in so callers that already computed it don't pay twice\n */\nexport function isBuiltInObject(obj: object, tag: string): boolean {\n\t// ArrayBuffer views (DataView + all TypedArrays, present and future)\n\t// carry an unforgeable internal slot — the strongest brand check.\n\tif (ArrayBuffer.isView(obj)) return true;\n\t// A built-in-looking TypedArray tag WITHOUT the view brand is spoofed.\n\tif (tag.endsWith(\"Array]\")) return false;\n\treturn BUILT_IN_TAGS.has(tag) && hasBrand(obj, tag);\n}\n","import { isBuiltInObject } from \"./is-built-in\";\n\nconst objProto = Object.prototype;\nconst objToString = objProto.toString;\nconst objHasOwn = objProto.hasOwnProperty;\n\n/**\n * SameValueZero: `===` plus NaN-equals-NaN (and `+0 === -0`, unlike\n * `Object.is`). The numeric semantics `deepEqual` documents for primitives,\n * applied consistently inside TypedArrays, Dates and Number wrappers.\n */\nfunction sameValueZero(a: unknown, b: unknown): boolean {\n\treturn (\n\t\ta === b || (Number.isNaN(a as number) && Number.isNaN(b as number))\n\t);\n}\n\n/**\n * Performs a deep equality check between two values.\n *\n * This function compares values recursively, handling:\n * - Primitives (with special handling for NaN)\n * - Arrays (nested arrays supported)\n * - Objects (plain objects and class instances)\n * - TypedArrays (Uint8Array, Int32Array, etc.)\n * - DataView\n * - Maps and Sets\n * - Dates and RegExp\n * - Wrapper objects (Boolean, Number, String)\n * - Circular references (detected and handled)\n *\n * @param a - The first value to compare\n * @param b - The second value to compare\n * @returns `true` if the values are deeply equal, `false` otherwise\n *\n * @example\n * ```ts\n * deepEqual([1, 2, 3], [1, 2, 3]); // true\n * deepEqual({ a: 1, b: [2, 3] }, { a: 1, b: [2, 3] }); // true\n * deepEqual(NaN, NaN); // true\n * deepEqual([1, 2], [1, 2, 3]); // false\n * ```\n */\nexport function deepEqual(a: unknown, b: unknown): boolean {\n\treturn deepEqualInner(a, b, new WeakMap<object, WeakSet<object>>());\n}\n\n/**\n * Visited pair tracker for cycle detection. The cache is a pair-set:\n * for every left-hand object we keep the set of right-hand objects we\n * have already paired it with. Encountering an already-known pair returns\n * the cycle hypothesis (assume equal); a new (a, b') pair with b' ≠ any\n * previously cached b for that a is walked normally — the previous shape\n * (`WeakMap<object, object>`) could only remember one B per A, which\n * could short-circuit unrelated comparisons that happened to revisit the\n * same A with a different B.\n */\ntype VisitedPairs = WeakMap<object, WeakSet<object>>;\n\n/**\n * Internal recursive function for deep equality comparison.\n *\n * @internal\n */\nfunction deepEqualInner(\n\ta: unknown,\n\tb: unknown,\n\tvisited: VisitedPairs,\n): boolean {\n\t// 1. Fast path: reference equality\n\tif (a === b) return true;\n\n\tconst typeA = typeof a;\n\tconst typeB = typeof b;\n\n\t// 2. If one is not an object → primitive / function\n\tif (typeA !== \"object\" || a === null || typeB !== \"object\" || b === null) {\n\t\t// Special case: NaN should be equal\n\t\tif (typeA === \"number\" && typeB === \"number\") {\n\t\t\treturn Number.isNaN(a as number) && Number.isNaN(b as number);\n\t\t}\n\t\t// Everything else is directly unequal with !== (including functions)\n\t\treturn false;\n\t}\n\n\t// From here on: both are non-null objects\n\n\tconst objA = a as object;\n\tconst objB = b as object;\n\n\t// 3. Cycles: already seen this exact (a, b) pair?\n\tlet cachedBs = visited.get(objA);\n\tif (cachedBs?.has(objB)) {\n\t\t// Cycle hypothesis: pretend equal so the walk can terminate. If the\n\t\t// structure is actually unequal elsewhere, a different recursive\n\t\t// branch will surface the mismatch.\n\t\treturn true;\n\t}\n\tif (!cachedBs) {\n\t\tcachedBs = new WeakSet();\n\t\tvisited.set(objA, cachedBs);\n\t}\n\tcachedBs.add(objB);\n\n\t// 4. Handle Typed Arrays / DataView first\n\tif (ArrayBuffer.isView(objA) || ArrayBuffer.isView(objB)) {\n\t\tif (!ArrayBuffer.isView(objA) || !ArrayBuffer.isView(objB)) return false;\n\n\t\tconst tagA = objToString.call(objA);\n\t\tconst tagB = objToString.call(objB);\n\t\tif (tagA !== tagB) return false;\n\n\t\t// DataView: compare byte by byte\n\t\tif (tagA === \"[object DataView]\") {\n\t\t\tconst viewA = objA as DataView;\n\t\t\tconst viewB = objB as DataView;\n\t\t\tif (viewA.byteLength !== viewB.byteLength) return false;\n\n\t\t\tconst len = viewA.byteLength;\n\t\t\tfor (let i = 0; i < len; i++) {\n\t\t\t\tif (viewA.getUint8(i) !== viewB.getUint8(i)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\t// Typed Arrays: element by element (length + numeric index access are\n\t\t// part of the TypedArray contract; the indexed read is sound).\n\t\tconst arrA = objA as unknown as Record<number, unknown> & { length: number };\n\t\tconst arrB = objB as unknown as Record<number, unknown> & { length: number };\n\n\t\tconst len = arrA.length;\n\t\tif (len !== arrB.length) return false;\n\n\t\tfor (let i = 0; i < len; i++) {\n\t\t\tif (!sameValueZero(arrA[i], arrB[i])) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t// 5. Arrays — `Array.isArray` is brand-based and immune to\n\t// `Symbol.toStringTag` spoofing (a spoofed tag would otherwise route a\n\t// real array away from element comparison, or a plain object into it).\n\tif (Array.isArray(objA) || Array.isArray(objB)) {\n\t\tif (!Array.isArray(objA) || !Array.isArray(objB)) return false;\n\t\tconst arrA = objA as unknown[];\n\t\tconst arrB = objB as unknown[];\n\t\tconst len = arrA.length;\n\t\tif (len !== arrB.length) return false;\n\n\t\tfor (let i = 0; i < len; i++) {\n\t\t\tif (!deepEqualInner(arrA[i], arrB[i], visited)) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t// 6. Tag-based type detection (robust across realms), brand-verified —\n\t// a plain object spoofing a built-in tag is compared as a plain object\n\t// instead of crashing type-specific code below.\n\tconst tagA = objToString.call(objA);\n\tconst tagB = objToString.call(objB);\n\tif (tagA !== tagB) return false;\n\n\tconst builtInA = isBuiltInObject(objA, tagA);\n\tconst builtInB = isBuiltInObject(objB, tagB);\n\t// A genuine built-in never equals a spoofed lookalike.\n\tif (builtInA !== builtInB) return false;\n\n\tif (!builtInA) {\n\t\treturn comparePlainObjects(objA, objB, visited);\n\t}\n\n\tswitch (tagA) {\n\t\tcase \"[object Map]\": {\n\t\t\tconst mapA = objA as Map<unknown, unknown>;\n\t\t\tconst mapB = objB as Map<unknown, unknown>;\n\n\t\t\tif (mapA.size !== mapB.size) return false;\n\n\t\t\tfor (const [key, valA] of mapA) {\n\t\t\t\t// Map keys according to JS semantics: reference / SameValueZero\n\t\t\t\tif (!mapB.has(key)) return false;\n\t\t\t\tconst valB = mapB.get(key);\n\t\t\t\tif (!deepEqualInner(valA, valB, visited)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tcase \"[object Set]\": {\n\t\t\tconst setA = objA as Set<unknown>;\n\t\t\tconst setB = objB as Set<unknown>;\n\n\t\t\tif (setA.size !== setB.size) return false;\n\n\t\t\t// Set elements: same reference (JS semantics)\n\t\t\tfor (const value of setA) {\n\t\t\t\tif (!setB.has(value)) return false;\n\t\t\t}\n\t\t\treturn true;\n\t\t}\n\n\t\tcase \"[object Date]\": {\n\t\t\t// SameValueZero so two invalid Dates (getTime() === NaN) compare\n\t\t\t// equal, matching the primitive NaN semantics.\n\t\t\treturn sameValueZero((objA as Date).getTime(), (objB as Date).getTime());\n\t\t}\n\n\t\tcase \"[object RegExp]\": {\n\t\t\tconst regA = objA as RegExp;\n\t\t\tconst regB = objB as RegExp;\n\t\t\treturn regA.source === regB.source && regA.flags === regB.flags;\n\t\t}\n\n\t\tcase \"[object Boolean]\":\n\t\tcase \"[object Number]\":\n\t\tcase \"[object String]\": {\n\t\t\t// Wrapper objects (new Boolean/Number/String); SameValueZero so\n\t\t\t// two NaN Number wrappers compare equal.\n\t\t\treturn sameValueZero(\n\t\t\t\t(objA as { valueOf(): unknown }).valueOf(),\n\t\t\t\t(objB as { valueOf(): unknown }).valueOf(),\n\t\t\t);\n\t\t}\n\n\t\tdefault: {\n\t\t\t// Unhandled but brand-trusted built-ins: compared by reference —\n\t\t\t// their internal structure is unknown, and this keeps new\n\t\t\t// built-ins from falling through to plain-object comparison.\n\t\t\t// This branch IS the REFERENCE_COMPARED_TAGS contract exported\n\t\t\t// from is-built-in.ts (and consumed by deepOmit's cloneBuiltIn):\n\t\t\t// adding a by-value case above means removing the tag there.\n\t\t\treturn objA === objB;\n\t\t}\n\t}\n}\n\n/**\n * Plain / custom objects: compare own enumerable string keys + own symbol\n * keys and their values. Used both as the final fallback and for objects\n * whose built-in-looking tag failed brand verification.\n */\nfunction comparePlainObjects(\n\tobjA: object,\n\tobjB: object,\n\tvisited: VisitedPairs,\n): boolean {\n\tconst recA = objA as Record<string | symbol, unknown>;\n\tconst recB = objB as Record<string | symbol, unknown>;\n\n\tconst stringKeysA = Object.keys(objA);\n\tconst stringKeysB = Object.keys(objB);\n\tif (stringKeysA.length !== stringKeysB.length) return false;\n\n\tconst symbolKeysA = Object.getOwnPropertySymbols(objA);\n\tconst symbolKeysB = Object.getOwnPropertySymbols(objB);\n\tif (symbolKeysA.length !== symbolKeysB.length) return false;\n\n\t// Build the B-side symbol set once; the previous impl rebuilt the\n\t// array and ran .includes per key, which was quadratic.\n\tconst symbolKeysBSet = new Set<symbol>(symbolKeysB);\n\n\tfor (const key of stringKeysA) {\n\t\tif (!objHasOwn.call(objB, key)) return false;\n\t}\n\tfor (const key of symbolKeysA) {\n\t\tif (!symbolKeysBSet.has(key)) return false;\n\t}\n\n\tfor (const key of stringKeysA) {\n\t\tif (!deepEqualInner(recA[key], recB[key], visited)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\tfor (const key of symbolKeysA) {\n\t\tif (!deepEqualInner(recA[key], recB[key], visited)) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n","import { isBuiltInObject, REFERENCE_COMPARED_TAGS } from \"./is-built-in\";\n\nexport type Key = string | symbol;\nexport type PathSegment = string | number | symbol;\n\nexport interface DeepOmitOptions {\n\t/**\n\t * Keys to ignore everywhere in the object tree.\n\t * Only applies to object properties, not Map/Set/TypedArray contents.\n\t */\n\treadonly ignoreKeys?: readonly Key[];\n\n\t/**\n\t * Fine-grained control: Key + path (without current key).\n\t * Example path: [\"user\", \"meta\", 0, \"data\"]\n\t */\n\treadonly ignoreKeyPredicate?: (\n\t\tkey: Key,\n\t\tpath: readonly PathSegment[],\n\t) => boolean;\n}\n\n/**\n * Creates a deep copy of `value` with certain keys removed according to the\n * provided rules.\n *\n * Walks the object tree and skips keys that match `ignoreKeys` /\n * `ignoreKeyPredicate`. Built-in atomic types that `deepEqual` compares by\n * value (Date, RegExp, Map, Set, TypedArrays, DataView) are cloned by type\n * rather than walked — their internal structure has no key filtering to\n * apply. Types that `deepEqual` compares by reference (Error, ArrayBuffer,\n * SharedArrayBuffer, Promise, WeakMap, WeakSet) are passed through by\n * reference, so `deepEqualExcept(x, x)` stays reflexive. Cycles are\n * preserved: a cycle `a → a` clones to `a' → a'`.\n *\n * **Shared references.** Without `ignoreKeyPredicate`, an object reached\n * via several paths dedupes to a single clone. With a predicate, each\n * path gets its own clone — the predicate may decide differently per\n * path, so memoising the first path's result would be wrong. This is\n * inherently exponential for diamond-shaped sharing (a node reachable\n * via 2^n paths is cloned 2^n times); the walk aborts with a descriptive\n * error after {@link PATH_SENSITIVE_VISIT_BUDGET} node visits instead of\n * hanging the process.\n *\n * **Prototype-pollution safety.** `__proto__` and `constructor` keys\n * encountered as *own* properties of the input (typical of `JSON.parse`\n * output) are copied as inert data properties via `Object.defineProperty`\n * so the clone graph cannot bleed into `Object.prototype`.\n *\n * **Class instances.** When the input is a class instance, the clone is\n * built via `Object.create(proto)` so the prototype is preserved, but the\n * constructor is NOT re-invoked — so class invariants enforced by the\n * constructor are not re-checked. `deepOmit` is therefore best used for\n * comparison/serialisation (`voEqualsExcept`, `deepEqualExcept`), not as\n * a general-purpose clone for behaviour-carrying objects.\n *\n * @param value - The value to create a deep copy from\n * @param options - Options specifying which keys to ignore\n * @returns A deep copy of `value` with specified keys removed\n */\nexport function deepOmit<T>(value: T, options: DeepOmitOptions): T {\n\tconst visited = new WeakMap<object, unknown>();\n\t// Materialise ignoreKeys as a Set once so the inner loop probes O(1).\n\tconst ignoreKeys = options.ignoreKeys\n\t\t? new Set<Key>(options.ignoreKeys)\n\t\t: undefined;\n\t// With a path-sensitive predicate, a clone computed under one path must\n\t// NOT be reused for the same object reached via another path (the\n\t// predicate may decide differently there). The cache then only tracks\n\t// in-progress ancestors — pure cycle detection — instead of memoising\n\t// completed subtrees. Without a predicate, results are path-independent\n\t// and shared references keep deduplicating to one clone. The budget\n\t// bounds the per-path expansion (exponential on diamond sharing).\n\tconst budget = options.ignoreKeyPredicate ? { visits: 0 } : undefined;\n\treturn omitInternal(value, options, ignoreKeys, [], visited, budget) as T;\n}\n\n/**\n * Maximum object-node visits for a single path-sensitive `deepOmit` walk.\n * Per-path cloning expands exponentially on diamond-shaped sharing; past\n * this bound the walk throws instead of hanging the process. One million\n * visits covers any realistically tree-shaped input.\n */\nconst PATH_SENSITIVE_VISIT_BUDGET = 1_000_000;\n\nfunction omitInternal(\n\tvalue: unknown,\n\toptions: DeepOmitOptions,\n\tignoreKeys: ReadonlySet<Key> | undefined,\n\tpath: PathSegment[],\n\tvisited: WeakMap<object, unknown>,\n\tbudget: { visits: number } | undefined,\n): unknown {\n\tif (value === null) return value;\n\tif (typeof value !== \"object\") return value;\n\n\tconst obj = value as object;\n\n\t// Cycles (and, in the path-independent case, shared references): return\n\t// the cached clone. Use `has` (not `cached !== undefined`) so a\n\t// legitimately-undefined cached clone would not be misclassified as\n\t// \"never seen\".\n\tif (visited.has(obj)) {\n\t\treturn visited.get(obj);\n\t}\n\n\tif (budget && ++budget.visits > PATH_SENSITIVE_VISIT_BUDGET) {\n\t\tthrow new Error(\n\t\t\t`deepOmit: exceeded ${PATH_SENSITIVE_VISIT_BUDGET} node visits. ` +\n\t\t\t\t`With ignoreKeyPredicate, objects reached via shared references ` +\n\t\t\t\t`are cloned once per path (the predicate may decide differently ` +\n\t\t\t\t`per path), which expands exponentially on diamond-shaped ` +\n\t\t\t\t`sharing. Restructure the input to a tree, or use ignoreKeys ` +\n\t\t\t\t`for path-independent filtering.`,\n\t\t);\n\t}\n\n\t// Arrays: recursively process elements. `Array.isArray` is brand-based —\n\t// immune to `Symbol.toStringTag` spoofing, unlike the tag check below.\n\tif (Array.isArray(obj)) {\n\t\tconst arr = obj as unknown[];\n\t\tconst clone: unknown[] = new Array(arr.length);\n\t\tvisited.set(obj, clone);\n\t\tfor (let i = 0; i < arr.length; i++) {\n\t\t\tpath.push(i);\n\t\t\tclone[i] = omitInternal(\n\t\t\t\tarr[i],\n\t\t\t\toptions,\n\t\t\t\tignoreKeys,\n\t\t\t\tpath,\n\t\t\t\tvisited,\n\t\t\t\tbudget,\n\t\t\t);\n\t\t\tpath.pop();\n\t\t}\n\t\tif (budget) visited.delete(obj);\n\t\treturn clone;\n\t}\n\n\tconst tag = Object.prototype.toString.call(obj);\n\n\t// Built-in atomic types: clone by type rather than walk. The detection\n\t// is brand-verified — a plain object spoofing a built-in tag falls\n\t// through to the plain-object walk below.\n\tif (isBuiltInObject(obj, tag)) {\n\t\tconst builtInClone = cloneBuiltIn(obj, tag);\n\t\tvisited.set(obj, builtInClone);\n\t\treturn builtInClone;\n\t}\n\n\t// Plain / Custom Objects: filter keys, recursively process values.\n\tconst clone = Object.create(Object.getPrototypeOf(obj));\n\tvisited.set(obj, clone);\n\n\tconst stringKeys = Object.keys(obj);\n\tconst symbolKeys = Object.getOwnPropertySymbols(obj);\n\n\tfor (const key of stringKeys) {\n\t\tif (shouldIgnoreKey(key, path, ignoreKeys, options)) continue;\n\t\tpath.push(key);\n\t\tassignOwn(\n\t\t\tclone,\n\t\t\tkey,\n\t\t\tomitInternal(\n\t\t\t\t(obj as Record<PropertyKey, unknown>)[key],\n\t\t\t\toptions,\n\t\t\t\tignoreKeys,\n\t\t\t\tpath,\n\t\t\t\tvisited,\n\t\t\t\tbudget,\n\t\t\t),\n\t\t);\n\t\tpath.pop();\n\t}\n\tfor (const key of symbolKeys) {\n\t\tif (shouldIgnoreKey(key, path, ignoreKeys, options)) continue;\n\t\tpath.push(key);\n\t\tassignOwn(\n\t\t\tclone,\n\t\t\tkey,\n\t\t\tomitInternal(\n\t\t\t\t(obj as Record<PropertyKey, unknown>)[key],\n\t\t\t\toptions,\n\t\t\t\tignoreKeys,\n\t\t\t\tpath,\n\t\t\t\tvisited,\n\t\t\t\tbudget,\n\t\t\t),\n\t\t);\n\t\tpath.pop();\n\t}\n\n\tif (budget) visited.delete(obj);\n\treturn clone;\n}\n\n/**\n * Assigns `value` as an OWN data property on `target` without going through\n * any inherited setter — critically, never invokes the `__proto__` setter\n * even when `key === \"__proto__\"`. Required to defeat prototype-pollution\n * payloads that ship `__proto__` as a parsed-JSON own key.\n */\nfunction assignOwn(target: object, key: PropertyKey, value: unknown): void {\n\tObject.defineProperty(target, key, {\n\t\tvalue,\n\t\twritable: true,\n\t\tenumerable: true,\n\t\tconfigurable: true,\n\t});\n}\n\n/**\n * Clones a built-in atomic type by case. Falls back to `structuredClone`\n * for anything not explicitly enumerated (e.g. DataView, TypedArrays,\n * Boolean/Number/String wrappers — all of which `deepEqual` compares by\n * value). Types that `deepEqual` compares BY REFERENCE (the shared\n * {@link REFERENCE_COMPARED_TAGS} set) are passed through by reference\n * instead — cloning them would make `deepEqualExcept(x, x)` false.\n * Promise/WeakMap/WeakSet additionally cannot be cloned at all\n * (`structuredClone` rejects them).\n */\nfunction cloneBuiltIn(obj: object, tag: string): unknown {\n\tif (REFERENCE_COMPARED_TAGS.has(tag)) return obj;\n\tswitch (tag) {\n\t\tcase \"[object Date]\":\n\t\t\treturn new Date((obj as Date).getTime());\n\t\tcase \"[object RegExp]\": {\n\t\t\tconst re = obj as RegExp;\n\t\t\tconst copy = new RegExp(re.source, re.flags);\n\t\t\tcopy.lastIndex = re.lastIndex;\n\t\t\treturn copy;\n\t\t}\n\t\tcase \"[object Map]\": {\n\t\t\tconst m = obj as Map<unknown, unknown>;\n\t\t\treturn new Map(m);\n\t\t}\n\t\tcase \"[object Set]\": {\n\t\t\tconst s = obj as Set<unknown>;\n\t\t\treturn new Set(s);\n\t\t}\n\t\tdefault:\n\t\t\treturn structuredClone(obj);\n\t}\n}\n\nfunction shouldIgnoreKey(\n\tkey: Key,\n\tpath: readonly PathSegment[],\n\tignoreKeys: ReadonlySet<Key> | undefined,\n\toptions: DeepOmitOptions,\n): boolean {\n\tif (ignoreKeys?.has(key)) return true;\n\tif (options.ignoreKeyPredicate?.(key, path)) return true;\n\treturn false;\n}\n","import { deepEqual } from \"./deep-equal\";\nimport { type DeepOmitOptions, deepOmit } from \"./deep-omit\";\n\nexport type DeepEqualExceptOptions = DeepOmitOptions;\n\n/**\n * Performs a deep equality comparison between two values after omitting specified keys.\n * \n * This function first removes the specified keys from both values using `deepOmit`,\n * then performs a deep equality check using `deepEqual`.\n * \n * @param a - The first value to compare\n * @param b - The second value to compare\n * @param options - Options specifying which keys to omit before comparison\n * @returns `true` if the values are deeply equal after omitting specified keys, `false` otherwise\n * \n * @example\n * ```ts\n * const obj1 = { id: 1, name: \"Alice\", updatedAt: \"2024-01-01\" };\n * const obj2 = { id: 2, name: \"Alice\", updatedAt: \"2024-01-02\" };\n * \n * deepEqualExcept(obj1, obj2, { ignoreKeys: [\"id\", \"updatedAt\"] }); // true\n * ```\n */\nexport function deepEqualExcept(\n\ta: unknown,\n\tb: unknown,\n\toptions: DeepEqualExceptOptions,\n): boolean {\n\tconst prunedA = deepOmit(a, options);\n\tconst prunedB = deepOmit(b, options);\n\treturn deepEqual(prunedA, prunedB);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shirudo/ddd-kit",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Composable TypeScript toolkit for tactical DDD",
5
5
  "type": "module",
6
6
  "repository": {
@@ -53,7 +53,7 @@
53
53
  "devDependencies": {
54
54
  "@biomejs/biome": "2.1.4",
55
55
  "@shirudo/base-error": "^5.0.0",
56
- "@shirudo/result": "^0.0.6",
56
+ "@shirudo/result": "^1.0.0",
57
57
  "tsup": "^8.5.0",
58
58
  "typedoc": "^0.28.19",
59
59
  "typedoc-plugin-markdown": "^4.11.0",
@@ -74,6 +74,6 @@
74
74
  },
75
75
  "peerDependencies": {
76
76
  "@shirudo/base-error": "^5.0.0",
77
- "@shirudo/result": "^0.0.6"
77
+ "@shirudo/result": "^1.0.0"
78
78
  }
79
79
  }