@@ -24,6 +24,7 @@ const { compare } = process.binding('buffer');
2424const  {  isSet,  isMap,  isDate,  isRegExp }  =  process . binding ( 'util' ) ; 
2525const  {  objectToString }  =  require ( 'internal/util' ) ; 
2626const  errors  =  require ( 'internal/errors' ) ; 
27+ const  {  propertyIsEnumerable }  =  Object . prototype ; 
2728
2829// The assert module provides functions that throw 
2930// AssertionError's when particular conditions are not met. The 
@@ -165,7 +166,7 @@ function isObjectOrArrayTag(tag) {
165166// For strict comparison, objects should have 
166167// a) The same built-in type tags 
167168// b) The same prototypes. 
168- function  strictDeepEqual ( actual ,  expected )  { 
169+ function  strictDeepEqual ( actual ,  expected ,   memos )  { 
169170  if  ( typeof  actual  !==  'object' )  { 
170171    return  typeof  actual  ===  'number'  &&  Number . isNaN ( actual )  && 
171172      Number . isNaN ( expected ) ; 
@@ -186,12 +187,12 @@ function strictDeepEqual(actual, expected) {
186187    // Check for sparse arrays and general fast path 
187188    if  ( actual . length  !==  expected . length ) 
188189      return  false ; 
189-     // Skip testing the part below and continue in  the callee function . 
190-     return ; 
190+     // Skip testing the part below and continue with  the keyCheck . 
191+     return   keyCheck ( actual ,   expected ,   true ,   memos ) ; 
191192  } 
192193  if  ( actualTag  ===  '[object Object]' )  { 
193-     // Skip testing the part below and continue in  the callee function . 
194-     return ; 
194+     // Skip testing the part below and continue with  the keyCheck . 
195+     return   keyCheck ( actual ,   expected ,   true ,   memos ) ; 
195196  } 
196197  if  ( isDate ( actual ) )  { 
197198    if  ( actual . getTime ( )  !==  expected . getTime ( ) )  { 
@@ -215,10 +216,8 @@ function strictDeepEqual(actual, expected) {
215216    } 
216217    // Buffer.compare returns true, so actual.length === expected.length 
217218    // if they both only contain numeric keys, we don't need to exam further 
218-     if  ( Object . keys ( actual ) . length  ===  actual . length  && 
219-         Object . keys ( expected ) . length  ===  expected . length )  { 
220-       return  true ; 
221-     } 
219+     return  keyCheck ( actual ,  expected ,  true ,  memos ,  actual . length , 
220+                     expected . length ) ; 
222221  }  else  if  ( typeof  actual . valueOf  ===  'function' )  { 
223222    const  actualValue  =  actual . valueOf ( ) ; 
224223    // Note: Boxed string keys are going to be compared again by Object.keys 
@@ -232,15 +231,14 @@ function strictDeepEqual(actual, expected) {
232231        lengthActual  =  actual . length ; 
233232        lengthExpected  =  expected . length ; 
234233      } 
235-       if  ( Object . keys ( actual ) . length  ===  lengthActual  && 
236-         Object . keys ( expected ) . length  ===  lengthExpected )  { 
237-         return  true ; 
238-       } 
234+       return  keyCheck ( actual ,  expected ,  true ,  memos ,  lengthActual , 
235+                       lengthExpected ) ; 
239236    } 
240237  } 
238+   return  keyCheck ( actual ,  expected ,  true ,  memos ) ; 
241239} 
242240
243- function  looseDeepEqual ( actual ,  expected )  { 
241+ function  looseDeepEqual ( actual ,  expected ,   memos )  { 
244242  if  ( actual  ===  null  ||  typeof  actual  !==  'object' )  { 
245243    if  ( expected  ===  null  ||  typeof  expected  !==  'object' )  { 
246244      // eslint-disable-next-line eqeqeq 
@@ -274,33 +272,62 @@ function looseDeepEqual(actual, expected) {
274272  }  else  if  ( isArguments ( actualTag )  ||  isArguments ( expectedTag ) )  { 
275273    return  false ; 
276274  } 
275+   return  keyCheck ( actual ,  expected ,  false ,  memos ) ; 
277276} 
278277
279- function  innerDeepEqual ( actual ,  expected ,  strict ,  memos )  { 
280-   // All identical values are equivalent, as determined by ===. 
281-   if  ( actual  ===  expected )  { 
282-     if  ( actual  !==  0 ) 
283-       return  true ; 
284-     return  strict  ? Object . is ( actual ,  expected )  : true ; 
285-   } 
286- 
287-   // Returns a boolean if (not) equal and undefined in case we have to check 
288-   // further. 
289-   const  partialCheck  =  strict  ?
290-     strictDeepEqual ( actual ,  expected )  :
291-     looseDeepEqual ( actual ,  expected ) ; 
292- 
293-   if  ( partialCheck  !==  undefined )  { 
294-     return  partialCheck ; 
295-   } 
296- 
278+ function  keyCheck ( actual ,  expected ,  strict ,  memos ,  lengthA ,  lengthB )  { 
297279  // For all remaining Object pairs, including Array, objects and Maps, 
298280  // equivalence is determined by having: 
299281  // a) The same number of owned enumerable properties 
300282  // b) The same set of keys/indexes (although not necessarily the same order) 
301283  // c) Equivalent values for every corresponding key/index 
302284  // d) For Sets and Maps, equal contents 
303285  // Note: this accounts for both named and indexed properties on Arrays. 
286+   var  aKeys  =  Object . keys ( actual ) ; 
287+   var  bKeys  =  Object . keys ( expected ) ; 
288+   var  i ; 
289+ 
290+   // The pair must have the same number of owned properties. 
291+   if  ( aKeys . length  !==  bKeys . length ) 
292+     return  false ; 
293+ 
294+   if  ( strict )  { 
295+     var  symbolKeysA  =  Object . getOwnPropertySymbols ( actual ) ; 
296+     var  symbolKeysB  =  Object . getOwnPropertySymbols ( expected ) ; 
297+     if  ( symbolKeysA . length  !==  0 )  { 
298+       symbolKeysA  =  symbolKeysA . filter ( ( k )  => 
299+         propertyIsEnumerable . call ( actual ,  k ) ) ; 
300+       symbolKeysB  =  symbolKeysB . filter ( ( k )  => 
301+         propertyIsEnumerable . call ( expected ,  k ) ) ; 
302+       if  ( symbolKeysA . length  !==  symbolKeysB . length ) 
303+         return  false ; 
304+     }  else  if  ( symbolKeysB . length  !==  0  &&  symbolKeysB . filter ( ( k )  => 
305+       propertyIsEnumerable . call ( expected ,  k ) ) . length  !==  0 )  { 
306+       return  false ; 
307+     } 
308+     if  ( lengthA  !==  undefined )  { 
309+       if  ( aKeys . length  !==  lengthA  ||  bKeys . length  !==  lengthB ) 
310+         return  false ; 
311+       if  ( symbolKeysA . length  ===  0 ) 
312+         return  true ; 
313+       aKeys  =  [ ] ; 
314+       bKeys  =  [ ] ; 
315+     } 
316+     if  ( symbolKeysA . length  !==  0 )  { 
317+       aKeys . push ( ...symbolKeysA ) ; 
318+       bKeys . push ( ...symbolKeysB ) ; 
319+     } 
320+   } 
321+ 
322+   // Cheap key test: 
323+   const  keys  =  { } ; 
324+   for  ( i  =  0 ;  i  <  aKeys . length ;  i ++ )  { 
325+     keys [ aKeys [ i ] ]  =  true ; 
326+   } 
327+   for  ( i  =  0 ;  i  <  aKeys . length ;  i ++ )  { 
328+     if  ( keys [ bKeys [ i ] ]  ===  undefined ) 
329+       return  false ; 
330+   } 
304331
305332  // Use memos to handle cycles. 
306333  if  ( memos  ===  undefined )  { 
@@ -323,25 +350,6 @@ function innerDeepEqual(actual, expected, strict, memos) {
323350    memos . position ++ ; 
324351  } 
325352
326-   const  aKeys  =  Object . keys ( actual ) ; 
327-   const  bKeys  =  Object . keys ( expected ) ; 
328-   var  i ; 
329- 
330-   // The pair must have the same number of owned properties 
331-   // (keys incorporates hasOwnProperty). 
332-   if  ( aKeys . length  !==  bKeys . length ) 
333-     return  false ; 
334- 
335-   // Cheap key test: 
336-   const  keys  =  { } ; 
337-   for  ( i  =  0 ;  i  <  aKeys . length ;  i ++ )  { 
338-     keys [ aKeys [ i ] ]  =  true ; 
339-   } 
340-   for  ( i  =  0 ;  i  <  aKeys . length ;  i ++ )  { 
341-     if  ( keys [ bKeys [ i ] ]  ===  undefined ) 
342-       return  false ; 
343-   } 
344- 
345353  memos . actual . set ( actual ,  memos . position ) ; 
346354  memos . expected . set ( expected ,  memos . position ) ; 
347355
@@ -353,6 +361,21 @@ function innerDeepEqual(actual, expected, strict, memos) {
353361  return  areEq ; 
354362} 
355363
364+ function  innerDeepEqual ( actual ,  expected ,  strict ,  memos )  { 
365+   // All identical values are equivalent, as determined by ===. 
366+   if  ( actual  ===  expected )  { 
367+     if  ( actual  !==  0 ) 
368+       return  true ; 
369+     return  strict  ? Object . is ( actual ,  expected )  : true ; 
370+   } 
371+ 
372+   // Check more closely if actual and expected are equal. 
373+   if  ( strict  ===  true ) 
374+     return  strictDeepEqual ( actual ,  expected ,  memos ) ; 
375+ 
376+   return  looseDeepEqual ( actual ,  expected ,  memos ) ; 
377+ } 
378+ 
356379function  setHasEqualElement ( set ,  val1 ,  strict ,  memo )  { 
357380  // Go looking. 
358381  for  ( const  val2  of  set )  { 
0 commit comments