Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
MR414N-ID
GitHub Repository: MR414N-ID/botku2
Path: blob/master/node_modules/@hapi/hoek/lib/clone.js
1126 views
1
'use strict';
2
3
const Reach = require('./reach');
4
const Types = require('./types');
5
const Utils = require('./utils');
6
7
8
const internals = {
9
needsProtoHack: new Set([Types.set, Types.map, Types.weakSet, Types.weakMap])
10
};
11
12
13
module.exports = internals.clone = function (obj, options = {}, _seen = null) {
14
15
if (typeof obj !== 'object' ||
16
obj === null) {
17
18
return obj;
19
}
20
21
let clone = internals.clone;
22
let seen = _seen;
23
24
if (options.shallow) {
25
if (options.shallow !== true) {
26
return internals.cloneWithShallow(obj, options);
27
}
28
29
clone = (value) => value;
30
}
31
else if (seen) {
32
const lookup = seen.get(obj);
33
if (lookup) {
34
return lookup;
35
}
36
}
37
else {
38
seen = new Map();
39
}
40
41
// Built-in object types
42
43
const baseProto = Types.getInternalProto(obj);
44
if (baseProto === Types.buffer) {
45
return Buffer && Buffer.from(obj); // $lab:coverage:ignore$
46
}
47
48
if (baseProto === Types.date) {
49
return new Date(obj.getTime());
50
}
51
52
if (baseProto === Types.regex) {
53
return new RegExp(obj);
54
}
55
56
// Generic objects
57
58
const newObj = internals.base(obj, baseProto, options);
59
if (newObj === obj) {
60
return obj;
61
}
62
63
if (seen) {
64
seen.set(obj, newObj); // Set seen, since obj could recurse
65
}
66
67
if (baseProto === Types.set) {
68
for (const value of obj) {
69
newObj.add(clone(value, options, seen));
70
}
71
}
72
else if (baseProto === Types.map) {
73
for (const [key, value] of obj) {
74
newObj.set(key, clone(value, options, seen));
75
}
76
}
77
78
const keys = Utils.keys(obj, options);
79
for (const key of keys) {
80
if (key === '__proto__') {
81
continue;
82
}
83
84
if (baseProto === Types.array &&
85
key === 'length') {
86
87
newObj.length = obj.length;
88
continue;
89
}
90
91
const descriptor = Object.getOwnPropertyDescriptor(obj, key);
92
if (descriptor) {
93
if (descriptor.get ||
94
descriptor.set) {
95
96
Object.defineProperty(newObj, key, descriptor);
97
}
98
else if (descriptor.enumerable) {
99
newObj[key] = clone(obj[key], options, seen);
100
}
101
else {
102
Object.defineProperty(newObj, key, { enumerable: false, writable: true, configurable: true, value: clone(obj[key], options, seen) });
103
}
104
}
105
else {
106
Object.defineProperty(newObj, key, {
107
enumerable: true,
108
writable: true,
109
configurable: true,
110
value: clone(obj[key], options, seen)
111
});
112
}
113
}
114
115
return newObj;
116
};
117
118
119
internals.cloneWithShallow = function (source, options) {
120
121
const keys = options.shallow;
122
options = Object.assign({}, options);
123
options.shallow = false;
124
125
const seen = new Map();
126
127
for (const key of keys) {
128
const ref = Reach(source, key);
129
if (typeof ref === 'object' ||
130
typeof ref === 'function') {
131
132
seen.set(ref, ref);
133
}
134
}
135
136
return internals.clone(source, options, seen);
137
};
138
139
140
internals.base = function (obj, baseProto, options) {
141
142
if (options.prototype === false) { // Defaults to true
143
if (internals.needsProtoHack.has(baseProto)) {
144
return new baseProto.constructor();
145
}
146
147
return baseProto === Types.array ? [] : {};
148
}
149
150
const proto = Object.getPrototypeOf(obj);
151
if (proto &&
152
proto.isImmutable) {
153
154
return obj;
155
}
156
157
if (baseProto === Types.array) {
158
const newObj = [];
159
if (proto !== baseProto) {
160
Object.setPrototypeOf(newObj, proto);
161
}
162
163
return newObj;
164
}
165
166
if (internals.needsProtoHack.has(baseProto)) {
167
const newObj = new proto.constructor();
168
if (proto !== baseProto) {
169
Object.setPrototypeOf(newObj, proto);
170
}
171
172
return newObj;
173
}
174
175
return Object.create(proto);
176
};
177
178