11'use strict' ;
2- /* globals Symbol: true, Uint8Array: true */
2+ /* globals Symbol: true, Uint8Array: true, WeakMap: true */
33/*!
44 * deep-eql
55 * Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com>
1313var type = require ( 'type-detect' ) ;
1414var objectIs = Object . is || require ( 'object-is' ) ; // eslint-disable-line
1515
16+ function FakeMap ( ) {
17+ this . clear ( ) ;
18+ }
19+ FakeMap . prototype = {
20+ clear : function clearMap ( ) {
21+ this . keys = [ ] ;
22+ this . values = [ ] ;
23+ return this ;
24+ } ,
25+ set : function setMap ( key , value ) {
26+ var index = this . keys . indexOf ( key ) ;
27+ if ( index >= 0 ) {
28+ this . values [ index ] = value ;
29+ } else {
30+ this . keys . push ( key ) ;
31+ this . values . push ( value ) ;
32+ }
33+ return this ;
34+ } ,
35+ get : function getMap ( key ) {
36+ return this . values [ this . keys . indexOf ( key ) ] ;
37+ } ,
38+ delete : function deleteMap ( key ) {
39+ var index = this . keys . indexOf ( key ) ;
40+ if ( index >= 0 ) {
41+ this . values = this . values . slice ( 0 , index ) . concat ( this . values . slice ( index + 1 ) ) ;
42+ this . keys = this . keys . slice ( 0 , index ) . concat ( this . keys . slice ( index + 1 ) ) ;
43+ }
44+ return this ;
45+ } ,
46+ } ;
47+
48+ var MemoizeMap = null ;
49+ if ( typeof WeakMap === 'function' ) {
50+ MemoizeMap = WeakMap ;
51+ } else {
52+ MemoizeMap = FakeMap ;
53+ }
54+
55+ function memoizeCompare ( leftHandOperand , rightHandOperand , memoizeMap ) {
56+ var leftHandMap = memoizeMap . get ( leftHandOperand ) ;
57+ if ( leftHandMap ) {
58+ var result = leftHandMap . get ( rightHandOperand ) ;
59+ if ( typeof result === 'boolean' ) {
60+ return result ;
61+ }
62+ }
63+ return null ;
64+ }
65+
66+ function memoizeSet ( leftHandOperand , rightHandOperand , memoizeMap , result ) {
67+ if ( ! memoizeMap ) {
68+ return ;
69+ }
70+ var leftHandMap = memoizeMap . get ( leftHandOperand ) ;
71+ if ( leftHandMap ) {
72+ leftHandMap . set ( rightHandOperand , result ) ;
73+ } else {
74+ leftHandMap = new MemoizeMap ( ) ;
75+ leftHandMap . set ( rightHandOperand , result ) ;
76+ memoizeMap . set ( leftHandOperand , leftHandMap ) ;
77+ }
78+ }
79+
1680/*!
1781 * Primary Export
1882 */
1983
2084module . exports = deepEqual ;
85+ module . exports . MemoizeMap = MemoizeMap ;
2186
2287/**
2388 * Assert deeply nested sameValue equality between two objects of any type.
@@ -29,28 +94,44 @@ module.exports = deepEqual;
2994 * @return {Boolean } equal match
3095 */
3196
32- function deepEqual ( leftHandOperand , rightHandOperand , comparatorOrMemoize , memoizeObject ) {
33- memoizeObject = memoizeObject || [ ] ;
34- var comparator = comparatorOrMemoize ;
35- if ( type ( comparatorOrMemoize ) !== 'function' ) {
36- memoizeObject = comparatorOrMemoize || [ ] ;
37- comparator = false ;
97+ function deepEqual ( leftHandOperand , rightHandOperand , options ) {
98+ options = options || { } ;
99+ options = {
100+ comparator : options . comparator || objectIs ,
101+ memoize : options . memoize || true ,
102+ } ;
103+ if ( options . memoize === true ) {
104+ options . memoize = new MemoizeMap ( ) ;
38105 }
39106
40- if ( comparator ) {
41- return comparator ( leftHandOperand , rightHandOperand ) ;
107+ var result = objectIs ( leftHandOperand , rightHandOperand ) ;
108+ if ( result ) {
109+ return true ;
110+ }
111+
112+ var memoizeResult = memoizeCompare ( leftHandOperand , rightHandOperand , options . memoize ) ;
113+ if ( typeof memoizeResult === 'boolean' ) {
114+ return memoizeResult ;
42115 }
43116
44- var sameValue = objectIs ( leftHandOperand , rightHandOperand ) ;
45- if ( sameValue ) {
117+ if ( options . comparator . call ( null , leftHandOperand , rightHandOperand ) ) {
118+ memoizeSet ( leftHandOperand , rightHandOperand , options . memoize , true ) ;
119+ memoizeSet ( rightHandOperand , leftHandOperand , options . memoize , true ) ;
46120 return true ;
47121 }
48122
49123 var leftHandType = type ( leftHandOperand ) ;
50124 if ( leftHandType !== type ( rightHandOperand ) ) {
125+ memoizeSet ( leftHandOperand , rightHandOperand , options . memoize , false ) ;
126+ memoizeSet ( rightHandOperand , leftHandOperand , options . memoize , false ) ;
51127 return false ;
52128 }
53129
130+ // Temporarily set the operands in the memoize object to prevent blowing the stack
131+ if ( typeof leftHandOperand === 'object' ) {
132+ memoizeSet ( leftHandOperand , rightHandOperand , options . memoize , result ) ;
133+ memoizeSet ( rightHandOperand , leftHandOperand , options . memoize , result ) ;
134+ }
54135 switch ( leftHandType ) {
55136 case 'string' :
56137 case 'number' :
@@ -61,7 +142,7 @@ function deepEqual(leftHandOperand, rightHandOperand, comparatorOrMemoize, memoi
61142 case 'weakmap' :
62143 case 'weakset' :
63144 case 'error' :
64- return sameValue ;
145+ return result ;
65146 case 'arguments' :
66147 case 'int8array' :
67148 case 'uint8array' :
@@ -73,22 +154,32 @@ function deepEqual(leftHandOperand, rightHandOperand, comparatorOrMemoize, memoi
73154 case 'float32array' :
74155 case 'float64array' :
75156 case 'array' :
76- return iterableEqual ( leftHandOperand , rightHandOperand , memoizeObject ) ;
157+ result = iterableEqual ( leftHandOperand , rightHandOperand , options ) ;
158+ break ;
77159 case 'date' :
78- return dateEqual ( leftHandOperand , rightHandOperand ) ;
160+ result = dateEqual ( leftHandOperand , rightHandOperand ) ;
161+ break ;
79162 case 'regexp' :
80- return regexpEqual ( leftHandOperand , rightHandOperand ) ;
163+ result = regexpEqual ( leftHandOperand , rightHandOperand ) ;
164+ break ;
81165 case 'generator' :
82- return generatorEqual ( leftHandOperand , rightHandOperand , memoizeObject ) ;
166+ result = generatorEqual ( leftHandOperand , rightHandOperand , options ) ;
167+ break ;
83168 case 'dataview' :
84- return iterableEqual ( new Uint8Array ( leftHandOperand . buffer ) , new Uint8Array ( rightHandOperand . buffer ) ) ;
169+ result = iterableEqual ( new Uint8Array ( leftHandOperand . buffer ) , new Uint8Array ( rightHandOperand . buffer ) , options ) ;
170+ break ;
85171 case 'arraybuffer' :
86- return iterableEqual ( new Uint8Array ( leftHandOperand ) , new Uint8Array ( rightHandOperand ) ) ;
172+ result = iterableEqual ( new Uint8Array ( leftHandOperand ) , new Uint8Array ( rightHandOperand ) , options ) ;
173+ break ;
87174 case 'set' :
88- return setEqual ( leftHandOperand , rightHandOperand , memoizeObject ) ;
175+ result = setEqual ( leftHandOperand , rightHandOperand , options ) ;
176+ break ;
89177 default :
90- return objectEqual ( leftHandOperand , rightHandOperand , memoizeObject ) ;
178+ result = objectEqual ( leftHandOperand , rightHandOperand , options ) ;
91179 }
180+ memoizeSet ( leftHandOperand , rightHandOperand , options . memoize , result ) ;
181+ memoizeSet ( rightHandOperand , leftHandOperand , options . memoize , result ) ;
182+ return result ;
92183}
93184
94185/*!
@@ -128,7 +219,7 @@ function regexpEqual(leftHandOperand, rightHandOperand) {
128219 * @return {Boolean } result
129220 */
130221
131- function setEqual ( leftHandOperand , rightHandOperand ) {
222+ function setEqual ( leftHandOperand , rightHandOperand , options ) {
132223 var leftHandItems = [ ] ;
133224 var rightHandItems = [ ] ;
134225 leftHandOperand . forEach ( function gatherSetEntries ( entry ) {
@@ -137,7 +228,7 @@ function setEqual(leftHandOperand, rightHandOperand) {
137228 rightHandOperand . forEach ( function gatherSetEntries ( entry ) {
138229 rightHandItems . push ( entry ) ;
139230 } ) ;
140- return iterableEqual ( leftHandItems . sort ( ) , rightHandItems . sort ( ) ) ;
231+ return iterableEqual ( leftHandItems . sort ( ) , rightHandItems . sort ( ) , options ) ;
141232}
142233
143234/*!
@@ -149,13 +240,13 @@ function setEqual(leftHandOperand, rightHandOperand) {
149240 * @return {Boolean } result
150241 */
151242
152- function iterableEqual ( leftHandOperand , rightHandOperand , memoizeObject ) {
243+ function iterableEqual ( leftHandOperand , rightHandOperand , options ) {
153244 var length = leftHandOperand . length ;
154245 if ( length !== rightHandOperand . length ) {
155246 return false ;
156247 }
157248 for ( var i = 0 ; i < length ; i += 1 ) {
158- if ( deepEqual ( leftHandOperand [ i ] , rightHandOperand [ i ] , memoizeObject ) === false ) {
249+ if ( deepEqual ( leftHandOperand [ i ] , rightHandOperand [ i ] , options ) === false ) {
159250 return false ;
160251 }
161252 }
@@ -171,8 +262,8 @@ function iterableEqual(leftHandOperand, rightHandOperand, memoizeObject) {
171262 * @return {Boolean } result
172263 */
173264
174- function generatorEqual ( leftHandOperand , rightHandOperand , memoizeObject ) {
175- return iterableEqual ( getGeneratorEntries ( leftHandOperand ) , getGeneratorEntries ( rightHandOperand ) , memoizeObject ) ;
265+ function generatorEqual ( leftHandOperand , rightHandOperand , options ) {
266+ return iterableEqual ( getGeneratorEntries ( leftHandOperand ) , getGeneratorEntries ( rightHandOperand ) , options ) ;
176267}
177268
178269/*!
@@ -231,10 +322,10 @@ function getGeneratorEntries(generator) {
231322 *
232323 *
233324 */
234- function keysEqual ( leftHandOperand , rightHandOperand , keys ) {
325+ function keysEqual ( leftHandOperand , rightHandOperand , keys , options ) {
235326 var length = keys . length ;
236327 for ( var i = 0 ; i < length ; i += 1 ) {
237- if ( deepEqual ( leftHandOperand [ keys [ i ] ] , rightHandOperand [ keys [ i ] ] ) === false ) {
328+ if ( deepEqual ( leftHandOperand [ keys [ i ] ] , rightHandOperand [ keys [ i ] ] , options ) === false ) {
238329 return false ;
239330 }
240331 }
@@ -252,7 +343,7 @@ function keysEqual(leftHandOperand, rightHandOperand, keys) {
252343 * @return {Boolean } result
253344 */
254345
255- function objectEqual ( leftHandOperand , rightHandOperand ) {
346+ function objectEqual ( leftHandOperand , rightHandOperand , options ) {
256347 if ( Object . getPrototypeOf ( leftHandOperand ) !== Object . getPrototypeOf ( rightHandOperand ) ) {
257348 return false ;
258349 }
@@ -265,15 +356,15 @@ function objectEqual(leftHandOperand, rightHandOperand) {
265356 if ( iterableEqual ( leftHandKeys , rightHandKeys ) === false ) {
266357 return false ;
267358 }
268- return keysEqual ( leftHandOperand , rightHandOperand , leftHandKeys ) ;
359+ return keysEqual ( leftHandOperand , rightHandOperand , leftHandKeys , options ) ;
269360 }
270361
271362 var leftHandEntries = getIteratorEntries ( leftHandOperand ) ;
272363 var rightHandEntries = getIteratorEntries ( rightHandOperand ) ;
273364 if ( leftHandEntries . length && leftHandEntries . length === rightHandEntries . length ) {
274365 leftHandEntries . sort ( ) ;
275366 rightHandEntries . sort ( ) ;
276- return iterableEqual ( leftHandEntries , rightHandEntries ) ;
367+ return iterableEqual ( leftHandEntries , rightHandEntries , options ) ;
277368 }
278369
279370 if ( leftHandKeys . length === 0 &&
0 commit comments