1+ var pSlice = Array . prototype . slice ;
2+ var objectKeys = require ( './lib/keys.js' ) ;
3+ var isArguments = require ( './lib/is_arguments.js' ) ;
4+
5+ var deepEqual = module . exports = function ( actual , expected , opts ) {
6+ if ( ! opts ) opts = { } ;
7+ // 7.1. All identical values are equivalent, as determined by ===.
8+ if ( actual === expected ) {
9+ return true ;
10+
11+ } else if ( actual instanceof Date && expected instanceof Date ) {
12+ return actual . getTime ( ) === expected . getTime ( ) ;
13+
14+ // 7.3. Other pairs that do not both pass typeof value == 'object',
15+ // equivalence is determined by ==.
16+ } else if ( ! actual || ! expected || typeof actual != 'object' && typeof expected != 'object' ) {
17+ return opts . strict ? actual === expected : actual == expected ;
18+
19+ // 7.4. For all other Object pairs, including Array objects, equivalence is
20+ // determined by having the same number of owned properties (as verified
21+ // with Object.prototype.hasOwnProperty.call), the same set of keys
22+ // (although not necessarily the same order), equivalent values for every
23+ // corresponding key, and an identical 'prototype' property. Note: this
24+ // accounts for both named and indexed properties on Arrays.
25+ } else {
26+ return objEquiv ( actual , expected , opts ) ;
27+ }
28+ }
29+
30+ function isUndefinedOrNull ( value ) {
31+ return value === null || value === undefined ;
32+ }
33+
34+ function isBuffer ( x ) {
35+ if ( ! x || typeof x !== 'object' || typeof x . length !== 'number' ) return false ;
36+ // MONKEY PATCH: Support buffer, Uint8Array and Array alike
37+ /* if (typeof x.copy !== 'function' || typeof x.slice !== 'function') {
38+ return false;
39+ } */
40+ if ( x . length > 0 && typeof x [ 0 ] !== 'number' ) return false ;
41+ return true ;
42+ }
43+
44+ function objEquiv ( a , b , opts ) {
45+ var i , key ;
46+ if ( isUndefinedOrNull ( a ) || isUndefinedOrNull ( b ) )
47+ return false ;
48+ // an identical 'prototype' property.
49+ if ( a . prototype !== b . prototype ) return false ;
50+ //~~~I've managed to break Object.keys through screwy arguments passing.
51+ // Converting to array solves the problem.
52+ if ( isArguments ( a ) ) {
53+ if ( ! isArguments ( b ) ) {
54+ return false ;
55+ }
56+ a = pSlice . call ( a ) ;
57+ b = pSlice . call ( b ) ;
58+ return deepEqual ( a , b , opts ) ;
59+ }
60+ if ( isBuffer ( a ) ) {
61+ if ( ! isBuffer ( b ) ) {
62+ return false ;
63+ }
64+ if ( a . length !== b . length ) return false ;
65+ for ( i = 0 ; i < a . length ; i ++ ) {
66+ if ( a [ i ] !== b [ i ] ) return false ;
67+ }
68+ return true ;
69+ }
70+ try {
71+ var ka = objectKeys ( a ) ,
72+ kb = objectKeys ( b ) ;
73+ } catch ( e ) { //happens when one is a string literal and the other isn't
74+ return false ;
75+ }
76+ // having the same number of owned properties (keys incorporates
77+ // hasOwnProperty)
78+ if ( ka . length != kb . length )
79+ return false ;
80+ //the same set of keys (although not necessarily the same order),
81+ ka . sort ( ) ;
82+ kb . sort ( ) ;
83+ //~~~cheap key test
84+ for ( i = ka . length - 1 ; i >= 0 ; i -- ) {
85+ if ( ka [ i ] != kb [ i ] )
86+ return false ;
87+ }
88+ //equivalent values for every corresponding key, and
89+ //~~~possibly expensive deep test
90+ for ( i = ka . length - 1 ; i >= 0 ; i -- ) {
91+ key = ka [ i ] ;
92+ if ( ! deepEqual ( a [ key ] , b [ key ] , opts ) ) return false ;
93+ }
94+ return typeof a === typeof b ;
95+ }
0 commit comments