@jest/expect-utils 30.2.0 → 30.4.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/build/index.d.ts CHANGED
@@ -91,5 +91,3 @@ export declare interface TesterContext {
91
91
  }
92
92
 
93
93
  export declare const typeEquality: (a: any, b: any) => boolean | undefined;
94
-
95
- export {};
package/build/index.js CHANGED
@@ -10,8 +10,8 @@
10
10
  /******/ "use strict";
11
11
  /******/ var __webpack_modules__ = ({
12
12
 
13
- /***/ "./src/immutableUtils.ts":
14
- /***/ ((__unused_webpack_module, exports) => {
13
+ /***/ "./src/immutableUtils.ts"
14
+ (__unused_webpack_module, exports) {
15
15
 
16
16
 
17
17
 
@@ -60,10 +60,10 @@ function isImmutableRecord(source) {
60
60
  return Boolean(source && isObjectLiteral(source) && source[IS_RECORD_SYMBOL]);
61
61
  }
62
62
 
63
- /***/ }),
63
+ /***/ },
64
64
 
65
- /***/ "./src/index.ts":
66
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
65
+ /***/ "./src/index.ts"
66
+ (__unused_webpack_module, exports, __webpack_require__) {
67
67
 
68
68
 
69
69
 
@@ -100,10 +100,10 @@ Object.keys(_utils).forEach(function (key) {
100
100
  });
101
101
  });
102
102
 
103
- /***/ }),
103
+ /***/ },
104
104
 
105
- /***/ "./src/jasmineUtils.ts":
106
- /***/ ((__unused_webpack_module, exports) => {
105
+ /***/ "./src/jasmineUtils.ts"
106
+ (__unused_webpack_module, exports) {
107
107
 
108
108
 
109
109
 
@@ -305,10 +305,10 @@ function isDomNode(obj) {
305
305
  return obj !== null && typeof obj === 'object' && typeof obj.nodeType === 'number' && typeof obj.nodeName === 'string' && typeof obj.isEqualNode === 'function';
306
306
  }
307
307
 
308
- /***/ }),
308
+ /***/ },
309
309
 
310
- /***/ "./src/utils.ts":
311
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
310
+ /***/ "./src/utils.ts"
311
+ (__unused_webpack_module, exports, __webpack_require__) {
312
312
 
313
313
 
314
314
 
@@ -410,7 +410,10 @@ const getObjectSubset = (object, subset, customTesters = [], seenReferences = ne
410
410
  }
411
411
  const trimmed = {};
412
412
  seenReferences.set(object, trimmed);
413
- for (const key of getObjectKeys(object).filter(key => hasPropertyInObject(subset, key))) {
413
+ for (const key of getObjectKeys(object)) {
414
+ if (!hasPropertyInObject(subset, key)) {
415
+ continue;
416
+ }
414
417
  trimmed[key] = seenReferences.has(object[key]) ? seenReferences.get(object[key]) : getObjectSubset(object[key], subset[key], customTesters, seenReferences);
415
418
  }
416
419
  if (getObjectKeys(trimmed).length > 0) {
@@ -430,7 +433,11 @@ aStack = [], bStack = []) => {
430
433
  return undefined;
431
434
  }
432
435
  if (a.constructor !== b.constructor) {
433
- return false;
436
+ // Same cross-realm constructor check as typeEquality — see #14011.
437
+ // https://github.com/jestjs/jest/issues/14011
438
+ if (a.constructor == null || b.constructor == null || a.constructor.name !== b.constructor.name || !isNativeFunction(a.constructor) || !isNativeFunction(b.constructor)) {
439
+ return false;
440
+ }
434
441
  }
435
442
  let length = aStack.length;
436
443
  while (length--) {
@@ -500,12 +507,26 @@ aStack = [], bStack = []) => {
500
507
  return allFound;
501
508
  }
502
509
  }
503
- const bIterator = b[IteratorSymbol]();
504
- for (const aValue of a) {
505
- const nextB = bIterator.next();
506
- if (nextB.done || !(0, _jasmineUtils.equals)(aValue, nextB.value, filteredCustomTesters)) {
510
+ let aIterator;
511
+ let bIterator;
512
+ try {
513
+ aIterator = a[IteratorSymbol]();
514
+ bIterator = b[IteratorSymbol]();
515
+ } catch {
516
+ // If the iterator factory itself throws (e.g. a TypedArray method used as
517
+ // [Symbol.iterator] on a plain object), we cannot compare as iterables.
518
+ // Return undefined so equals() falls through to Object.is / property checks.
519
+ aStack.pop();
520
+ bStack.pop();
521
+ return undefined;
522
+ }
523
+ let aStep = aIterator.next();
524
+ while (!aStep.done) {
525
+ const bStep = bIterator.next();
526
+ if (bStep.done || !(0, _jasmineUtils.equals)(aStep.value, bStep.value, filteredCustomTesters)) {
507
527
  return false;
508
528
  }
529
+ aStep = aIterator.next();
509
530
  }
510
531
  if (!bIterator.next().done) {
511
532
  return false;
@@ -564,8 +585,13 @@ const subsetEquality = (object, subset, customTesters = []) => {
564
585
  return subsetEqualityWithContext()(object, subset);
565
586
  };
566
587
 
567
- // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
588
+ // Returns true if `fn` is a native function (its toString contains "[native code]").
568
589
  exports.subsetEquality = subsetEquality;
590
+ function isNativeFunction(fn) {
591
+ return typeof fn === 'function' && Function.prototype.toString.call(fn).includes('[native code]');
592
+ }
593
+
594
+ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
569
595
  const typeEquality = (a, b) => {
570
596
  if (a == null || b == null || a.constructor === b.constructor ||
571
597
  // Since Jest globals are different from Node globals,
@@ -575,6 +601,15 @@ const typeEquality = (a, b) => {
575
601
  Array.isArray(a) && Array.isArray(b)) {
576
602
  return undefined;
577
603
  }
604
+
605
+ // structuredClone (and other cross-realm calls) return objects whose
606
+ // constructors come from a different VM context, so identity checks fail.
607
+ // Fall back to comparing constructor names for native built-ins only —
608
+ // user-defined classes still need identity equality.
609
+ // https://github.com/jestjs/jest/issues/14011
610
+ if (a.constructor != null && b.constructor != null && a.constructor.name === b.constructor.name && isNativeFunction(a.constructor) && isNativeFunction(b.constructor)) {
611
+ return undefined;
612
+ }
578
613
  return false;
579
614
  };
580
615
  exports.typeEquality = typeEquality;
@@ -667,7 +702,7 @@ const MULTILINE_REGEXP = /[\n\r]/;
667
702
  const isOneline = (expected, received) => typeof expected === 'string' && typeof received === 'string' && (!MULTILINE_REGEXP.test(expected) || !MULTILINE_REGEXP.test(received));
668
703
  exports.isOneline = isOneline;
669
704
 
670
- /***/ })
705
+ /***/ }
671
706
 
672
707
  /******/ });
