@@ -285,7 +285,7 @@ function _deepEqual(actual, expected, strict, memos) {
285285 return areEq ;
286286}
287287
288- function setHasSimilarElement ( set , val1 , strict , memo ) {
288+ function setHasSimilarElement ( set , val1 , bEntriesUsed , strict , memo ) {
289289 if ( set . has ( val1 ) )
290290 return true ;
291291
@@ -296,8 +296,14 @@ function setHasSimilarElement(set, val1, strict, memo) {
296296
297297 // Otherwise go looking.
298298 for ( const val2 of set ) {
299- if ( _deepEqual ( val1 , val2 , strict , memo ) )
299+ if ( bEntriesUsed && bEntriesUsed . has ( val2 ) )
300+ continue ;
301+
302+ if ( _deepEqual ( val1 , val2 , strict , memo ) ) {
303+ if ( bEntriesUsed )
304+ bEntriesUsed . add ( val2 ) ;
300305 return true ;
306+ }
301307 }
302308
303309 return false ;
@@ -314,21 +320,29 @@ function setEquiv(a, b, strict, memo) {
314320 if ( a . size !== b . size )
315321 return false ;
316322
323+ // This is a set of the entries in b which have been consumed in our pairwise
324+ // comparison. Initialized lazily so sets which only have value types can
325+ // skip an extra allocation.
326+ let bEntriesUsed = null ;
327+
317328 for ( const val1 of a ) {
318329 // If the value doesn't exist in the second set by reference, and its an
319330 // object or an array we'll need to go hunting for something thats
320331 // deep-equal to it. Note that this is O(n^2) complexity, and will get
321332 // slower if large, very similar sets / maps are nested inside.
322333 // Unfortunately there's no real way around this.
323- if ( ! setHasSimilarElement ( b , val1 , strict , memo ) ) {
334+ if ( bEntriesUsed == null && typeof val1 === 'object' )
335+ bEntriesUsed = new Set ( ) ;
336+
337+ if ( ! setHasSimilarElement ( b , val1 , bEntriesUsed , strict , memo ) ) {
324338 return false ;
325339 }
326340 }
327341
328342 return true ;
329343}
330344
331- function mapHasSimilarEntry ( map , key1 , item1 , strict , memo ) {
345+ function mapHasSimilarEntry ( map , key1 , item1 , bEntriesUsed , strict , memo ) {
332346 // To be able to handle cases like:
333347 // Map([[1, 'a'], ['1', 'b']]) vs Map([['1', 'a'], [1, 'b']])
334348 // or:
@@ -349,8 +363,13 @@ function mapHasSimilarEntry(map, key1, item1, strict, memo) {
349363 if ( key2 === key1 )
350364 continue ;
351365
366+ if ( bEntriesUsed && bEntriesUsed . has ( key2 ) )
367+ continue ;
368+
352369 if ( _deepEqual ( key1 , key2 , strict , memo ) &&
353370 _deepEqual ( item1 , item2 , strict , memo ) ) {
371+ if ( bEntriesUsed )
372+ bEntriesUsed . add ( key2 ) ;
354373 return true ;
355374 }
356375 }
@@ -366,10 +385,15 @@ function mapEquiv(a, b, strict, memo) {
366385 if ( a . size !== b . size )
367386 return false ;
368387
388+ let bEntriesUsed = null ;
389+
369390 for ( const [ key1 , item1 ] of a ) {
391+ if ( bEntriesUsed == null && typeof key1 === 'object' )
392+ bEntriesUsed = new Set ( ) ;
393+
370394 // Just like setEquiv above, this hunt makes this function O(n^2) when
371395 // using objects and lists as keys
372- if ( ! mapHasSimilarEntry ( b , key1 , item1 , strict , memo ) )
396+ if ( ! mapHasSimilarEntry ( b , key1 , item1 , bEntriesUsed , strict , memo ) )
373397 return false ;
374398 }
375399
0 commit comments