@lumjs/core 1.37.1 → 1.38.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/obj/assignd.js +30 -0
- package/lib/obj/df.js +213 -0
- package/lib/obj/index.js +4 -1
- package/lib/types/def.js +18 -9
- package/lib/types/lazy.js +6 -0
- package/lib/types/needs.js +99 -26
- package/lib/types/root.js +60 -19
- package/lib/types/unbound/extend.js +15 -19
- package/lib/types/unbound/objects.js +2 -1
- package/package.json +2 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const def = require('../types/def');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Copy properties into a target object.
|
|
7
|
+
*
|
|
8
|
+
* Like Object.assign(), but it uses getOwnPropertyDescriptors()
|
|
9
|
+
* to get the properties to copy and type.def() to assign them.
|
|
10
|
+
*
|
|
11
|
+
* Basically a super simple, non-recursive replacement for my copyProps()
|
|
12
|
+
* and cp() functions that were overly complex and tried to do way too much.
|
|
13
|
+
*
|
|
14
|
+
* @param {object} target - The target object to copy properties into
|
|
15
|
+
* @param {...object} sources - Source objects to copy properties from
|
|
16
|
+
* @returns {object} the `target` object
|
|
17
|
+
*
|
|
18
|
+
* @alias module:@lumjs/core/obj.assignd
|
|
19
|
+
*/
|
|
20
|
+
function assignd (target, ...sources)
|
|
21
|
+
{
|
|
22
|
+
for (const src of sources)
|
|
23
|
+
{
|
|
24
|
+
const descs = Object.getOwnPropertyDescriptors(src);
|
|
25
|
+
def(target, descs);
|
|
26
|
+
}
|
|
27
|
+
return target;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = assignd;
|
package/lib/obj/df.js
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {doesDescriptor,needObj,needType,lazy,B,TYPES} = require('../types');
|
|
4
|
+
|
|
5
|
+
const DEF_DESC = {configurable: true}
|
|
6
|
+
const DEF_OPTS = {autoDesc: true}
|
|
7
|
+
|
|
8
|
+
const cp = Object.assign;
|
|
9
|
+
const clone = (...args) => cp({}, ...args);
|
|
10
|
+
const dps = Object.defineProperties;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Handle populating descriptor objects for df() and family.
|
|
14
|
+
*
|
|
15
|
+
* Exported as `obj.df.descriptor`, but since jsdoc doesn't like
|
|
16
|
+
* properties attached to functions, I've listed it as internal.
|
|
17
|
+
*
|
|
18
|
+
* @param {object} desc - Descriptor object from df()
|
|
19
|
+
* @param {object} opts - Options from df();
|
|
20
|
+
*
|
|
21
|
+
* Will be checked for default descriptor options in the
|
|
22
|
+
* case where those options were not explicitly defined
|
|
23
|
+
* in the descriptor object.
|
|
24
|
+
*
|
|
25
|
+
* @param {boolean} [opts.configurable=true] configurable rule;
|
|
26
|
+
* this is the only option with a fallback default value.
|
|
27
|
+
*
|
|
28
|
+
* @param {boolean} [opts.enumerable] enumerable rule
|
|
29
|
+
*
|
|
30
|
+
* @param {boolean} [opts.writable] writable rule;
|
|
31
|
+
* only applies to data descriptors (ones with a `value` property),
|
|
32
|
+
* NOT to accessor descriptors.
|
|
33
|
+
*
|
|
34
|
+
* @returns {object} `desc`
|
|
35
|
+
* @alias module:@lumjs/core/obj~descriptor
|
|
36
|
+
*/
|
|
37
|
+
function descriptor(desc, opts)
|
|
38
|
+
{
|
|
39
|
+
opts = clone(DEF_DESC, opts);
|
|
40
|
+
|
|
41
|
+
const dps = ['configurable', 'enumerable'];
|
|
42
|
+
if (desc.value) dps.push('writable');
|
|
43
|
+
|
|
44
|
+
for (const dp of dps)
|
|
45
|
+
{
|
|
46
|
+
if (typeof desc[dp] !== B && typeof opts[dp] === B)
|
|
47
|
+
{
|
|
48
|
+
desc[dp] = opts[dp];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return desc;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* A replacement for `types.def()`, but MUCH simpler.
|
|
57
|
+
*
|
|
58
|
+
* Instead of one function where every argument has several different
|
|
59
|
+
* purposes depending on the type of value, there are now a bunch
|
|
60
|
+
* of functions, each one with a single purpose, and a single signature.
|
|
61
|
+
*
|
|
62
|
+
* This is the main one that all the rest use and is just a wrapper
|
|
63
|
+
* around Object.defineProperty() that simplifies its use a bit.
|
|
64
|
+
*
|
|
65
|
+
* @param {(object|function)} obj - Target to define property in
|
|
66
|
+
* @param {(string|symbol)} name - Property identifier
|
|
67
|
+
* @param {*} value - Value to assign
|
|
68
|
+
*
|
|
69
|
+
* If `opts.autoDesc` is `true` and this is an `object` that passes the
|
|
70
|
+
* {@link module:@lumjs/core/types.doesDescriptor} test, it will be
|
|
71
|
+
* used as the template descriptor to assign the property.
|
|
72
|
+
*
|
|
73
|
+
* In any other case, this will be used as the `value` property of
|
|
74
|
+
* a generated descriptor to be assigned.
|
|
75
|
+
*
|
|
76
|
+
* @param {object} [opts] Options
|
|
77
|
+
*
|
|
78
|
+
* @returns {object} `obj`
|
|
79
|
+
* @alias module:@lumjs/core/obj.df
|
|
80
|
+
*/
|
|
81
|
+
function df(obj, name, value, opts)
|
|
82
|
+
{
|
|
83
|
+
const log = {obj,name,value,opts};
|
|
84
|
+
needObj(obj, {log, fun: true});
|
|
85
|
+
needType(TYPES.PROP, name, {log});
|
|
86
|
+
|
|
87
|
+
opts = clone(DEF_OPTS, opts);
|
|
88
|
+
|
|
89
|
+
const desc = descriptor(((opts.autoDesc && doesDescriptor(value))
|
|
90
|
+
? value
|
|
91
|
+
: {value}), opts);
|
|
92
|
+
|
|
93
|
+
return Object.defineProperty(obj, name, desc);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Sub-export
|
|
97
|
+
df(df, 'descriptor', descriptor);
|
|
98
|
+
df(df, 'lazy', lazy);
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* A wrapper around df() that defines multiple properties at once.
|
|
102
|
+
*
|
|
103
|
+
* @param {(object|function)} obj - Target to define property in
|
|
104
|
+
* @param {object} values
|
|
105
|
+
* All string-keyed enumerable properties will be passed to df()
|
|
106
|
+
* @param {object} [opts] See df() for details
|
|
107
|
+
*
|
|
108
|
+
* @returns {object} `obj`
|
|
109
|
+
* @alias module:@lumjs/core/obj.dfa
|
|
110
|
+
*/
|
|
111
|
+
function dfa(obj, values, opts)
|
|
112
|
+
{
|
|
113
|
+
const log = {obj,values,opts};
|
|
114
|
+
needObj(values, {log});
|
|
115
|
+
|
|
116
|
+
for (const key in values)
|
|
117
|
+
{
|
|
118
|
+
df(obj, key, values[key], opts);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return obj;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Build magic closures to define properties using a chained syntax.
|
|
126
|
+
*
|
|
127
|
+
* This actually creates three closures, one around df(), another
|
|
128
|
+
* that wraps dfa(), and one that wraps the lazy() function.
|
|
129
|
+
* You can switch between them using magic properties.
|
|
130
|
+
*
|
|
131
|
+
* The closures when called will pass their arguments to the function
|
|
132
|
+
* they are wrapping, and in a bit of brain-melting recursion, the
|
|
133
|
+
* return value from each closure is the closure itself.
|
|
134
|
+
*
|
|
135
|
+
* Magic Properties that are added to both closures:
|
|
136
|
+
*
|
|
137
|
+
* - `one(name, value)` → A closure that wraps df()
|
|
138
|
+
* - `all(values)` → A closure that wraps dfa()
|
|
139
|
+
* - `update(opts)` → Update the options used by the closures.
|
|
140
|
+
* Uses Object.assign() to copy options from the specied object
|
|
141
|
+
* to the internal options object from the original dfc() call.
|
|
142
|
+
* This is a method call, NOT a closure function.
|
|
143
|
+
* - `opts` → The actual options object used by the closures.
|
|
144
|
+
* - `obj` → The target object used by the closures.
|
|
145
|
+
* - `next(obj)` → A wrapper method that will call dfc().
|
|
146
|
+
* When using this method, a *new set of closures* will be created,
|
|
147
|
+
* with the current options, but a new target object.
|
|
148
|
+
* If you use this in a chained statement, any calls after this
|
|
149
|
+
* will be using the new closures rather than the original ones.
|
|
150
|
+
*
|
|
151
|
+
* @param {(object|function)} obj - Target to define property in;
|
|
152
|
+
* available as the `obj` magic property on the closures.
|
|
153
|
+
*
|
|
154
|
+
* @param {object} [opts] Options - see df() for details;
|
|
155
|
+
* available as the `opts` magic property on the closures.
|
|
156
|
+
*
|
|
157
|
+
* @returns {function} The `one` closure.
|
|
158
|
+
*/
|
|
159
|
+
function dfc(obj, opts={})
|
|
160
|
+
{
|
|
161
|
+
const fnOne = function (name, value)
|
|
162
|
+
{
|
|
163
|
+
df(obj, name, value, opts);
|
|
164
|
+
return fnOne;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const fnAll = function (values)
|
|
168
|
+
{
|
|
169
|
+
dfa(obj, values, opts);
|
|
170
|
+
return fnAll;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const fnLazy = function (name, initfunc)
|
|
174
|
+
{
|
|
175
|
+
lazy(obj, name, initfunc, opts);
|
|
176
|
+
return fnLazy;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const ctx =
|
|
180
|
+
{
|
|
181
|
+
obj: {value: obj},
|
|
182
|
+
opts: {value: opts},
|
|
183
|
+
one: {value: fnOne},
|
|
184
|
+
all: {value: fnAll},
|
|
185
|
+
update:
|
|
186
|
+
{
|
|
187
|
+
value()
|
|
188
|
+
{
|
|
189
|
+
cp(opts, ...arguments);
|
|
190
|
+
return this;
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
next:
|
|
194
|
+
{
|
|
195
|
+
value(newobj)
|
|
196
|
+
{
|
|
197
|
+
return dfc(newobj, opts);
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
dps(fnOne, ctx);
|
|
203
|
+
dps(fnAll, ctx);
|
|
204
|
+
|
|
205
|
+
return fnOne;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
module.exports =
|
|
211
|
+
{
|
|
212
|
+
df, dfa, dfc, lazy,
|
|
213
|
+
}
|
package/lib/obj/index.js
CHANGED
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
const apply = require('./apply');
|
|
7
|
+
const assignd = require('./assignd');
|
|
7
8
|
const {copyAll,duplicateOne,duplicateAll} = require('./copyall');
|
|
8
9
|
const copyProps = require('./copyprops');
|
|
9
10
|
const {CLONE,clone,addClone,cloneIfLocked} = require('./clone');
|
|
11
|
+
const {df,dfa,dfc,lazy} = require('./df');
|
|
10
12
|
const {flip, flipKeyVal, flipMap} = require('./flip');
|
|
11
13
|
const {getMethods,signatureOf,MethodFilter} = require('./getmethods');
|
|
12
14
|
const getProperty = require('./getproperty');
|
|
@@ -24,7 +26,8 @@ const
|
|
|
24
26
|
|
|
25
27
|
module.exports =
|
|
26
28
|
{
|
|
27
|
-
cp, CLONE, clone, addClone, cloneIfLocked, lock, addLock,
|
|
29
|
+
assignd, cp, CLONE, clone, addClone, cloneIfLocked, lock, addLock,
|
|
30
|
+
df, dfa, dfc, lazy,
|
|
28
31
|
mergeNested, syncNested, copyProps, copyAll, ns,
|
|
29
32
|
getObjectPath, setObjectPath, getNamespace, setNamespace,
|
|
30
33
|
getProperty, duplicateAll, duplicateOne, getMethods, signatureOf,
|
package/lib/types/def.js
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const {F,
|
|
4
|
-
const {isObj,
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {F,B} = require('./js');
|
|
4
|
+
const {isObj,isNil,isProperty,doesDescriptor} = require('./basics');
|
|
5
5
|
const clone = (...args) => Object.assign({}, ...args);
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* A wrapper around `Object.defineProperty()` with added flair!
|
|
9
9
|
*
|
|
10
|
+
* FUTURE DEPRECATION: When I release @lumjs/core 2.0, this function
|
|
11
|
+
* will be deprecated! It's gotten almost as convoluted as the old
|
|
12
|
+
* prop() method it replaced from my original Nano.js libraries.
|
|
13
|
+
* I have written new `obj.{df,dfa,dfc}` functions that will replace this
|
|
14
|
+
* function going forward. The related `types.lazy()` function will also
|
|
15
|
+
* be refactored to use the new functions, and moved to the `obj` module,
|
|
16
|
+
* although for the `2.x` lifetime an alias will remain in the `type` module.
|
|
17
|
+
*
|
|
10
18
|
* @param {(object|function)} obj - The object to add a property to.
|
|
11
19
|
*
|
|
12
20
|
* @param {?(string|symbol|boolean|object)} name
|
|
@@ -73,8 +81,8 @@ const clone = (...args) => Object.assign({}, ...args);
|
|
|
73
81
|
* directly, so any changes will be made on the original.
|
|
74
82
|
*
|
|
75
83
|
* @param {boolean} [opts.configurable=true] Default `configurable` value
|
|
76
|
-
* @param {boolean} [opts.enumerable
|
|
77
|
-
* @param {boolean} [opts.writable
|
|
84
|
+
* @param {boolean} [opts.enumerable] Default `enumerable` value
|
|
85
|
+
* @param {boolean} [opts.writable] Default `writable` value
|
|
78
86
|
*
|
|
79
87
|
* Only used with *data descriptors* and will be ignored with
|
|
80
88
|
* *accessor* descriptors.
|
|
@@ -95,9 +103,10 @@ const clone = (...args) => Object.assign({}, ...args);
|
|
|
95
103
|
*/
|
|
96
104
|
function def(obj, name, value, opts)
|
|
97
105
|
{
|
|
98
|
-
const isBound
|
|
99
|
-
=
|
|
100
|
-
&& typeof this.bound === F
|
|
106
|
+
const isBound
|
|
107
|
+
= isObj(this)
|
|
108
|
+
&& typeof this.bound === F
|
|
109
|
+
&& this.bound.$this === this;
|
|
101
110
|
|
|
102
111
|
if (isNil(name) || typeof name === B)
|
|
103
112
|
{ // Binding of Isaac?
|
package/lib/types/lazy.js
CHANGED
|
@@ -100,6 +100,12 @@ const {doesDescriptor} = require('./basics');
|
|
|
100
100
|
*
|
|
101
101
|
* This is an extension of the [def()]{@link module:@lumjs/core/types.def}
|
|
102
102
|
* method, and indeed an alias called `def.lazy()` is also available.
|
|
103
|
+
*
|
|
104
|
+
* IMPORTANT: In version 2.x, this will be refactored to use the new
|
|
105
|
+
* [obj.df()]{@link module:@lumjs/core/obj.df} function that will replace
|
|
106
|
+
* def(). There's already an alias called `df.lazy()` available now.
|
|
107
|
+
* This will also be moved to the `obj` module, with an alias left
|
|
108
|
+
* in the `types` module for the duration of the 2.x lifecycle.
|
|
103
109
|
*
|
|
104
110
|
* @param {(object|function)} target - The object to add the property to.
|
|
105
111
|
*
|
package/lib/types/needs.js
CHANGED
|
@@ -2,44 +2,103 @@ const {F, S, B} = require('./js');
|
|
|
2
2
|
const {isType, isa} = require('./isa');
|
|
3
3
|
const {isObj, isComplex} = require('./basics');
|
|
4
4
|
|
|
5
|
+
// Internal function used by both needObj and needType
|
|
6
|
+
function needOpts(opts, fn, bopt, ons)
|
|
7
|
+
{
|
|
8
|
+
if (isObj(opts))
|
|
9
|
+
{
|
|
10
|
+
if (opts.log)
|
|
11
|
+
{ // Make a closure to handle the logging
|
|
12
|
+
const info = (opts.log === true) ? [opts]
|
|
13
|
+
: (Array.isArray(opts.log) ? opts.log : [opts.log]);
|
|
14
|
+
opts.$log = () => console.error(...info);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
else if (typeof opts === S)
|
|
18
|
+
{ // A message was passed.
|
|
19
|
+
opts =
|
|
20
|
+
{
|
|
21
|
+
msg: opts,
|
|
22
|
+
}
|
|
23
|
+
if (ons) ons(opts);
|
|
24
|
+
}
|
|
25
|
+
else if (typeof opts === B)
|
|
26
|
+
{
|
|
27
|
+
opts = {[bopt]: opts}
|
|
28
|
+
}
|
|
29
|
+
else
|
|
30
|
+
{
|
|
31
|
+
console.error('invalid options', {fn, opts});
|
|
32
|
+
opts = {};
|
|
33
|
+
}
|
|
34
|
+
return opts;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
exports._needOptions = needOpts;
|
|
38
|
+
|
|
5
39
|
/**
|
|
6
40
|
* If a value is not an object, throw an error.
|
|
7
41
|
*
|
|
8
42
|
* @param {*} v - The value we're testing.
|
|
9
|
-
*
|
|
43
|
+
*
|
|
44
|
+
* @param {(object|boolean|string)} [opts] Options
|
|
45
|
+
*
|
|
46
|
+
* - If this is a string, it will be used as `opts.msg`,
|
|
47
|
+
* and `opts.fun` will be determined by the presence
|
|
48
|
+
* of the word 'function' (case-insensitive) in the message.
|
|
49
|
+
* - If this is a boolean, it will be used as `opts.fun`,
|
|
50
|
+
* and the default message will be used.
|
|
51
|
+
*
|
|
52
|
+
* @param {boolean} [opts.fun=false] Also accept `function`?
|
|
10
53
|
*
|
|
11
54
|
* By default this function uses `isObj()` to perform the
|
|
12
|
-
* test. If `
|
|
55
|
+
* test. If `opts.fun` is `true` then it'll use `isComplex()` instead.
|
|
56
|
+
*
|
|
57
|
+
* @param {(object|string|true)} [opts.log] Optional debugging information.
|
|
58
|
+
*
|
|
59
|
+
* This is a way to specify arguments to be sent to the
|
|
60
|
+
* console.error() method before the TypeError is thrown.
|
|
61
|
+
*
|
|
62
|
+
* If this is an `Array` object, it will be used as positional arguments.
|
|
13
63
|
*
|
|
14
|
-
* If
|
|
15
|
-
* parameter, and `allowFunc` will be `true` if the word
|
|
16
|
-
* `function` is found in the message, or `false` otherwise.
|
|
64
|
+
* If it is boolean `true`, the `opts` object itself will be used.
|
|
17
65
|
*
|
|
18
|
-
*
|
|
66
|
+
* Any other value will be used as the sole argument.
|
|
19
67
|
*
|
|
20
|
-
*
|
|
68
|
+
* @param {string} [opts.msg] The error message to use on failure.
|
|
69
|
+
*
|
|
70
|
+
* If not specified, a simple default message will be used.
|
|
71
|
+
*
|
|
72
|
+
* @param {?string} [msg=null] A positional version of `opts.msg`.
|
|
73
|
+
*
|
|
74
|
+
* Setting `opts.msg` as a named option will take precedence
|
|
75
|
+
* over this positional argument.
|
|
21
76
|
*
|
|
22
77
|
* @throws {TypeError} If the type check failed.
|
|
23
78
|
* @alias module:@lumjs/core/types.needObj
|
|
24
79
|
*/
|
|
25
|
-
function needObj (v,
|
|
80
|
+
function needObj (v, opts={}, msg=null)
|
|
26
81
|
{
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
msg = allowFunc;
|
|
30
|
-
allowFunc = msg.toLowerCase().includes(F);
|
|
31
|
-
}
|
|
82
|
+
opts = needOpts(opts, 'needObj', 'fun',
|
|
83
|
+
(o) => o.fun = o.msg.toLowerCase().includes(F));
|
|
32
84
|
|
|
33
|
-
const ok =
|
|
85
|
+
const ok = opts.fun ? isComplex(v) : isObj(v);
|
|
34
86
|
|
|
35
87
|
if (!ok)
|
|
36
88
|
{ // Did not pass the test.
|
|
37
|
-
if (typeof msg
|
|
89
|
+
if (typeof opts.msg === S)
|
|
90
|
+
{
|
|
91
|
+
msg = opts.msg;
|
|
92
|
+
}
|
|
93
|
+
else if (typeof msg !== S)
|
|
38
94
|
{ // Use a default message.
|
|
39
95
|
msg = "Invalid object";
|
|
40
|
-
if (
|
|
96
|
+
if (opts.fun)
|
|
41
97
|
msg += " or function";
|
|
42
98
|
}
|
|
99
|
+
|
|
100
|
+
if (opts.$log) opts.$log();
|
|
101
|
+
|
|
43
102
|
throw new TypeError(msg);
|
|
44
103
|
}
|
|
45
104
|
}
|
|
@@ -51,28 +110,42 @@ exports.needObj = needObj;
|
|
|
51
110
|
*
|
|
52
111
|
* @param {string} type - The type name as per `isType()`.
|
|
53
112
|
* @param {*} v - The value we're testing.
|
|
54
|
-
*
|
|
113
|
+
*
|
|
114
|
+
* @param {(object|string)} [opts] Options
|
|
115
|
+
*
|
|
116
|
+
* If this is a string, it will be used as `opts.msg`.
|
|
117
|
+
*
|
|
118
|
+
* @param {string} [opts.msg] See needObj() for details.
|
|
119
|
+
* @param {(object|string|true)} [opts.log] See needObj() for details.
|
|
120
|
+
*
|
|
121
|
+
* @param {?string} [msg=null] A positional version of `opts.msg`;
|
|
122
|
+
* handled the same was as needObj().
|
|
123
|
+
*
|
|
55
124
|
* @throws {TypeError} If the type check failed.
|
|
56
125
|
* @alias module:@lumjs/core/types.needType
|
|
57
126
|
*/
|
|
58
|
-
function needType (type, v,
|
|
127
|
+
function needType (type, v, opts={}, msg=null)
|
|
59
128
|
{
|
|
129
|
+
opts = needOpts(opts, 'needType', 'null');
|
|
130
|
+
|
|
131
|
+
if (typeof opts.null === B)
|
|
132
|
+
{
|
|
133
|
+
console.warn("needType(): 'allowNull' is no longer supported");
|
|
134
|
+
}
|
|
135
|
+
|
|
60
136
|
if (!isType(type, v))
|
|
61
137
|
{
|
|
62
|
-
if (typeof msg ===
|
|
138
|
+
if (typeof opts.msg === S)
|
|
63
139
|
{
|
|
64
|
-
|
|
65
|
-
if (typeof unused === S)
|
|
66
|
-
{ // Compatibility with old code.
|
|
67
|
-
msg = unused;
|
|
68
|
-
}
|
|
140
|
+
msg = opts.msg;
|
|
69
141
|
}
|
|
70
|
-
|
|
71
|
-
if (typeof msg !== S)
|
|
142
|
+
else if (typeof msg !== S)
|
|
72
143
|
{ // Use a default message.
|
|
73
144
|
msg = `Invalid ${type} value`;
|
|
74
145
|
}
|
|
75
146
|
|
|
147
|
+
if (opts.$log) opts.$log();
|
|
148
|
+
|
|
76
149
|
throw new TypeError(msg);
|
|
77
150
|
}
|
|
78
151
|
}
|
package/lib/types/root.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const {U} = require('./js');
|
|
2
|
-
const {isNil,isArray} = require('./basics');
|
|
2
|
+
const {isNil,isObj,isArray} = require('./basics');
|
|
3
3
|
|
|
4
4
|
// «private»
|
|
5
5
|
function no_root()
|
|
@@ -11,40 +11,81 @@ function no_root()
|
|
|
11
11
|
* The global root object. Usually `globalThis` these days.
|
|
12
12
|
* @alias module:@lumjs/core/types.root
|
|
13
13
|
*/
|
|
14
|
-
const root
|
|
15
|
-
|
|
16
|
-
: typeof
|
|
17
|
-
: typeof
|
|
14
|
+
const root
|
|
15
|
+
= typeof globalThis !== U ? globalThis
|
|
16
|
+
: typeof global !== U ? global
|
|
17
|
+
: typeof self !== U ? self
|
|
18
|
+
: typeof window !== U ? window
|
|
18
19
|
: no_root(); // Unlike the old way, we'll die if the environment is undetermined.
|
|
19
20
|
|
|
20
21
|
exports.root = root;
|
|
21
22
|
|
|
22
|
-
// A
|
|
23
|
+
// A Set of objects to be considered unbound globally.
|
|
23
24
|
const unboundObjects = require('./unbound/objects');
|
|
24
25
|
|
|
26
|
+
// Default options for unbound()
|
|
27
|
+
const UBDO =
|
|
28
|
+
{
|
|
29
|
+
nil: true,
|
|
30
|
+
root: true,
|
|
31
|
+
}
|
|
32
|
+
|
|
25
33
|
/**
|
|
26
34
|
* Pass `this` here to see if it is bound to an object.
|
|
27
35
|
*
|
|
28
|
-
*
|
|
36
|
+
* @param {*} whatIsThis - The `this` from any context
|
|
37
|
+
*
|
|
38
|
+
* @param {(boolean|object)} [opts] Options for advanced behaviours.
|
|
39
|
+
*
|
|
40
|
+
* If this is boolean then it'll be used as `opts.root`;
|
|
41
|
+
* If it is an `Array` or `Set` it will be used as `opts.list`;
|
|
42
|
+
* Use just a plain object literal for specifying named options.
|
|
43
|
+
*
|
|
44
|
+
* TODO: as of v2.0 this will no longer accept a boolean value
|
|
45
|
+
* as a shortcut to `opts.root`. That must be explicitly set.
|
|
46
|
+
*
|
|
47
|
+
* @param {boolean} [opts.root=true] The global root is unbound?
|
|
48
|
+
* @param {boolean} [opts.nil=true] `null` and `undefined` are unbound?
|
|
49
|
+
* @param {(Array|Set)} [opts.list] A list of additional values that
|
|
50
|
+
* for the purposes of this test will be considered unbound.
|
|
51
|
+
*
|
|
52
|
+
* @param {(Array|Set|boolean)} [list] A positional version of `opts.list`;
|
|
53
|
+
* ONLY used when the `opts` argument is boolean.
|
|
54
|
+
*
|
|
55
|
+
* TODO: remove this argument as of v2.0
|
|
29
56
|
*
|
|
30
|
-
* @param {*} whatIsThis - The `this` from any context.
|
|
31
|
-
* @param {boolean} [rootIsUnbound=true] The global root is unbound.
|
|
32
|
-
* @param {(boolean|Array)} [areUnbound=false] A list of unbound objects.
|
|
33
|
-
* If the is `true` we use an global list that can register special
|
|
34
|
-
* internal objects. Otherwise an `Array` of unbound objects may be used.
|
|
35
57
|
* @returns {boolean}
|
|
36
58
|
* @alias module:@lumjs/core/types.unbound
|
|
37
59
|
*/
|
|
38
|
-
function unbound(whatIsThis,
|
|
60
|
+
function unbound(whatIsThis, opts=true, list)
|
|
39
61
|
{
|
|
40
|
-
if (
|
|
41
|
-
{ //
|
|
42
|
-
|
|
62
|
+
if (isObj(opts))
|
|
63
|
+
{ // Merge in defaults
|
|
64
|
+
if (opts instanceof Set || isArray(opts))
|
|
65
|
+
{ // A shortcut to the `list` property
|
|
66
|
+
list = opts;
|
|
67
|
+
opts = Object.assign({}, UBDO);
|
|
68
|
+
}
|
|
69
|
+
else
|
|
70
|
+
{ // Regular options were specified.
|
|
71
|
+
opts = Object.assign({}, UBDO, {list}, opts);
|
|
72
|
+
list = opts.list;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else
|
|
76
|
+
{ // Assume old positional arguments are being used
|
|
77
|
+
opts = Object.assign({}, UBDO, {root: opts});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (list === true)
|
|
81
|
+
{ // Internal special unbound values
|
|
82
|
+
list = unboundObjects;
|
|
43
83
|
}
|
|
44
84
|
|
|
45
|
-
if (isNil(whatIsThis)) return true;
|
|
46
|
-
if (
|
|
47
|
-
if (
|
|
85
|
+
if (opts.nil && isNil(whatIsThis)) return true;
|
|
86
|
+
if (opts.root && whatIsThis === root) return true;
|
|
87
|
+
if (list instanceof Set && list.has(whatIsThis)) return true;
|
|
88
|
+
if (isArray(list) && list.includes(whatIsThis)) return true;
|
|
48
89
|
|
|
49
90
|
// Nothing considered unbound.
|
|
50
91
|
return false;
|
|
@@ -2,45 +2,41 @@
|
|
|
2
2
|
|
|
3
3
|
const def = require('../def');
|
|
4
4
|
const {needObj} = require('../needs');
|
|
5
|
-
const removeFromArray = require('../../arrays/list').removeItems;
|
|
6
5
|
const unboundObjects = require('./objects');
|
|
7
6
|
|
|
8
|
-
// Adds a couple
|
|
7
|
+
// Adds a couple proxy methods to the `unbound` function.
|
|
9
8
|
module.exports = function(unbound)
|
|
10
9
|
{
|
|
11
10
|
/**
|
|
12
11
|
* Add an item to the unbound global objects list.
|
|
13
12
|
*
|
|
14
|
-
* @
|
|
15
|
-
* @
|
|
16
|
-
* @
|
|
17
|
-
* @
|
|
18
|
-
* @
|
|
13
|
+
* @deprecated the global list is going away in 2.0
|
|
14
|
+
* @function module:@lumjs/core/types.unbound.add
|
|
15
|
+
* @param {(object|function)} obj - Value to be added
|
|
16
|
+
* @returns {boolean} always true as of v1.37.2
|
|
17
|
+
* @throws {TypeError} If `obj` was not a valid value
|
|
19
18
|
*/
|
|
20
19
|
def(unbound, 'add', function (obj)
|
|
21
20
|
{
|
|
22
21
|
needObj(obj, true);
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
// Add to list and we're done.
|
|
28
|
-
unboundObjects.push(obj);
|
|
22
|
+
if (unboundObjects.has(obj)) return false;
|
|
23
|
+
unboundObjects.add(obj);
|
|
29
24
|
return true;
|
|
30
25
|
});
|
|
31
26
|
|
|
32
27
|
/**
|
|
33
28
|
* Remove an item from the unbound global objects list.
|
|
34
29
|
*
|
|
35
|
-
* @
|
|
36
|
-
* @
|
|
37
|
-
* @
|
|
38
|
-
* @
|
|
39
|
-
* @
|
|
30
|
+
* @deprecated the global list is going away in 2.0
|
|
31
|
+
* @function module:@lumjs/core/types.unbound.remove
|
|
32
|
+
* @param {(object|function)} obj - value to be removed
|
|
33
|
+
* @returns {boolean} always true as of v1.37.2
|
|
34
|
+
* @throws {TypeError} If `obj` was not a valid value
|
|
40
35
|
*/
|
|
41
36
|
def(unbound, 'remove', function(obj)
|
|
42
37
|
{
|
|
43
38
|
needObj(obj, true);
|
|
44
|
-
|
|
39
|
+
unboundObjects.delete(obj);
|
|
40
|
+
return true;
|
|
45
41
|
});
|
|
46
42
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lumjs/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.38.0",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"exports":
|
|
6
6
|
{
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"./modules": "./lib/modules.js",
|
|
18
18
|
"./obj": "./lib/obj/index.js",
|
|
19
19
|
"./obj/cp": "./lib/obj/cp.js",
|
|
20
|
+
"./obj/df": "./lib/obj/df.js",
|
|
20
21
|
"./observable": "./lib/observable.js",
|
|
21
22
|
"./opt": "./lib/opt/index.js",
|
|
22
23
|
"./opt/args": "./lib/opt/args.js",
|