673
708
  /************************************************************************/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jest/expect-utils",
3
- "version": "30.2.0",
3
+ "version": "30.4.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/jestjs/jest.git",
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "devDependencies": {
25
25
  "immutable": "^5.1.2",
26
- "jest-matcher-utils": "30.2.0"
26
+ "jest-matcher-utils": "30.4.0"
27
27
  },
28
28
  "engines": {
29
29
  "node": "^18.14.0 || ^20.0.0 || ^22.0.0 || >=24.0.0"
@@ -31,5 +31,5 @@
31
31
  "publishConfig": {
32
32
  "access": "public"
33
33
  },
34
- "gitHead": "855864e3f9751366455246790be2bf912d4d0dac"
34
+ "gitHead": "5cbb21e0b3037edb42e503ec1a1ce80efad40c20"
35
35
  }
package/build/index.d.mts DELETED
@@ -1,35 +0,0 @@
1
- //#region src/types.d.ts
2
-
3
- type Tester = (this: TesterContext, a: any, b: any, customTesters: Array<Tester>) => boolean | undefined;
4
- interface TesterContext {
5
- equals: EqualsFunction;
6
- }
7
- //#endregion
8
- //#region src/jasmineUtils.d.ts
9
- type EqualsFunction = (a: unknown, b: unknown, customTesters?: Array<Tester>, strictCheck?: boolean) => boolean;
10
- declare const equals: EqualsFunction;
11
- declare function isA<T>(typeName: string, value: unknown): value is T;
12
- //#endregion
13
- //#region src/utils.d.ts
14
- type GetPath = {
15
- hasEndProp?: boolean;
16
- endPropIsDefined?: boolean;
17
- lastTraversedObject: unknown;
18
- traversedPath: Array<string>;
19
- value?: unknown;
20
- };
21
- declare const getObjectKeys: (object: object) => Array<string | symbol>;
22
- declare const getPath: (object: Record<string, any>, propertyPath: string | Array<string>) => GetPath;
23
- declare const getObjectSubset: (object: any, subset: any, customTesters?: Array<Tester>, seenReferences?: WeakMap<object, boolean>) => any;
24
- declare const iterableEquality: (a: any, b: any, customTesters?: Array<Tester>, aStack?: Array<any>, bStack?: Array<any>) => boolean | undefined;
25
- declare const subsetEquality: (object: unknown, subset: unknown, customTesters?: Array<Tester>) => boolean | undefined;
26
- declare const typeEquality: (a: any, b: any) => boolean | undefined;
27
- declare const arrayBufferEquality: (a: unknown, b: unknown) => boolean | undefined;
28
- declare const sparseArrayEquality: (a: unknown, b: unknown, customTesters?: Array<Tester>) => boolean | undefined;
29
- declare const partition: <T>(items: Array<T>, predicate: (arg: T) => boolean) => [Array<T>, Array<T>];
30
- declare const pathAsArray: (propertyPath: string) => Array<any>;
31
- declare const isError: (value: unknown) => value is Error;
32
- declare function emptyObject(obj: unknown): boolean;
33
- declare const isOneline: (expected: unknown, received: unknown) => boolean;
34
- //#endregion
35
- export { EqualsFunction, Tester, TesterContext, arrayBufferEquality, emptyObject, equals, getObjectKeys, getObjectSubset, getPath, isA, isError, isOneline, iterableEquality, partition, pathAsArray, sparseArrayEquality, subsetEquality, typeEquality };