Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MR414N-ID
GitHub Repository: MR414N-ID/botku2
Path: blob/master/node_modules/@hapi/hoek/lib/deepEqual.js
1126 views
1
'use strict';
2
3
const Types = require('./types');
4
5
6
const internals = {
7
mismatched: null
8
};
9
10
11
module.exports = function (obj, ref, options) {
12
13
options = Object.assign({ prototype: true }, options);
14
15
return !!internals.isDeepEqual(obj, ref, options, []);
16
};
17
18
19
internals.isDeepEqual = function (obj, ref, options, seen) {
20
21
if (obj === ref) { // Copied from Deep-eql, copyright(c) 2013 Jake Luer, [email protected], MIT Licensed, https://github.com/chaijs/deep-eql
22
return obj !== 0 || 1 / obj === 1 / ref;
23
}
24
25
const type = typeof obj;
26
27
if (type !== typeof ref) {
28
return false;
29
}
30
31
if (obj === null ||
32
ref === null) {
33
34
return false;
35
}
36
37
if (type === 'function') {
38
if (!options.deepFunction ||
39
obj.toString() !== ref.toString()) {
40
41
return false;
42
}
43
44
// Continue as object
45
}
46
else if (type !== 'object') {
47
return obj !== obj && ref !== ref; // NaN
48
}
49
50
const instanceType = internals.getSharedType(obj, ref, !!options.prototype);
51
switch (instanceType) {
52
case Types.buffer:
53
return Buffer && Buffer.prototype.equals.call(obj, ref); // $lab:coverage:ignore$
54
case Types.promise:
55
return obj === ref;
56
case Types.regex:
57
return obj.toString() === ref.toString();
58
case internals.mismatched:
59
return false;
60
}
61
62
for (let i = seen.length - 1; i >= 0; --i) {
63
if (seen[i].isSame(obj, ref)) {
64
return true; // If previous comparison failed, it would have stopped execution
65
}
66
}
67
68
seen.push(new internals.SeenEntry(obj, ref));
69
70
try {
71
return !!internals.isDeepEqualObj(instanceType, obj, ref, options, seen);
72
}
73
finally {
74
seen.pop();
75
}
76
};
77
78
79
internals.getSharedType = function (obj, ref, checkPrototype) {
80
81
if (checkPrototype) {
82
if (Object.getPrototypeOf(obj) !== Object.getPrototypeOf(ref)) {
83
return internals.mismatched;
84
}
85
86
return Types.getInternalProto(obj);
87
}
88
89
const type = Types.getInternalProto(obj);
90
if (type !== Types.getInternalProto(ref)) {
91
return internals.mismatched;
92
}
93
94
return type;
95
};
96
97
98
internals.valueOf = function (obj) {
99
100
const objValueOf = obj.valueOf;
101
if (objValueOf === undefined) {
102
return obj;
103
}
104
105
try {
106
return objValueOf.call(obj);
107
}
108
catch (err) {
109
return err;
110
}
111
};
112
113
114
internals.hasOwnEnumerableProperty = function (obj, key) {
115
116
return Object.prototype.propertyIsEnumerable.call(obj, key);
117
};
118
119
120
internals.isSetSimpleEqual = function (obj, ref) {
121
122
for (const entry of Set.prototype.values.call(obj)) {
123
if (!Set.prototype.has.call(ref, entry)) {
124
return false;
125
}
126
}
127
128
return true;
129
};
130
131
132
internals.isDeepEqualObj = function (instanceType, obj, ref, options, seen) {
133
134
const { isDeepEqual, valueOf, hasOwnEnumerableProperty } = internals;
135
const { keys, getOwnPropertySymbols } = Object;
136
137
if (instanceType === Types.array) {
138
if (options.part) {
139
140
// Check if any index match any other index
141
142
for (const objValue of obj) {
143
for (const refValue of ref) {
144
if (isDeepEqual(objValue, refValue, options, seen)) {
145
return true;
146
}
147
}
148
}
149
}
150
else {
151
if (obj.length !== ref.length) {
152
return false;
153
}
154
155
for (let i = 0; i < obj.length; ++i) {
156
if (!isDeepEqual(obj[i], ref[i], options, seen)) {
157
return false;
158
}
159
}
160
161
return true;
162
}
163
}
164
else if (instanceType === Types.set) {
165
if (obj.size !== ref.size) {
166
return false;
167
}
168
169
if (!internals.isSetSimpleEqual(obj, ref)) {
170
171
// Check for deep equality
172
173
const ref2 = new Set(Set.prototype.values.call(ref));
174
for (const objEntry of Set.prototype.values.call(obj)) {
175
if (ref2.delete(objEntry)) {
176
continue;
177
}
178
179
let found = false;
180
for (const refEntry of ref2) {
181
if (isDeepEqual(objEntry, refEntry, options, seen)) {
182
ref2.delete(refEntry);
183
found = true;
184
break;
185
}
186
}
187
188
if (!found) {
189
return false;
190
}
191
}
192
}
193
}
194
else if (instanceType === Types.map) {
195
if (obj.size !== ref.size) {
196
return false;
197
}
198
199
for (const [key, value] of Map.prototype.entries.call(obj)) {
200
if (value === undefined && !Map.prototype.has.call(ref, key)) {
201
return false;
202
}
203
204
if (!isDeepEqual(value, Map.prototype.get.call(ref, key), options, seen)) {
205
return false;
206
}
207
}
208
}
209
else if (instanceType === Types.error) {
210
211
// Always check name and message
212
213
if (obj.name !== ref.name ||
214
obj.message !== ref.message) {
215
216
return false;
217
}
218
}
219
220
// Check .valueOf()
221
222
const valueOfObj = valueOf(obj);
223
const valueOfRef = valueOf(ref);
224
if ((obj !== valueOfObj || ref !== valueOfRef) &&
225
!isDeepEqual(valueOfObj, valueOfRef, options, seen)) {
226
227
return false;
228
}
229
230
// Check properties
231
232
const objKeys = keys(obj);
233
if (!options.part &&
234
objKeys.length !== keys(ref).length &&
235
!options.skip) {
236
237
return false;
238
}
239
240
let skipped = 0;
241
for (const key of objKeys) {
242
if (options.skip &&
243
options.skip.includes(key)) {
244
245
if (ref[key] === undefined) {
246
++skipped;
247
}
248
249
continue;
250
}
251
252
if (!hasOwnEnumerableProperty(ref, key)) {
253
return false;
254
}
255
256
if (!isDeepEqual(obj[key], ref[key], options, seen)) {
257
return false;
258
}
259
}
260
261
if (!options.part &&
262
objKeys.length - skipped !== keys(ref).length) {
263
264
return false;
265
}
266
267
// Check symbols
268
269
if (options.symbols !== false) { // Defaults to true
270
const objSymbols = getOwnPropertySymbols(obj);
271
const refSymbols = new Set(getOwnPropertySymbols(ref));
272
273
for (const key of objSymbols) {
274
if (!options.skip ||
275
!options.skip.includes(key)) {
276
277
if (hasOwnEnumerableProperty(obj, key)) {
278
if (!hasOwnEnumerableProperty(ref, key)) {
279
return false;
280
}
281
282
if (!isDeepEqual(obj[key], ref[key], options, seen)) {
283
return false;
284
}
285
}
286
else if (hasOwnEnumerableProperty(ref, key)) {
287
return false;
288
}
289
}
290
291
refSymbols.delete(key);
292
}
293
294
for (const key of refSymbols) {
295
if (hasOwnEnumerableProperty(ref, key)) {
296
return false;
297
}
298
}
299
}
300
301
return true;
302
};
303
304
305
internals.SeenEntry = class {
306
307
constructor(obj, ref) {
308
309
this.obj = obj;
310
this.ref = ref;
311
}
312
313
isSame(obj, ref) {
314
315
return this.obj === obj && this.ref === ref;
316
}
317
};
318
319