@lumjs/core 1.38.8 → 1.39.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/context.js +3 -3
- package/lib/enum.js +9 -5
- package/lib/env.js +28 -12
- package/lib/index.js +7 -2
- package/lib/meta.js +259 -57
- package/lib/obj/apply.js +1 -3
- package/lib/obj/basics.js +12 -0
- package/lib/obj/cp.js +1 -1
- package/lib/obj/df.js +9 -9
- package/lib/obj/getproperty.js +1 -1
- package/lib/obj/index.js +18 -14
- package/lib/obj/keys.js +55 -0
- package/lib/obj/lock.js +2 -68
- package/lib/obj/unlocked.js +8 -10
- package/lib/proxy.js +417 -0
- package/lib/state.js +35 -4
- package/lib/types/js.js +3 -0
- package/lib/types/root.js +1 -0
- package/package.json +4 -2
- package/lib/obj/clone.js +0 -378
- package/lib/obj/copyall.js +0 -45
- package/lib/obj/copyprops.js +0 -73
- package/lib/obj/merge.js +0 -84
package/lib/obj/clone.js
DELETED
|
@@ -1,378 +0,0 @@
|
|
|
1
|
-
// Import *most* required bits here.
|
|
2
|
-
const {N,F, isObj, isComplex, def, isArray} = require('../types');
|
|
3
|
-
const copyProps = require('./copyprops');
|
|
4
|
-
const getProp = require('./getproperty');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Clone an object or function.
|
|
8
|
-
*
|
|
9
|
-
* @param {object} obj - The object we want to clone.
|
|
10
|
-
*
|
|
11
|
-
* @param {(object|number)} [opts={}] Options for the cloning process.
|
|
12
|
-
*
|
|
13
|
-
* If this is a `number` then it's assumed to be the `opts.mode` parameter.
|
|
14
|
-
*
|
|
15
|
-
* @param {number} [opts.mode=CLONE.DEF] One of the `CLONE.*` enum values.
|
|
16
|
-
*
|
|
17
|
-
* When the `clone()` method was written to replace some similar methods
|
|
18
|
-
* from earlier libraries, I for some reason decided to simply have a bunch
|
|
19
|
-
* of different cloning modes. I have since added a full set of options that
|
|
20
|
-
* allows overriding the options of any mode (except `CLONE.JSON`).
|
|
21
|
-
*
|
|
22
|
-
* The `CLONE` enum is also aliased as `clone.MODE` as an alternative.
|
|
23
|
-
*
|
|
24
|
-
* @param {boolean} [opts.all] Clone **all** of the object's properties?
|
|
25
|
-
*
|
|
26
|
-
* If `false` only *enumerable* properties will be cloned.
|
|
27
|
-
*
|
|
28
|
-
* The default value depends on the `opts.mode` used.
|
|
29
|
-
*
|
|
30
|
-
* This is not used if `opts.mode` was `CLONE.JSON`.
|
|
31
|
-
*
|
|
32
|
-
* @param {boolean} [opts.slice] Use the `Array.slice()` shortcut?
|
|
33
|
-
*
|
|
34
|
-
* If `true` then when cloning `Array` objects, a shallow clone will be
|
|
35
|
-
* created using the `Array.slice()` method.
|
|
36
|
-
*
|
|
37
|
-
* The default value depends on the `opts.mode` used.
|
|
38
|
-
*
|
|
39
|
-
* This is not used if `opts.mode` was `CLONE.JSON`.
|
|
40
|
-
*
|
|
41
|
-
* @param {boolean} [opts.recursive] Clone nested objects recursively?
|
|
42
|
-
*
|
|
43
|
-
* The default value depends on the `opts.mode` used.
|
|
44
|
-
* If `opts.slice` is also `true` then `Array` objects will
|
|
45
|
-
* be *shallow clones* while any other kind of object will be recursive.
|
|
46
|
-
*
|
|
47
|
-
* This is not used if `opts.mode` was `CLONE.JSON`.
|
|
48
|
-
*
|
|
49
|
-
* @param {boolean} [opts.descriptors] Clone using the property descriptors?
|
|
50
|
-
*
|
|
51
|
-
* If `true` we will get the property descriptors from the original object,
|
|
52
|
-
* and assign them to the clone.
|
|
53
|
-
* This is the only way to clone *accessor* type properties properly.
|
|
54
|
-
*
|
|
55
|
-
* If `false` we will directly assign the *property value* from the original
|
|
56
|
-
* object into the clone. This means the *current value* returned from an
|
|
57
|
-
* *accessor* type property will be assigned statically to the clone.
|
|
58
|
-
*
|
|
59
|
-
* The default value will be `true` if `opts.all` **OR** `opts.recursive`
|
|
60
|
-
* are `true`. It will be `false` otherwise.
|
|
61
|
-
*
|
|
62
|
-
* This is not used if `opts.mode` was `CLONE.JSON`.
|
|
63
|
-
*
|
|
64
|
-
* @param {boolean} [opts.prototype] Set the clone's `prototype`?
|
|
65
|
-
*
|
|
66
|
-
* If `true`, once the cloning is complete, we will call
|
|
67
|
-
* `Object.getPrototypeOf()` on the original `obj`, and then call
|
|
68
|
-
* `Object.setProrotypeOf()` on the clone.
|
|
69
|
-
*
|
|
70
|
-
* If `false` then the clone with have a prototype of `Object` or
|
|
71
|
-
* `Array` depending on whether the original object was an `Array`
|
|
72
|
-
* or not. No further prototype handling will be done.
|
|
73
|
-
*
|
|
74
|
-
* The default value will be `true` if `opts.all` **AND** `opts.recursive`
|
|
75
|
-
* are *both* `true`. Otherwise the default value is `false`.
|
|
76
|
-
* So for *modes*, only `CLONE.ENTIRE` uses this by default.
|
|
77
|
-
*
|
|
78
|
-
* @param {(object|boolean)} [opts.addClone=false]
|
|
79
|
-
* Call `addClone()` on the cloned object.
|
|
80
|
-
*
|
|
81
|
-
* If `opts.addClone` is an `object` then it will be used as the options
|
|
82
|
-
* passed to the `addClone()` method. If it is `true` then the `opts`
|
|
83
|
-
* will be passed as is.
|
|
84
|
-
*
|
|
85
|
-
* @param {(object|boolean)} [opts.addLock=false]
|
|
86
|
-
* Call `addLock()` on the cloned object.
|
|
87
|
-
*
|
|
88
|
-
* If `opts.addLock` is an `object` then it will be used as the options
|
|
89
|
-
* passed to the `addLock()` method. If it is `true` then the `opts`
|
|
90
|
-
* will be passed as is.
|
|
91
|
-
*
|
|
92
|
-
* @param {(object|boolean)} [opts.copy=false]
|
|
93
|
-
* Call `copyProps()` on the cloned object.
|
|
94
|
-
*
|
|
95
|
-
* This is called *after* the normal cloning process, so only properties
|
|
96
|
-
* that weren't copied during the cloning process will be copied here.
|
|
97
|
-
* This is a leftover from when `CLONE.JSON` was the default cloning mode,
|
|
98
|
-
* and this was the only way to restore `function` properties.
|
|
99
|
-
*
|
|
100
|
-
* If `opts.copy` is an `object` then it will be used as the options
|
|
101
|
-
* passed to the `copyProps()` method. If it is `true` then the `opts`
|
|
102
|
-
* will be passed as is.
|
|
103
|
-
*
|
|
104
|
-
* @return {object} The clone of the object.
|
|
105
|
-
*
|
|
106
|
-
* @alias module:@lumjs/core/obj.clone
|
|
107
|
-
*/
|
|
108
|
-
function clone(obj, opts={})
|
|
109
|
-
{
|
|
110
|
-
//console.debug("clone()", obj, opts);
|
|
111
|
-
|
|
112
|
-
if (!isComplex(obj))
|
|
113
|
-
{ // Doesn't need cloning.
|
|
114
|
-
//console.debug("no cloning required");
|
|
115
|
-
return obj;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
if (typeof opts === N)
|
|
119
|
-
{ // The 'mode' option.
|
|
120
|
-
opts = {mode: opts};
|
|
121
|
-
}
|
|
122
|
-
else if (!isObj(opts))
|
|
123
|
-
{ // Opts has to be a valid object.
|
|
124
|
-
opts = {};
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
// The mode is the base option.
|
|
128
|
-
const mode = typeof opts.mode === N ? opts.mode : CLONE.DEF;
|
|
129
|
-
|
|
130
|
-
// Options with defaults based on the mode.
|
|
131
|
-
const allProps = opts.all ?? ALL_PROPS.includes(mode);
|
|
132
|
-
const useSlice = opts.slice ?? SLICE_ARRAYS.includes(mode);
|
|
133
|
-
const recursive = opts.recursive ?? RECURSIVE.includes(mode);
|
|
134
|
-
|
|
135
|
-
// Some that depend on the values of the above options.
|
|
136
|
-
const descriptors = opts.descriptors ?? (allProps || recursive);
|
|
137
|
-
const withProto = opts.prototype ?? (allProps && recursive);
|
|
138
|
-
|
|
139
|
-
// Finally, a few that can be boolean or objects.
|
|
140
|
-
const subOpts = opt =>
|
|
141
|
-
{
|
|
142
|
-
if (isObj(opts[opt]))
|
|
143
|
-
return opts[opt];
|
|
144
|
-
else if (opts[opt] === true)
|
|
145
|
-
return opts;
|
|
146
|
-
}
|
|
147
|
-
const reclone = subOpts('addClone');
|
|
148
|
-
const relock = subOpts('addLock');
|
|
149
|
-
const cpProps = subOpts('copy');
|
|
150
|
-
|
|
151
|
-
let copy;
|
|
152
|
-
|
|
153
|
-
//console.debug("::clone", {mode, reclone, relock});
|
|
154
|
-
|
|
155
|
-
if (mode === CLONE.JSON)
|
|
156
|
-
{ // Deep clone enumerable properties using JSON trickery.
|
|
157
|
-
//console.debug("::clone using JSON cloning");
|
|
158
|
-
copy = JSON.parse(JSON.stringify(obj));
|
|
159
|
-
}
|
|
160
|
-
else if (Array.isArray(obj) && useSlice)
|
|
161
|
-
{ // Make a shallow copy using slice.
|
|
162
|
-
//console.debug("::clone using Array.slice()");
|
|
163
|
-
copy = obj.slice();
|
|
164
|
-
}
|
|
165
|
-
else
|
|
166
|
-
{ // Build a clone using a simple loop.
|
|
167
|
-
//console.debug("::clone using simple loop");
|
|
168
|
-
copy = isArray(obj) ? [] : {};
|
|
169
|
-
|
|
170
|
-
let props;
|
|
171
|
-
if (allProps)
|
|
172
|
-
{ // All object properties.
|
|
173
|
-
//console.debug("::clone getting all properties");
|
|
174
|
-
props = Object.getOwnPropertyNames(obj);
|
|
175
|
-
}
|
|
176
|
-
else
|
|
177
|
-
{ // Enumerable properties.
|
|
178
|
-
//console.debug("::clone getting enumerable properties");
|
|
179
|
-
props = Object.keys(obj);
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
//console.debug("::clone[props]", props);
|
|
183
|
-
|
|
184
|
-
let recOpts;
|
|
185
|
-
if (recursive)
|
|
186
|
-
{ // Recursive opts; skips addClone, addLock, and copy.
|
|
187
|
-
recOpts =
|
|
188
|
-
{
|
|
189
|
-
mode, recursive, descriptors,
|
|
190
|
-
all: allProps,
|
|
191
|
-
slice: useSlice,
|
|
192
|
-
prototype: withProto,
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
for (const prop of props)
|
|
197
|
-
{
|
|
198
|
-
if (descriptors)
|
|
199
|
-
{ // Use descriptor assignment.
|
|
200
|
-
const objDesc = getProp(obj, prop);
|
|
201
|
-
if (isObj(objDesc))
|
|
202
|
-
{ // Make a fast, shallow clone of the descriptor.
|
|
203
|
-
const cloneDesc = clone(objDesc);
|
|
204
|
-
if (isObj(objDesc.value) && recursive)
|
|
205
|
-
{ // Recursively clone the value.
|
|
206
|
-
cloneDesc.value = clone(objDesc.value, recOpts);
|
|
207
|
-
}
|
|
208
|
-
def(copy, prop, cloneDesc);
|
|
209
|
-
}
|
|
210
|
-
else
|
|
211
|
-
{
|
|
212
|
-
console.error("getProperty failed", {obj, prop, props, opts});
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
else
|
|
216
|
-
{ // Use direct assignment.
|
|
217
|
-
let val = obj[prop];
|
|
218
|
-
if (isObj(val) && recursive)
|
|
219
|
-
{ // Deep cloning.
|
|
220
|
-
val = clone(val, recOpts);
|
|
221
|
-
}
|
|
222
|
-
copy[prop] = val;
|
|
223
|
-
}
|
|
224
|
-
} // for prop
|
|
225
|
-
|
|
226
|
-
} // simple loop cloning algorithm
|
|
227
|
-
|
|
228
|
-
if (withProto)
|
|
229
|
-
{ // Copy the prototype if it is different.
|
|
230
|
-
const objProto = Object.getPrototypeOf(obj);
|
|
231
|
-
const copyProto = Object.getPrototypeOf(copy);
|
|
232
|
-
if (objProto && objProto !== copyProto)
|
|
233
|
-
{ // Update the clone's prototype to match the original.
|
|
234
|
-
Object.setPrototypeOf(copy, objProto);
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
if (isObj(reclone))
|
|
239
|
-
{ // Add the clone() method to the clone, with the passed opts as defaults.
|
|
240
|
-
addClone(copy, reclone);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
if (isObj(relock))
|
|
244
|
-
{ // Add the lock() method to the clone.
|
|
245
|
-
addLock(copy, relock);
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
if (isObj(cpProps))
|
|
249
|
-
{ // Pass the clone through the copyProps() function as well.
|
|
250
|
-
copyProps(obj, copy, cpProps);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
return copy;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// Export the clone here.
|
|
257
|
-
exports.clone = clone;
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Add a clone() method to an object.
|
|
261
|
-
*
|
|
262
|
-
* @param {object|function} obj - The object to add clone() to.
|
|
263
|
-
* @param {object} [defOpts=null] Default options for the clone() method.
|
|
264
|
-
*
|
|
265
|
-
* If `null` or anything other than an object, the defaults will be:
|
|
266
|
-
*
|
|
267
|
-
* ```{mode: CLONE.DEF, addClone: true, addLock: false}```
|
|
268
|
-
*
|
|
269
|
-
* @alias module:@lumjs/core/obj.addClone
|
|
270
|
-
*/
|
|
271
|
-
function addClone(obj, defOpts=null)
|
|
272
|
-
{
|
|
273
|
-
if (!isObj(defOpts))
|
|
274
|
-
{ // Assign a default set of defaults.
|
|
275
|
-
defOpts = {addClone: true};
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const defDesc = defOpts.cloneDesc ?? {};
|
|
279
|
-
|
|
280
|
-
defDesc.value = function (opts)
|
|
281
|
-
{
|
|
282
|
-
if (!isObj(opts))
|
|
283
|
-
opts = defOpts;
|
|
284
|
-
return clone(obj, opts);
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
return def(obj, 'clone', defDesc);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
exports.addClone = addClone;
|
|
291
|
-
|
|
292
|
-
/**
|
|
293
|
-
* Clone an object if it's not extensible (locked, sealed, frozen, etc.)
|
|
294
|
-
*
|
|
295
|
-
* If the object is extensible, it's returned as is.
|
|
296
|
-
*
|
|
297
|
-
* If not, if the object has a `clone()` method it will be used.
|
|
298
|
-
* Otherwise use our `clone()` function.
|
|
299
|
-
*
|
|
300
|
-
* **NOTE**: A newer replacement for this function exists, see
|
|
301
|
-
* {@link module:@lumjs/core/obj.unlocked} for details.
|
|
302
|
-
*
|
|
303
|
-
* @param {object} obj - The object to clone if needed.
|
|
304
|
-
* @param {object} [opts] - Options to pass to `clone()` method.
|
|
305
|
-
*
|
|
306
|
-
* @return {object} - Either the original object, or an extensible clone.
|
|
307
|
-
*
|
|
308
|
-
* @alias module:@lumjs/core/obj.cloneIfLocked
|
|
309
|
-
*/
|
|
310
|
-
function cloneIfLocked(obj, opts)
|
|
311
|
-
{
|
|
312
|
-
if (!Object.isExtensible(obj))
|
|
313
|
-
{
|
|
314
|
-
if (typeof obj.clone === F)
|
|
315
|
-
{ // Use the object's clone() method.
|
|
316
|
-
return obj.clone(opts);
|
|
317
|
-
}
|
|
318
|
-
else
|
|
319
|
-
{ // Use our own clone method.
|
|
320
|
-
return clone(obj, opts);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// Return the object itself, it's fine.
|
|
325
|
-
return obj;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
exports.cloneIfLocked = cloneIfLocked;
|
|
329
|
-
|
|
330
|
-
// Import `addLock()` here *after* assigning the clone methods.
|
|
331
|
-
const {addLock} = require('./lock');
|
|
332
|
-
|
|
333
|
-
// And setting all the Enum definitions at the very end.
|
|
334
|
-
const Enum = require('../enum');
|
|
335
|
-
|
|
336
|
-
/**
|
|
337
|
-
* An `enum` of supported *modes* for the `clone()` method.
|
|
338
|
-
*
|
|
339
|
-
* - **P** → All properties. If unchecked, *enumerable* properties only.
|
|
340
|
-
* - **A** → Uses `Array.slice()` shortcut for shallow `Array` cloning.
|
|
341
|
-
* - **R** → Recursive (deep) cloning of nested objects.
|
|
342
|
-
* - **D** → Uses *descriptor* cloning instead of direct assignment.
|
|
343
|
-
* - **T** → Sets the `prototype` of the clone as well.
|
|
344
|
-
*
|
|
345
|
-
* | Mode | P | A | R | D | T | Notes |
|
|
346
|
-
* | ---- | - | - | - | - | - | ----- |
|
|
347
|
-
* | `CLONE.N` | × | × | × | × | × | Can be used to manually specify options. |
|
|
348
|
-
* | `CLONE.DEF` | × | ✓ | × | × | × | Default mode for cloning functions. |
|
|
349
|
-
* | `CLONE.DEEP` | × | × | ✓ | ✓ | × | |
|
|
350
|
-
* | `CLONE.FULL` | ✓ | ✓ | × | ✓ | × | |
|
|
351
|
-
* | `CLONE.ALL` | ✓ | × | × | ✓ | × | |
|
|
352
|
-
* | `CLONE.ENTIRE` | ✓ | × | ✓ | ✓ | ✓ | |
|
|
353
|
-
* | `CLONE.JSON` | - | - | ✓ | - | × | Uses JSON, so no `function` or `symbol` support. |
|
|
354
|
-
*
|
|
355
|
-
* The `✓` and `×` marks signify the *default settings* in the mode.
|
|
356
|
-
* In *most* cases there are options that can override the
|
|
357
|
-
* defaults.
|
|
358
|
-
*
|
|
359
|
-
* Any feature in the `CLONE.JSON` row marked with `-` are
|
|
360
|
-
* incompatible with that mode and cannot be enabled at all.
|
|
361
|
-
*
|
|
362
|
-
* @alias module:@lumjs/core/obj.CLONE
|
|
363
|
-
*/
|
|
364
|
-
const CLONE = Enum(['N','DEF','FULL','ALL','DEEP','ENTIRE','JSON']);
|
|
365
|
-
|
|
366
|
-
exports.CLONE = CLONE;
|
|
367
|
-
|
|
368
|
-
// A list of modes that should use the array.slice shallow shortcut.
|
|
369
|
-
const SLICE_ARRAYS = [CLONE.DEF, CLONE.FULL];
|
|
370
|
-
|
|
371
|
-
// A list of modes that should get *all* properties.
|
|
372
|
-
const ALL_PROPS = [CLONE.FULL, CLONE.ALL, CLONE.ENTIRE];
|
|
373
|
-
|
|
374
|
-
// A list of modes that should do recursive cloning of objects.
|
|
375
|
-
const RECURSIVE = [CLONE.DEEP, CLONE.ENTIRE];
|
|
376
|
-
|
|
377
|
-
// Alias the CLONE enum as clone.MODE
|
|
378
|
-
def(clone, 'MODE', CLONE);
|
package/lib/obj/copyall.js
DELETED
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* This is a 'dumb' copy method.
|
|
3
|
-
*
|
|
4
|
-
* It only copies enumerable properties, does no type checking,
|
|
5
|
-
* and has no qualms about overwriting properties.
|
|
6
|
-
*
|
|
7
|
-
* Use `copyProps`, or `mergeNested` for more robust versions.
|
|
8
|
-
*
|
|
9
|
-
* NOTE: As of v1.38.5 this is an alias of @lumjs/cp/fun.copyAll
|
|
10
|
-
*
|
|
11
|
-
* @name module:@lumjs/core/obj.copyAll
|
|
12
|
-
* @deprecated Moved to @lumjs/cp package.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* Make a (shallow) copy of a single object using `copyAll`.
|
|
17
|
-
*
|
|
18
|
-
* Use `clone` for a more robust version.
|
|
19
|
-
*
|
|
20
|
-
* Alias: `copyAll.clone`
|
|
21
|
-
*
|
|
22
|
-
* NOTE: As of v1.38.5 this is an alias of @lumjs/cp/fun.duplicateOne
|
|
23
|
-
*
|
|
24
|
-
* @name module:@lumjs/core/obj.duplicateOne
|
|
25
|
-
* @param {object} obj - The object to duplicate.
|
|
26
|
-
* @returns {object} A clone of the object.
|
|
27
|
-
* @deprecated Moved to @lumjs/cp package.
|
|
28
|
-
*/
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Make a new object containing properties from other objects using `copyAll`.
|
|
32
|
-
*
|
|
33
|
-
* Use `copyProps.into({}).from(...sources)` for a more robust version.
|
|
34
|
-
*
|
|
35
|
-
* Alias: `copyAll.duplicate`
|
|
36
|
-
*
|
|
37
|
-
* NOTE: As of v1.38.5 this is an alias of @lumjs/cp/fun.duplicateAll
|
|
38
|
-
*
|
|
39
|
-
* @name module:@lumjs/core/obj.duplicateAll
|
|
40
|
-
* @param {object} obj - The object to duplicate.
|
|
41
|
-
* @returns {object} A clone of the object.
|
|
42
|
-
* @deprecated Moved to @lumjs/cp package.
|
|
43
|
-
*/
|
|
44
|
-
|
|
45
|
-
module.exports = require('@lumjs/cp/fun');
|
package/lib/obj/copyprops.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copy properties from one object to another.
|
|
3
|
-
*
|
|
4
|
-
* NOTE: As of v1.38.5 this is an alias of @lumjs/cp/fun.copyProps
|
|
5
|
-
*
|
|
6
|
-
* @function module:@lumjs/core/obj.copyProps
|
|
7
|
-
*
|
|
8
|
-
* @param {(object|function)} source - The object to copy properties from.
|
|
9
|
-
* @param {(object|function)} target - The target to copy properties to.
|
|
10
|
-
*
|
|
11
|
-
* @param {object} [opts] Options for how to copy properties.
|
|
12
|
-
* @param {boolean} [opts.default=true] Copy only enumerable properties.
|
|
13
|
-
* @param {boolean} [opts.all=false] Copy ALL object properties.
|
|
14
|
-
* @param {Array} [opts.props] A list of specific properties to copy.
|
|
15
|
-
* @param {Array} [opts.exclude] A list of properties NOT to copy.
|
|
16
|
-
* @param {object} [opts.overrides] Descriptor overrides for properties.
|
|
17
|
-
*
|
|
18
|
-
* The object is considered a map, where each *key* is the name of the
|
|
19
|
-
* property, and the value should be an `object` containing any valid
|
|
20
|
-
* descriptor properties.
|
|
21
|
-
*
|
|
22
|
-
* If `opts.default` is explicitly set to `false` and `opts.overrides`
|
|
23
|
-
* is set, then not only will it be used as a list of overrides,
|
|
24
|
-
* but only the properties specified in it will be copied.
|
|
25
|
-
*
|
|
26
|
-
* @param {*} [opts.overwrite=false] Overwrite existing properties.
|
|
27
|
-
*
|
|
28
|
-
* If this is a `boolean` value, it will allow or disallow overwriting
|
|
29
|
-
* of any and all properties in the target object.
|
|
30
|
-
*
|
|
31
|
-
* If this is an `object`, it can be an `Array` of property names to allow
|
|
32
|
-
* to be overwritten, or a *map* of property name to a `boolean` indicating
|
|
33
|
-
* if that property can be overwritten or not.
|
|
34
|
-
*
|
|
35
|
-
* Finally, if this is a `function` it'll be passed the property name and
|
|
36
|
-
* must return a boolean indicating if overwriting is allowed.
|
|
37
|
-
*
|
|
38
|
-
* @param {number} [opts.recursive=0] Enable recursive copying of objects.
|
|
39
|
-
*
|
|
40
|
-
* If it is `0` (also `copyProps.RECURSE_NONE`) then no recursion is done.
|
|
41
|
-
* In this case, the regular assignment rules (including `opts.overwrite`)
|
|
42
|
-
* will be used regardless of the property type.
|
|
43
|
-
* This is the default value.
|
|
44
|
-
*
|
|
45
|
-
* If this is *above zero*, it's the recursion depth for `object` properties.
|
|
46
|
-
*
|
|
47
|
-
* If this is *below zero*, then it should be one of the constant values:
|
|
48
|
-
*
|
|
49
|
-
* | Contant | Value | Description |
|
|
50
|
-
* | ------------------------ | ----- | ------------------------------------ |
|
|
51
|
-
* | `copyProps.RECURSE_ALL` | `-1` | Recurse to an *unlimited* depth. |
|
|
52
|
-
* | `copyProps.RECURSE_LIST` | `-2` | Recurse `opts.recurseOpts` props. |
|
|
53
|
-
*
|
|
54
|
-
* @param {object} [opts.recurseOpts] Options for recursive properties.
|
|
55
|
-
*
|
|
56
|
-
* If `opts.recursive` is not `0` then `opts.recurseOpts` can be a map of
|
|
57
|
-
* property names to further objects, which will be used as the `opts` for
|
|
58
|
-
* that property when calling `copyProps()` recursively.
|
|
59
|
-
*
|
|
60
|
-
* So you could have nested `opts.recurseOpts` values if required.
|
|
61
|
-
*
|
|
62
|
-
* The `recursive` property will automatically be added to the individual
|
|
63
|
-
* `recurseOpts`, automatically applying the correct value.
|
|
64
|
-
*
|
|
65
|
-
* The `opts.recurseOpts` option has an extra-special meaning if `opts.recurse`
|
|
66
|
-
* is set to `RECURSE_LIST`, as then *only* the properties with options defined
|
|
67
|
-
* in `opts.recurseOpts` will be recursed. The rest will simply be copied.
|
|
68
|
-
*
|
|
69
|
-
* @returns {object} The `target` object.
|
|
70
|
-
* @deprecated Moved to @lumjs/cp package.
|
|
71
|
-
*/
|
|
72
|
-
|
|
73
|
-
module.exports = require('@lumjs/cp/fun').copyProps;
|
package/lib/obj/merge.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
// Import required bits here.
|
|
2
|
-
const {B, isObj} = require('../types');
|
|
3
|
-
const copyProps = require('./copyprops');
|
|
4
|
-
|
|
5
|
-
// A shortcut for the recursive option.
|
|
6
|
-
const recursive = copyProps.RECURSE_ALL;
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Merge two objects recursively.
|
|
10
|
-
*
|
|
11
|
-
* This used to be a standalone function, but was poorly designed.
|
|
12
|
-
* It's now a wrapper around the
|
|
13
|
-
* [copyProps()]{@link module:@lumjs/core/obj.copyProps} method.
|
|
14
|
-
*
|
|
15
|
-
* @param {object} source - The source object we're copying from.
|
|
16
|
-
* @param {object} target - The target object we're copying into.
|
|
17
|
-
*
|
|
18
|
-
* @param {(object|boolean)} [opts] Options for `copyProps()`
|
|
19
|
-
*
|
|
20
|
-
* If `opts.recursive` is not a `number`, it'll be set to
|
|
21
|
-
* `copyProps.RECURSE_ALL` to enable recursion with no
|
|
22
|
-
* depth limits.
|
|
23
|
-
*
|
|
24
|
-
* Also, if `opts.overwrite` is not explicitly set, it will
|
|
25
|
-
* be set as `true`, a different default value than `copyProps()`.
|
|
26
|
-
*
|
|
27
|
-
* For backwards compatibility, if this specified as a `boolean`
|
|
28
|
-
* value instead of an object, it'll be assumed to be value
|
|
29
|
-
* for the `opts.overwrite` option.
|
|
30
|
-
*
|
|
31
|
-
* @returns {object} The `target` object.
|
|
32
|
-
* @alias module:@lumjs/core/obj.mergeNested
|
|
33
|
-
*/
|
|
34
|
-
function mergeNested(source, target, opts={})
|
|
35
|
-
{
|
|
36
|
-
if (typeof opts === B)
|
|
37
|
-
{ // Boolean overwrite option was specified.
|
|
38
|
-
opts = {overwrite: opts, recursive};
|
|
39
|
-
}
|
|
40
|
-
else if (!isObj(opts))
|
|
41
|
-
{ // Wasn't an object, use default values.
|
|
42
|
-
opts = {overwrite: true, recursive};
|
|
43
|
-
}
|
|
44
|
-
else
|
|
45
|
-
{ // If recursive or overwrite aren't set, set them.
|
|
46
|
-
if (opts.recursive === undefined)
|
|
47
|
-
opts.recursive = recursive;
|
|
48
|
-
if (opts.overwrite === undefined)
|
|
49
|
-
opts.overwrite = true;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
return copyProps(source, target, opts);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
exports.mergeNested = mergeNested;
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Synchronize two objects.
|
|
59
|
-
*
|
|
60
|
-
* Literally just calls `mergeNested` twice, with the two objects swapped.
|
|
61
|
-
* Probably has all kinds of screwy behaviours because of how it works.
|
|
62
|
-
*
|
|
63
|
-
* @param {object} obj1 - The first object.
|
|
64
|
-
* Because overwrite mode is on by default, any properties in `obj1` will
|
|
65
|
-
* take precedence over the same properties in `obj2`.
|
|
66
|
-
*
|
|
67
|
-
* @param {object} obj2 - The second object.
|
|
68
|
-
* Any properties in `obj2` that were not already in `obj1` will be added
|
|
69
|
-
* to `obj1` thanks to the second merge operation.
|
|
70
|
-
*
|
|
71
|
-
* @param {object} [opts1] Options for the first merge operation.
|
|
72
|
-
* See `mergeNested` for details on the supported options.
|
|
73
|
-
* @param {object} [opts2=opts1] Options for the second merge operation.
|
|
74
|
-
* If this is not specified, `opts2` will be the same as `opts1`.
|
|
75
|
-
*
|
|
76
|
-
* @alias module:@lumjs/core/obj.syncNested
|
|
77
|
-
*/
|
|
78
|
-
function syncNested(obj1, obj2, opts1={}, opts2=opts1)
|
|
79
|
-
{
|
|
80
|
-
mergeNested(obj1, obj2, opts1)
|
|
81
|
-
mergeNested(obj2, obj1, opts2);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
exports.syncNested = syncNested;
|