fast-is-equal 1.0.2 → 1.0.4

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/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # fast-is-equal
2
2
 
3
- Blazing-fast equality checks, minus the baggage. A lean, standalone alternative to Lodash’s `isEqual`—because speed matters.
3
+ Blazing-fast equality checks, minus the baggage. A lean, standalone alternative to Lodash’s `isEqual` - because speed matters.
4
+
5
+ [![npm version](https://img.shields.io/npm/v/fast-is-equal)](https://badge.fury.io/js/fast-is-equal)
4
6
 
5
7
  ## Installation
6
8
 
@@ -174,4 +176,4 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
174
176
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
175
177
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
176
178
  SOFTWARE.
177
- ```
179
+ ```
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const index_1 = require("../index");
4
- describe('isEqual', () => {
4
+ describe('fastIsEqual', () => {
5
5
  // **Primitives**
6
6
  it('should return true for identical primitives', () => {
7
7
  expect((0, index_1.fastIsEqual)(1, 1)).toBe(true);
@@ -37,6 +37,21 @@ describe('isEqual', () => {
37
37
  const obj2 = { a: 1, b: { c: 2 } };
38
38
  expect((0, index_1.fastIsEqual)(obj1, obj2)).toBe(true);
39
39
  });
40
+ it('should return true for deeply unequal objects', () => {
41
+ const obj1 = { a: 1, b: { c: 2 } };
42
+ const obj2 = { a: 1, b: { c: 3 } };
43
+ expect((0, index_1.fastIsEqual)(obj1, obj2)).toBe(false);
44
+ });
45
+ it('should return true for deeply equal objects with array', () => {
46
+ const obj1 = { a: 1, b: { c: [1, 2, 3] } };
47
+ const obj2 = { a: 1, b: { c: [1, 2, 3] } };
48
+ expect((0, index_1.fastIsEqual)(obj1, obj2)).toBe(true);
49
+ });
50
+ it('should return true for deeply unequal objects with array', () => {
51
+ const obj1 = { a: 1, b: { c: [1, 2, 3] } };
52
+ const obj2 = { a: 1, b: { c: [1, 2, 3, 4] } };
53
+ expect((0, index_1.fastIsEqual)(obj1, obj2)).toBe(false);
54
+ });
40
55
  it('should return false for objects with different keys', () => {
41
56
  const obj1 = { a: 1 };
42
57
  const obj2 = { b: 1 };
@@ -67,6 +82,11 @@ describe('isEqual', () => {
67
82
  const arr2 = [1, 3];
68
83
  expect((0, index_1.fastIsEqual)(arr1, arr2)).toBe(false);
69
84
  });
85
+ it('should return true for arrays with different order', () => {
86
+ const arr1 = [1, 2, 3, 4];
87
+ const arr2 = [1, 2, 4, 3];
88
+ expect((0, index_1.fastIsEqual)(arr1, arr2)).toBe(false);
89
+ });
70
90
  // **Dates**
71
91
  it('should return true for identical dates', () => {
72
92
  const date = new Date();
@@ -177,4 +197,137 @@ describe('isEqual', () => {
177
197
  expect((0, index_1.fastIsEqual)({}, [])).toBe(false);
178
198
  expect((0, index_1.fastIsEqual)(new Map(), new Set())).toBe(false);
179
199
  });
200
+ // **Symbol Tests**
201
+ it('should return true for identical symbols', () => {
202
+ const sym = Symbol('test');
203
+ expect((0, index_1.fastIsEqual)(sym, sym)).toBe(true);
204
+ });
205
+ it('should return false for different symbols with same description', () => {
206
+ expect((0, index_1.fastIsEqual)(Symbol('test'), Symbol('test'))).toBe(false);
207
+ });
208
+ // **BigInt Tests**
209
+ it('should return true for identical BigInts', () => {
210
+ expect((0, index_1.fastIsEqual)(BigInt(123), BigInt(123))).toBe(true);
211
+ });
212
+ it('should return false for different BigInts', () => {
213
+ expect((0, index_1.fastIsEqual)(BigInt(123), BigInt(456))).toBe(false);
214
+ });
215
+ // **Nested Complex Structures**
216
+ it('should handle deeply nested objects with arrays, maps and sets', () => {
217
+ const obj1 = {
218
+ a: [1, 2, { b: new Map([['key', new Set([1, 2, { c: 3 }])]]) }],
219
+ d: new Set([new Map([['e', { f: 7 }]])])
220
+ };
221
+ const obj2 = {
222
+ a: [1, 2, { b: new Map([['key', new Set([1, 2, { c: 3 }])]]) }],
223
+ d: new Set([new Map([['e', { f: 7 }]])])
224
+ };
225
+ expect((0, index_1.fastIsEqual)(obj1, obj2)).toBe(true);
226
+ });
227
+ it('should detect differences in deeply nested structures', () => {
228
+ const obj1 = {
229
+ a: [1, 2, { b: new Map([['key', new Set([1, 2, { c: 3 }])]]) }]
230
+ };
231
+ const obj2 = {
232
+ a: [1, 2, { b: new Map([['key', new Set([1, 2, { c: 4 }])]]) }]
233
+ };
234
+ expect((0, index_1.fastIsEqual)(obj1, obj2)).toBe(false);
235
+ });
236
+ // **Typed Arrays**
237
+ it('should compare typed arrays correctly', () => {
238
+ expect((0, index_1.fastIsEqual)(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2, 3]))).toBe(true);
239
+ expect((0, index_1.fastIsEqual)(new Int32Array([1, 2, 3]), new Int32Array([1, 2, 3]))).toBe(true);
240
+ expect((0, index_1.fastIsEqual)(new Float64Array([1.1, 2.2]), new Float64Array([1.1, 2.2]))).toBe(true);
241
+ expect((0, index_1.fastIsEqual)(new Uint8Array([1, 2, 3]), new Uint8Array([1, 2, 4]))).toBe(false);
242
+ expect((0, index_1.fastIsEqual)(new Uint8Array([1, 2]), new Int8Array([1, 2]))).toBe(false);
243
+ });
244
+ // **Partial Object Comparison with Extra Keys**
245
+ it('should detect when objects have extra keys', () => {
246
+ const obj1 = { a: 1, b: 2 };
247
+ const obj2 = { a: 1, b: 2, c: 3 };
248
+ expect((0, index_1.fastIsEqual)(obj1, obj2)).toBe(false);
249
+ });
250
+ // **Object with Different Property Orders**
251
+ it('should return true for objects with same properties in different order', () => {
252
+ const obj1 = { a: 1, b: 2, c: 3 };
253
+ const obj2 = { c: 3, a: 1, b: 2 };
254
+ expect((0, index_1.fastIsEqual)(obj1, obj2)).toBe(true);
255
+ });
256
+ // **Map/Set with Object Keys/Values**
257
+ it('should handle Maps with object keys correctly', () => {
258
+ const key1 = { id: 1 };
259
+ const key2 = { id: 1 };
260
+ const map1 = new Map([[key1, 'value']]);
261
+ const map2 = new Map([[key2, 'value']]);
262
+ // Objects as keys are compared by reference
263
+ expect((0, index_1.fastIsEqual)(map1, map2)).toBe(false);
264
+ // Same reference should work
265
+ const map3 = new Map([[key1, 'value']]);
266
+ expect((0, index_1.fastIsEqual)(map1, map3)).toBe(true);
267
+ });
268
+ // **WeakMap and WeakSet** (if supported by fastIsEqual)
269
+ it('should return true for identical WeakMap/WeakSet references', () => {
270
+ const weakMap = new WeakMap();
271
+ const weakSet = new WeakSet();
272
+ expect((0, index_1.fastIsEqual)(weakMap, weakMap)).toBe(true);
273
+ expect((0, index_1.fastIsEqual)(weakSet, weakSet)).toBe(true);
274
+ });
275
+ it('should return false for different WeakMap/WeakSet instances', () => {
276
+ expect((0, index_1.fastIsEqual)(new WeakMap(), new WeakMap())).toBe(false);
277
+ expect((0, index_1.fastIsEqual)(new WeakSet(), new WeakSet())).toBe(false);
278
+ });
279
+ // **Cross-circular References**
280
+ it('should handle cross-circular references', () => {
281
+ const obj1 = { name: 'object1' };
282
+ const obj2 = { name: 'object2' };
283
+ obj1.ref = obj2;
284
+ obj2.ref = obj1;
285
+ const obj3 = { name: 'object1' };
286
+ const obj4 = { name: 'object2' };
287
+ obj3.ref = obj4;
288
+ obj4.ref = obj3;
289
+ expect((0, index_1.fastIsEqual)(obj1, obj3)).toBe(true);
290
+ });
291
+ it('should detect differences in cross-circular references', () => {
292
+ const obj1 = { name: 'object1' };
293
+ const obj2 = { name: 'object2' };
294
+ obj1.ref = obj2;
295
+ obj2.ref = obj1;
296
+ const obj3 = { name: 'object1' };
297
+ const obj4 = { name: 'differentName' };
298
+ obj3.ref = obj4;
299
+ obj4.ref = obj3;
300
+ expect((0, index_1.fastIsEqual)(obj1, obj3)).toBe(false);
301
+ });
302
+ // **Edge Cases**
303
+ it('should handle -0 and +0 comparison', () => {
304
+ expect((0, index_1.fastIsEqual)(0, -0)).toBe(true); // Depending on implementation
305
+ });
306
+ it('should handle Object.create(null)', () => {
307
+ const obj1 = Object.create(null);
308
+ obj1.a = 1;
309
+ const obj2 = Object.create(null);
310
+ obj2.a = 1;
311
+ expect((0, index_1.fastIsEqual)(obj1, obj2)).toBe(true);
312
+ });
313
+ // **Performance Stress Test**
314
+ it('should handle large objects without stack overflow', () => {
315
+ // Create a very deep object
316
+ let obj1 = {};
317
+ let obj2 = {};
318
+ let temp1 = obj1;
319
+ let temp2 = obj2;
320
+ for (let i = 0; i < 1000; i++) {
321
+ temp1.next = {};
322
+ temp2.next = {};
323
+ temp1 = temp1.next;
324
+ temp2 = temp2.next;
325
+ temp1.value = i;
326
+ temp2.value = i;
327
+ }
328
+ expect((0, index_1.fastIsEqual)(obj1, obj2)).toBe(true);
329
+ // Change a value deep in the structure
330
+ temp2.value = 'different';
331
+ expect((0, index_1.fastIsEqual)(obj1, obj2)).toBe(false);
332
+ });
180
333
  });
package/dist/index.js CHANGED
@@ -52,6 +52,13 @@ function deepEqual(valA, valB, visited) {
52
52
  return valA === valB;
53
53
  if (typeof valA !== typeof valB)
54
54
  return false;
55
+ // Handle WeakMap and WeakSet (reference equality)
56
+ if (valA instanceof WeakMap && valB instanceof WeakMap) {
57
+ return valA === valB;
58
+ }
59
+ if (valA instanceof WeakSet && valB instanceof WeakSet) {
60
+ return valA === valB;
61
+ }
55
62
  // Handle Dates
56
63
  if (valA instanceof Date && valB instanceof Date) {
57
64
  return valA.getTime() === valB.getTime();
@@ -96,12 +103,23 @@ function deepEqual(valA, valB, visited) {
96
103
  }
97
104
  return true;
98
105
  }
99
- // Handle Sets
106
+ // Handle Sets with deep equality
100
107
  if (valA instanceof Set && valB instanceof Set) {
101
108
  if (valA.size !== valB.size)
102
109
  return false;
103
- for (const value of valA) {
104
- if (!valB.has(value))
110
+ const arrA = Array.from(valA);
111
+ const arrB = Array.from(valB);
112
+ const matched = new Set();
113
+ for (const elemA of arrA) {
114
+ let found = false;
115
+ for (const elemB of arrB) {
116
+ if (!matched.has(elemB) && deepEqual(elemA, elemB, visited)) {
117
+ matched.add(elemB);
118
+ found = true;
119
+ break;
120
+ }
121
+ }
122
+ if (!found)
105
123
  return false;
106
124
  }
107
125
  return true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fast-is-equal",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Blazing-fast equality checks, minus the baggage. A lean, standalone alternative to Lodash's isEqual—because speed matters.",
5
5
  "keywords": [
6
6
  "lodash",
@@ -40,5 +40,19 @@
40
40
  "ts-node": "^10.9.2",
41
41
  "tslib": "^2.8.1",
42
42
  "typescript": "^5.8.2"
43
- }
43
+ },
44
+ "funding": [
45
+ {
46
+ "type": "individual",
47
+ "url": "https://www.paypal.com/paypalme/jairajjangle001/usd"
48
+ },
49
+ {
50
+ "type": "individual",
51
+ "url": "https://liberapay.com/FutureJJ/donate"
52
+ },
53
+ {
54
+ "type": "individual",
55
+ "url": "https://ko-fi.com/futurejj"
56
+ }
57
+ ]
44
58
  }