2323const {
2424 ArrayBufferIsView,
2525 ArrayBufferPrototypeGetByteLength,
26- ArrayFrom,
2726 ArrayIsArray,
2827 ArrayPrototypeIndexOf,
2928 ArrayPrototypeJoin,
@@ -395,12 +394,11 @@ function partiallyCompareMaps(actual, expected, comparedObjects) {
395394 const expectedIterator = FunctionPrototypeCall ( SafeMap . prototype [ SymbolIterator ] , expected ) ;
396395
397396 for ( const { 0 : key , 1 : expectedValue } of expectedIterator ) {
398- if ( ! MapPrototypeHas ( actual , key ) ) {
397+ const actualValue = MapPrototypeGet ( actual , key ) ;
398+ if ( actualValue === undefined && ! MapPrototypeHas ( actual , key ) ) {
399399 return false ;
400400 }
401401
402- const actualValue = MapPrototypeGet ( actual , key ) ;
403-
404402 if ( ! compareBranch ( actualValue , expectedValue , comparedObjects ) ) {
405403 return false ;
406404 }
@@ -476,23 +474,44 @@ function partiallyCompareArrayBuffersOrViews(actual, expected) {
476474
477475function partiallyCompareSets ( actual , expected , comparedObjects ) {
478476 if ( SetPrototypeGetSize ( expected ) > SetPrototypeGetSize ( actual ) ) {
479- return false ; // `expected` can't be a subset if it has more elements
477+ return false ;
480478 }
481479
482480 if ( isDeepEqual === undefined ) lazyLoadComparison ( ) ;
483481
484- const actualArray = ArrayFrom ( FunctionPrototypeCall ( SafeSet . prototype [ SymbolIterator ] , actual ) ) ;
485482 const expectedIterator = FunctionPrototypeCall ( SafeSet . prototype [ SymbolIterator ] , expected ) ;
486- const usedIndices = new SafeSet ( ) ;
483+ let actualSet ;
484+
485+ for ( const expectedItem of expectedIterator ) {
486+ let foundMatch = false ;
487+
488+ // Check for direct inclusion first (fast path for both primitives and identical object references)
489+ if ( actual . has ( expectedItem ) ) {
490+ foundMatch = true ;
491+ } else if ( ! isPrimitive ( expectedItem ) ) {
492+ // Only create actualSet if we need it, and only add objects to it
493+ if ( actualSet === undefined ) {
494+ actualSet = new SafeSet ( ) ;
495+
496+ for ( const item of FunctionPrototypeCall ( SafeSet . prototype [ SymbolIterator ] , actual ) ) {
497+ if ( ! isPrimitive ( item ) ) {
498+ actualSet . add ( item ) ;
499+ }
500+ }
501+ }
487502
488- expectedIteration: for ( const expectedItem of expectedIterator ) {
489- for ( let actualIdx = 0 ; actualIdx < actualArray . length ; actualIdx ++ ) {
490- if ( ! usedIndices . has ( actualIdx ) && isDeepStrictEqual ( actualArray [ actualIdx ] , expectedItem ) ) {
491- usedIndices . add ( actualIdx ) ;
492- continue expectedIteration;
503+ for ( const actualItem of actualSet ) {
504+ if ( isDeepStrictEqual ( actualItem , expectedItem ) ) {
505+ actualSet . delete ( actualItem ) ;
506+ foundMatch = true ;
507+ break ;
508+ }
493509 }
494510 }
495- return false ;
511+
512+ if ( ! foundMatch ) {
513+ return false ;
514+ }
496515 }
497516
498517 return true ;
@@ -510,21 +529,26 @@ function getZeroKey(item) {
510529}
511530
512531function partiallyCompareArrays ( actual , expected , comparedObjects ) {
532+ if ( actual === expected ) return true ;
533+
513534 if ( expected . length > actual . length ) {
514535 return false ;
515536 }
516537
538+ if ( expected . length === 0 ) {
539+ return true ;
540+ }
541+
517542 if ( isDeepEqual === undefined ) lazyLoadComparison ( ) ;
518543
519544 // Create a map to count occurrences of each element in the expected array
520545 const expectedCounts = new SafeMap ( ) ;
521- const safeExpected = new SafeArrayIterator ( expected ) ;
522546
523- for ( const expectedItem of safeExpected ) {
524- // Check if the item is a zero or a -0, as these need to be handled separately
547+ const expectedIterator = new SafeArrayIterator ( expected ) ;
548+ for ( const expectedItem of expectedIterator ) {
525549 if ( expectedItem === 0 ) {
526550 const zeroKey = getZeroKey ( expectedItem ) ;
527- expectedCounts . set ( zeroKey , ( expectedCounts . get ( zeroKey ) ?. count || 0 ) + 1 ) ;
551+ expectedCounts . set ( zeroKey , ( expectedCounts . get ( zeroKey ) ?? 0 ) + 1 ) ;
528552 } else {
529553 let found = false ;
530554 for ( const { 0 : key , 1 : count } of expectedCounts ) {
@@ -540,10 +564,8 @@ function partiallyCompareArrays(actual, expected, comparedObjects) {
540564 }
541565 }
542566
543- const safeActual = new SafeArrayIterator ( actual ) ;
544-
545- for ( const actualItem of safeActual ) {
546- // Check if the item is a zero or a -0, as these need to be handled separately
567+ const actualIterator = new SafeArrayIterator ( actual ) ;
568+ for ( const actualItem of actualIterator ) {
547569 if ( actualItem === 0 ) {
548570 const zeroKey = getZeroKey ( actualItem ) ;
549571
@@ -567,6 +589,10 @@ function partiallyCompareArrays(actual, expected, comparedObjects) {
567589 }
568590 }
569591 }
592+
593+ if ( expectedCounts . size === 0 ) {
594+ return true ;
595+ }
570596 }
571597
572598 return expectedCounts . size === 0 ;
@@ -723,6 +749,10 @@ function compareExceptionKey(actual, expected, key, message, keys, fn) {
723749 }
724750}
725751
752+ function isPrimitive ( value ) {
753+ return typeof value !== 'object' || value === null ;
754+ }
755+
726756function expectedException ( actual , expected , message , fn ) {
727757 let generatedMessage = false ;
728758 let throwError = false ;
@@ -741,7 +771,7 @@ function expectedException(actual, expected, message, fn) {
741771 }
742772 throwError = true ;
743773 // Handle primitives properly.
744- } else if ( typeof actual !== 'object' || actual === null ) {
774+ } else if ( isPrimitive ( actual ) ) {
745775 const err = new AssertionError ( {
746776 actual,
747777 expected,
0 commit comments