@lumjs/core 1.37.0 → 1.37.2
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/events/event.js +10 -6
- package/lib/events/listener.js +11 -9
- package/lib/events/registry.js +69 -37
- package/lib/types/def.js +8 -7
- package/lib/types/isa.js +1 -1
- package/lib/types/root.js +60 -19
- package/lib/types/unbound/extend.js +15 -19
- package/lib/types/unbound/objects.js +2 -1
- package/package.json +1 -1
package/lib/events/event.js
CHANGED
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
const {F,isObj} = require('../types');
|
|
3
|
+
const {SY,F,isObj} = require('../types');
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* An Event object to emit to handler callbacks.
|
|
7
7
|
*
|
|
8
8
|
* @prop {module:@lumjs/core/events.Listener} eventListener
|
|
9
9
|
* The event Listener instance this event was emitted from.
|
|
10
|
-
* @prop {string}
|
|
10
|
+
* @prop {(string|Symbol)} type - The event type that was triggered.
|
|
11
|
+
* @prop {string} name - The event name that was triggered;
|
|
12
|
+
* if `type` is a string this will be the same value,
|
|
13
|
+
* for a Symbol type this will be the `type.description` value.
|
|
11
14
|
* @prop {object} target - Target object for this event.
|
|
12
15
|
* @prop {Array} args - Arguments passed to `emit()`
|
|
13
16
|
* @prop {object} options - Composes options from the
|
|
@@ -38,17 +41,18 @@ class LumEvent
|
|
|
38
41
|
* @protected
|
|
39
42
|
* @param {module:@lumjs/core/events.Listener} listener
|
|
40
43
|
* @param {object} target
|
|
41
|
-
* @param {string}
|
|
42
|
-
* @param {Array}
|
|
44
|
+
* @param {(string|Symbol)} type
|
|
45
|
+
* @param {Array} args
|
|
43
46
|
* @param {object} status
|
|
44
47
|
*/
|
|
45
|
-
constructor(listener, target,
|
|
48
|
+
constructor(listener, target, type, args, status)
|
|
46
49
|
{
|
|
47
50
|
const reg = listener.registry;
|
|
48
51
|
this.eventListener = listener;
|
|
49
52
|
this.args = args;
|
|
50
53
|
this.target = target;
|
|
51
|
-
this.
|
|
54
|
+
this.type = type;
|
|
55
|
+
this.name = (typeof type === SY) ? type.description : type;
|
|
52
56
|
this.emitStatus = status;
|
|
53
57
|
this.options = Object.assign({},
|
|
54
58
|
reg.options,
|
package/lib/events/listener.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
const {F,isObj
|
|
3
|
+
const {F,isObj} = require('../types');
|
|
4
4
|
const Event = require('./event');
|
|
5
5
|
|
|
6
|
-
const REMOVE_OPTS = ['listener','handler','eventNames'];
|
|
6
|
+
const REMOVE_OPTS = ['listener','handler','eventNames','eventTypes'];
|
|
7
7
|
|
|
8
8
|
function makeOpts(spec)
|
|
9
9
|
{
|
|
@@ -41,7 +41,8 @@ function isListener(v)
|
|
|
41
41
|
* @prop {module:@lumjs/core/events.Registry} registry
|
|
42
42
|
* The Registry instance this Listener belongs to.
|
|
43
43
|
* @prop {(function|object)} handler - Event handler callback
|
|
44
|
-
* @prop {Set}
|
|
44
|
+
* @prop {Set} eventTypes - A set of all event types handled by this
|
|
45
|
+
* @prop {Set} eventNames - Alias to `eventTypes`
|
|
45
46
|
* @prop {object} options - Options specific to this listener.
|
|
46
47
|
*
|
|
47
48
|
* See {@link module:@lumjs/core/events.Registry#makeListener makeListener()}
|
|
@@ -76,7 +77,8 @@ class LumEventListener
|
|
|
76
77
|
// Assign the rest here.
|
|
77
78
|
this.registry = registry;
|
|
78
79
|
this.options = makeOpts(spec);
|
|
79
|
-
|
|
80
|
+
const events = spec.eventTypes ?? spec.eventNames;
|
|
81
|
+
this.eventTypes = this.eventNames = registry.getEventNames(events);
|
|
80
82
|
|
|
81
83
|
const setup = this.options.setupListener ?? registry.options.setupListener;
|
|
82
84
|
if (typeof setup === F)
|
|
@@ -86,12 +88,12 @@ class LumEventListener
|
|
|
86
88
|
}
|
|
87
89
|
|
|
88
90
|
/**
|
|
89
|
-
* See if there is at least one item in `this.
|
|
91
|
+
* See if there is at least one item in `this.eventTypes`
|
|
90
92
|
* @type {boolean}
|
|
91
93
|
*/
|
|
92
94
|
get hasEvents()
|
|
93
95
|
{
|
|
94
|
-
return this.
|
|
96
|
+
return this.eventTypes.size > 0;
|
|
95
97
|
}
|
|
96
98
|
|
|
97
99
|
/**
|
|
@@ -100,15 +102,15 @@ class LumEventListener
|
|
|
100
102
|
*
|
|
101
103
|
* This is a *protected method* and should not be called directly.
|
|
102
104
|
* @protected
|
|
103
|
-
* @param {string}
|
|
105
|
+
* @param {string} type - A single event type/name that was triggered
|
|
104
106
|
* @param {object} target - A single target object
|
|
105
107
|
* @param {Array} args - Arguments passed to `emit()`
|
|
106
108
|
* @param {module:@lumjs/core/events~Status} status - Emit status info
|
|
107
109
|
* @returns {module:@lumjs/core/events.Event} The new Event that was emitted
|
|
108
110
|
*/
|
|
109
|
-
emitEvent(
|
|
111
|
+
emitEvent(type, target, args, status)
|
|
110
112
|
{
|
|
111
|
-
const event = new Event(this, target,
|
|
113
|
+
const event = new Event(this, target, type, args, status);
|
|
112
114
|
|
|
113
115
|
if (typeof this.handler === F)
|
|
114
116
|
{ // The simplest is the good old function
|
package/lib/events/registry.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
const {S,F,isObj,def,isIterable} = require('../types');
|
|
3
|
+
const {S,F,SY,isObj,def,isIterable} = require('../types');
|
|
4
4
|
const Listener = require('./listener');
|
|
5
5
|
const RegSym = Symbol('@lumjs/core/events:registry');
|
|
6
6
|
const cp = Object.assign;
|
|
@@ -30,8 +30,8 @@ const DEF_OPTIONS =
|
|
|
30
30
|
|
|
31
31
|
const RES_PROPS =
|
|
32
32
|
[
|
|
33
|
-
'eventNames', 'targets', 'multiMatch', 'onceRemoved',
|
|
34
|
-
'emitted', 'targetListeners', 'registry',
|
|
33
|
+
'eventNames', 'eventTypes', 'targets', 'multiMatch', 'onceRemoved',
|
|
34
|
+
'stopEmitting', 'emitted', 'targetListeners', 'registry',
|
|
35
35
|
]
|
|
36
36
|
|
|
37
37
|
/**
|
|
@@ -47,7 +47,7 @@ const isRegistered = target => isObj(target[RegSym]);
|
|
|
47
47
|
* @private
|
|
48
48
|
* @param {object} target - Object to get metadata for
|
|
49
49
|
* @param {boolean} [create=false] Create metadata if it's not found?
|
|
50
|
-
* @returns {object} metadata (TODO: schema docs)
|
|
50
|
+
* @returns {(object|undefined)} metadata (TODO: schema docs)
|
|
51
51
|
* @alias module:@lumjs/core/events.Registry.getMetadata
|
|
52
52
|
*/
|
|
53
53
|
function getMetadata(target, create=false)
|
|
@@ -58,10 +58,16 @@ function getMetadata(target, create=false)
|
|
|
58
58
|
}
|
|
59
59
|
else if (create)
|
|
60
60
|
{ // Create new metadata
|
|
61
|
+
const exts = Object.keys(DEF_EXTENDS);
|
|
61
62
|
const tpm =
|
|
62
63
|
{
|
|
63
64
|
r: new Map(),
|
|
64
65
|
p: {},
|
|
66
|
+
x: {},
|
|
67
|
+
}
|
|
68
|
+
for (const ext of exts)
|
|
69
|
+
{
|
|
70
|
+
tpm.x[ext] = [];
|
|
65
71
|
}
|
|
66
72
|
def(target, RegSym, tpm);
|
|
67
73
|
return tpm;
|
|
@@ -263,7 +269,8 @@ class LumEventRegistry
|
|
|
263
269
|
{
|
|
264
270
|
for (const iname of intNames)
|
|
265
271
|
{
|
|
266
|
-
if (typeof extOpts[iname] === S && extOpts[iname].trim() !== '')
|
|
272
|
+
if ((typeof extOpts[iname] === S && extOpts[iname].trim() !== '')
|
|
273
|
+
|| typeof extOpts[iname] === SY)
|
|
267
274
|
{
|
|
268
275
|
const ename = extOpts[iname];
|
|
269
276
|
const value = iname === 'registry'
|
|
@@ -274,6 +281,7 @@ class LumEventRegistry
|
|
|
274
281
|
def(target, ename, {value});
|
|
275
282
|
tps[ename] = iname;
|
|
276
283
|
tpm.p[ename] = this;
|
|
284
|
+
tpm.x[iname].push([this, ename]);
|
|
277
285
|
}
|
|
278
286
|
else
|
|
279
287
|
{
|
|
@@ -307,7 +315,8 @@ class LumEventRegistry
|
|
|
307
315
|
for (const iname of intNames)
|
|
308
316
|
{
|
|
309
317
|
if (iname === 'registry') continue; // skip the registry property
|
|
310
|
-
if (typeof extOpts[iname] === S && extOpts[iname].trim() !== '')
|
|
318
|
+
if ((typeof extOpts[iname] === S && extOpts[iname].trim() !== '')
|
|
319
|
+
|| typeof extOpts[iname] === SY)
|
|
311
320
|
{
|
|
312
321
|
const ename = extOpts[iname];
|
|
313
322
|
if (reserved.includes(ename))
|
|
@@ -332,28 +341,30 @@ class LumEventRegistry
|
|
|
332
341
|
/**
|
|
333
342
|
* Build a new Listener instance; used by `listen()` method.
|
|
334
343
|
*
|
|
335
|
-
* @param {(string|object)}
|
|
344
|
+
* @param {(string|symbol|object)} eventTypes
|
|
336
345
|
* What this does depends on the type, and the number of arguments passed.
|
|
337
346
|
*
|
|
338
347
|
* If this is an `object` **AND** is *the only argument* passed,
|
|
339
|
-
* it will be used as the `spec`, and the `spec.
|
|
348
|
+
* it will be used as the `spec`, and the `spec.eventTypes`
|
|
340
349
|
* and `spec.listener` properties will become mandatory.
|
|
341
350
|
*
|
|
342
|
-
* If it's
|
|
343
|
-
* will be used as the `spec.
|
|
351
|
+
* If it's NOT an object *OR* there is more than one argument, this
|
|
352
|
+
* will be used as the `spec.eventTypes` property.
|
|
344
353
|
*
|
|
345
354
|
* @param {module:@lumjs/core/events~Handler} [handler]
|
|
346
355
|
* Used as the `spec.handler` property if specified.
|
|
347
356
|
*
|
|
348
|
-
* This is mandatory if `
|
|
357
|
+
* This is mandatory if `eventTypes` argument is a string or Symbol!
|
|
349
358
|
*
|
|
350
359
|
* @param {object} [spec] The listener specification rules
|
|
351
360
|
*
|
|
352
|
-
* @param {(string|Iterable)} [spec.
|
|
361
|
+
* @param {(string|symbol|Iterable)} [spec.eventTypes] Event type(s)
|
|
353
362
|
*
|
|
354
363
|
* See {@link module:@lumjs/core/events.Registry#getEventNames} for details.
|
|
355
364
|
*
|
|
356
|
-
* @param {
|
|
365
|
+
* @param {(string|symbol|Iterable)} [spec.eventNames] Alias of `eventTypes`
|
|
366
|
+
*
|
|
367
|
+
* @param {module:@lumjs/core/events~Handler} [spec.handler] Event handler
|
|
357
368
|
*
|
|
358
369
|
* @param {(function|object)} [spec.listener] An alias for `handler`
|
|
359
370
|
*
|
|
@@ -365,8 +376,8 @@ class LumEventRegistry
|
|
|
365
376
|
*
|
|
366
377
|
* If `spec.options` is used, the properties in it take precedence over
|
|
367
378
|
* those directly in the `spec` object. Note that you cannot use the
|
|
368
|
-
* names `listener`, `handler` or `eventNames` as option
|
|
369
|
-
* and if found, they will be removed.
|
|
379
|
+
* names `listener`, `handler`, `eventTypes`, or `eventNames` as option
|
|
380
|
+
* properties, and if found, they will be removed.
|
|
370
381
|
*
|
|
371
382
|
* You may also override the `setupEvent` and `setupListener` registry
|
|
372
383
|
* options here if needed.
|
|
@@ -394,9 +405,9 @@ class LumEventRegistry
|
|
|
394
405
|
spec = cp({}, args[0]);
|
|
395
406
|
}
|
|
396
407
|
else
|
|
397
|
-
{ // listen(
|
|
408
|
+
{ // listen(eventTypes, listener, [spec])
|
|
398
409
|
spec = cp({}, args[2]);
|
|
399
|
-
spec.
|
|
410
|
+
spec.eventTypes = args[0];
|
|
400
411
|
spec.handler = args[1];
|
|
401
412
|
}
|
|
402
413
|
|
|
@@ -464,7 +475,7 @@ class LumEventRegistry
|
|
|
464
475
|
|
|
465
476
|
this.allListeners.add(listener);
|
|
466
477
|
|
|
467
|
-
for (const ename of listener.
|
|
478
|
+
for (const ename of listener.eventTypes)
|
|
468
479
|
{
|
|
469
480
|
let lset;
|
|
470
481
|
if (this.listenersFor.has(ename))
|
|
@@ -522,7 +533,7 @@ class LumEventRegistry
|
|
|
522
533
|
const eventListeners = this.listenersFor.get(name);
|
|
523
534
|
for (const lsnr of eventListeners)
|
|
524
535
|
{
|
|
525
|
-
lsnr.
|
|
536
|
+
lsnr.eventTypes.delete(name);
|
|
526
537
|
if (!lsnr.hasEvents)
|
|
527
538
|
{ // The last event name was removed.
|
|
528
539
|
this.removeListeners(lsnr);
|
|
@@ -547,7 +558,7 @@ class LumEventRegistry
|
|
|
547
558
|
{ // First remove it from allListeners
|
|
548
559
|
this.allListeners.delete(listener);
|
|
549
560
|
|
|
550
|
-
for (const ename of listener.
|
|
561
|
+
for (const ename of listener.eventTypes)
|
|
551
562
|
{
|
|
552
563
|
if (this.listenersFor.has(ename))
|
|
553
564
|
{
|
|
@@ -568,6 +579,7 @@ class LumEventRegistry
|
|
|
568
579
|
* - If this is the `wildcard` string, then this will call `removeAll()`.
|
|
569
580
|
* - If this is any other `string` it will be split using `splitNames()`,
|
|
570
581
|
* and the resulting strings passed as arguments to `removeEvents()`.
|
|
582
|
+
* - If this is a `Symbol` it will be passed to `removeEvents()`.
|
|
571
583
|
* - If this is a `Listener` instance, its passed to `removeListeners()`.
|
|
572
584
|
*
|
|
573
585
|
* @returns {module:@lumjs/core/events.Registry} `this`
|
|
@@ -584,6 +596,10 @@ class LumEventRegistry
|
|
|
584
596
|
const events = this.splitNames(what);
|
|
585
597
|
return this.removeEvents(...events);
|
|
586
598
|
}
|
|
599
|
+
else if (typeof what === SY)
|
|
600
|
+
{
|
|
601
|
+
return this.removeEvents(what);
|
|
602
|
+
}
|
|
587
603
|
else if (what instanceof Listener)
|
|
588
604
|
{
|
|
589
605
|
return this.removeListeners(what);
|
|
@@ -598,9 +614,8 @@ class LumEventRegistry
|
|
|
598
614
|
/**
|
|
599
615
|
* Emit (trigger) one or more events.
|
|
600
616
|
*
|
|
601
|
-
* @param {(string|
|
|
602
|
-
*
|
|
603
|
-
* If this is a single `string` it will be split via `splitNames()`.
|
|
617
|
+
* @param {(string|symbol|Array)} eventTypes - Events to emit;
|
|
618
|
+
* see {@link module:@lumjs/core/events#getEventTypes} for details.
|
|
604
619
|
*
|
|
605
620
|
* @param {object} [data] A data object (highly recommended);
|
|
606
621
|
* will be assigned to `event.data` if specified.
|
|
@@ -613,18 +628,19 @@ class LumEventRegistry
|
|
|
613
628
|
*
|
|
614
629
|
* @returns {module:@lumjs/core/events~Status}
|
|
615
630
|
*/
|
|
616
|
-
emit(
|
|
631
|
+
emit(eventTypes, ...args)
|
|
617
632
|
{
|
|
618
633
|
const extOpts = this.options.extend;
|
|
619
634
|
const sti =
|
|
620
635
|
{
|
|
621
|
-
|
|
636
|
+
eventTypes: this.getEventTypes(eventTypes),
|
|
622
637
|
multiMatch: this.options.multiMatch,
|
|
623
638
|
onceRemoved: new Set(),
|
|
624
639
|
stopEmitting: false,
|
|
625
640
|
emitted: [],
|
|
626
641
|
registry: this,
|
|
627
642
|
}
|
|
643
|
+
sti.eventNames = sti.eventTypes;
|
|
628
644
|
|
|
629
645
|
if (extOpts.results)
|
|
630
646
|
{
|
|
@@ -645,7 +661,7 @@ class LumEventRegistry
|
|
|
645
661
|
emitting: for (const tg of sti.targets)
|
|
646
662
|
{
|
|
647
663
|
const called = sti.targetListeners = new Set();
|
|
648
|
-
for (const ename of sti.
|
|
664
|
+
for (const ename of sti.eventTypes)
|
|
649
665
|
{
|
|
650
666
|
if (!this.listenersFor.has(ename)) continue;
|
|
651
667
|
|
|
@@ -793,32 +809,37 @@ class LumEventRegistry
|
|
|
793
809
|
}
|
|
794
810
|
|
|
795
811
|
/**
|
|
796
|
-
* Get a Set of event names from various kinds of values
|
|
797
|
-
* @param {(string|Iterable)}
|
|
812
|
+
* Get a Set of event types/names from various kinds of values
|
|
813
|
+
* @param {(string|symbol|Iterable)} types - Event types source
|
|
798
814
|
*
|
|
799
815
|
* If this is a string, it'll be passed to `splitNames()`.
|
|
800
|
-
* If it's
|
|
816
|
+
* If it's a Symbol, it'll be wrapped in a Set.
|
|
817
|
+
* If it's any kind of Iterable value, it'll be converted to a Set.
|
|
801
818
|
*
|
|
802
819
|
* @returns {Set}
|
|
803
820
|
* @throws {TypeError} If `names` is not a valid value
|
|
804
821
|
*/
|
|
805
|
-
|
|
822
|
+
getEventTypes(types)
|
|
806
823
|
{
|
|
807
|
-
if (typeof
|
|
824
|
+
if (typeof types === S)
|
|
808
825
|
{
|
|
809
|
-
return this.splitNames(
|
|
826
|
+
return this.splitNames(types);
|
|
810
827
|
}
|
|
811
|
-
else if (
|
|
828
|
+
else if (typeof types === SY)
|
|
812
829
|
{
|
|
813
|
-
return
|
|
830
|
+
return new Set([types]);
|
|
814
831
|
}
|
|
815
|
-
else if (
|
|
832
|
+
else if (types instanceof Set)
|
|
816
833
|
{
|
|
817
|
-
return
|
|
834
|
+
return types;
|
|
835
|
+
}
|
|
836
|
+
else if (isIterable(types))
|
|
837
|
+
{
|
|
838
|
+
return new Set(types);
|
|
818
839
|
}
|
|
819
840
|
else
|
|
820
841
|
{
|
|
821
|
-
console.error({names, registry: this});
|
|
842
|
+
console.error({names: types, registry: this});
|
|
822
843
|
throw new TypeError("Invalid event names");
|
|
823
844
|
}
|
|
824
845
|
}
|
|
@@ -835,9 +856,20 @@ class LumEventRegistry
|
|
|
835
856
|
|
|
836
857
|
}
|
|
837
858
|
|
|
859
|
+
const LERP = LumEventRegistry.prototype;
|
|
860
|
+
def(LERP, 'getEventNames', LERP.getEventTypes);
|
|
861
|
+
|
|
838
862
|
cp(LumEventRegistry,
|
|
839
863
|
{
|
|
840
864
|
isRegistered, getMetadata, targetsAre,
|
|
841
865
|
});
|
|
842
866
|
|
|
843
867
|
module.exports = LumEventRegistry;
|
|
868
|
+
|
|
869
|
+
/**
|
|
870
|
+
* An alias to `getEventTypes`
|
|
871
|
+
* @function module:@lumjs/core/events.Registry#getEventNames
|
|
872
|
+
* @param {(string|symbol|Iterable)} names - Event names source
|
|
873
|
+
* @returns {Set}
|
|
874
|
+
* @see module:@lumjs/core/events.Registry#getEventTypes
|
|
875
|
+
*/
|
package/lib/types/def.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const {F,
|
|
4
|
-
const {isObj,
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const {F,B} = require('./js');
|
|
4
|
+
const {isObj,isNil,isProperty,doesDescriptor} = require('./basics');
|
|
5
5
|
const clone = (...args) => Object.assign({}, ...args);
|
|
6
6
|
|
|
7
7
|
/**
|
|
@@ -95,9 +95,10 @@ const clone = (...args) => Object.assign({}, ...args);
|
|
|
95
95
|
*/
|
|
96
96
|
function def(obj, name, value, opts)
|
|
97
97
|
{
|
|
98
|
-
const isBound
|
|
99
|
-
=
|
|
100
|
-
&& typeof this.bound === F
|
|
98
|
+
const isBound
|
|
99
|
+
= isObj(this)
|
|
100
|
+
&& typeof this.bound === F
|
|
101
|
+
&& this.bound.$this === this;
|
|
101
102
|
|
|
102
103
|
if (isNil(name) || typeof name === B)
|
|
103
104
|
{ // Binding of Isaac?
|
package/lib/types/isa.js
CHANGED
package/lib/types/root.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
const {U} = require('./js');
|
|
2
|
-
const {isNil,isArray} = require('./basics');
|
|
2
|
+
const {isNil,isObj,isArray} = require('./basics');
|
|
3
3
|
|
|
4
4
|
// «private»
|
|
5
5
|
function no_root()
|
|
@@ -11,40 +11,81 @@ function no_root()
|
|
|
11
11
|
* The global root object. Usually `globalThis` these days.
|
|
12
12
|
* @alias module:@lumjs/core/types.root
|
|
13
13
|
*/
|
|
14
|
-
const root
|
|
15
|
-
|
|
16
|
-
: typeof
|
|
17
|
-
: typeof
|
|
14
|
+
const root
|
|
15
|
+
= typeof globalThis !== U ? globalThis
|
|
16
|
+
: typeof global !== U ? global
|
|
17
|
+
: typeof self !== U ? self
|
|
18
|
+
: typeof window !== U ? window
|
|
18
19
|
: no_root(); // Unlike the old way, we'll die if the environment is undetermined.
|
|
19
20
|
|
|
20
21
|
exports.root = root;
|
|
21
22
|
|
|
22
|
-
// A
|
|
23
|
+
// A Set of objects to be considered unbound globally.
|
|
23
24
|
const unboundObjects = require('./unbound/objects');
|
|
24
25
|
|
|
26
|
+
// Default options for unbound()
|
|
27
|
+
const UBDO =
|
|
28
|
+
{
|
|
29
|
+
nil: true,
|
|
30
|
+
root: true,
|
|
31
|
+
}
|
|
32
|
+
|
|
25
33
|
/**
|
|
26
34
|
* Pass `this` here to see if it is bound to an object.
|
|
27
35
|
*
|
|
28
|
-
*
|
|
36
|
+
* @param {*} whatIsThis - The `this` from any context
|
|
37
|
+
*
|
|
38
|
+
* @param {(boolean|object)} [opts] Options for advanced behaviours.
|
|
39
|
+
*
|
|
40
|
+
* If this is boolean then it'll be used as `opts.root`;
|
|
41
|
+
* If it is an `Array` or `Set` it will be used as `opts.list`;
|
|
42
|
+
* Use just a plain object literal for specifying named options.
|
|
43
|
+
*
|
|
44
|
+
* TODO: as of v2.0 this will no longer accept a boolean value
|
|
45
|
+
* as a shortcut to `opts.root`. That must be explicitly set.
|
|
46
|
+
*
|
|
47
|
+
* @param {boolean} [opts.root=true] The global root is unbound?
|
|
48
|
+
* @param {boolean} [opts.nil=true] `null` and `undefined` are unbound?
|
|
49
|
+
* @param {(Array|Set)} [opts.list] A list of additional values that
|
|
50
|
+
* for the purposes of this test will be considered unbound.
|
|
51
|
+
*
|
|
52
|
+
* @param {(Array|Set|boolean)} [list] A positional version of `opts.list`;
|
|
53
|
+
* ONLY used when the `opts` argument is boolean.
|
|
54
|
+
*
|
|
55
|
+
* TODO: remove this argument as of v2.0
|
|
29
56
|
*
|
|
30
|
-
* @param {*} whatIsThis - The `this` from any context.
|
|
31
|
-
* @param {boolean} [rootIsUnbound=true] The global root is unbound.
|
|
32
|
-
* @param {(boolean|Array)} [areUnbound=false] A list of unbound objects.
|
|
33
|
-
* If the is `true` we use an global list that can register special
|
|
34
|
-
* internal objects. Otherwise an `Array` of unbound objects may be used.
|
|
35
57
|
* @returns {boolean}
|
|
36
58
|
* @alias module:@lumjs/core/types.unbound
|
|
37
59
|
*/
|
|
38
|
-
function unbound(whatIsThis,
|
|
60
|
+
function unbound(whatIsThis, opts=true, list)
|
|
39
61
|
{
|
|
40
|
-
if (
|
|
41
|
-
{ //
|
|
42
|
-
|
|
62
|
+
if (isObj(opts))
|
|
63
|
+
{ // Merge in defaults
|
|
64
|
+
if (opts instanceof Set || isArray(opts))
|
|
65
|
+
{ // A shortcut to the `list` property
|
|
66
|
+
list = opts;
|
|
67
|
+
opts = Object.assign({}, UBDO);
|
|
68
|
+
}
|
|
69
|
+
else
|
|
70
|
+
{ // Regular options were specified.
|
|
71
|
+
opts = Object.assign({}, UBDO, {list}, opts);
|
|
72
|
+
list = opts.list;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else
|
|
76
|
+
{ // Assume old positional arguments are being used
|
|
77
|
+
opts = Object.assign({}, UBDO, {root: opts});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (list === true)
|
|
81
|
+
{ // Internal special unbound values
|
|
82
|
+
list = unboundObjects;
|
|
43
83
|
}
|
|
44
84
|
|
|
45
|
-
if (isNil(whatIsThis)) return true;
|
|
46
|
-
if (
|
|
47
|
-
if (
|
|
85
|
+
if (opts.nil && isNil(whatIsThis)) return true;
|
|
86
|
+
if (opts.root && whatIsThis === root) return true;
|
|
87
|
+
if (list instanceof Set && list.has(whatIsThis)) return true;
|
|
88
|
+
if (isArray(list) && list.includes(whatIsThis)) return true;
|
|
48
89
|
|
|
49
90
|
// Nothing considered unbound.
|
|
50
91
|
return false;
|
|
@@ -2,45 +2,41 @@
|
|
|
2
2
|
|
|
3
3
|
const def = require('../def');
|
|
4
4
|
const {needObj} = require('../needs');
|
|
5
|
-
const removeFromArray = require('../../arrays/list').removeItems;
|
|
6
5
|
const unboundObjects = require('./objects');
|
|
7
6
|
|
|
8
|
-
// Adds a couple
|
|
7
|
+
// Adds a couple proxy methods to the `unbound` function.
|
|
9
8
|
module.exports = function(unbound)
|
|
10
9
|
{
|
|
11
10
|
/**
|
|
12
11
|
* Add an item to the unbound global objects list.
|
|
13
12
|
*
|
|
14
|
-
* @
|
|
15
|
-
* @
|
|
16
|
-
* @
|
|
17
|
-
* @
|
|
18
|
-
* @
|
|
13
|
+
* @deprecated the global list is going away in 2.0
|
|
14
|
+
* @function module:@lumjs/core/types.unbound.add
|
|
15
|
+
* @param {(object|function)} obj - Value to be added
|
|
16
|
+
* @returns {boolean} always true as of v1.37.2
|
|
17
|
+
* @throws {TypeError} If `obj` was not a valid value
|
|
19
18
|
*/
|
|
20
19
|
def(unbound, 'add', function (obj)
|
|
21
20
|
{
|
|
22
21
|
needObj(obj, true);
|
|
23
|
-
if (
|
|
24
|
-
|
|
25
|
-
return false;
|
|
26
|
-
}
|
|
27
|
-
// Add to list and we're done.
|
|
28
|
-
unboundObjects.push(obj);
|
|
22
|
+
if (unboundObjects.has(obj)) return false;
|
|
23
|
+
unboundObjects.add(obj);
|
|
29
24
|
return true;
|
|
30
25
|
});
|
|
31
26
|
|
|
32
27
|
/**
|
|
33
28
|
* Remove an item from the unbound global objects list.
|
|
34
29
|
*
|
|
35
|
-
* @
|
|
36
|
-
* @
|
|
37
|
-
* @
|
|
38
|
-
* @
|
|
39
|
-
* @
|
|
30
|
+
* @deprecated the global list is going away in 2.0
|
|
31
|
+
* @function module:@lumjs/core/types.unbound.remove
|
|
32
|
+
* @param {(object|function)} obj - value to be removed
|
|
33
|
+
* @returns {boolean} always true as of v1.37.2
|
|
34
|
+
* @throws {TypeError} If `obj` was not a valid value
|
|
40
35
|
*/
|
|
41
36
|
def(unbound, 'remove', function(obj)
|
|
42
37
|
{
|
|
43
38
|
needObj(obj, true);
|
|
44
|
-
|
|
39
|
+
unboundObjects.delete(obj);
|
|
40
|
+
return true;
|
|
45
41
|
});
|
|
46
42
|
}
|