@lumjs/core 1.25.2 → 1.30.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/README.md +14 -0
- package/TODO.md +2 -0
- package/lib/console.js +54 -0
- package/lib/enum.js +27 -6
- package/lib/index.js +12 -16
- package/lib/meta.js +68 -88
- package/lib/obj/clone.js +1 -1
- package/lib/obj/copyprops.js +1 -1
- package/lib/obj/merge.js +1 -1
- package/lib/obj/ns.js +8 -3
- package/lib/objectid.js +34 -13
- package/lib/observable.js +1 -1
- package/lib/old/abstractclass.js +82 -0
- package/lib/opt/args.js +50 -0
- package/lib/opt/getpath.js +70 -0
- package/lib/opt/getval.js +61 -0
- package/lib/opt/index.js +21 -0
- package/lib/opt/val.js +63 -0
- package/lib/strings.js +1 -1
- package/lib/types/basics.js +43 -16
- package/lib/types/def.js +49 -36
- package/lib/types/dt.js +147 -18
- package/lib/types/index.js +35 -59
- package/lib/types/isa.js +4 -0
- package/lib/types/js.js +29 -12
- package/lib/types/lazy.js +3 -2
- package/lib/types/needs.js +0 -1
- package/package.json +7 -3
- package/lib/opt.js +0 -404
package/lib/opt/args.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {isObj} = require('../types/basics');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A helper function to support both positional arguments
|
|
7
|
+
* and named options in the same method signature.
|
|
8
|
+
*
|
|
9
|
+
* @param {object} opts - Options built from positional arguments
|
|
10
|
+
*
|
|
11
|
+
* Keep in mind that this object **WILL** be modified!
|
|
12
|
+
*
|
|
13
|
+
* @param {string} optArg - The option that may contain named options
|
|
14
|
+
*
|
|
15
|
+
* Generally the name of the first positional argument that may be
|
|
16
|
+
* an `object` full of options or a different positional argument value.
|
|
17
|
+
*
|
|
18
|
+
* The biggest limitation is that it cannot be an `object` value when used
|
|
19
|
+
* as a positional argument, as that will always be seen as the _options_.
|
|
20
|
+
*
|
|
21
|
+
* @param {*} optDef - A default value for `opts[optArg]`
|
|
22
|
+
*
|
|
23
|
+
* If `opts[optArg]` was an `object`, we'll compose its properties
|
|
24
|
+
* into `opts` directly. If after that `opts[optArg]` is still the
|
|
25
|
+
* options `object` then this value will be used instead.
|
|
26
|
+
*
|
|
27
|
+
* @example <caption>Example usage</caption>
|
|
28
|
+
*
|
|
29
|
+
* function example(first=true, second=null, third="test")
|
|
30
|
+
* {
|
|
31
|
+
* const opts = argOpts({first, second, third}, 'first', true);
|
|
32
|
+
* }
|
|
33
|
+
*
|
|
34
|
+
* @exports module:@lumjs/core/opt/args
|
|
35
|
+
*/
|
|
36
|
+
function argOpts(opts, optArg, optDef)
|
|
37
|
+
{
|
|
38
|
+
if (isObj(opts[optArg]))
|
|
39
|
+
{ // Merge the named options.
|
|
40
|
+
const specOpts = opts[optArg];
|
|
41
|
+
Object.assign(opts, specOpts);
|
|
42
|
+
if (opts[optArg] === specOpts)
|
|
43
|
+
{ // specOpts didn't override the real option.
|
|
44
|
+
opts[optArg] = optDef;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return opts;
|
|
48
|
+
} // argOpts()
|
|
49
|
+
|
|
50
|
+
module.exports = argOpts;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {isArrayOf,S} = require('../types/basics');
|
|
4
|
+
const {getObjectPath} = require('../obj/ns');
|
|
5
|
+
const {val} = require('./val');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* An alternative to `get()` that uses `getObjectPath()`
|
|
9
|
+
* to look for a specific nested property value.
|
|
10
|
+
*
|
|
11
|
+
* While `get()` supports positional arguments like `val()`,
|
|
12
|
+
* this function _only_ supports named options.
|
|
13
|
+
*
|
|
14
|
+
* @param {object} obj - Object we're looking for properties in
|
|
15
|
+
* @param {(string|Array)} path - Path for `getObjectPath()`
|
|
16
|
+
* @param {object} [opts] Options
|
|
17
|
+
*
|
|
18
|
+
* This supports all of the same options as `get()`, plus all of the
|
|
19
|
+
* options supported by `getObjectPath()`. See the docs for both those
|
|
20
|
+
* functions to see what all is supported. If the same option is supported
|
|
21
|
+
* by *both* functions (e.g. `allowFun`) then the default value
|
|
22
|
+
* will be the one from `getObjectPath()` rather than `get()`.
|
|
23
|
+
*
|
|
24
|
+
* @param {boolean} [opts.ro=false] Should `opts` be read-only?
|
|
25
|
+
*
|
|
26
|
+
* If `true`, a copy of the `opts` will be made before any changes
|
|
27
|
+
* are performed, ensuring the original options aren't modified.
|
|
28
|
+
*
|
|
29
|
+
* @returns {*} The property if found, or `opts.default` if not.
|
|
30
|
+
*
|
|
31
|
+
* @see module:@lumjs/core/opt.get
|
|
32
|
+
* @see module:@lumjs/core/obj.getObjectPath
|
|
33
|
+
* @alias module:@lumjs/core/opt.getPath
|
|
34
|
+
*/
|
|
35
|
+
function getPath(obj, path, opts={})
|
|
36
|
+
{
|
|
37
|
+
const defvalue = opts.default;
|
|
38
|
+
if (opts.ro)
|
|
39
|
+
{
|
|
40
|
+
opts = Object.assign({}, opts);
|
|
41
|
+
}
|
|
42
|
+
delete opts.default;
|
|
43
|
+
|
|
44
|
+
return val(getObjectPath(obj, path, opts), defvalue,
|
|
45
|
+
(opts.allowNull ?? true),
|
|
46
|
+
opts.isLazy,
|
|
47
|
+
(opts.lazyThis ?? obj),
|
|
48
|
+
opts.lazyArgs);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Does a value appear to be a path usable by the
|
|
53
|
+
* {@link module:@lumjs/core/opt.getPath} function?
|
|
54
|
+
*
|
|
55
|
+
* @param {*} value - Value to test;
|
|
56
|
+
* will be considered a path if it is:
|
|
57
|
+
*
|
|
58
|
+
* - An `Array` with only `string` values in it.
|
|
59
|
+
* - A string with a `.` character in it.
|
|
60
|
+
*
|
|
61
|
+
* @returns {boolean}
|
|
62
|
+
* @alias module:@lumjs/core/opt.isPath
|
|
63
|
+
*/
|
|
64
|
+
function isPath(value)
|
|
65
|
+
{
|
|
66
|
+
return (isArrayOf(value, S)
|
|
67
|
+
|| (typeof value === S && value.includes('.')));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = {getPath, isPath};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {S,needObj,needType} = require('../types');
|
|
4
|
+
const {_opts,val} = require('./val');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* See if a property in an object is set.
|
|
8
|
+
*
|
|
9
|
+
* If it is, return the property, otherwise return a default value.
|
|
10
|
+
* This uses the `val()` method, and as such supports the same arguments.
|
|
11
|
+
* However read the descriptions, as defaults may be quite different!
|
|
12
|
+
*
|
|
13
|
+
* @param {object} obj - An object to test for a property in.
|
|
14
|
+
* @param {string} optname - The property name we're checking for.
|
|
15
|
+
* @param {*} defvalue - The default value.
|
|
16
|
+
*
|
|
17
|
+
* @param {(object|boolean)} [opts] Options
|
|
18
|
+
*
|
|
19
|
+
* If this is a `boolean` it is used as the `allowNull` option.
|
|
20
|
+
*
|
|
21
|
+
* @param {boolean} [opts.allowNull=true] Passed to `val()`;
|
|
22
|
+
* default is `true`, which differs from `val()`.
|
|
23
|
+
* @param {boolean} [opts.isLazy=false] Passed to `val()`;
|
|
24
|
+
* default is `false`, the same as `val()`.
|
|
25
|
+
* @param {object} [opts.lazyThis=obj] Passed to `val()`;
|
|
26
|
+
* default is `obj`, which differs from `val()`.
|
|
27
|
+
* @param {Array} [opts.lazyArgs] Passed to `val()`
|
|
28
|
+
* @param {boolean} [opts.allowFun=false] Allow `obj` to be a `function` ?
|
|
29
|
+
*
|
|
30
|
+
* By default only `object` values are valid for `obj`; this can be set to
|
|
31
|
+
* `true` to allow `function` values to be used.
|
|
32
|
+
*
|
|
33
|
+
* @param {boolean} [isLazy=false] Same as `opts.isLazy`
|
|
34
|
+
* @param {object} [lazyThis=opts] Same as `opts.lazyThis`
|
|
35
|
+
* @param {Array} [lazyArgs] Same as `opts.lazyArgs`
|
|
36
|
+
* @param {boolean} [allowFun] Same as `opts.allowFun`
|
|
37
|
+
*
|
|
38
|
+
* @returns {*} Either the property value, or the default value.
|
|
39
|
+
* @see module:@lumjs/core/opt.val
|
|
40
|
+
* @alias module:@lumjs/core/opt.get
|
|
41
|
+
*/
|
|
42
|
+
function get(obj, optname, defvalue,
|
|
43
|
+
allowNull=true,
|
|
44
|
+
isLazy=false,
|
|
45
|
+
lazyThis=obj,
|
|
46
|
+
lazyArgs=[],
|
|
47
|
+
allowFun=false)
|
|
48
|
+
{
|
|
49
|
+
const opts = _opts({allowNull,isLazy,lazyThis,lazyArgs,allowFun}, true);
|
|
50
|
+
|
|
51
|
+
needObj(obj, opts.allowFun);
|
|
52
|
+
needType(S, optname);
|
|
53
|
+
|
|
54
|
+
return val(obj[optname], defvalue,
|
|
55
|
+
opts.allowNull,
|
|
56
|
+
opts.isLazy,
|
|
57
|
+
opts.lazyThis,
|
|
58
|
+
opts.lazyArgs);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
module.exports = {val, get};
|
package/lib/opt/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Functions for working with options and default values.
|
|
3
|
+
* @module @lumjs/core/opt
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const argOpts = require('./args');
|
|
7
|
+
const {getPath,isPath} = require('./getpath');
|
|
8
|
+
const {val,get} = require('./getval');
|
|
9
|
+
|
|
10
|
+
exports = module.exports =
|
|
11
|
+
{
|
|
12
|
+
argOpts, get, getPath, isPath, val,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const {wrapDepr} = require('../meta');
|
|
16
|
+
wrapDepr(exports, 'Opts',
|
|
17
|
+
{
|
|
18
|
+
dep: '@lumjs/core.opt.Opts',
|
|
19
|
+
rep: '@lumjs/opts',
|
|
20
|
+
get: () => require('@lumjs/opts'),
|
|
21
|
+
});
|
package/lib/opt/val.js
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {U,F} = require('../types/js');
|
|
4
|
+
const argOpts = require('./args');
|
|
5
|
+
|
|
6
|
+
// Helper for `val()` and `get()` to support new-style options.
|
|
7
|
+
function _opts(opts, defNull)
|
|
8
|
+
{
|
|
9
|
+
return argOpts(opts, 'allowNull', defNull);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* See if a value is *set*, and if not, return a default value.
|
|
14
|
+
*
|
|
15
|
+
* This function used to use all positional arguments, but it now
|
|
16
|
+
* supports named options if an `object` is passed as the third argument.
|
|
17
|
+
* If both named options and the corresponding positional arguments are
|
|
18
|
+
* specified, the named options will take precedence.
|
|
19
|
+
*
|
|
20
|
+
* @param {*} optvalue - The value we are testing.
|
|
21
|
+
* @param {*} defvalue - The default value if opt was null or undefined.
|
|
22
|
+
*
|
|
23
|
+
* @param {(object|boolean)} opts - Options
|
|
24
|
+
*
|
|
25
|
+
* If this is a `boolean` it is used as the `allowNull` option.
|
|
26
|
+
*
|
|
27
|
+
* @param {boolean} [opts.allowNull=false] If true, allow null to count as *set*.
|
|
28
|
+
* @param {boolean} [opts.isLazy=false] If true, and `defvalue` is a function,
|
|
29
|
+
* use the value from the function as
|
|
30
|
+
* the default.
|
|
31
|
+
* @param {object} [opts.lazyThis=null] If `isLazy` is true, this object will
|
|
32
|
+
* be used as `this` for the function.
|
|
33
|
+
* @param {Array} [opts.lazyArgs] If `isLazy` is true, this may be used
|
|
34
|
+
* as a list of arguments to pass.
|
|
35
|
+
*
|
|
36
|
+
* @param {boolean} [isLazy=false] Same as `opts.isLazy`
|
|
37
|
+
* @param {object} [lazyThis=null] Same as `opts.lazyThis`
|
|
38
|
+
* @param {Array} [lazyArgs] Same as `opts.lazyArgs`
|
|
39
|
+
*
|
|
40
|
+
* @return {*} Either `optvalue` or `defvalue` depending on the test.
|
|
41
|
+
* @alias module:@lumjs/core/opt.val
|
|
42
|
+
*/
|
|
43
|
+
function val(optvalue, defvalue,
|
|
44
|
+
allowNull=false,
|
|
45
|
+
isLazy=false,
|
|
46
|
+
lazyThis=null,
|
|
47
|
+
lazyArgs=[])
|
|
48
|
+
{
|
|
49
|
+
const opts = _opts({allowNull,isLazy,lazyThis,lazyArgs}, false);
|
|
50
|
+
|
|
51
|
+
if (typeof optvalue === U || (!opts.allowNull && optvalue === null))
|
|
52
|
+
{ // The defined value was not "set" as per our rules.
|
|
53
|
+
if (opts.isLazy && typeof defvalue === F)
|
|
54
|
+
{ // Get the default value from a passed in function.
|
|
55
|
+
return defvalue.apply(opts.lazyThis, opts.lazyArgs);
|
|
56
|
+
}
|
|
57
|
+
return defvalue;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return optvalue;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
module.exports = {_opts, val};
|
package/lib/strings.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* String and locale related functions.
|
|
3
3
|
* @module @lumjs/core/strings
|
|
4
4
|
*/
|
|
5
|
-
const {S,B,F,isObj,root,isArray,needType,needObj
|
|
5
|
+
const {S,B,F,isObj,root,isArray,needType,needObj} = require('./types');
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Get the locale/language string.
|
package/lib/types/basics.js
CHANGED
|
@@ -1,10 +1,35 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Basic types sub-module.
|
|
5
|
+
*
|
|
6
|
+
* Provides simple type tests, and a few one or two character constants
|
|
7
|
+
* One or two character identifiers for the core JS type names.
|
|
8
|
+
*
|
|
9
|
+
* These are only the strings returned by the `typeof` operator.
|
|
10
|
+
* See {@link module:@lumjs/core/types.TYPES} for a list
|
|
11
|
+
* that includes special types and compound pseudo-types, etc.
|
|
12
|
+
*
|
|
13
|
+
* @prop {string} O - object
|
|
14
|
+
* @prop {string} F - function
|
|
15
|
+
* @prop {string} S - string
|
|
16
|
+
* @prop {string} B - boolean
|
|
17
|
+
* @prop {string} N - number
|
|
18
|
+
* @prop {string} U - undefined
|
|
19
|
+
* @prop {string} SY - symbol
|
|
20
|
+
* @prop {string} BI - bigint
|
|
21
|
+
*
|
|
22
|
+
* @module @lumjs/core/types/basics
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
const JS = require('./js');
|
|
26
|
+
const {O, F, S, SY} = JS;
|
|
2
27
|
|
|
3
28
|
/**
|
|
4
29
|
* See if a value is a non-null `object`.
|
|
5
30
|
* @param {*} v - The value we're testing.
|
|
6
31
|
* @returns {boolean}
|
|
7
|
-
* @alias module:@lumjs/core/types.isObj
|
|
32
|
+
* @alias module:@lumjs/core/types/basics.isObj
|
|
8
33
|
*/
|
|
9
34
|
function isObj(v) { return (typeof v === O && v !== null); }
|
|
10
35
|
|
|
@@ -13,7 +38,7 @@ function isObj(v) { return (typeof v === O && v !== null); }
|
|
|
13
38
|
* Like `isObj()`, `null` does not count as an `object`.
|
|
14
39
|
* @param {*} v - The value we're testing.
|
|
15
40
|
* @returns {boolean}
|
|
16
|
-
* @alias module:@lumjs/core/types.isComplex
|
|
41
|
+
* @alias module:@lumjs/core/types/basics.isComplex
|
|
17
42
|
*/
|
|
18
43
|
function isComplex(v) { return (typeof v === F || isObj(v)); }
|
|
19
44
|
|
|
@@ -21,7 +46,7 @@ function isComplex(v) { return (typeof v === F || isObj(v)); }
|
|
|
21
46
|
* See if a value is *nil* (i.e. either `null` or `undefined`).
|
|
22
47
|
* @param {*} v - The value we're testing.
|
|
23
48
|
* @returns {boolean}
|
|
24
|
-
* @alias module:@lumjs/core/types.isNil
|
|
49
|
+
* @alias module:@lumjs/core/types/basics.isNil
|
|
25
50
|
*/
|
|
26
51
|
function isNil(v) { return (v === undefined || v === null); }
|
|
27
52
|
|
|
@@ -29,7 +54,7 @@ function isNil(v) { return (v === undefined || v === null); }
|
|
|
29
54
|
* See if a value is not *nil* (i.e. neither `null` nor `undefined`).
|
|
30
55
|
* @param {*} v - The value we're testing.
|
|
31
56
|
* @returns {boolean}
|
|
32
|
-
* @alias module:@lumjs/core/types.notNil
|
|
57
|
+
* @alias module:@lumjs/core/types/basics.notNil
|
|
33
58
|
*/
|
|
34
59
|
function notNil(v) { return (v !== undefined && v !== null); }
|
|
35
60
|
|
|
@@ -39,7 +64,7 @@ function notNil(v) { return (v !== undefined && v !== null); }
|
|
|
39
64
|
* is neither *nil* nor *complex*.
|
|
40
65
|
* @param {*} v - The value we're testing.
|
|
41
66
|
* @returns {boolean}
|
|
42
|
-
* @alias module:@lumjs/core/types.isScalar
|
|
67
|
+
* @alias module:@lumjs/core/types/basics.isScalar
|
|
43
68
|
*/
|
|
44
69
|
function isScalar(v) { return (notNil(v) && !isComplex(v)); }
|
|
45
70
|
|
|
@@ -49,7 +74,7 @@ function isScalar(v) { return (notNil(v) && !isComplex(v)); }
|
|
|
49
74
|
* @function
|
|
50
75
|
* @param {*} v - The value we're testing.
|
|
51
76
|
* @returns {boolean}
|
|
52
|
-
* @alias module:@lumjs/core/types.isArray
|
|
77
|
+
* @alias module:@lumjs/core/types/basics.isArray
|
|
53
78
|
*/
|
|
54
79
|
const isArray = Array.isArray;
|
|
55
80
|
|
|
@@ -57,7 +82,7 @@ const isArray = Array.isArray;
|
|
|
57
82
|
* See if a value is a `TypedArray` object.
|
|
58
83
|
* @param {*} v - The value we're testing.
|
|
59
84
|
* @returns {boolean}
|
|
60
|
-
* @alias module:@lumjs/core/types.isTypedArray
|
|
85
|
+
* @alias module:@lumjs/core/types/basics.isTypedArray
|
|
61
86
|
*/
|
|
62
87
|
function isTypedArray(v)
|
|
63
88
|
{
|
|
@@ -70,7 +95,7 @@ function isTypedArray(v)
|
|
|
70
95
|
* @param {boolean} [typed=false] If `true` we want a `TypedArray`.
|
|
71
96
|
* If `false` (default) we want a regular `Array`.
|
|
72
97
|
* @returns {boolean}
|
|
73
|
-
* @alias module:@lumjs/core/types.nonEmptyArray
|
|
98
|
+
* @alias module:@lumjs/core/types/basics.nonEmptyArray
|
|
74
99
|
*/
|
|
75
100
|
function nonEmptyArray(v, typed=false)
|
|
76
101
|
{
|
|
@@ -84,7 +109,7 @@ function nonEmptyArray(v, typed=false)
|
|
|
84
109
|
* See if a value is an `arguments` object.
|
|
85
110
|
* @param {*} v - The value we're testing.
|
|
86
111
|
* @returns {boolean}
|
|
87
|
-
* @alias module:@lumjs/core/types.isArguments
|
|
112
|
+
* @alias module:@lumjs/core/types/basics.isArguments
|
|
88
113
|
*/
|
|
89
114
|
function isArguments(v)
|
|
90
115
|
{
|
|
@@ -95,7 +120,7 @@ function isArguments(v)
|
|
|
95
120
|
* See if a value is a Property name.
|
|
96
121
|
* @param {*} v - The value we're testing.
|
|
97
122
|
* @returns {boolean}
|
|
98
|
-
* @alias module:@lumjs/core/types.isProperty
|
|
123
|
+
* @alias module:@lumjs/core/types/basics.isProperty
|
|
99
124
|
*/
|
|
100
125
|
function isProperty(v)
|
|
101
126
|
{
|
|
@@ -117,7 +142,7 @@ function isProperty(v)
|
|
|
117
142
|
* function will pass the test.
|
|
118
143
|
*
|
|
119
144
|
* @returns {boolean}
|
|
120
|
-
* @alias module:@lumjs/core/types.isIterable
|
|
145
|
+
* @alias module:@lumjs/core/types/basics.isIterable
|
|
121
146
|
*/
|
|
122
147
|
function isIterable(v)
|
|
123
148
|
{
|
|
@@ -129,7 +154,7 @@ function isIterable(v)
|
|
|
129
154
|
*
|
|
130
155
|
* @param {*} v - Value to test
|
|
131
156
|
* @returns {boolean}
|
|
132
|
-
* @alias module:@lumjs/core/types.isConstructor
|
|
157
|
+
* @alias module:@lumjs/core/types/basics.isConstructor
|
|
133
158
|
*/
|
|
134
159
|
function isConstructor(v)
|
|
135
160
|
{
|
|
@@ -153,7 +178,7 @@ function isConstructor(v)
|
|
|
153
178
|
*
|
|
154
179
|
* @param {object} obj - The object we are testing.
|
|
155
180
|
* @returns {boolean} - Is the object a valid descriptor?
|
|
156
|
-
* @alias module:@lumjs/core/types.doesDescriptor
|
|
181
|
+
* @alias module:@lumjs/core/types/basics.doesDescriptor
|
|
157
182
|
*/
|
|
158
183
|
function doesDescriptor(obj)
|
|
159
184
|
{
|
|
@@ -193,7 +218,7 @@ function doesDescriptor(obj)
|
|
|
193
218
|
* If this is `false` then any unknown properties will be ignored.
|
|
194
219
|
*
|
|
195
220
|
* @returns {boolean} Is the object a valid descriptor template?
|
|
196
|
-
* @alias module:@lumjs/core/types.doesDescriptorTemplate
|
|
221
|
+
* @alias module:@lumjs/core/types/basics.doesDescriptorTemplate
|
|
197
222
|
*/
|
|
198
223
|
function doesDescriptorTemplate(obj, accessor=false, strict=true)
|
|
199
224
|
{
|
|
@@ -229,5 +254,7 @@ module.exports =
|
|
|
229
254
|
{
|
|
230
255
|
isObj, isComplex, isNil, notNil, isScalar, isArray, isTypedArray,
|
|
231
256
|
isIterable, nonEmptyArray, isArguments, isProperty, isConstructor,
|
|
232
|
-
doesDescriptor, doesDescriptorTemplate,
|
|
257
|
+
doesDescriptor, doesDescriptorTemplate, JS,
|
|
233
258
|
}
|
|
259
|
+
|
|
260
|
+
JS.addTo(module.exports);
|
package/lib/types/def.js
CHANGED
|
@@ -2,29 +2,27 @@
|
|
|
2
2
|
const unbound = require('./root').unbound;
|
|
3
3
|
const {F, B} = require('./js');
|
|
4
4
|
const {isObj, isNil, isProperty, doesDescriptor} = require('./basics');
|
|
5
|
-
const
|
|
5
|
+
const clone = (...args) => Object.assign({}, ...args);
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
|
-
* A wrapper around `Object.defineProperty()
|
|
9
|
-
*
|
|
10
|
-
* This has a few features that makes adding properties a lot nicer.
|
|
11
|
-
* It replaces the `prop()` method from the old Lum.js v4.
|
|
8
|
+
* A wrapper around `Object.defineProperty()` with added flair!
|
|
12
9
|
*
|
|
13
10
|
* @param {(object|function)} obj - The object to add a property to.
|
|
11
|
+
*
|
|
14
12
|
* @param {?(string|symbol|boolean|object)} name
|
|
15
13
|
* If a `string` or `symbol`, it's the property name.
|
|
16
14
|
*
|
|
17
15
|
* If this is `null` or `undefined` then the `value` is ignored entirely,
|
|
18
16
|
* and instead a bound version of this function is created with the
|
|
19
|
-
* `obj` already passed as the first parameter
|
|
20
|
-
*
|
|
21
|
-
*
|
|
17
|
+
* `obj` already passed as the first parameter. It will generate context
|
|
18
|
+
* options which will compose the enumerable properties of `opts` if
|
|
19
|
+
* that argument is passed.
|
|
22
20
|
*
|
|
23
21
|
* If this is a `boolean`, then the same logic as if it was `null` or
|
|
24
22
|
* `undefined` will apply, except that an `enumerable` property with this
|
|
25
23
|
* value will also be added to the descriptors.
|
|
26
24
|
*
|
|
27
|
-
* If this is an `object`,
|
|
25
|
+
* If this is an `object`, the `value` will be ignored, as each of
|
|
28
26
|
* the keys of this object will be used as the name of a property,
|
|
29
27
|
* and the value associated with the key will be the value to assign it.
|
|
30
28
|
*
|
|
@@ -101,6 +99,40 @@ function def(obj, name, value, opts)
|
|
|
101
99
|
= !unbound(this, true, true)
|
|
102
100
|
&& typeof this.bound === F;
|
|
103
101
|
|
|
102
|
+
if (isNil(name) || typeof name === B)
|
|
103
|
+
{ // Binding of Isaac?
|
|
104
|
+
const bindOpts = (to) =>
|
|
105
|
+
{
|
|
106
|
+
Object.assign(to, opts);
|
|
107
|
+
if (typeof name === B) to.enumerable = name;
|
|
108
|
+
return to;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (isBound)
|
|
112
|
+
{ // Already bound, update options and return.
|
|
113
|
+
return bindOpts(this).bound;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const V = (value) => ({value, configurable: false});
|
|
117
|
+
|
|
118
|
+
// Create a fresh binding context for the bound function.
|
|
119
|
+
const bind = bindOpts({});
|
|
120
|
+
// Create a bound function.
|
|
121
|
+
const bound = def.bind(bind, obj);
|
|
122
|
+
// Add a reference to the function in the binding context.
|
|
123
|
+
def(bind, 'bound', V(bound));
|
|
124
|
+
// And a reference to the binding options from the function.
|
|
125
|
+
def(bound, '$this', V(bind));
|
|
126
|
+
|
|
127
|
+
if (value)
|
|
128
|
+
{ // Add DescriptorTemplate magic properties.
|
|
129
|
+
const dopts = clone(value, {desc: bind});
|
|
130
|
+
DT.addInstance(bound, dopts);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return bound;
|
|
134
|
+
}
|
|
135
|
+
|
|
104
136
|
// When we're finished, return this value.
|
|
105
137
|
const done = () =>
|
|
106
138
|
{
|
|
@@ -114,9 +146,12 @@ function def(obj, name, value, opts)
|
|
|
114
146
|
}
|
|
115
147
|
}
|
|
116
148
|
|
|
117
|
-
if (isBound
|
|
118
|
-
{ //
|
|
119
|
-
opts
|
|
149
|
+
if (isBound)
|
|
150
|
+
{ // Assign `this` options.
|
|
151
|
+
if (isNil(opts))
|
|
152
|
+
opts = this;
|
|
153
|
+
else if (isObj(opts))
|
|
154
|
+
opts = clone(this, opts);
|
|
120
155
|
}
|
|
121
156
|
|
|
122
157
|
if (isObj(name))
|
|
@@ -128,29 +163,6 @@ function def(obj, name, value, opts)
|
|
|
128
163
|
// Okay, we're done now.
|
|
129
164
|
return done();
|
|
130
165
|
}
|
|
131
|
-
else if (isNil(name) || typeof name === B)
|
|
132
|
-
{ // Create a fresh binding context for the bound function.
|
|
133
|
-
const bind = {};
|
|
134
|
-
|
|
135
|
-
if (isObj(opts))
|
|
136
|
-
{ // Copy our existing options as defaults.
|
|
137
|
-
copy(bind, opts);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
if (typeof name === B)
|
|
141
|
-
{ // A boolean `name` overrides the enumerable option.
|
|
142
|
-
bind.enumerable = name;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// Create a bound function.
|
|
146
|
-
const bound = def.bind(bind, obj);
|
|
147
|
-
// Add a reference to the function in the binding context.
|
|
148
|
-
bind.bound = bound;
|
|
149
|
-
// And a reference to the binding options from the function.
|
|
150
|
-
bound.$this = bind;
|
|
151
|
-
|
|
152
|
-
return bound;
|
|
153
|
-
}
|
|
154
166
|
else if (!isProperty(name))
|
|
155
167
|
{ // That's not valid.
|
|
156
168
|
throw new TypeError("Property name must be a string or a Symbol");
|
|
@@ -225,4 +237,5 @@ module.exports = def;
|
|
|
225
237
|
|
|
226
238
|
// Now we'll setup the descriptor template accessors.
|
|
227
239
|
const DT = require('./dt');
|
|
228
|
-
DT.
|
|
240
|
+
DT.addInit(def);
|
|
241
|
+
def.DT = DT;
|