2121'use strict' ; 
2222
2323const  { 
24+   ArrayBufferIsView, 
25+   ArrayBufferPrototypeGetByteLength, 
2426  ArrayFrom, 
2527  ArrayIsArray, 
2628  ArrayPrototypeIndexOf, 
2729  ArrayPrototypeJoin, 
2830  ArrayPrototypePush, 
2931  ArrayPrototypeSlice, 
32+   DataViewPrototypeGetBuffer, 
33+   DataViewPrototypeGetByteLength, 
34+   DataViewPrototypeGetByteOffset, 
3035  Error, 
3136  FunctionPrototypeCall, 
32-   MapPrototypeDelete, 
3337  MapPrototypeGet, 
38+   MapPrototypeGetSize, 
3439  MapPrototypeHas, 
35-   MapPrototypeSet, 
3640  NumberIsNaN, 
3741  ObjectAssign, 
3842  ObjectIs, 
3943  ObjectKeys, 
4044  ObjectPrototypeIsPrototypeOf, 
45+   ObjectPrototypeToString, 
4146  ReflectApply, 
4247  ReflectHas, 
4348  ReflectOwnKeys, 
4449  RegExpPrototypeExec, 
50+   SafeArrayIterator, 
4551  SafeMap, 
4652  SafeSet, 
4753  SafeWeakSet, 
54+   SetPrototypeGetSize, 
4855  String, 
4956  StringPrototypeIndexOf, 
5057  StringPrototypeSlice, 
5158  StringPrototypeSplit, 
5259  SymbolIterator, 
60+   TypedArrayPrototypeGetLength, 
61+   Uint8Array, 
5362}  =  primordials ; 
5463
5564const  { 
@@ -65,6 +74,8 @@ const AssertionError = require('internal/assert/assertion_error');
6574const  {  inspect }  =  require ( 'internal/util/inspect' ) ; 
6675const  {  Buffer }  =  require ( 'buffer' ) ; 
6776const  { 
77+   isArrayBuffer, 
78+   isDataView, 
6879  isKeyObject, 
6980  isPromise, 
7081  isRegExp, 
@@ -73,6 +84,8 @@ const {
7384  isDate, 
7485  isWeakSet, 
7586  isWeakMap, 
87+   isSharedArrayBuffer, 
88+   isAnyArrayBuffer, 
7689}  =  require ( 'internal/util/types' ) ; 
7790const  {  isError,  deprecate,  emitExperimentalWarning }  =  require ( 'internal/util' ) ; 
7891const  {  innerOk }  =  require ( 'internal/assert/utils' ) ; 
@@ -369,9 +382,161 @@ function isSpecial(obj) {
369382} 
370383
371384const  typesToCallDeepStrictEqualWith  =  [ 
372-   isKeyObject ,  isWeakSet ,  isWeakMap ,  Buffer . isBuffer , 
385+   isKeyObject ,  isWeakSet ,  isWeakMap ,  Buffer . isBuffer ,   isSharedArrayBuffer , 
373386] ; 
374387
388+ function  compareMaps ( actual ,  expected ,  comparedObjects )  { 
389+   if  ( MapPrototypeGetSize ( actual )  !==  MapPrototypeGetSize ( expected ) )  { 
390+     return  false ; 
391+   } 
392+   const  safeIterator  =  FunctionPrototypeCall ( SafeMap . prototype [ SymbolIterator ] ,  actual ) ; 
393+ 
394+   comparedObjects  ??=  new  SafeWeakSet ( ) ; 
395+ 
396+   for  ( const  {  0 : key ,  1 : val  }  of  safeIterator )  { 
397+     if  ( ! MapPrototypeHas ( expected ,  key ) )  { 
398+       return  false ; 
399+     } 
400+     if  ( ! compareBranch ( val ,  MapPrototypeGet ( expected ,  key ) ,  comparedObjects ) )  { 
401+       return  false ; 
402+     } 
403+   } 
404+   return  true ; 
405+ } 
406+ 
407+ function  partiallyCompareArrayBuffers ( actual ,  expected )  { 
408+   let  actualView ,  expectedView ,  expectedViewLength ; 
409+ 
410+   if  ( ! ArrayBufferIsView ( actual ) )  { 
411+     let  actualViewLength ; 
412+ 
413+     if  ( isArrayBuffer ( actual )  &&  isArrayBuffer ( expected ) )  { 
414+       actualViewLength  =  ArrayBufferPrototypeGetByteLength ( actual ) ; 
415+       expectedViewLength  =  ArrayBufferPrototypeGetByteLength ( expected ) ; 
416+     }  else  if  ( isSharedArrayBuffer ( actual )  &&  isSharedArrayBuffer ( expected ) )  { 
417+       actualViewLength  =  actual . byteLength ; 
418+       expectedViewLength  =  expected . byteLength ; 
419+     }  else  { 
420+       // Cannot compare ArrayBuffers with SharedArrayBuffers 
421+       return  false ; 
422+     } 
423+ 
424+     if  ( expectedViewLength  >  actualViewLength )  { 
425+       return  false ; 
426+     } 
427+     actualView  =  new  Uint8Array ( actual ) ; 
428+     expectedView  =  new  Uint8Array ( expected ) ; 
429+ 
430+   }  else  if  ( isDataView ( actual ) )  { 
431+     if  ( ! isDataView ( expected ) )  { 
432+       return  false ; 
433+     } 
434+     const  actualByteLength  =  DataViewPrototypeGetByteLength ( actual ) ; 
435+     expectedViewLength  =  DataViewPrototypeGetByteLength ( expected ) ; 
436+     if  ( expectedViewLength  >  actualByteLength )  { 
437+       return  false ; 
438+     } 
439+ 
440+     actualView  =  new  Uint8Array ( 
441+       DataViewPrototypeGetBuffer ( actual ) , 
442+       DataViewPrototypeGetByteOffset ( actual ) , 
443+       actualByteLength , 
444+     ) ; 
445+     expectedView  =  new  Uint8Array ( 
446+       DataViewPrototypeGetBuffer ( expected ) , 
447+       DataViewPrototypeGetByteOffset ( expected ) , 
448+       expectedViewLength , 
449+     ) ; 
450+   }  else  { 
451+     if  ( ObjectPrototypeToString ( actual )  !==  ObjectPrototypeToString ( expected ) )  { 
452+       return  false ; 
453+     } 
454+     actualView  =  actual ; 
455+     expectedView  =  expected ; 
456+     expectedViewLength  =  TypedArrayPrototypeGetLength ( expected ) ; 
457+ 
458+     if  ( expectedViewLength  >  TypedArrayPrototypeGetLength ( actual ) )  { 
459+       return  false ; 
460+     } 
461+   } 
462+ 
463+   for  ( let  i  =  0 ;  i  <  expectedViewLength ;  i ++ )  { 
464+     if  ( actualView [ i ]  !==  expectedView [ i ] )  { 
465+       return  false ; 
466+     } 
467+   } 
468+ 
469+   return  true ; 
470+ } 
471+ 
472+ function  partiallyCompareSets ( actual ,  expected ,  comparedObjects )  { 
473+   if  ( SetPrototypeGetSize ( expected )  >  SetPrototypeGetSize ( actual ) )  { 
474+     return  false ;  // `expected` can't be a subset if it has more elements 
475+   } 
476+ 
477+   if  ( isDeepEqual  ===  undefined )  lazyLoadComparison ( ) ; 
478+ 
479+   const  actualArray  =  ArrayFrom ( FunctionPrototypeCall ( SafeSet . prototype [ SymbolIterator ] ,  actual ) ) ; 
480+   const  expectedIterator  =  FunctionPrototypeCall ( SafeSet . prototype [ SymbolIterator ] ,  expected ) ; 
481+   const  usedIndices  =  new  SafeSet ( ) ; 
482+ 
483+   expectedIteration: for  ( const  expectedItem  of  expectedIterator )  { 
484+     for  ( let  actualIdx  =  0 ;  actualIdx  <  actualArray . length ;  actualIdx ++ )  { 
485+       if  ( ! usedIndices . has ( actualIdx )  &&  isDeepStrictEqual ( actualArray [ actualIdx ] ,  expectedItem ) )  { 
486+         usedIndices . add ( actualIdx ) ; 
487+         continue  expectedIteration; 
488+       } 
489+     } 
490+     return  false ; 
491+   } 
492+ 
493+   return  true ; 
494+ } 
495+ 
496+ function  partiallyCompareArrays ( actual ,  expected ,  comparedObjects )  { 
497+   if  ( expected . length  >  actual . length )  { 
498+     return  false ; 
499+   } 
500+ 
501+   if  ( isDeepEqual  ===  undefined )  lazyLoadComparison ( ) ; 
502+ 
503+   // Create a map to count occurrences of each element in the expected array 
504+   const  expectedCounts  =  new  SafeMap ( ) ; 
505+   for  ( const  expectedItem  of  expected )  { 
506+     let  found  =  false ; 
507+     for  ( const  {  0 : key ,  1 : count  }  of  expectedCounts )  { 
508+       if  ( isDeepStrictEqual ( key ,  expectedItem ) )  { 
509+         expectedCounts . set ( key ,  count  +  1 ) ; 
510+         found  =  true ; 
511+         break ; 
512+       } 
513+     } 
514+     if  ( ! found )  { 
515+       expectedCounts . set ( expectedItem ,  1 ) ; 
516+     } 
517+   } 
518+ 
519+   const  safeActual  =  new  SafeArrayIterator ( actual ) ; 
520+ 
521+   // Create a map to count occurrences of relevant elements in the actual array 
522+   for  ( const  actualItem  of  safeActual )  { 
523+     for  ( const  {  0 : key ,  1 : count  }  of  expectedCounts )  { 
524+       if  ( isDeepStrictEqual ( key ,  actualItem ) )  { 
525+         if  ( count  ===  1 )  { 
526+           expectedCounts . delete ( key ) ; 
527+         }  else  { 
528+           expectedCounts . set ( key ,  count  -  1 ) ; 
529+         } 
530+         break ; 
531+       } 
532+     } 
533+   } 
534+ 
535+   const  {  size }  =  expectedCounts ; 
536+   expectedCounts . clear ( ) ; 
537+   return  size  ===  0 ; 
538+ } 
539+ 
375540/** 
376541 * Compares two objects or values recursively to check if they are equal. 
377542 * @param  {any } actual - The actual value to compare. 
@@ -388,22 +553,16 @@ function compareBranch(
388553)  { 
389554  // Check for Map object equality 
390555  if  ( isMap ( actual )  &&  isMap ( expected ) )  { 
391-     if  ( actual . size  !==  expected . size )  { 
392-       return  false ; 
393-     } 
394-     const  safeIterator  =  FunctionPrototypeCall ( SafeMap . prototype [ SymbolIterator ] ,  actual ) ; 
395- 
396-     comparedObjects  ??=  new  SafeWeakSet ( ) ; 
556+     return  compareMaps ( actual ,  expected ,  comparedObjects ) ; 
557+   } 
397558
398-     for  ( const  {  0 : key ,  1 : val  }  of  safeIterator )  { 
399-       if  ( ! MapPrototypeHas ( expected ,  key ) )  { 
400-         return  false ; 
401-       } 
402-       if  ( ! compareBranch ( val ,  MapPrototypeGet ( expected ,  key ) ,  comparedObjects ) )  { 
403-         return  false ; 
404-       } 
405-     } 
406-     return  true ; 
559+   if  ( 
560+     ArrayBufferIsView ( actual )  || 
561+     isAnyArrayBuffer ( actual )  || 
562+     ArrayBufferIsView ( expected )  || 
563+     isAnyArrayBuffer ( expected ) 
564+   )  { 
565+     return  partiallyCompareArrayBuffers ( actual ,  expected ) ; 
407566  } 
408567
409568  for  ( const  type  of  typesToCallDeepStrictEqualWith )  { 
@@ -415,68 +574,12 @@ function compareBranch(
415574
416575  // Check for Set object equality 
417576  if  ( isSet ( actual )  &&  isSet ( expected ) )  { 
418-     if  ( expected . size  >  actual . size )  { 
419-       return  false ;  // `expected` can't be a subset if it has more elements 
420-     } 
421- 
422-     if  ( isDeepEqual  ===  undefined )  lazyLoadComparison ( ) ; 
423- 
424-     const  actualArray  =  ArrayFrom ( FunctionPrototypeCall ( SafeSet . prototype [ SymbolIterator ] ,  actual ) ) ; 
425-     const  expectedIterator  =  FunctionPrototypeCall ( SafeSet . prototype [ SymbolIterator ] ,  expected ) ; 
426-     const  usedIndices  =  new  SafeSet ( ) ; 
427- 
428-     expectedIteration: for  ( const  expectedItem  of  expectedIterator )  { 
429-       for  ( let  actualIdx  =  0 ;  actualIdx  <  actualArray . length ;  actualIdx ++ )  { 
430-         if  ( ! usedIndices . has ( actualIdx )  &&  isDeepStrictEqual ( actualArray [ actualIdx ] ,  expectedItem ) )  { 
431-           usedIndices . add ( actualIdx ) ; 
432-           continue  expectedIteration; 
433-         } 
434-       } 
435-       return  false ; 
436-     } 
437- 
438-     return  true ; 
577+     return  partiallyCompareSets ( actual ,  expected ,  comparedObjects ) ; 
439578  } 
440579
441580  // Check if expected array is a subset of actual array 
442581  if  ( ArrayIsArray ( actual )  &&  ArrayIsArray ( expected ) )  { 
443-     if  ( expected . length  >  actual . length )  { 
444-       return  false ; 
445-     } 
446- 
447-     if  ( isDeepEqual  ===  undefined )  lazyLoadComparison ( ) ; 
448- 
449-     // Create a map to count occurrences of each element in the expected array 
450-     const  expectedCounts  =  new  SafeMap ( ) ; 
451-     for  ( const  expectedItem  of  expected )  { 
452-       let  found  =  false ; 
453-       for  ( const  {  0 : key ,  1 : count  }  of  expectedCounts )  { 
454-         if  ( isDeepStrictEqual ( key ,  expectedItem ) )  { 
455-           MapPrototypeSet ( expectedCounts ,  key ,  count  +  1 ) ; 
456-           found  =  true ; 
457-           break ; 
458-         } 
459-       } 
460-       if  ( ! found )  { 
461-         MapPrototypeSet ( expectedCounts ,  expectedItem ,  1 ) ; 
462-       } 
463-     } 
464- 
465-     // Create a map to count occurrences of relevant elements in the actual array 
466-     for  ( const  actualItem  of  actual )  { 
467-       for  ( const  {  0 : key ,  1 : count  }  of  expectedCounts )  { 
468-         if  ( isDeepStrictEqual ( key ,  actualItem ) )  { 
469-           if  ( count  ===  1 )  { 
470-             MapPrototypeDelete ( expectedCounts ,  key ) ; 
471-           }  else  { 
472-             MapPrototypeSet ( expectedCounts ,  key ,  count  -  1 ) ; 
473-           } 
474-           break ; 
475-         } 
476-       } 
477-     } 
478- 
479-     return  ! expectedCounts . size ; 
582+     return  partiallyCompareArrays ( actual ,  expected ,  comparedObjects ) ; 
480583  } 
481584
482585  // Comparison done when at least one of the values is not an object 
0 commit comments