Projekt

Obecné

Profil

Stáhnout (3.44 KB) Statistiky
| Větev: | Revize:
1
var objectKeys = require('object-keys');
2
var isArguments = require('is-arguments');
3
var is = require('object-is');
4
var isRegex = require('is-regex');
5
var flags = require('regexp.prototype.flags');
6
var isDate = require('is-date-object');
7

    
8
var getTime = Date.prototype.getTime;
9

    
10
function deepEqual(actual, expected, options) {
11
  var opts = options || {};
12

    
13
  // 7.1. All identical values are equivalent, as determined by ===.
14
  if (opts.strict ? is(actual, expected) : actual === expected) {
15
    return true;
16
  }
17

    
18
  // 7.3. Other pairs that do not both pass typeof value == 'object', equivalence is determined by ==.
19
  if (!actual || !expected || (typeof actual !== 'object' && typeof expected !== 'object')) {
20
    return opts.strict ? is(actual, expected) : actual == expected;
21
  }
22

    
23
  /*
24
   * 7.4. For all other Object pairs, including Array objects, equivalence is
25
   * determined by having the same number of owned properties (as verified
26
   * with Object.prototype.hasOwnProperty.call), the same set of keys
27
   * (although not necessarily the same order), equivalent values for every
28
   * corresponding key, and an identical 'prototype' property. Note: this
29
   * accounts for both named and indexed properties on Arrays.
30
   */
31
  // eslint-disable-next-line no-use-before-define
32
  return objEquiv(actual, expected, opts);
33
}
34

    
35
function isUndefinedOrNull(value) {
36
  return value === null || value === undefined;
37
}
38

    
39
function isBuffer(x) {
40
  if (!x || typeof x !== 'object' || typeof x.length !== 'number') {
41
    return false;
42
  }
43
  if (typeof x.copy !== 'function' || typeof x.slice !== 'function') {
44
    return false;
45
  }
46
  if (x.length > 0 && typeof x[0] !== 'number') {
47
    return false;
48
  }
49
  return true;
50
}
51

    
52
function objEquiv(a, b, opts) {
53
  /* eslint max-statements: [2, 50] */
54
  var i, key;
55
  if (typeof a !== typeof b) { return false; }
56
  if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) { return false; }
57

    
58
  // an identical 'prototype' property.
59
  if (a.prototype !== b.prototype) { return false; }
60

    
61
  if (isArguments(a) !== isArguments(b)) { return false; }
62

    
63
  var aIsRegex = isRegex(a);
64
  var bIsRegex = isRegex(b);
65
  if (aIsRegex !== bIsRegex) { return false; }
66
  if (aIsRegex || bIsRegex) {
67
    return a.source === b.source && flags(a) === flags(b);
68
  }
69

    
70
  if (isDate(a) && isDate(b)) {
71
    return getTime.call(a) === getTime.call(b);
72
  }
73

    
74
  var aIsBuffer = isBuffer(a);
75
  var bIsBuffer = isBuffer(b);
76
  if (aIsBuffer !== bIsBuffer) { return false; }
77
  if (aIsBuffer || bIsBuffer) { // && would work too, because both are true or both false here
78
    if (a.length !== b.length) { return false; }
79
    for (i = 0; i < a.length; i++) {
80
      if (a[i] !== b[i]) { return false; }
81
    }
82
    return true;
83
  }
84

    
85
  if (typeof a !== typeof b) { return false; }
86

    
87
  try {
88
    var ka = objectKeys(a);
89
    var kb = objectKeys(b);
90
  } catch (e) { // happens when one is a string literal and the other isn't
91
    return false;
92
  }
93
  // having the same number of owned properties (keys incorporates hasOwnProperty)
94
  if (ka.length !== kb.length) { return false; }
95

    
96
  // the same set of keys (although not necessarily the same order),
97
  ka.sort();
98
  kb.sort();
99
  // ~~~cheap key test
100
  for (i = ka.length - 1; i >= 0; i--) {
101
    if (ka[i] != kb[i]) { return false; }
102
  }
103
  // equivalent values for every corresponding key, and ~~~possibly expensive deep test
104
  for (i = ka.length - 1; i >= 0; i--) {
105
    key = ka[i];
106
    if (!deepEqual(a[key], b[key], opts)) { return false; }
107
  }
108

    
109
  return true;
110
}
111

    
112
module.exports = deepEqual;
(5-5/7)