@lumjs/core 1.3.0 → 1.4.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/docs/changelogs/1.0-beta.md +3 -9
- package/docs/changelogs/1.x.md +25 -7
- package/docs/changelogs/index.md +19 -0
- package/lib/arrays.js +4 -0
- package/lib/enum.js +14 -8
- package/lib/index.js +10 -5
- package/lib/obj/clone.js +48 -46
- package/lib/strings.js +1 -2
- package/lib/types/index.js +2 -1
- package/lib/types/lazy.js +196 -0
- package/lib/types/needs.js +0 -9
- package/package.json +1 -1
- package/lib/lazy.js +0 -100
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
All notable changes to this project will be documented in this file.
|
|
1
|
+
# Changelog → 1.0-beta.x
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
3
|
+
This is the changelog for the `1.0-beta.x` versions.
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
This is the *Changelog* for the `1.0.0-beta.x` releases.
|
|
10
|
-
See [1.x.md](1.x.md) for the stable `1.x` *Changelog*.
|
|
5
|
+
See [Changelogs](index.md) for more information on the changelogs.
|
|
11
6
|
|
|
12
7
|
## [1.0.0-beta.6]
|
|
13
8
|
- This is the **final** beta version.
|
|
@@ -96,4 +91,3 @@ See [1.x.md](1.x.md) for the stable `1.x` *Changelog*.
|
|
|
96
91
|
[1.0.0-beta.3]: https://github.com/supernovus/lum.core.js/compare/v1.0.0-beta.2...v1.0.0-beta.3
|
|
97
92
|
[1.0.0-beta.2]: https://github.com/supernovus/lum.core.js/compare/v1.0.0-beta.1...v1.0.0-beta.2
|
|
98
93
|
[1.0.0-beta.1]: https://github.com/supernovus/lum.core.js/releases/tag/v1.0.0-beta.1
|
|
99
|
-
|
package/docs/changelogs/1.x.md
CHANGED
|
@@ -1,11 +1,28 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
All notable changes to this project will be documented in this file.
|
|
1
|
+
# Changelog → 1.x
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
This is the changelog for the `1.x` versions.
|
|
4
|
+
|
|
5
|
+
See [Changelogs](index.md) for more information on the changelogs.
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.4.0] - 2022-09-26
|
|
10
|
+
### Changed
|
|
11
|
+
- Moved `lazy` into `types` module by default (leaving an alias in `core`).
|
|
12
|
+
- Completely rewrote the `lazy` function entirely.
|
|
13
|
+
- Greatly extended the documentation for `lazy` function.
|
|
14
|
+
- Removed an unused development artefact from `types.needs`.
|
|
15
|
+
|
|
16
|
+
## [1.3.1] - 2022-09-23
|
|
17
|
+
### Fixed
|
|
18
|
+
- The `arrays` module exports `powerset` and `random` as it should.
|
|
19
|
+
- Recursive dependency order issues with `clone`, `lock`, and `enum` resolved.
|
|
20
|
+
- Custom `lock` options in `enum` module actually work now.
|
|
21
|
+
### Changed
|
|
22
|
+
- The `Enum()` function now has `configurable` and `enumerable` options.
|
|
23
|
+
- The `configurable` property in `enums` defaults to `false` now.
|
|
24
|
+
- Tweaked the *changelogs* a bit and added a new [changelog listing](index.md).
|
|
25
|
+
|
|
9
26
|
## [1.3.0] - 2022-09-11
|
|
10
27
|
### Changed
|
|
11
28
|
- Overhauled the `obj.clone()` method.
|
|
@@ -62,13 +79,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
62
79
|
### Changed
|
|
63
80
|
- Initial *stable* release.
|
|
64
81
|
- See [1.0-beta.md](1.0-beta.md) for the beta versions of `1.0`
|
|
65
|
-
- See [lum.js](https://github.com/supernovus/lum.js) for the original library this is replacing.
|
|
82
|
+
- See [lum.js](https://github.com/supernovus/lum.js) for the original library set this is replacing.
|
|
66
83
|
|
|
67
|
-
[Unreleased]: https://github.com/supernovus/lum.core.js/compare/v1.
|
|
84
|
+
[Unreleased]: https://github.com/supernovus/lum.core.js/compare/v1.4.0...HEAD
|
|
85
|
+
[1.4.0]: https://github.com/supernovus/lum.core.js/compare/v1.3.1...v1.4.0
|
|
86
|
+
[1.3.1]: https://github.com/supernovus/lum.core.js/compare/v1.3.0...v1.3.1
|
|
68
87
|
[1.3.0]: https://github.com/supernovus/lum.core.js/compare/v1.2.1...v1.3.0
|
|
69
88
|
[1.2.1]: https://github.com/supernovus/lum.core.js/compare/v1.2.0...v1.2.1
|
|
70
89
|
[1.2.0]: https://github.com/supernovus/lum.core.js/compare/v1.1.1...v1.2.0
|
|
71
90
|
[1.1.1]: https://github.com/supernovus/lum.core.js/compare/v1.1.0...v1.1.1
|
|
72
91
|
[1.1.0]: https://github.com/supernovus/lum.core.js/compare/v1.0.0...v1.1.0
|
|
73
92
|
[1.0.0]: https://github.com/supernovus/lum.core.js/releases/tag/v1.0.0
|
|
74
|
-
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Changelogs
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in these files.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## Versions
|
|
9
|
+
|
|
10
|
+
To avoid the changelogs getting too big, I'm planning on splitting them up based
|
|
11
|
+
on the major version changes.
|
|
12
|
+
|
|
13
|
+
Each major version will be listed here in reverse chronological order (newest first.)
|
|
14
|
+
|
|
15
|
+
- [1.x](1.x.md) → The first standalone core library.
|
|
16
|
+
- [1.0-beta.x](1.0-beta.md)
|
|
17
|
+
→ The *pre-releases* from when this split off of the older
|
|
18
|
+
[Lum.js](https://github.com/supernovus/lum.js) library collection.
|
|
19
|
+
|
package/lib/arrays.js
CHANGED
|
@@ -99,6 +99,8 @@ function powerset(array)
|
|
|
99
99
|
return ps;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
exports.powerset = powerset;
|
|
103
|
+
|
|
102
104
|
/**
|
|
103
105
|
* Get a random element from an array.
|
|
104
106
|
* @param {Array} array The array to get an item from.
|
|
@@ -109,3 +111,5 @@ function random(array)
|
|
|
109
111
|
{
|
|
110
112
|
return array[Math.floor(Math.random()*array.length)];
|
|
111
113
|
}
|
|
114
|
+
|
|
115
|
+
exports.random = random;
|
package/lib/enum.js
CHANGED
|
@@ -21,6 +21,9 @@ function Enum (spec, opts={})
|
|
|
21
21
|
|
|
22
22
|
const anEnum = ENUM_ID.tag({});
|
|
23
23
|
|
|
24
|
+
const configurable = opts.configurable ?? false;
|
|
25
|
+
const enumerable = opts.enumerable ?? true;
|
|
26
|
+
|
|
24
27
|
function getVal (name, def)
|
|
25
28
|
{
|
|
26
29
|
if (opts.symbols)
|
|
@@ -42,7 +45,7 @@ function Enum (spec, opts={})
|
|
|
42
45
|
|
|
43
46
|
function addVal(pName, sName, inVal)
|
|
44
47
|
{
|
|
45
|
-
const desc = {configurable
|
|
48
|
+
const desc = {configurable, enumerable};
|
|
46
49
|
desc.value = getVal(sName, inVal);
|
|
47
50
|
def(anEnum, pName, desc);
|
|
48
51
|
}
|
|
@@ -83,25 +86,25 @@ function Enum (spec, opts={})
|
|
|
83
86
|
}
|
|
84
87
|
|
|
85
88
|
if (notNil(opts.lock))
|
|
86
|
-
{ // Use lock.
|
|
89
|
+
{ // Use lock() function.
|
|
87
90
|
let lockOpts;
|
|
88
91
|
if (Array.isArray(opts.lock))
|
|
89
|
-
{
|
|
92
|
+
{ // Specified the lock parameters as an array.
|
|
90
93
|
lockOpts = opts.lock;
|
|
91
94
|
}
|
|
92
95
|
else if (isObj(opts.lock))
|
|
93
|
-
{
|
|
96
|
+
{ // An object is assumed to be the `cloneOpts` parameter.
|
|
94
97
|
lockOpts = [true, opts.lock, false];
|
|
95
98
|
}
|
|
96
99
|
else if (typeof opts.lock === B)
|
|
97
|
-
{
|
|
100
|
+
{ // Boolean is assumed to be the `cloneable` parameter.
|
|
98
101
|
lockOpts = [opts.lock, null, false];
|
|
99
102
|
}
|
|
100
103
|
else
|
|
101
|
-
{
|
|
102
|
-
lockOpts = [
|
|
104
|
+
{ // Anything else we use default values.
|
|
105
|
+
lockOpts = [];
|
|
103
106
|
}
|
|
104
|
-
return lock(anEnum);
|
|
107
|
+
return lock(anEnum, ...lockOpts);
|
|
105
108
|
}
|
|
106
109
|
else if (!opts.open)
|
|
107
110
|
{ // Use Object.freeze()
|
|
@@ -138,3 +141,6 @@ def(Enum, 'is', isEnum);
|
|
|
138
141
|
TYPES.add('ENUM', 'enum', isEnum, 'isEnum');
|
|
139
142
|
|
|
140
143
|
module.exports = Enum;
|
|
144
|
+
|
|
145
|
+
// Loading this at the end.
|
|
146
|
+
const {lock} = require('./obj/lock');
|
package/lib/index.js
CHANGED
|
@@ -112,9 +112,6 @@ const Enum = require('./enum');
|
|
|
112
112
|
*/
|
|
113
113
|
const observable = require('./observable');
|
|
114
114
|
|
|
115
|
-
// One function exported directly with no sub-module available.
|
|
116
|
-
const lazy = require('./lazy');
|
|
117
|
-
|
|
118
115
|
/**
|
|
119
116
|
* Define properties on an object or function.
|
|
120
117
|
* @alias module:@lumjs/core.def
|
|
@@ -123,9 +120,17 @@ const lazy = require('./lazy');
|
|
|
123
120
|
*/
|
|
124
121
|
const def = types.def;
|
|
125
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Define properties on an object or function.
|
|
125
|
+
* @alias module:@lumjs/core.lazy
|
|
126
|
+
* @function
|
|
127
|
+
* @see module:@lumjs/core/types.lazy
|
|
128
|
+
*/
|
|
129
|
+
const lazy = types.lazy;
|
|
130
|
+
|
|
126
131
|
module.exports =
|
|
127
132
|
{
|
|
128
|
-
types,
|
|
133
|
+
types, context, flags, obj, opt, modules, arrays, strings,
|
|
129
134
|
def, randomNumber, InternalObjectId, Enum, lazy, observable,
|
|
130
|
-
stacktrace, AbstractClass, Functions, NYI,
|
|
135
|
+
stacktrace, AbstractClass, Functions, NYI,
|
|
131
136
|
}
|
package/lib/obj/clone.js
CHANGED
|
@@ -1,49 +1,7 @@
|
|
|
1
1
|
// Import *most* required bits here.
|
|
2
|
-
const {
|
|
3
|
-
const Enum = require('../enum');
|
|
2
|
+
const {N,F, isObj, isComplex, def, isArray} = require('../types');
|
|
4
3
|
const copyProps = require('./copyprops');
|
|
5
4
|
const getProp = require('./getproperty');
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* An `enum` of supported *modes* for the `clone()` method.
|
|
9
|
-
*
|
|
10
|
-
* - **P** → All properties. If unchecked, *enumerable* properties only.
|
|
11
|
-
* - **A** → Uses `Array.slice()` shortcut for shallow `Array` cloning.
|
|
12
|
-
* - **R** → Recursive (deep) cloning of nested objects.
|
|
13
|
-
* - **D** → Uses *descriptor* cloning instead of direct assignment.
|
|
14
|
-
* - **T** → Sets the `prototype` of the clone as well.
|
|
15
|
-
*
|
|
16
|
-
* | Mode | P | A | R | D | T | Notes |
|
|
17
|
-
* | ---- | - | - | - | - | - | ----- |
|
|
18
|
-
* | `CLONE.N` | × | × | × | × | × | Can be used to manually specify options. |
|
|
19
|
-
* | `CLONE.DEF` | × | ✓ | × | × | × | Default mode for cloning functions. |
|
|
20
|
-
* | `CLONE.DEEP` | × | × | ✓ | ✓ | × | |
|
|
21
|
-
* | `CLONE.FULL` | ✓ | ✓ | × | ✓ | × | |
|
|
22
|
-
* | `CLONE.ALL` | ✓ | × | × | ✓ | × | |
|
|
23
|
-
* | `CLONE.ENTIRE` | ✓ | × | ✓ | ✓ | ✓ | |
|
|
24
|
-
* | `CLONE.JSON` | - | - | ✓ | - | × | Uses JSON, so no `function` or `symbol` support. |
|
|
25
|
-
*
|
|
26
|
-
* The `✓` and `×` marks signify the *default settings* in the mode.
|
|
27
|
-
* In *most* cases there are options that can override the
|
|
28
|
-
* defaults.
|
|
29
|
-
*
|
|
30
|
-
* Any feature in the `CLONE.JSON` row marked with `-` are
|
|
31
|
-
* incompatible with that mode and cannot be enabled at all.
|
|
32
|
-
*
|
|
33
|
-
* @alias module:@lumjs/core/obj.CLONE
|
|
34
|
-
*/
|
|
35
|
-
const CLONE = Enum(['N','DEF','FULL','ALL','DEEP','ENTIRE','JSON']);
|
|
36
|
-
|
|
37
|
-
exports.CLONE = CLONE;
|
|
38
|
-
|
|
39
|
-
// A list of modes that should use the array.slice shallow shortcut.
|
|
40
|
-
const SLICE_ARRAYS = [CLONE.DEF, CLONE.FULL];
|
|
41
|
-
|
|
42
|
-
// A list of modes that should get *all* properties.
|
|
43
|
-
const ALL_PROPS = [CLONE.FULL, CLONE.ALL, CLONE.ENTIRE];
|
|
44
|
-
|
|
45
|
-
// A list of modes that should do recursive cloning of objects.
|
|
46
|
-
const RECURSIVE = [CLONE.DEEP, CLONE.ENTIRE];
|
|
47
5
|
|
|
48
6
|
/**
|
|
49
7
|
* Clone an object or function.
|
|
@@ -295,9 +253,6 @@ function clone(obj, opts={})
|
|
|
295
253
|
return copy;
|
|
296
254
|
}
|
|
297
255
|
|
|
298
|
-
// Alias the CLONE enum as clone.MODE
|
|
299
|
-
def(clone, 'MODE', CLONE);
|
|
300
|
-
|
|
301
256
|
// Export the clone here.
|
|
302
257
|
exports.clone = clone;
|
|
303
258
|
|
|
@@ -371,3 +326,50 @@ exports.cloneIfLocked = cloneIfLocked;
|
|
|
371
326
|
|
|
372
327
|
// Import `addLock()` here *after* assigning the clone methods.
|
|
373
328
|
const {addLock} = require('./lock');
|
|
329
|
+
|
|
330
|
+
// And setting all the Enum definitions at the very end.
|
|
331
|
+
const Enum = require('../enum');
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* An `enum` of supported *modes* for the `clone()` method.
|
|
335
|
+
*
|
|
336
|
+
* - **P** → All properties. If unchecked, *enumerable* properties only.
|
|
337
|
+
* - **A** → Uses `Array.slice()` shortcut for shallow `Array` cloning.
|
|
338
|
+
* - **R** → Recursive (deep) cloning of nested objects.
|
|
339
|
+
* - **D** → Uses *descriptor* cloning instead of direct assignment.
|
|
340
|
+
* - **T** → Sets the `prototype` of the clone as well.
|
|
341
|
+
*
|
|
342
|
+
* | Mode | P | A | R | D | T | Notes |
|
|
343
|
+
* | ---- | - | - | - | - | - | ----- |
|
|
344
|
+
* | `CLONE.N` | × | × | × | × | × | Can be used to manually specify options. |
|
|
345
|
+
* | `CLONE.DEF` | × | ✓ | × | × | × | Default mode for cloning functions. |
|
|
346
|
+
* | `CLONE.DEEP` | × | × | ✓ | ✓ | × | |
|
|
347
|
+
* | `CLONE.FULL` | ✓ | ✓ | × | ✓ | × | |
|
|
348
|
+
* | `CLONE.ALL` | ✓ | × | × | ✓ | × | |
|
|
349
|
+
* | `CLONE.ENTIRE` | ✓ | × | ✓ | ✓ | ✓ | |
|
|
350
|
+
* | `CLONE.JSON` | - | - | ✓ | - | × | Uses JSON, so no `function` or `symbol` support. |
|
|
351
|
+
*
|
|
352
|
+
* The `✓` and `×` marks signify the *default settings* in the mode.
|
|
353
|
+
* In *most* cases there are options that can override the
|
|
354
|
+
* defaults.
|
|
355
|
+
*
|
|
356
|
+
* Any feature in the `CLONE.JSON` row marked with `-` are
|
|
357
|
+
* incompatible with that mode and cannot be enabled at all.
|
|
358
|
+
*
|
|
359
|
+
* @alias module:@lumjs/core/obj.CLONE
|
|
360
|
+
*/
|
|
361
|
+
const CLONE = Enum(['N','DEF','FULL','ALL','DEEP','ENTIRE','JSON']);
|
|
362
|
+
|
|
363
|
+
exports.CLONE = CLONE;
|
|
364
|
+
|
|
365
|
+
// A list of modes that should use the array.slice shallow shortcut.
|
|
366
|
+
const SLICE_ARRAYS = [CLONE.DEF, CLONE.FULL];
|
|
367
|
+
|
|
368
|
+
// A list of modes that should get *all* properties.
|
|
369
|
+
const ALL_PROPS = [CLONE.FULL, CLONE.ALL, CLONE.ENTIRE];
|
|
370
|
+
|
|
371
|
+
// A list of modes that should do recursive cloning of objects.
|
|
372
|
+
const RECURSIVE = [CLONE.DEEP, CLONE.ENTIRE];
|
|
373
|
+
|
|
374
|
+
// Alias the CLONE enum as clone.MODE
|
|
375
|
+
def(clone, 'MODE', CLONE);
|
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} = require('./types')
|
|
5
|
+
const {S,B,F,isObj,root,isArray,needType,needObj} = require('./types');
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Get the locale/language string.
|
|
@@ -189,4 +189,3 @@ function replaceItems(string, replacements, useAll)
|
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
exports.replaceItems = replaceItems;
|
|
192
|
-
|
package/lib/types/index.js
CHANGED
|
@@ -39,6 +39,7 @@ const {needObj, needType, needs} = require('./needs');
|
|
|
39
39
|
// A few standalone items.
|
|
40
40
|
|
|
41
41
|
const def = require('./def');
|
|
42
|
+
const lazy = require('./lazy');
|
|
42
43
|
const TYPES = require('./typelist');
|
|
43
44
|
const stringify = require('./stringify');
|
|
44
45
|
|
|
@@ -46,7 +47,7 @@ const stringify = require('./stringify');
|
|
|
46
47
|
// Further tests can be added by `TYPES.add()` later.
|
|
47
48
|
module.exports =
|
|
48
49
|
{
|
|
49
|
-
O, F, S, B, N, U, SY, BI, TYPES, root, unbound, def,
|
|
50
|
+
O, F, S, B, N, U, SY, BI, TYPES, root, unbound, def, lazy,
|
|
50
51
|
isObj, isComplex, isNil, notNil, isScalar, isArray, isTypedArray,
|
|
51
52
|
nonEmptyArray, isArguments, isProperty, doesDescriptor,
|
|
52
53
|
isInstance, isType, isa, needObj, needType, needs, stringify,
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
const def = require('./def');
|
|
2
|
+
const {S,F} = require('./js');
|
|
3
|
+
const {COMPLEX} = require('./typelist');
|
|
4
|
+
const {needType,needObj} = require('./needs');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Metadata for the property definition.
|
|
8
|
+
*
|
|
9
|
+
* @typedef module:@lumjs/core/types~LazyDef
|
|
10
|
+
* @property {string} name - The `name` passed to `lazy()`
|
|
11
|
+
* @property {(object|function)} target - The `target` passed to `lazy()`
|
|
12
|
+
* @property {object} opts - The `opts` passed to `lazy()`
|
|
13
|
+
* @property {object} arguments - The full `arguments` passed to `lazy()`
|
|
14
|
+
*
|
|
15
|
+
* @property {boolean} [assign] Override default assignment rules?
|
|
16
|
+
*
|
|
17
|
+
* This property may be added by the `LazyGetter` or `LazySetter`
|
|
18
|
+
* functions to override the default assignment rules.
|
|
19
|
+
*
|
|
20
|
+
* If this is `true` the return value will be assigned, replacing the
|
|
21
|
+
* lazy accessor property, even if the value is `undefined`.
|
|
22
|
+
*
|
|
23
|
+
* If this is `false`, the value will be returned, but will **not** be
|
|
24
|
+
* *assigned*, so the lazy accessor property will remain.
|
|
25
|
+
*
|
|
26
|
+
* @property {*} [def] Special options for `def()`
|
|
27
|
+
*
|
|
28
|
+
* The [def()]{@link module:@lumjs/core/types.def} function has an
|
|
29
|
+
* optional fourth parameter called `opts` which is used for a few
|
|
30
|
+
* specialized purposes. If this property is set, it will be used as
|
|
31
|
+
* the value for `opts` when assigning the return value to the property.
|
|
32
|
+
*
|
|
33
|
+
* Leave it `undefined` to use the default `def()` behaviour.
|
|
34
|
+
*
|
|
35
|
+
*/
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* A function to generate the property value.
|
|
39
|
+
*
|
|
40
|
+
* @callback module:@lumjs/core/types~LazyGetter
|
|
41
|
+
* @returns {*} The generated *value* of the property
|
|
42
|
+
*
|
|
43
|
+
* By default if this is `undefined` the value will **not** be
|
|
44
|
+
* assigned, and instead the accessor property will remain in
|
|
45
|
+
* place to be used on subsequent calls until a value other than
|
|
46
|
+
* `undefined` is returned.
|
|
47
|
+
*
|
|
48
|
+
* This assignment behaviour can be overridden by the function
|
|
49
|
+
* if it sets `this.assign` to an explicit boolean value.
|
|
50
|
+
*
|
|
51
|
+
* As we are using [def()]{@link module:@lumjs/core/types.def}
|
|
52
|
+
* to assign the value, by default if the return value appears
|
|
53
|
+
* to be a valid *Descriptor* object, it will be used as the
|
|
54
|
+
* property descriptor. See `def()` for further details on how
|
|
55
|
+
* it handles the various arguments.
|
|
56
|
+
*
|
|
57
|
+
* Regardless of the value of `this.assign`, this value will
|
|
58
|
+
* be *returned* as the property value.
|
|
59
|
+
*
|
|
60
|
+
* @this {module:@lumjs/core/types~LazyDef} A metadata object.
|
|
61
|
+
*/
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* A function to handle attempts at assignment.
|
|
65
|
+
*
|
|
66
|
+
* Very similar to [LazyGetter]{@link module:@lumjs/core/types~LazyGetter}
|
|
67
|
+
* but called when property assignment is attempted on the
|
|
68
|
+
* lazy accessor property.
|
|
69
|
+
*
|
|
70
|
+
* If you explicitly want to forbid assignment, you can throw
|
|
71
|
+
* an `Error` from this function.
|
|
72
|
+
*
|
|
73
|
+
* @callback module:@lumjs/core/types~LazySetter
|
|
74
|
+
* @param {*} value - The value attempting to be assigned.
|
|
75
|
+
* @returns {*} The *actual* assignment value (if any.)
|
|
76
|
+
*
|
|
77
|
+
* The same assignment rules apply as in the
|
|
78
|
+
* [LazyGetter]{@link module:@lumjs/core/types~LazyGetter}
|
|
79
|
+
* callback.
|
|
80
|
+
*
|
|
81
|
+
* @this {module:@lumjs/core/types~LazyDef} A metadata object.
|
|
82
|
+
*/
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Build a lazy initializer property.
|
|
86
|
+
*
|
|
87
|
+
* This builds an *accessor* property that will replace itself
|
|
88
|
+
* with a initialized property, the value of which is obtained from
|
|
89
|
+
* a supplied initialization function. Any subsequent use of the
|
|
90
|
+
* property will obviously be using the initialized property directly.
|
|
91
|
+
*
|
|
92
|
+
* The general purpose is if there is a property that requires
|
|
93
|
+
* a fairly intensive load time, or requires a large library that
|
|
94
|
+
* you may not always *need* for basic things, you can use this
|
|
95
|
+
* to ensure that the property is only initialized when needed.
|
|
96
|
+
*
|
|
97
|
+
* This is an extension of the [def()]{@link module:@lumjs/core/types.def}
|
|
98
|
+
* method, and indeed an alias called `def.lazy()` is also available.
|
|
99
|
+
*
|
|
100
|
+
* @param {(object|function)} target - The object to add the property to.
|
|
101
|
+
*
|
|
102
|
+
* As with `def()` itself, this can be either an `object` or `function`,
|
|
103
|
+
* as in Javascript the latter is an extension of the former.
|
|
104
|
+
*
|
|
105
|
+
* @param {string} name - The name of the property to add.
|
|
106
|
+
*
|
|
107
|
+
* @param {module:@lumjs/core/types~LazyGetter} initfunc
|
|
108
|
+
* The function to initialize the property.
|
|
109
|
+
*
|
|
110
|
+
* This will normally only ever be called the first time the property
|
|
111
|
+
* is accessed in a *read* operation. The return value from this
|
|
112
|
+
* will be assigned to the property using `def()`, replacing the
|
|
113
|
+
* lazy accessor property.
|
|
114
|
+
*
|
|
115
|
+
* @param {object} [opts] Options to customize behavior.
|
|
116
|
+
*
|
|
117
|
+
* @param {module:@lumjs/core/types~LazySetter} [opts.set]
|
|
118
|
+
* A function to handle assignment attempts.
|
|
119
|
+
*
|
|
120
|
+
* This obviously only applies to the *lazy accessor* property,
|
|
121
|
+
* and will have no affect once the property has been replaced
|
|
122
|
+
* by its initialized value.
|
|
123
|
+
*
|
|
124
|
+
* @param {boolean} [opts.enumerable=false] Is the property enumerable?
|
|
125
|
+
*
|
|
126
|
+
* This applies to the *lazy accessor* property only.
|
|
127
|
+
* You can set custom descriptor rules in the `initfunc`
|
|
128
|
+
* if you need them on the initialized property.
|
|
129
|
+
*
|
|
130
|
+
* @param {?boolean} [opts.assign] The *default* value for the `assign` property
|
|
131
|
+
* in the [LazyDef]{@link module:@lumjs/core/types~LazyDef} object.
|
|
132
|
+
*
|
|
133
|
+
* @param {*} [opts.def] The *default* value for the `def` property in
|
|
134
|
+
* the [LazyDef]{@link module:@lumjs/core/types~LazyDef} object.
|
|
135
|
+
*
|
|
136
|
+
* @returns {(object|function)} The `target` argument
|
|
137
|
+
*
|
|
138
|
+
* @alias module:@lumjs/core/types.lazy
|
|
139
|
+
*/
|
|
140
|
+
function lazy(target, name, initfunc, opts={})
|
|
141
|
+
{
|
|
142
|
+
needType(COMPLEX, target, 'obj must be an object');
|
|
143
|
+
needType(S, name, 'name must be a string');
|
|
144
|
+
needType(F, initfunc, 'initfunc must be a function');
|
|
145
|
+
needObj(opts, 'opts parameter was not an object');
|
|
146
|
+
|
|
147
|
+
// The `this` object for the functions.
|
|
148
|
+
const context =
|
|
149
|
+
{
|
|
150
|
+
name,
|
|
151
|
+
target,
|
|
152
|
+
opts,
|
|
153
|
+
arguments,
|
|
154
|
+
assign: opts.assign,
|
|
155
|
+
def: opts.def,
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// The descriptor for the lazy accessor.
|
|
159
|
+
const desc =
|
|
160
|
+
{
|
|
161
|
+
configurable: true,
|
|
162
|
+
enumerable: opts.enumerable ?? false,
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
// Replace the property if rules are correct.
|
|
166
|
+
const defval = function(value)
|
|
167
|
+
{
|
|
168
|
+
const assign = (context.assign ?? value !== undefined);
|
|
169
|
+
if (assign)
|
|
170
|
+
{ // Replace the lazy accessor with the returned value.
|
|
171
|
+
def(target, name, value, context.def);
|
|
172
|
+
}
|
|
173
|
+
return value;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
desc.get = function()
|
|
177
|
+
{
|
|
178
|
+
return defval(initfunc.call(context));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (typeof opts.set === F)
|
|
182
|
+
{ // We want to assign a lazy setter as well.
|
|
183
|
+
desc.set = function(value)
|
|
184
|
+
{
|
|
185
|
+
defval(opts.set.call(context, value));
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Assign the lazy accessor property.
|
|
190
|
+
def(target, name, desc);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Gotta be one of the greatest lines...
|
|
194
|
+
def(def, 'lazy', lazy);
|
|
195
|
+
|
|
196
|
+
module.exports = lazy;
|
package/lib/types/needs.js
CHANGED
|
@@ -59,15 +59,6 @@ function needType (type, v, msg, unused)
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
exports.needType = needType;
|
|
62
|
-
|
|
63
|
-
// Options parser for needs();
|
|
64
|
-
const NEEDS_PARSER = function(type, v)
|
|
65
|
-
{ // `this` is the options object itself.
|
|
66
|
-
if (typeof type.is === F)
|
|
67
|
-
{ // We assume `is()` methods are the type check.
|
|
68
|
-
if (type.is(v)) return true;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
62
|
|
|
72
63
|
/**
|
|
73
64
|
* A wrapper around `isa()` that will throw an error on failure.
|
package/package.json
CHANGED
package/lib/lazy.js
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
const {S,F,TYPES:{COMPLEX},needType,needObj,def} = require('./types');
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* @callback module:@lumjs/core~InitFunc
|
|
6
|
-
* @param {string} name - The `name` parameter passed to `lazy()`
|
|
7
|
-
* @this {object} - The `obj` parameter passed to `lazy()`
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Build a lazy initializer property.
|
|
12
|
-
*
|
|
13
|
-
* Basically the first time the property is accessed it's built.
|
|
14
|
-
* Subsequent accesses will use the already built property.
|
|
15
|
-
* This is an extension of the {@link def} method, and indeed an
|
|
16
|
-
* alias called `def.lazy()` is also available.
|
|
17
|
-
*
|
|
18
|
-
* @param {Object} obj - The object to add the property to.
|
|
19
|
-
* @param {string} name - The name of the property to add.
|
|
20
|
-
* @param {module:@lumjs/core~InitFunc} initfunc
|
|
21
|
-
* The function to initialize the property.
|
|
22
|
-
* @param {*} [onset] How to handle assignment.
|
|
23
|
-
*
|
|
24
|
-
* If this is `true` then the new value will be assigned directly,
|
|
25
|
-
* skipping the initialization process entirely.
|
|
26
|
-
*
|
|
27
|
-
* If this is `false` then any attempt at assignment will throw
|
|
28
|
-
* a `ReferenceError` with a message indicating the property is read-only.
|
|
29
|
-
*
|
|
30
|
-
* If this is a `function` it will take two arguments, the
|
|
31
|
-
* first being the value that is trying to be assigned, and
|
|
32
|
-
* the second being the currently assigned value.
|
|
33
|
-
* As with any getter or setter, `this` will be the `obj` itself.
|
|
34
|
-
* The function must return the value to be assigned.
|
|
35
|
-
* If it returns `undefined`, then the value was not valid,
|
|
36
|
-
* and will not be assigned.
|
|
37
|
-
*
|
|
38
|
-
* If this is anything else, assignment will do nothing at all.
|
|
39
|
-
*
|
|
40
|
-
* @param {Object} [desc={}] Descriptor rules for the property.
|
|
41
|
-
* We only support two descriptor rules with this function, and
|
|
42
|
-
* their default values are the same as the `def()` function.
|
|
43
|
-
* - `configurable` → `true`
|
|
44
|
-
* - `enumerable` → `false`
|
|
45
|
-
* Any other descriptor properties are invalid here.
|
|
46
|
-
*
|
|
47
|
-
* @return {Object} The object we defined the property on.
|
|
48
|
-
* @alias module:@lumjs/core.lazy
|
|
49
|
-
*/
|
|
50
|
-
function lazy(obj, name, initfunc, onset, desc={})
|
|
51
|
-
{
|
|
52
|
-
needType(COMPLEX, obj, 'obj must be an object');
|
|
53
|
-
needType(S, name, 'name must be a string');
|
|
54
|
-
needType(F, initfunc, 'initfunc must be a function');
|
|
55
|
-
needObj(desc, 'desc parameter was not an object');
|
|
56
|
-
|
|
57
|
-
let value;
|
|
58
|
-
|
|
59
|
-
desc.get = function()
|
|
60
|
-
{
|
|
61
|
-
if (value === undefined)
|
|
62
|
-
{
|
|
63
|
-
value = initfunc.call(this, name);
|
|
64
|
-
}
|
|
65
|
-
return value;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
if (onset === true)
|
|
69
|
-
{ // Allow direct assignment.
|
|
70
|
-
desc.set = function(newval)
|
|
71
|
-
{
|
|
72
|
-
value = newval;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
else if (onset === false)
|
|
76
|
-
{ // Throw an error on assignment.
|
|
77
|
-
desc.set = function()
|
|
78
|
-
{
|
|
79
|
-
throw new ReferenceError("The "+name+" property is read-only");
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
else if (typeof onset === F)
|
|
83
|
-
{ // A proxy method for assignment.
|
|
84
|
-
desc.set = function(newval)
|
|
85
|
-
{
|
|
86
|
-
const setval = onset.call(this, newval, value);
|
|
87
|
-
if (setval !== undefined)
|
|
88
|
-
{
|
|
89
|
-
value = setval;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
def(obj, name, desc);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Gotta be one of the greatest lines...
|
|
98
|
-
def(def, 'lazy', lazy);
|
|
99
|
-
|
|
100
|
-
module.exports = lazy;
|