@lumjs/core 1.5.1 → 1.6.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/index.js +16 -50
- package/lib/modulebuilder.js +336 -0
- package/package.json +2 -1
- package/docs/changelogs/1.0-beta.md +0 -93
- package/docs/changelogs/1.x.md +0 -111
- package/docs/changelogs/index.md +0 -19
- package/test/arrays.js +0 -19
- package/test/meta.js +0 -17
- package/test/types.js +0 -268
package/lib/index.js
CHANGED
|
@@ -19,6 +19,17 @@
|
|
|
19
19
|
*/
|
|
20
20
|
const types = require('./types');
|
|
21
21
|
|
|
22
|
+
/**
|
|
23
|
+
* A helper for building modules
|
|
24
|
+
*
|
|
25
|
+
* @alias module:@lumjs/core.ModuleBuilder
|
|
26
|
+
* @see module:@lumjs/core/modulebuilder
|
|
27
|
+
*/
|
|
28
|
+
const Builder = require('./modulebuilder');
|
|
29
|
+
|
|
30
|
+
// And we'll use the builder to define the rest of this.
|
|
31
|
+
const {has,can,from} = Builder.build(module);
|
|
32
|
+
|
|
22
33
|
/**
|
|
23
34
|
* Define properties on an object or function
|
|
24
35
|
* @name module:@lumjs/core.def
|
|
@@ -33,59 +44,14 @@ const types = require('./types');
|
|
|
33
44
|
* @see module:@lumjs/core/types.lazy
|
|
34
45
|
*/
|
|
35
46
|
|
|
36
|
-
// Get a descriptor for one of our sub-modules.
|
|
37
|
-
function lib(name, def={})
|
|
38
|
-
{
|
|
39
|
-
let value = def.value;
|
|
40
|
-
|
|
41
|
-
if (value === undefined)
|
|
42
|
-
{
|
|
43
|
-
const module = def.module ?? name;
|
|
44
|
-
value = require('./'+module);
|
|
45
|
-
|
|
46
|
-
if (value && def.prop && value[def.prop] !== undefined)
|
|
47
|
-
{
|
|
48
|
-
value = value[def.prop];
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const desc =
|
|
53
|
-
{
|
|
54
|
-
configurable: false,
|
|
55
|
-
enumerable: true,
|
|
56
|
-
writable: false,
|
|
57
|
-
value,
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
return desc;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Export one of our always loaded properties.
|
|
64
|
-
function has(name, def)
|
|
65
|
-
{
|
|
66
|
-
types.def(exports, name, lib(name, def));
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Export one of our lazy loaded properties.
|
|
70
|
-
function can(name, def)
|
|
71
|
-
{
|
|
72
|
-
types.lazy(exports, name, () => lib(name, def), {enumerable: true});
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// Export a set of always loaded properties from a sub-module
|
|
76
|
-
function from(modname, ...libs)
|
|
77
|
-
{
|
|
78
|
-
for (const lib of libs)
|
|
79
|
-
{
|
|
80
|
-
has(lib, {module: modname, prop: lib});
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
47
|
// Our fundamental bits.
|
|
85
48
|
has('types', {value: types});
|
|
86
49
|
has('def', {value: types.def});
|
|
87
50
|
has('lazy', {value: types.lazy});
|
|
88
51
|
|
|
52
|
+
// The module builder itself.
|
|
53
|
+
has('ModuleBuilder', {value: Builder});
|
|
54
|
+
|
|
89
55
|
/**
|
|
90
56
|
* Array utility functions «Lazy»
|
|
91
57
|
* @name module:@lumjs/core.arrays
|
|
@@ -119,7 +85,7 @@ can('flags');
|
|
|
119
85
|
* @name module:@lumjs/core.obj
|
|
120
86
|
* @type {module:@lumjs/core/obj}
|
|
121
87
|
*/
|
|
122
|
-
|
|
88
|
+
can('obj');
|
|
123
89
|
|
|
124
90
|
/**
|
|
125
91
|
* Functions for getting values and properties with fallback defaults «Lazy»
|
|
@@ -174,7 +140,7 @@ from('meta', 'stacktrace', 'AbstractClass', 'Functions', 'NYI');
|
|
|
174
140
|
* @function
|
|
175
141
|
* @see module:@lumjs/core/enum
|
|
176
142
|
*/
|
|
177
|
-
|
|
143
|
+
can('Enum', {module: 'enum'});
|
|
178
144
|
|
|
179
145
|
/**
|
|
180
146
|
* Make an object support the *Observable* API «Lazy»
|
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
|
|
2
|
+
const {S,F,B,isObj,needObj,needType,def,lazy} = require('./types');
|
|
3
|
+
|
|
4
|
+
function clone(obj)
|
|
5
|
+
{
|
|
6
|
+
const copy = {};
|
|
7
|
+
for (const name in obj)
|
|
8
|
+
{
|
|
9
|
+
copy[name] = obj[name];
|
|
10
|
+
}
|
|
11
|
+
return copy;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Methods we want to export in the functional API.
|
|
15
|
+
const BUILD_METHODS = ['has', 'can', 'from'];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A class to make building modules easier.
|
|
19
|
+
*
|
|
20
|
+
* Basically wraps calls to `require()`, `def()`, `lazy()`,
|
|
21
|
+
* and assignments to `module.exports` into a simple set of methods.
|
|
22
|
+
*
|
|
23
|
+
* @exports module:@lumjs/core/modulebuilder
|
|
24
|
+
*/
|
|
25
|
+
class ModuleBuilder
|
|
26
|
+
{
|
|
27
|
+
/**
|
|
28
|
+
* Build a new ModuleBuilder instance.
|
|
29
|
+
*
|
|
30
|
+
* @param {object} targetModule - The `module` context variable.
|
|
31
|
+
* @param {object} [opts] - Options to change some default settings.
|
|
32
|
+
* @param {boolean} [opts.configurable=false] Default `configurable` value.
|
|
33
|
+
* @param {boolean} [opts.enumerable=true] Default `enumerable` value.
|
|
34
|
+
* @param {boolean} [opts.writable=false] Default `writable` value.
|
|
35
|
+
*
|
|
36
|
+
* @param {number} [opts.nested=NESTED_ERROR] How to handle nested names.
|
|
37
|
+
*
|
|
38
|
+
* If the `name` parameter in either the `has()` or `can()` method is passed
|
|
39
|
+
* as the path to a nested module with one or more `/` characters,
|
|
40
|
+
* this mode will determine how we derive the property name.
|
|
41
|
+
*
|
|
42
|
+
* For each mode, we'll use an example `name` of `./some/nested/path`.
|
|
43
|
+
*
|
|
44
|
+
* - `ModuleBuilder.NESTED_ERROR` `[0]` (default mode)
|
|
45
|
+
* Throw an `Error` saying paths are unhandled.
|
|
46
|
+
* - `ModuleBuilder.NESTED_FIRST` `[1]`
|
|
47
|
+
* Use the first (non-dot) path element, e.g. `some`
|
|
48
|
+
* - `ModuleBuilder.NESTED_LAST` `[2]`
|
|
49
|
+
* Use the last path element, e.g. `path`
|
|
50
|
+
* - `ModuleBuilder.NESTED_CAMEL` `[3]`
|
|
51
|
+
* Convert the name to camelCase, e.g. `someNestedPath`
|
|
52
|
+
*
|
|
53
|
+
* It's always possible to set the `conf.module` parameter manually as well,
|
|
54
|
+
* which avoids the need to generate a separate parameter name.
|
|
55
|
+
*
|
|
56
|
+
*/
|
|
57
|
+
constructor(targetModule, opts={})
|
|
58
|
+
{
|
|
59
|
+
needObj(opts, 'opts was not an object');
|
|
60
|
+
needObj(targetModule, 'targetModule was not an object');
|
|
61
|
+
needObj(targetModule.exports, 'targetModule.exports was not an object');
|
|
62
|
+
needType(F, targetModule.require, 'targetModule.require was not a function');
|
|
63
|
+
|
|
64
|
+
this.module = targetModule;
|
|
65
|
+
|
|
66
|
+
this.configurable = opts.configurable ?? false;
|
|
67
|
+
this.enumerable = opts.enumerable ?? true;
|
|
68
|
+
this.writable = opts.writable ?? false;
|
|
69
|
+
|
|
70
|
+
this.nested = opts.nested ?? ModuleBuilder.NESTED_ERROR;
|
|
71
|
+
|
|
72
|
+
this.strings = opts.strings;
|
|
73
|
+
this.locale = opts.locale;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Get a descriptor for a module export.
|
|
77
|
+
requireDescriptor(name, conf={})
|
|
78
|
+
{
|
|
79
|
+
let value = conf.value;
|
|
80
|
+
|
|
81
|
+
if (value === undefined)
|
|
82
|
+
{
|
|
83
|
+
if (typeof conf.module === S)
|
|
84
|
+
name = conf.module;
|
|
85
|
+
if (!name.startsWith('./'))
|
|
86
|
+
name = './'+name;
|
|
87
|
+
|
|
88
|
+
value = this.module.require(name);
|
|
89
|
+
|
|
90
|
+
if (value && conf.prop && value[conf.prop] !== undefined)
|
|
91
|
+
{
|
|
92
|
+
value = value[conf.prop];
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const configurable = conf.configurable ?? this.configurable;
|
|
97
|
+
const enumerable = conf.enumerable ?? this.enumerable;
|
|
98
|
+
const writable = conf.writable ?? this.writable;
|
|
99
|
+
|
|
100
|
+
return {configurable, enumerable, writable, value};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// Normalize a property name.
|
|
104
|
+
$normalizeProperty(name)
|
|
105
|
+
{
|
|
106
|
+
if (name.startsWith('./'))
|
|
107
|
+
{ // Get rid of the prefix.
|
|
108
|
+
name = name.substring(2);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (name.includes('/'))
|
|
112
|
+
{ // Multiple paths found.
|
|
113
|
+
const names = name.split('/');
|
|
114
|
+
if (this.nested === ModuleBuilder.NESTED_FIRST)
|
|
115
|
+
{
|
|
116
|
+
name = names[0];
|
|
117
|
+
}
|
|
118
|
+
else if (this.nested === ModuleBuilder.NESTED_LAST)
|
|
119
|
+
{
|
|
120
|
+
name = names[names.length-1];
|
|
121
|
+
}
|
|
122
|
+
else if (this.nested === ModuleBuilder.NESTED_CAMEL)
|
|
123
|
+
{
|
|
124
|
+
name = this.$normalizeWithCamelCase(names);
|
|
125
|
+
}
|
|
126
|
+
else
|
|
127
|
+
{
|
|
128
|
+
throw new Error("No valid nested path handling method was set");
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return name;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
$normalizeWithCamelCase(names)
|
|
136
|
+
{
|
|
137
|
+
if (this.strings === undefined)
|
|
138
|
+
{
|
|
139
|
+
this.strings = require('./strings');
|
|
140
|
+
}
|
|
141
|
+
if (this.locale === undefined)
|
|
142
|
+
{
|
|
143
|
+
this.locale = this.strings.getLocale();
|
|
144
|
+
}
|
|
145
|
+
let name = names.shift().toLocaleLowerCase(this.locale);
|
|
146
|
+
for (const path in names)
|
|
147
|
+
{
|
|
148
|
+
name += this.strings.ucfirst(path, true, this.locale);
|
|
149
|
+
}
|
|
150
|
+
return name;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Export a module directly.
|
|
155
|
+
*
|
|
156
|
+
* @param {string} name - The property name to export.
|
|
157
|
+
*
|
|
158
|
+
* @param {object} [conf] Additional export configuration options.
|
|
159
|
+
* @param {string} [conf.module=`./${name}`] The module to `require()`.
|
|
160
|
+
* @param {string} [conf.prop] If set, we want an exported property
|
|
161
|
+
* of this name from the loaded module.
|
|
162
|
+
*
|
|
163
|
+
* If not set, the entire loaded module will be our exported value.
|
|
164
|
+
*
|
|
165
|
+
* @param {boolean} [conf.configurable=this.configurable]
|
|
166
|
+
* Descriptor `configurable` value.
|
|
167
|
+
* @param {boolean} [conf.enumerable=this.enumerable]
|
|
168
|
+
* Descriptor `enumerable` value.
|
|
169
|
+
* @param {boolean} [conf.writable=this.writable]
|
|
170
|
+
* Descriptor `writable` value.
|
|
171
|
+
*
|
|
172
|
+
* @param {*} [conf.value] An explicit value to set.
|
|
173
|
+
*
|
|
174
|
+
* This skips the `require()` call entirely.
|
|
175
|
+
*
|
|
176
|
+
* @returns {object} `this`
|
|
177
|
+
*/
|
|
178
|
+
has(name, conf={})
|
|
179
|
+
{
|
|
180
|
+
const pname = this.$normalizeProperty(name);
|
|
181
|
+
const desc = this.requireDescriptor(name, conf);
|
|
182
|
+
def(this.module.exports, pname, desc);
|
|
183
|
+
return this;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Export a lazy-loaded module.
|
|
188
|
+
*
|
|
189
|
+
* @param {string} name - The property name to export.
|
|
190
|
+
*
|
|
191
|
+
* @param {object} [conf] Additional export configuration options.
|
|
192
|
+
*
|
|
193
|
+
* In addition to all the options supported by
|
|
194
|
+
* [has()]{@link module:@lumjs/core/modules.has}
|
|
195
|
+
* this also supports one further option.
|
|
196
|
+
*
|
|
197
|
+
* @param {object} [conf.lazy] Advanced options for the `lazy()` call.
|
|
198
|
+
*
|
|
199
|
+
* If not specified, sane defaults will be used, that ensures the
|
|
200
|
+
* `enumerable` descriptor property for the lazy getter is set the
|
|
201
|
+
* same as the final descriptor property once its loaded.
|
|
202
|
+
*
|
|
203
|
+
* @returns {object} `this`
|
|
204
|
+
*/
|
|
205
|
+
can(name, conf={})
|
|
206
|
+
{
|
|
207
|
+
const pname = this.$normalizeProperty(name);
|
|
208
|
+
const enumerable = conf.enumerable ?? this.enumerable;
|
|
209
|
+
const lazyOpts = isObj(conf.lazy) ? conf.lazy : {enumerable};
|
|
210
|
+
const getter = () => this.requireDescriptor(name, conf);
|
|
211
|
+
lazy(this.module.exports, pname, getter, lazyOpts);
|
|
212
|
+
return this;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Re-export some exported properties from a module.
|
|
217
|
+
*
|
|
218
|
+
* By default this uses `has()` to define the exports, but that
|
|
219
|
+
* can be changed using special parameter values.
|
|
220
|
+
*
|
|
221
|
+
* @param {string} modname - The module to export the properties from.
|
|
222
|
+
* @param {...any} libs - What we're exporting.
|
|
223
|
+
*
|
|
224
|
+
* If this is a `string` it is the name of an exported property we want to
|
|
225
|
+
* re-export directly.
|
|
226
|
+
*
|
|
227
|
+
* If this is `true`, all subsequent values will be exported using `can()`.
|
|
228
|
+
*
|
|
229
|
+
* If this is `false`, all subsequent values will be exported using `has()`.
|
|
230
|
+
*
|
|
231
|
+
* If this is an `object`, then it's considered the `conf` parameter for
|
|
232
|
+
* the `has()` or `can()` methods. If the `conf` does not have a `module`
|
|
233
|
+
* property, the `modname` will be assigned as the `module` property.
|
|
234
|
+
* You cannot set the `prop` property, as it's overwritten for every
|
|
235
|
+
* exported property.
|
|
236
|
+
*
|
|
237
|
+
* @returns {object} `this`
|
|
238
|
+
*/
|
|
239
|
+
from(modname, ...libs)
|
|
240
|
+
{
|
|
241
|
+
let func = 'has';
|
|
242
|
+
let curConf = {module: modname};
|
|
243
|
+
for (const lib of libs)
|
|
244
|
+
{
|
|
245
|
+
if (isObj(lib))
|
|
246
|
+
{ // Change the current config.
|
|
247
|
+
curConf = clone(lib);
|
|
248
|
+
if (curConf.module === undefined)
|
|
249
|
+
{ // Make sure the module name is assigned.
|
|
250
|
+
curConf.module = modname;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
else if (typeof lib === B)
|
|
254
|
+
{ // Change the function we're calling.
|
|
255
|
+
func = lib ? 'can' : 'has';
|
|
256
|
+
}
|
|
257
|
+
else if (typeof lib === S)
|
|
258
|
+
{
|
|
259
|
+
const conf = clone(curConf);
|
|
260
|
+
conf.prop = lib;
|
|
261
|
+
this[func](lib, conf);
|
|
262
|
+
}
|
|
263
|
+
else
|
|
264
|
+
{
|
|
265
|
+
throw new TypeError("libs must be strings, booleans, or objects");
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return this;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Create a functional API for the Builder class.
|
|
273
|
+
*
|
|
274
|
+
* Basically makes a new `Builder` instance, then creates standalone
|
|
275
|
+
* closure functions that wrap the main instance methods.
|
|
276
|
+
*
|
|
277
|
+
* These functions can be imported into a namespace directly.
|
|
278
|
+
* They each have a special `builder` property which is a reference
|
|
279
|
+
* to the underlying `Builder` instance.
|
|
280
|
+
*
|
|
281
|
+
* There's also a `builder` property in the exported function list.
|
|
282
|
+
*
|
|
283
|
+
* Example usage:
|
|
284
|
+
*
|
|
285
|
+
* ```js
|
|
286
|
+
* const {has,can,from} = require('@lumjs/core').modules.build(module);
|
|
287
|
+
*
|
|
288
|
+
*
|
|
289
|
+
* // exports.foo = require('./foo');
|
|
290
|
+
* has('foo');
|
|
291
|
+
*
|
|
292
|
+
* // exports.someNestedPath = require('./some/nested/path');
|
|
293
|
+
* has('./some/nested/path');
|
|
294
|
+
*
|
|
295
|
+
* ```
|
|
296
|
+
*
|
|
297
|
+
* @param {object} targetModule - The `module` for the Builder instance.
|
|
298
|
+
* @param {object} [opts] - Any options for the Builder instance.
|
|
299
|
+
* @returns {object} An object containing the closure functions.
|
|
300
|
+
*/
|
|
301
|
+
static build(targetModule, opts)
|
|
302
|
+
{
|
|
303
|
+
const builder = new this(targetModule, opts);
|
|
304
|
+
const funcs = {builder};
|
|
305
|
+
for (const name of BUILD_METHODS)
|
|
306
|
+
{
|
|
307
|
+
const func = function()
|
|
308
|
+
{
|
|
309
|
+
return builder[name](...arguments);
|
|
310
|
+
}
|
|
311
|
+
def(func, 'builder', builder);
|
|
312
|
+
funcs[name] = func;
|
|
313
|
+
}
|
|
314
|
+
return funcs;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* A static alternative to `new ModuleBuilder()`;
|
|
319
|
+
*
|
|
320
|
+
* @param {object} targetModule
|
|
321
|
+
* @param {object} [opts]
|
|
322
|
+
* @returns {object} The new `ModuleBuilder` instance.
|
|
323
|
+
*/
|
|
324
|
+
static new(targetModule, opts)
|
|
325
|
+
{
|
|
326
|
+
return new this(targetModule, opts);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
def(ModuleBuilder, 'NESTED_ERROR', 0)
|
|
332
|
+
def(ModuleBuilder, 'NESTED_FIRST', 1);
|
|
333
|
+
def(ModuleBuilder, 'NESTED_LAST', 2);
|
|
334
|
+
def(ModuleBuilder, 'NESTED_CAMEL', 3);
|
|
335
|
+
|
|
336
|
+
module.exports = ModuleBuilder;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lumjs/core",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.0",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"exports":
|
|
6
6
|
{
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"./flags": "./lib/flags.js",
|
|
13
13
|
"./obj": "./lib/obj/index.js",
|
|
14
14
|
"./opt": "./lib/opt.js",
|
|
15
|
+
"./modulebuilder": "./lib/modulebuilder.js",
|
|
15
16
|
"./modules": "./lib/modules.js",
|
|
16
17
|
"./meta": "./lib/meta.js",
|
|
17
18
|
"./enum": "./lib/enum.js",
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
# Changelog → 1.0-beta.x
|
|
2
|
-
|
|
3
|
-
This is the changelog for the `1.0-beta.x` versions.
|
|
4
|
-
|
|
5
|
-
See [Changelogs](index.md) for more information on the changelogs.
|
|
6
|
-
|
|
7
|
-
## [1.0.0-beta.6]
|
|
8
|
-
- This is the **final** beta version.
|
|
9
|
-
- Version `1.0.0` will be this but with the docs updated a bit.
|
|
10
|
-
### Added
|
|
11
|
-
- More tests for the `types` module.
|
|
12
|
-
- Changelog file for the upcoming `1.x` *stable* releases.
|
|
13
|
-
### Changed
|
|
14
|
-
- Removed some convoluted options from `def()`.
|
|
15
|
-
- Reworked `types.stringify()` to handle recursive mode better.
|
|
16
|
-
- Added `Error` stringification to `types.stringify()`
|
|
17
|
-
|
|
18
|
-
## [1.0.0-beta.5] - 2022-07-18
|
|
19
|
-
### Added
|
|
20
|
-
- A new `types.stringify()` method.
|
|
21
|
-
- Shortcut `string` options for the `types.def()` method.
|
|
22
|
-
- A `build-docs` script in `package.json`.
|
|
23
|
-
### Changed
|
|
24
|
-
- Overhauled all DocBlocks to conform to `JSDoc 3` format.
|
|
25
|
-
- Changed `context.has` to support a magic `Proxy` version.
|
|
26
|
-
- Some tweaks to `Enum` to cleanup some things.
|
|
27
|
-
- Both `Enum` and `observable` use `TYPES.add()` now.
|
|
28
|
-
- In `modules.name()` nixed `opts.noAuto` and added `opts.useAuto` instead.
|
|
29
|
-
- Created explicit `exports` definition in `package.json` with our sub-modules.
|
|
30
|
-
### Fixed
|
|
31
|
-
- Fixed a property definition issue in `obj.SOA()`.
|
|
32
|
-
|
|
33
|
-
## [1.0.0-beta.4] - 2022-07-15
|
|
34
|
-
### Added
|
|
35
|
-
- Two new clone modes:
|
|
36
|
-
- `CLONE.DEEP` : A recursive clone of enumerable properties.
|
|
37
|
-
- `CLONE.ENTIRE` : A recursive clone of all properties.
|
|
38
|
-
- Added `types.isa()` which wraps `isType()` and `isInstance()` along with some added magic that makes it a generic *smart match* function.
|
|
39
|
-
- Added `types.needs()` which does for `isa()` what `needOb()` and `needType()` do for `isObj()` and `isType()` respectively.
|
|
40
|
-
- A `jsdoc.json` based on the one from the old [Lum.js](https://github.com/supernovus/lum.js) codebase.
|
|
41
|
-
- A temporary `test` script to the `package.json` which uses the `prove` utility from Perl 5.
|
|
42
|
-
### Removed
|
|
43
|
-
- Removed `descriptors` and `prop()` modules.
|
|
44
|
-
- They'll be in a new `@lumjs/compat` library for legacy compatibility code.
|
|
45
|
-
### Changed
|
|
46
|
-
- Updated this *changelog* which I forgot to do last time.
|
|
47
|
-
- Fixed some formatting in the changelog.
|
|
48
|
-
- Split `types` into separated files.
|
|
49
|
-
- Moved/renamed a few functions:
|
|
50
|
-
- `types.containsAny()` → `arrays.containsAny()`
|
|
51
|
-
- `types.containsAll()` → `arrays.containsAll()`
|
|
52
|
-
- `types.removeFromArray()` → `arrays.removeItems()`
|
|
53
|
-
- `types.NYI()` → `meta.NYI()`
|
|
54
|
-
- Updated tests to reflect the moved/renamed functions.
|
|
55
|
-
- Enhanced `def()` function as it has fully replaced `prop()` now.
|
|
56
|
-
- Has a new `opts` parameter which can be used for a few different options.
|
|
57
|
-
- Allows assigning a *getter* and *setter* without using a descriptor.
|
|
58
|
-
- Updated `lazy()` to be an extension of `def()` instead of `prop()`.
|
|
59
|
-
- Updated `obj/clone` and `obj/lock` to remove use of `descriptors` magic.
|
|
60
|
-
- Updated `CLONE` mode documentation to use a table format.
|
|
61
|
-
- A few minor tweaks and cleanups related to the rest of the above changes.
|
|
62
|
-
- Updated [../../TODO.md](TODO.md) with the plans for the final `1.0.0` release.
|
|
63
|
-
|
|
64
|
-
## [1.0.0-beta.3] - 2022-07-11
|
|
65
|
-
### Added
|
|
66
|
-
- `core.context.hasRequire`: A boolean value indicating `require()`
|
|
67
|
-
- `core.context.isNode`: A boolean value guessing the environment is node.js
|
|
68
|
-
### Changed
|
|
69
|
-
- `core.context.CJS`: Made slightly tighter in definition.
|
|
70
|
-
- `core.modules.name()`: Made it more flexible.
|
|
71
|
-
- `core.obj`: Changed namespace exports.
|
|
72
|
-
### Fixed
|
|
73
|
-
- `core.modules.name()`: Actually return the value!
|
|
74
|
-
|
|
75
|
-
## [1.0.0-beta.2] - 2022-07-08
|
|
76
|
-
### Changed
|
|
77
|
-
- Renamed `src` to `lib` as we're not compiling/transpiling this code.
|
|
78
|
-
- Moved `index.js` into `lib` with the rest of the module files.
|
|
79
|
-
- Added `modules.js` with a method for generating a name/id for a module.
|
|
80
|
-
- Added `isSearch()`,`isReplacement()`, and `replaceItems()` to `strings.js`.
|
|
81
|
-
|
|
82
|
-
## [1.0.0-beta.1] - 2022-07-07
|
|
83
|
-
### Added
|
|
84
|
-
- Initial release.
|
|
85
|
-
- Pulled a bunch of the core libraries from the old Lum.js project.
|
|
86
|
-
- Refactored and reorganized the libraries a lot.
|
|
87
|
-
|
|
88
|
-
[1.0.0-beta.6]: https://github.com/supernovus/lum.core.js/compare/v1.0.0-beta.5...v1.0.0-beta.6
|
|
89
|
-
[1.0.0-beta.5]: https://github.com/supernovus/lum.core.js/compare/v1.0.0-beta.4...v1.0.0-beta.5
|
|
90
|
-
[1.0.0-beta.4]: https://github.com/supernovus/lum.core.js/compare/v1.0.0-beta.3...v1.0.0-beta.4
|
|
91
|
-
[1.0.0-beta.3]: https://github.com/supernovus/lum.core.js/compare/v1.0.0-beta.2...v1.0.0-beta.3
|
|
92
|
-
[1.0.0-beta.2]: https://github.com/supernovus/lum.core.js/compare/v1.0.0-beta.1...v1.0.0-beta.2
|
|
93
|
-
[1.0.0-beta.1]: https://github.com/supernovus/lum.core.js/releases/tag/v1.0.0-beta.1
|
package/docs/changelogs/1.x.md
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
# Changelog → 1.x
|
|
2
|
-
|
|
3
|
-
This is the changelog for the `1.x` versions.
|
|
4
|
-
|
|
5
|
-
See [Changelogs](index.md) for more information on the changelogs.
|
|
6
|
-
|
|
7
|
-
## [Unreleased]
|
|
8
|
-
|
|
9
|
-
## [1.5.1] - 2022-09-29
|
|
10
|
-
### Changed
|
|
11
|
-
- Removed `constructor()` from `AbstractClass`.
|
|
12
|
-
- Added `$needs()` to `AbstractClass`.
|
|
13
|
-
### Fixed
|
|
14
|
-
- `AbstractClass` actually works properly now.
|
|
15
|
-
|
|
16
|
-
## [1.5.0] - 2022-09-27
|
|
17
|
-
### Changed
|
|
18
|
-
- Updated a few DocBlocks.
|
|
19
|
-
- Added a couple explicitly named options to `def()`
|
|
20
|
-
- Rewrote the default module to use `def()` to define its exported properties.
|
|
21
|
-
- Made `arrays`, `strings`, `flags`, `opt`, `modules`, and `observable` use `lazy()`.
|
|
22
|
-
### Fixed
|
|
23
|
-
- Fixed `def()` so that the descriptor defaults are applied properly.
|
|
24
|
-
- Fixed `lazy()` so it returns a proper value and not a descriptor on first access.
|
|
25
|
-
|
|
26
|
-
## [1.4.0] - 2022-09-26
|
|
27
|
-
### Changed
|
|
28
|
-
- Moved `lazy` into `types` module by default (leaving an alias in `core`).
|
|
29
|
-
- Completely rewrote the `lazy` function entirely.
|
|
30
|
-
- Greatly extended the documentation for `lazy` function.
|
|
31
|
-
- Removed an unused development artefact from `types.needs`.
|
|
32
|
-
|
|
33
|
-
## [1.3.1] - 2022-09-23
|
|
34
|
-
### Fixed
|
|
35
|
-
- The `arrays` module exports `powerset` and `random` as it should.
|
|
36
|
-
- Recursive dependency order issues with `clone`, `lock`, and `enum` resolved.
|
|
37
|
-
- Custom `lock` options in `enum` module actually work now.
|
|
38
|
-
### Changed
|
|
39
|
-
- The `Enum()` function now has `configurable` and `enumerable` options.
|
|
40
|
-
- The `configurable` property in `enums` defaults to `false` now.
|
|
41
|
-
- Tweaked the *changelogs* a bit and added a new [changelog listing](index.md).
|
|
42
|
-
|
|
43
|
-
## [1.3.0] - 2022-09-11
|
|
44
|
-
### Changed
|
|
45
|
-
- Overhauled the `obj.clone()` method.
|
|
46
|
-
- Added *named options* for all of the behaviours that the `CLONE` *modes* affect.
|
|
47
|
-
While this technically could make the *modes* obsolete, I'm leaving them in as
|
|
48
|
-
simple sets of default options that can be used instead of manually choosing all
|
|
49
|
-
of the individual options.
|
|
50
|
-
- Added a new `CLONE.N` *mode* which has **no** options turned on.
|
|
51
|
-
It will always remain first in the *enum* list so it's value will always be `0`.
|
|
52
|
-
- Added the ability to clone properties using their descriptors.
|
|
53
|
-
It is enabled by default on most of the *modes* now, as it simply makes sense.
|
|
54
|
-
- Added the ability to set the `prototype` on the cloned object.
|
|
55
|
-
- The `opts` parameter of `clone()` may be a `CLONE.*` enum value.
|
|
56
|
-
It's a shortcut for `{mode: CLONE.MODE}` for convenience.
|
|
57
|
-
- A small tweak to `obj.copyProps()`, not important, just a cleanup.
|
|
58
|
-
### Fixed
|
|
59
|
-
- A reference in the DocBlock for `obj.getProperty()`.
|
|
60
|
-
|
|
61
|
-
## [1.2.1] - 2022-09-05
|
|
62
|
-
### Added
|
|
63
|
-
- `core.InternalObjectId#untag()`
|
|
64
|
-
### Changed
|
|
65
|
-
- Cleaned up the wording in a docblock, and updated a test to use `done()`.
|
|
66
|
-
|
|
67
|
-
## [1.2.0] - 2022-08-10
|
|
68
|
-
### Added
|
|
69
|
-
- Moved the `array.powerset()` and `array.random()` methods from Lum.js v4 into `core.arrays`.
|
|
70
|
-
- Added a new `core.context.isCommonJS()` method which is only used in certain circumstances.
|
|
71
|
-
|
|
72
|
-
### Fixed
|
|
73
|
-
- A typo in one of the `package.json` exports.
|
|
74
|
-
- Commented out a debugging line.
|
|
75
|
-
|
|
76
|
-
## [1.1.1] - 2022-08-02
|
|
77
|
-
### Fixed
|
|
78
|
-
- A couple missing constants in some functions.
|
|
79
|
-
|
|
80
|
-
## [1.1.0] - 2022-07-29
|
|
81
|
-
### Added
|
|
82
|
-
- `types.doesDescriptorTemplate()` method.
|
|
83
|
-
- `obj.getProperty()` method (used to be in the `descriptors` sub-module.)
|
|
84
|
-
### Changed
|
|
85
|
-
- Tweaked documentation for:
|
|
86
|
-
- `obj.getObjectPath()`
|
|
87
|
-
- `obj.setObjectPath()`
|
|
88
|
-
- `obj.getNamespace()`
|
|
89
|
-
- `obj.setNamespace()`
|
|
90
|
-
- Updated error messages in `obj.setObjectPath()`
|
|
91
|
-
- Made `obj.setObjectPath()` use `types.doesDescriptorTemplate()` for validation of `opts.desc` option.
|
|
92
|
-
- Changed `obj.getObjectPath()` and `obj.setObjectPath()` to support `function` parent objects.
|
|
93
|
-
- Enhanced `types.stringify()` to support `RegExp` as well as supporting custom extensions down the road.
|
|
94
|
-
|
|
95
|
-
## [1.0.0] - 2022-07-27
|
|
96
|
-
### Changed
|
|
97
|
-
- Initial *stable* release.
|
|
98
|
-
- See [1.0-beta.md](1.0-beta.md) for the beta versions of `1.0`
|
|
99
|
-
- See [lum.js](https://github.com/supernovus/lum.js) for the original library set this is replacing.
|
|
100
|
-
|
|
101
|
-
[Unreleased]: https://github.com/supernovus/lum.core.js/compare/v1.5.1...HEAD
|
|
102
|
-
[1.5.1]: https://github.com/supernovus/lum.core.js/compare/v1.5.0...v1.5.1
|
|
103
|
-
[1.5.0]: https://github.com/supernovus/lum.core.js/compare/v1.4.0...v1.5.0
|
|
104
|
-
[1.4.0]: https://github.com/supernovus/lum.core.js/compare/v1.3.1...v1.4.0
|
|
105
|
-
[1.3.1]: https://github.com/supernovus/lum.core.js/compare/v1.3.0...v1.3.1
|
|
106
|
-
[1.3.0]: https://github.com/supernovus/lum.core.js/compare/v1.2.1...v1.3.0
|
|
107
|
-
[1.2.1]: https://github.com/supernovus/lum.core.js/compare/v1.2.0...v1.2.1
|
|
108
|
-
[1.2.0]: https://github.com/supernovus/lum.core.js/compare/v1.1.1...v1.2.0
|
|
109
|
-
[1.1.1]: https://github.com/supernovus/lum.core.js/compare/v1.1.0...v1.1.1
|
|
110
|
-
[1.1.0]: https://github.com/supernovus/lum.core.js/compare/v1.0.0...v1.1.0
|
|
111
|
-
[1.0.0]: https://github.com/supernovus/lum.core.js/releases/tag/v1.0.0
|
package/docs/changelogs/index.md
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
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/test/arrays.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// Current test count.
|
|
2
|
-
const plan = 5;
|
|
3
|
-
// A new test instance.
|
|
4
|
-
const t = require('@lumjs/tests').new({module, plan});
|
|
5
|
-
// The arrays core module
|
|
6
|
-
const arr = require('../lib/arrays');
|
|
7
|
-
|
|
8
|
-
t.ok(arr.containsAny(['hello','world'], 'world'), 'containsAny([a], a)');
|
|
9
|
-
t.ok(!arr.containsAny(['hello','world'], 'universe'), '!containsAny([a], b)');
|
|
10
|
-
t.ok(arr.containsAll(['hello','darkness','my','old','friend'], 'hello', 'friend'), 'containsAll([a,b,c], a, c)');
|
|
11
|
-
t.ok(!arr.containsAll(['nothing','to','see'], 'nothing', 'here'), '!containsAll([a,b,c], a, d)');
|
|
12
|
-
|
|
13
|
-
const a1 = ['hello', 'darkness', 'my', 'old', 'friend'];
|
|
14
|
-
arr.removeItems(a1, 'darkness');
|
|
15
|
-
t.isJSON(a1, ['hello','my','old','friend'], 'removeFromArray(...)');
|
|
16
|
-
|
|
17
|
-
// All done.
|
|
18
|
-
t.output();
|
|
19
|
-
|
package/test/meta.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// Current test count.
|
|
2
|
-
const plan = 1;
|
|
3
|
-
// A new test instance.
|
|
4
|
-
const t = require('@lumjs/tests').new({module, plan});
|
|
5
|
-
// The meta core module
|
|
6
|
-
const meta = require('../lib/meta');
|
|
7
|
-
|
|
8
|
-
t.dies(()=>meta.NYI(), 'NYI()');
|
|
9
|
-
|
|
10
|
-
// TODO:
|
|
11
|
-
// - stacktrace()
|
|
12
|
-
// - AbstractClass
|
|
13
|
-
// - Functions.*
|
|
14
|
-
|
|
15
|
-
// All done.
|
|
16
|
-
t.output();
|
|
17
|
-
|
package/test/types.js
DELETED
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
// Current test count.
|
|
2
|
-
const plan = 120;
|
|
3
|
-
// A new test instance.
|
|
4
|
-
const t = require('@lumjs/tests').new({module, plan});
|
|
5
|
-
// The types core module
|
|
6
|
-
const types = require('../lib/types');
|
|
7
|
-
|
|
8
|
-
// A quick reference to the type names.
|
|
9
|
-
const TYP = types.TYPES;
|
|
10
|
-
// And the stringify function.
|
|
11
|
-
const stringify = types.stringify;
|
|
12
|
-
|
|
13
|
-
// Now for some further basics.
|
|
14
|
-
t.ok(types.isObj({}), 'isObj({})');
|
|
15
|
-
t.ok(types.isComplex({}), 'isComplex(object)');
|
|
16
|
-
t.ok(types.isComplex(function(){}), 'isComplex(function)');
|
|
17
|
-
t.ok(types.isNil(undefined), 'isNil(undefined)');
|
|
18
|
-
t.ok(types.isNil(null), 'isNil(null)');
|
|
19
|
-
t.ok(types.notNil(true), 'notNil(true)');
|
|
20
|
-
t.ok(types.notNil(false), 'notNil(false)');
|
|
21
|
-
t.ok(types.notNil(''), "notNil('')");
|
|
22
|
-
t.ok(types.isScalar(true), 'isScalar(true)');
|
|
23
|
-
t.ok(types.isScalar(0), 'isScalar(0)');
|
|
24
|
-
t.ok(!types.isScalar({}), '!isScalar({})');
|
|
25
|
-
t.ok(!types.isScalar(null), '!isScalar(null)');
|
|
26
|
-
t.ok(types.isArray([]), 'isArray([])');
|
|
27
|
-
t.ok(types.isTypedArray(new Int8Array(8)), 'isTypedArray(Int8Array)');
|
|
28
|
-
t.ok(types.nonEmptyArray([1,2,3]), 'nonEmptyArray([1,2,3])');
|
|
29
|
-
t.ok(!types.nonEmptyArray([]), '!nonEmptyArray([])');
|
|
30
|
-
t.ok(types.isProperty('hi'), 'isProperty(string)');
|
|
31
|
-
t.ok(types.isProperty(Symbol('hi')), 'isProperty(Symbol)');
|
|
32
|
-
t.ok(!types.isProperty(false), '!isProperty(false)')
|
|
33
|
-
|
|
34
|
-
function getArguments() { return arguments; }
|
|
35
|
-
|
|
36
|
-
t.ok(types.isArguments(getArguments()), 'isArguments(arguments)');
|
|
37
|
-
t.ok(!types.isArguments({}), '!isArguments({})');
|
|
38
|
-
|
|
39
|
-
class TypeClass
|
|
40
|
-
{
|
|
41
|
-
notUnbound()
|
|
42
|
-
{
|
|
43
|
-
t.ok(!types.unbound(this), '!unbound(instanceThis)');
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
class SubtypeClass extends TypeClass {}
|
|
48
|
-
|
|
49
|
-
const typesInstance = new TypeClass();
|
|
50
|
-
const subtypeInstance = new SubtypeClass();
|
|
51
|
-
|
|
52
|
-
class DifferentClass {}
|
|
53
|
-
|
|
54
|
-
const differentInstance = new DifferentClass();
|
|
55
|
-
|
|
56
|
-
t.ok(types.isInstance(typesInstance, TypeClass), 'isInstance(typeInstance,TypeClass)');
|
|
57
|
-
t.ok(types.isInstance(subtypeInstance, SubtypeClass), 'isInstance(subtypeInstance, SubtypeClass)');
|
|
58
|
-
t.ok(types.isInstance(subtypeInstance, TypeClass), 'isInstance(subtypeInstance, TypeClass)');
|
|
59
|
-
t.ok(!types.isInstance(typesInstance, SubtypeClass), '!isInstance(typeInstance, SubtypeClass)');
|
|
60
|
-
t.ok(!types.isInstance(differentInstance, TypeClass), '!isInstance(differentInstance, TypeClass)');
|
|
61
|
-
t.ok(!types.isInstance(typesInstance, DifferentClass), '!isInstance(typesInstance, DifferentClass)');
|
|
62
|
-
|
|
63
|
-
function doesDesc (tests, not=false)
|
|
64
|
-
{
|
|
65
|
-
for (const it of tests)
|
|
66
|
-
{
|
|
67
|
-
let result = types.doesDescriptor(it);
|
|
68
|
-
if (not) result = !result;
|
|
69
|
-
const desc = (not?'!':'')+'doesDescriptor'+stringify(it)+')';
|
|
70
|
-
t.ok(result, desc);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
doesDesc(
|
|
75
|
-
[
|
|
76
|
-
{value: true},
|
|
77
|
-
{value: {}, writable: true},
|
|
78
|
-
{get: function(){}},
|
|
79
|
-
{set: function(){}},
|
|
80
|
-
{get: function(){}, set: function(){}},
|
|
81
|
-
{get: function(){}, configurable: true},
|
|
82
|
-
]);
|
|
83
|
-
|
|
84
|
-
doesDesc(
|
|
85
|
-
[
|
|
86
|
-
{},
|
|
87
|
-
{value: true, get: function(){}},
|
|
88
|
-
{value: true, set: function(){}},
|
|
89
|
-
{get: function(){}, writable: true},
|
|
90
|
-
{set: function(){}, writable: true},
|
|
91
|
-
], true);
|
|
92
|
-
|
|
93
|
-
function testIsType (tests, not=false)
|
|
94
|
-
{
|
|
95
|
-
for (const it of tests)
|
|
96
|
-
{
|
|
97
|
-
let result = types.isType(it[0], it[1]);
|
|
98
|
-
if (not) result = !result;
|
|
99
|
-
const desc = (it.length > 2)
|
|
100
|
-
? it[2]
|
|
101
|
-
: (it[0]+','+stringify(it[1]));
|
|
102
|
-
t.ok(result, (not?'!':'')+'isType('+desc+')');
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
testIsType(
|
|
107
|
-
[
|
|
108
|
-
[TYP.O, {}],
|
|
109
|
-
[TYP.F, function(){}],
|
|
110
|
-
[TYP.S, 'hello'],
|
|
111
|
-
[TYP.B, true],
|
|
112
|
-
[TYP.B, false],
|
|
113
|
-
[TYP.N, 100],
|
|
114
|
-
[TYP.U, undefined],
|
|
115
|
-
[TYP.SY, Symbol('foo'), TYP.SY+',Symbol'],
|
|
116
|
-
[TYP.BI, BigInt(12345), TYP.BI+',BigInt(12345)'],
|
|
117
|
-
[TYP.BI, 54321n, TYP.BI+',54321n'],
|
|
118
|
-
[TYP.ARGS, getArguments()],
|
|
119
|
-
[TYP.ARRAY, []],
|
|
120
|
-
[TYP.NULL, null],
|
|
121
|
-
[TYP.TYPEDARRAY, new Int16Array(16), TYP.TYPEDARRAY+',Int16Array(16)'],
|
|
122
|
-
[TYP.DESCRIPTOR, {value: true}],
|
|
123
|
-
[TYP.DESCRIPTOR, {get: function(){}}],
|
|
124
|
-
[TYP.COMPLEX, {}],
|
|
125
|
-
[TYP.COMPLEX, function(){}],
|
|
126
|
-
[TYP.SCALAR, true],
|
|
127
|
-
[TYP.SCALAR, 'hi'],
|
|
128
|
-
[TYP.PROP, 'woah'],
|
|
129
|
-
[TYP.PROP, Symbol('woah')],
|
|
130
|
-
]);
|
|
131
|
-
|
|
132
|
-
testIsType(
|
|
133
|
-
[
|
|
134
|
-
[TYP.O, 'foo'],
|
|
135
|
-
[TYP.O, null],
|
|
136
|
-
[TYP.F, {}],
|
|
137
|
-
[TYP.B, 0],
|
|
138
|
-
[TYP.B, 1],
|
|
139
|
-
[TYP.N, '0'],
|
|
140
|
-
[TYP.U, null],
|
|
141
|
-
[TYP.SY, 'foo'],
|
|
142
|
-
[TYP.BI, 12345],
|
|
143
|
-
[TYP.ARGS, {}],
|
|
144
|
-
[TYP.ARRAY, {}],
|
|
145
|
-
[TYP.NULL, false],
|
|
146
|
-
[TYP.TYPEDARRAY, []],
|
|
147
|
-
[TYP.DESCRIPTOR, {value: true, get: function(){}}],
|
|
148
|
-
[TYP.DESCRIPTOR, {}],
|
|
149
|
-
[TYP.COMPLEX, 'a string'],
|
|
150
|
-
[TYP.SCALAR, {}],
|
|
151
|
-
[TYP.PROP, null],
|
|
152
|
-
], true);
|
|
153
|
-
|
|
154
|
-
(function(){ t.ok(types.unbound(this), 'unbound(unboundThis)'); })();
|
|
155
|
-
(function(){ t.ok(!types.unbound(this), '!unbound(boundThis)') }).bind({})();
|
|
156
|
-
typesInstance.notUnbound();
|
|
157
|
-
|
|
158
|
-
t.ok((function(){types.needObj({}); return true})(), 'needObj({})');
|
|
159
|
-
t.dies(function(){types.needObj(null); return true}, '!needObj(null)');
|
|
160
|
-
|
|
161
|
-
t.ok((function(){types.needType(TYP.S, 'hi'); return true})(), "needType('string','hi')");
|
|
162
|
-
t.dies(function(){types.needType(TYP.O, null); return true}, "!needType('object',null)");
|
|
163
|
-
|
|
164
|
-
{ // Tests of isa() method.
|
|
165
|
-
let wants = [TYP.S, TYP.N];
|
|
166
|
-
t.ok(types.isa('hi', ...wants), 'isa(val, ...types)');
|
|
167
|
-
t.isa('hello', wants, ' ^ using Test.isa()');
|
|
168
|
-
t.isa(42, wants, ' ^ with second type');
|
|
169
|
-
t.ok(!types.isa({}, ...wants), '!isa(val, ...types)');
|
|
170
|
-
t.nota({}, wants, ' ^ using Test.nota()');
|
|
171
|
-
|
|
172
|
-
wants = [SubtypeClass, DifferentClass];
|
|
173
|
-
t.isa(subtypeInstance, wants, 'isa(val, ...classes)');
|
|
174
|
-
t.isa(differentInstance, wants, ' ^ with second class');
|
|
175
|
-
t.nota(typesInstance, wants, 'nota(val, ...classes)');
|
|
176
|
-
|
|
177
|
-
wants = [TYP.B, TypeClass];
|
|
178
|
-
t.isa(true, wants, 'isa() → with mixed types/classes');
|
|
179
|
-
t.isa(subtypeInstance, wants, ' ^ with second type/class');
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
{ // Tests of needs() method.
|
|
183
|
-
let needs = [TYP.S, TYP.N];
|
|
184
|
-
t.lives(() => types.needs('hi', ...needs), 'needs(val, ...types)');
|
|
185
|
-
t.lives(() => types.needs(42, ...needs), ' ^ with second type');
|
|
186
|
-
t.dies(() => types.needs({}, ...needs), ' ^ throws on failure');
|
|
187
|
-
|
|
188
|
-
needs = [SubtypeClass, DifferentClass];
|
|
189
|
-
t.lives(() => types.needs(subtypeInstance, ...needs), 'needs(val, ...classes)');
|
|
190
|
-
t.lives(() => types.needs(differentInstance, ...needs), ' ^ with second class');
|
|
191
|
-
t.dies(() => types.needs(typesInstance, ...needs), ' ^ throws on failure');
|
|
192
|
-
|
|
193
|
-
needs = [TYP.B, TypeClass];
|
|
194
|
-
t.lives(() => types.needs(true, ...needs), 'needs() → with mixed types/classes');
|
|
195
|
-
t.lives(() => types.needs(subtypeInstance, ...needs), ' ^ with second type/class');
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
{ // Try a few versions of 'def'
|
|
199
|
-
const obj = {};
|
|
200
|
-
types.def(obj, 'test1', 'Test 1');
|
|
201
|
-
t.is(obj.test1, 'Test 1', 'def(obj, name, value)');
|
|
202
|
-
types.def(obj)('test2', 'Test 2');
|
|
203
|
-
t.is(obj.test2, 'Test 2', 'def(obj)(name, value)');
|
|
204
|
-
obj.test2 = '2 Test';
|
|
205
|
-
t.is(obj.test2, 'Test 2', 'def() is read-only by default');
|
|
206
|
-
|
|
207
|
-
types.def(obj, true)('test3', 'Test 3');
|
|
208
|
-
t.is(Object.keys(obj).length, 1, 'def(obj, true)(...)');
|
|
209
|
-
|
|
210
|
-
types.def(obj, 'a1', function()
|
|
211
|
-
{ // Returning a different property.
|
|
212
|
-
return this.test2;
|
|
213
|
-
},
|
|
214
|
-
function(val)
|
|
215
|
-
{ // Assigning to a different property.
|
|
216
|
-
this.$$ = val;
|
|
217
|
-
});
|
|
218
|
-
|
|
219
|
-
const gs = 'def(obj, name, getter, setter)';
|
|
220
|
-
t.is(obj.a1, 'Test 2', gs+'~getter');
|
|
221
|
-
obj.a1 = 'A1->$$';
|
|
222
|
-
t.is(obj.$$, 'A1->$$', gs+'~setter');
|
|
223
|
-
|
|
224
|
-
types.def(obj, 'test4', 'Test 4', {writable: true});
|
|
225
|
-
t.is(obj.test4, 'Test 4', 'def(..., {writable}) → added property');
|
|
226
|
-
obj.test4 = '4 Test';
|
|
227
|
-
t.is(obj.test4, '4 Test', ' ^ and it was writable');
|
|
228
|
-
|
|
229
|
-
const td = types.def(obj);
|
|
230
|
-
td('getOnly', {get: function() { return 'GETTER'; }});
|
|
231
|
-
obj.getOnly = 'blah blah blah';
|
|
232
|
-
t.is(obj.getOnly, 'GETTER', 'def(..., {get: getter}) → getter worked');
|
|
233
|
-
td('setOnly', {set: function(val) { this.__ = val; }});
|
|
234
|
-
obj.setOnly = 'SETTER';
|
|
235
|
-
t.is(obj.__, 'SETTER', 'def(..., {set: setter}) → setter worked');
|
|
236
|
-
t.is(obj.setOnly, undefined, ' ^ get is undefined');
|
|
237
|
-
|
|
238
|
-
td('foobar', {value: 'FOO BAR'});
|
|
239
|
-
t.is(obj.foobar, 'FOO BAR', 'def(..., {value})');
|
|
240
|
-
|
|
241
|
-
let anObj = {value: 'BAR FOO'};
|
|
242
|
-
td('barfoo', anObj, false);
|
|
243
|
-
t.is(obj.barfoo, anObj, 'def(..., descriptor, false) → assigned object as value');
|
|
244
|
-
|
|
245
|
-
td('barfoo2', anObj);
|
|
246
|
-
t.is(anObj.configurable, true, 'def(..., descriptor) → descriptor is a reference');
|
|
247
|
-
|
|
248
|
-
anObj = {value: 'new test'};
|
|
249
|
-
td('barfoo3', anObj, true);
|
|
250
|
-
|
|
251
|
-
t.is(anObj.configurable, undefined, 'def(..., descriptor, true) → cloned descriptor');
|
|
252
|
-
t.is(obj.barfoo3, 'new test', ' ^ value was correct')
|
|
253
|
-
|
|
254
|
-
td(
|
|
255
|
-
{
|
|
256
|
-
hello: 'World',
|
|
257
|
-
goodbye: 'Universe',
|
|
258
|
-
});
|
|
259
|
-
|
|
260
|
-
t.ok((obj.hello === 'World' && obj.goodbye === 'Universe'), 'def(obj, {prop1: value1, prop2: value2})')
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// TODO: isa() and needs()
|
|
264
|
-
// TODO: stringify()
|
|
265
|
-
|
|
266
|
-
// All done.
|
|
267
|
-
t.done();
|
|
268
|
-
|