@lumjs/core 1.38.1 → 1.38.3

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.
@@ -4,7 +4,7 @@
4
4
  * @module @lumjs/core/arrays
5
5
  */
6
6
 
7
- const {lazy} = require('../types');
7
+ const {lazy} = require('../obj/df');
8
8
  const {powerset, random} = require('./util');
9
9
 
10
10
  // Utils.
@@ -0,0 +1,139 @@
1
+ 'use strict';
2
+
3
+ const {F, isObj, isPlainObject} = require('../types/basics');
4
+ const Enum = require('../enum');
5
+ const TypedArray = Object.getPrototypeOf(Int8Array);
6
+ const CT = Enum(['GT','LT','ALL'], {flags: true});
7
+
8
+ /**
9
+ * An Enum object with bitwise flags for the `opts.convert` argument
10
+ * of the makeType() function.
11
+ *
12
+ * @name module:@lumjs/core/arrays.ConvertType
13
+ * @type {object}
14
+ * @prop {number} GT - Convert any values which have a larger bytes per
15
+ * element size than the `opts.type` TypedArray class.
16
+ * @prop {number} LT - Convert any values which have a smaller bytes per
17
+ * element size than the `opts.type` TypedArray class.
18
+ * @prop {number} ALL - Convert all values that aren't already instances
19
+ * of the `opts.type` class.
20
+ * Note: if you use this flag, then the other flags are ignored!
21
+ *
22
+ */
23
+
24
+ /**
25
+ * Build a new TypedArray with multiple input values.
26
+ *
27
+ * @alias module:@lumjs/core/arrays.makeTyped
28
+ *
29
+ * @param {(object|function)} [opts] - Options.
30
+ *
31
+ * If this is a `function` then it is assumed to be the `opts.type` value.
32
+ *
33
+ * If this is anything other than a _plain object_ (i.e. it was created
34
+ * with a class constructor rather than `{}` literal syntax), then it will
35
+ * be considered an element of the `inValues` parameter instead of options.
36
+ *
37
+ * @param {function} [opts.type=Uint8Array] TypedArray class to return.
38
+ * @param {number} [opts.convert=0] Convert TypedArrays before merge?
39
+ *
40
+ * By default all TypedArray objects passed (or created by the TextEncoder)
41
+ * will be added to the new TypedArray as-is, which may result in data
42
+ * corruption if the unit byte-size of the source TypeArray is larger
43
+ * than the newly created TypeArray. If the unit byte-size of the requested
44
+ * type is the same or larger than any input sources, then it doesn't matter.
45
+ *
46
+ * You can however convert all source TypedArray objects to the `opts.type`
47
+ * class using an intermediary ArrayBuffer, and choose the criteria for
48
+ * the conversion by specifying various bitwise flags in this option.
49
+ *
50
+ * Use the properties of the `ConvertType` Enum as the flag values.
51
+ *
52
+ * e.g.: `makeTyped({convert: ConvertType.GT | ConvertType.LT}, ...values);`
53
+ *
54
+ * WARNING: The type conversion methodology is not the greatest and doesn't
55
+ * cover every possible issue, so don't be surprised if you end up with
56
+ * corrupted data (or you have an Exception thrown) when mixing different
57
+ * TypeArray classes. If at all possible, only merge values of the same type.
58
+ *
59
+ * @param {...mixed} inValues - Values to be added to the new TypeArray.
60
+ *
61
+ * If the value is considered a _View_ (i.e. a TypedArray or DataView),
62
+ * it will be used directly.
63
+ *
64
+ * Any other kind of `object` will be serialized using JSON and then
65
+ * encoded into a Uint8Array using TextEncoder.
66
+ *
67
+ * Any other type of value will be encoded using TextEncoder, which will
68
+ * call `value.toString()` on any non-string values before encoding.
69
+ *
70
+ * @returns {TypedArray}
71
+ *
72
+ * @throws {TypeError} If `opts.type` is not a TypedArray constructor.
73
+ * @throws {RangeError} If the byte length of any of the `inValues`
74
+ * is not an integral multiple of the `opts.type` bytes per element size.
75
+ *
76
+ */
77
+ function makeTyped(opts, ...inValues)
78
+ {
79
+ if (typeof opts === F)
80
+ {
81
+ opts = {type: opts};
82
+ }
83
+ else if (isPlainObject(opts))
84
+ {
85
+ inValues.unshift(opts);
86
+ opts = {};
87
+ }
88
+
89
+ let wantType = opts.type ?? Uint8Array;
90
+ let convert = opts.convert ?? 0;
91
+
92
+ if (typeof wantType !== F || !TypedArray.isPrototypeOf(wantType))
93
+ {
94
+ console.error({wantType, opts, inValues});
95
+ throw new TypeError("Invalid TypedArray class");
96
+ }
97
+
98
+ let fullLen = 0;
99
+ let tenc = new TextEncoder();
100
+ let wantSize = wantType.BYTES_PER_ELEMENT;
101
+
102
+ let mergeValues = inValues.map(value =>
103
+ {
104
+ if (!ArrayBuffer.isView(value))
105
+ {
106
+ if (isObj(value))
107
+ {
108
+ value = JSON.stringify(value);
109
+ }
110
+ value = tenc.encode(value);
111
+ }
112
+
113
+ let valSize = value.constructor.BYTES_PER_ELEMENT;
114
+
115
+ if ( ((convert & CT.ALL) && !(value instanceof wantType))
116
+ || ((convert & CT.GT) && valSize > wantSize)
117
+ || ((convert & CT.LT) && valSize < wantSize))
118
+ { // Convert value to our wanted type
119
+ value = new wantType(value.buffer);
120
+ }
121
+
122
+ fullLen += value.byteLength;
123
+
124
+ return value;
125
+ });
126
+
127
+ let output = new wantType(new ArrayBuffer(fullLen));
128
+ let offset = 0;
129
+
130
+ for (let value of mergeValues)
131
+ {
132
+ output.set(value, offset);
133
+ offset += value.length;
134
+ }
135
+
136
+ return output;
137
+ }
138
+
139
+ module.exports = {makeTyped, ConvertType: CT, TypedArray}
@@ -1,93 +1,126 @@
1
1
  /**
2
2
  * A simplistic event registration and dispatch module.
3
- *
4
- * Designed to be a replacement for the `observable` API which started
5
- * out simple enough (when I forked it from `riot.js`), but has since
6
- * grown into a big mess with many unusual and unexpected behaviours.
7
- *
8
- * So this has been designed to work with a cleaner, more consistent,
9
- * yet extremely flexible event model.
10
- *
11
3
  * @module @lumjs/core/events
4
+ * @deprecated Moved to @lumjs/events and @lumjs/events-observable packages.
12
5
  */
6
+ 'use strict';
13
7
 
14
- const lazy = require('../types/lazy');
8
+ const Events = require('@lumjs/events');
9
+ const {lazy} = require('../obj/df');
15
10
 
16
- exports = module.exports =
11
+ exports = module.exports = Object.assign(
17
12
  {
18
- Registry: require('./registry'),
19
- Listener: require('./listener'),
20
- Event: require('./event'),
21
-
22
- /**
23
- * A shortcut function to create a new Registry instance.
24
- * All arguments are passed to the Registry constructor.
25
- * @param {(object|module:@lumjs/core/events~GetTargets)} targets
26
- * @param {object} [opts]
27
- * @returns {module:@lumjs/core/events.Registry}
28
- */
29
- register(targets, opts)
30
- {
31
- return new exports.Registry(targets, opts);
32
- },
33
-
34
- /**
35
- * Create a registry for a single target object, then return the target.
36
- * @param {object} target
37
- * @param {object} [opts]
38
- * @returns {object} `target`
39
- */
40
- extend(target, opts)
41
- {
42
- exports.register([target], opts);
43
- return target;
44
- },
45
-
46
13
  /**
47
14
  * Apply the compatibility version of the observable API;
48
15
  * will load the events/observable sub-module on demand.
16
+ * @name module:@lumjs/core/events.observable
49
17
  * @param {object} target
50
18
  * @param {object} [opts]
51
19
  * @returns {object} `target`
52
- * @see module:@lumjs/core/events/observable.makeObservable
20
+ * @deprecated Use the @lumjs/events-observable package.
53
21
  */
54
22
  observable(target, opts)
55
23
  {
56
24
  const {makeObservable} = exports.Observable;
57
25
  return makeObservable(target, opts);
58
26
  },
27
+ }, Events);
59
28
 
60
- /**
61
- * See if an object has a known trigger method.
62
- *
63
- * Currently will look for one of:
64
- *
65
- * - `emit`
66
- * - `trigger`
67
- *
68
- * @param {object} obj - Object we want to find a trigger method on
69
- *
70
- * @returns {?string} The name of the method found,
71
- * or null if none found.
72
- */
73
- hasTrigger(obj)
74
- {
75
- for (const trigger of exports.KNOWN_TRIGGERS)
76
- {
77
- if (typeof obj[trigger] === F)
78
- {
79
- return trigger;
80
- }
81
- }
82
-
83
- return null;
84
- },
29
+ lazy(exports, 'Observable', () => require('./observable'));
85
30
 
86
- /**
87
- * The list of known trigger method names for `hasTrigger()`
88
- */
89
- KNOWN_TRIGGERS: ['emit','trigger'],
31
+ /**
32
+ * An Event object to emit to handler callbacks.
33
+ *
34
+ * @class module:@lumjs/core/events.Event
35
+ *
36
+ * @prop {module:@lumjs/core/events.Listener} eventListener
37
+ * The event Listener instance this event was emitted from.
38
+ * @prop {(string|Symbol)} type - The event type that was triggered.
39
+ * @prop {string} name - The event name that was triggered;
40
+ * if `type` is a string this will be the same value,
41
+ * for a Symbol type this will be the `type.description` value.
42
+ * @prop {object} target - Target object for this event.
43
+ * @prop {Array} args - Arguments passed to `emit()`
44
+ * @prop {object} options - Composes options from the
45
+ * Registry and the Listener. Listener options take priority.
46
+ * @prop {?object} data
47
+ * If `args[0]` is any kind of `object` other than another Event
48
+ * instance, it will be used as the `data` property.
49
+ * If `args[0]` is not an `object`, this property will be `null`.
50
+ * @prop {module:@lumjs/core/events.Event} origEvent
51
+ * Unless `this.prevEvent` is set, this should always be
52
+ * a reference to `this` instance itself.
53
+ * @prop {?module:@lumjs/core/events.Event} prevEvent
54
+ * If `args[0]` is another Event instance this property
55
+ * will be set with its value, as well as the following
56
+ * changes to the default behavior:
57
+ *
58
+ * - `this.data` will be set to `prevEvent.data`.
59
+ * - `this.origEvent` will be set to `prevEvent.origEvent`
60
+ *
61
+ * @prop {module:@lumjs/core/events~Status} emitStatus
62
+ *
63
+ * @deprecated Moved to @lumjs/events package.
64
+ */
90
65
 
91
- }
66
+ /**
67
+ * An Event Listener instance used by a Registry
68
+ *
69
+ * Used internally by the Registry class, there's likely very few
70
+ * reasons you'd want to call any methods on this manually.
71
+ *
72
+ * @class module:@lumjs/core/events.Listener
73
+ *
74
+ * @prop {module:@lumjs/core/events.Registry} registry
75
+ * The Registry instance this Listener belongs to.
76
+ * @prop {(function|object)} handler - Event handler callback
77
+ * @prop {Set} eventTypes - A set of all event types handled by this
78
+ * @prop {Set} eventNames - Alias to `eventTypes`
79
+ * @prop {object} options - Options specific to this listener.
80
+ *
81
+ * @deprecated Moved to @lumjs/events package.
82
+ */
92
83
 
93
- lazy(exports, 'Observable', () => require('./observable'));
84
+ /**
85
+ * A class that handles events for target objects
86
+ *
87
+ * @class module:@lumjs/core/events.Registry
88
+ *
89
+ * @prop {module:@lumjs/core/events~GetTargets} getTargets
90
+ * A constructor-assigned callback method that returns a set of targets.
91
+ * @prop {object} options - Registry-level options
92
+ * @prop {Set.<module:@lumjs/core/events.Listener>} allListeners
93
+ * All registered event listeners
94
+ * @prop {Map.<string,Set.<module:@lumjs/core/events.Listener>>} listenersFor
95
+ * Each key is a single event name, and the value is a Set of
96
+ * listener objects that handle that event.
97
+ *
98
+ * @deprecated Moved to @lumjs/events package.
99
+ */
100
+
101
+ /**
102
+ * A shortcut function to create a new Registry instance.
103
+ * All arguments are passed to the Registry constructor.
104
+ * @function module:@lumjs/core/events.register
105
+ * @param {(object|module:@lumjs/core/events~GetTargets)} targets
106
+ * @param {object} [opts]
107
+ * @returns {object} A @lumjs/events.Registry instance.
108
+ * @deprecated Moved to @lumjs/events package.
109
+ */
110
+
111
+ /**
112
+ * Create a registry for a single target object, then return the target.
113
+ * @function module:@lumjs/core/events.extend
114
+ * @param {object} target
115
+ * @param {object} [opts]
116
+ * @returns {object} `target`
117
+ * @deprecated Moved to @lumjs/events package.
118
+ */
119
+
120
+ /**
121
+ * See if an object has a known trigger method.
122
+ * @function module:@lumjs/core/events.hasTrigger
123
+ * @param {object} obj - Object we want to find a trigger method on
124
+ * @returns {?string} The name of the method found
125
+ * @deprecated Moved to @lumjs/events package.
126
+ */
@@ -1,243 +1,8 @@
1
1
  /**
2
2
  * Observable Compatibility API
3
3
  * @module @lumjs/core/events/observable
4
+ * @deprecated Moved to @lumjs/events-observable package.
4
5
  */
5
6
  "use strict";
6
7
 
7
- const {B,F,S,def,isComplex,TYPES} = require('../types');
8
- const lock = Object.freeze;
9
- const copy = Object.assign;
10
- const Registry = require('./registry');
11
-
12
- const ISOB = 'isObservable';
13
-
14
- const OBS_EXTENDS =
15
- {
16
- registry: '$events',
17
- listen: 'on',
18
- emit: 'trigger',
19
- remove: 'off',
20
- once: 'one',
21
- }
22
-
23
- const OBS_OPTIONS =
24
- {
25
- wrapargs: false,
26
- wrapthis: false,
27
- wraplock: true,
28
- wrapsetup: null,
29
- addme: null,
30
- // addname: !(wrapargs || wrapthis)
31
- // addis: (wrapargs || wrapthis)
32
- }
33
-
34
- /**
35
- * A version of the observable API using the events module.
36
- *
37
- * It's obviously not going to be 100% identical due to
38
- * the very different nature of the backend engine, but it'll
39
- * try its best to make existing code work.
40
- *
41
- * A few obscure features that I don't think are particularly
42
- * important and won't affect *most* exising uses will be dropped.
43
- *
44
- * @param {(object|function)} el - The target to add observable API to.
45
- *
46
- * @param {object} [oo]
47
- * {@link module:@lumjs/core/observable Observable} options
48
- *
49
- * @param {boolean} [oo.addwrap] If this is `true`,
50
- * and `oo.wrapargs` is `false`, then the `event` object
51
- * will be appended to the arguments sent to the handler.
52
- *
53
- * The default value is: `!oo.wrapthis`
54
- *
55
- * @param {object} [ro]
56
- * {@link module:@lumjs/core/events.Registry Registry} options;
57
- *
58
- * The `setupEvent` and `setupListener` options cannot be specified,
59
- * as the versions from this module will always be used.
60
- *
61
- * The `extend` defaults are changed to match those used
62
- * by the observable API (`on`,`trigger`,`off`,`one`),
63
- * and `extend.registry` is set to `$events` by default.
64
- *
65
- * Setting the `extend` option to `false` will have no effect
66
- * in this implementation.
67
- *
68
- * @param {boolean} [wantReg=false] Return the Registry?
69
- * @returns {object} normally `el`, unless `wantReg` was `true`
70
- * @see module:@lumjs/core/observable~API
71
- * @alias module:@lumjs/core/events/observable.makeObservable
72
- */
73
- function makeObservable(el, oo, ro, wantReg=false)
74
- {
75
- if (!isComplex(el))
76
- {
77
- throw new TypeError("el was not an object or function");
78
- }
79
-
80
- ro = copy({}, ro);
81
- ro.extend = copy({}, OBS_EXTENDS, ro.extend);
82
- ro.setupEvent = setupEvent;
83
- ro.setupListener = setupListener;
84
- oo = ro.observable = copy({}, OBS_OPTIONS, oo);
85
-
86
- let wrapped = (oo.wrapargs || oo.wrapthis);
87
- if (!wrapped && typeof oo.wrapsetup === F)
88
- {
89
- wrapped = oo.wrapargs = true;
90
- }
91
-
92
- if (typeof oo.wildcard === S)
93
- { // oo.wildcard takes precedence
94
- ro.wildcard = oo.wildcard;
95
- }
96
-
97
- const setIf = (opt, get) =>
98
- {
99
- if (typeof oo[opt] !== B)
100
- {
101
- oo[opt] = get();
102
- }
103
- }
104
-
105
- setIf('addname', () => !wrapped);
106
- setIf('addis', () => wrapped);
107
- setIf('addwrap', () => !oo.wrapthis);
108
-
109
- const reg = new Registry([el], ro);
110
-
111
- if (oo.addis)
112
- {
113
- def(el, ISOB, lock({event: false, target: true}));
114
- }
115
-
116
- if (typeof oo.addme === S)
117
- {
118
- def(el, oo.addme, function(el2, oo2, ro2)
119
- {
120
- return makeObservable(el2,
121
- copy({}, oo, oo2),
122
- copy({}, ro, ro2)
123
- );
124
- });
125
- }
126
-
127
- return wantReg ? reg : el;
128
- }
129
-
130
- /**
131
- * Event setup for observable compatibility
132
- * @type {module:@lumjs/core/events~SetupEvent}
133
- * @alias module:@lumjs/core/events/observable.setupEvent
134
- */
135
- function setupEvent(ev)
136
- {
137
- const ro = this.registry.options;
138
- const oo = ro.observable;
139
- ev.wildcard = this.eventNames.has(ro.wildcard);
140
- ev.self = ev.target;
141
- ev.type = ev.name;
142
- def(ev, ISOB, lock({event: true, target: false}));
143
-
144
- if (typeof oo.wrapsetup === F)
145
- {
146
- oo.wrapsetup.call(ev.target, ev);
147
- }
148
-
149
- if (oo.wraplock)
150
- {
151
- lock(ev);
152
- }
153
- }
154
-
155
- /**
156
- * Listener setup for observable compatibility
157
- * @type {module:@lumjs/core/events~SetupListener}
158
- * @alias module:@lumjs/core/events/observable.setupListener
159
- */
160
- function setupListener(ln)
161
- {
162
- const oo = this.options.observable;
163
- const oh = ln.observableHandler = ln.handler;
164
- const go = (ev, args) =>
165
- {
166
- if (typeof oh === F)
167
- {
168
- const thisTarget = oo.wrapthis ? ev : ev.target;
169
- oh.apply(thisTarget, args);
170
- }
171
- else
172
- {
173
- oh.handleEvent(...args);
174
- }
175
- }
176
-
177
- if (!oo.wrapargs)
178
- { // Not wrapping args, we need to wrap the handler.
179
- const ec = ln.eventNames.size;
180
- ln.handler = function(ev)
181
- {
182
- const args = ev.args;
183
- if (ec > 1 && oo.addname)
184
- {
185
- args.unshift(ev.name);
186
- }
187
- if (oo.addwrap)
188
- {
189
- args.push(ev);
190
- }
191
-
192
- go(ev, args);
193
- }
194
- }
195
- else if (oo.wrapthis)
196
- { // Both wrapargs and wrapthis are in use, woah!
197
- ln.handler = function(ev)
198
- {
199
- go(ev, [ev]);
200
- }
201
- }
202
- }
203
-
204
- /**
205
- * See if a value appears to implement the observable API.
206
- *
207
- * This is a simple function that relies on duck-typing,
208
- * and only looks for `trigger` and `on` methods.
209
- *
210
- * @param {(object|function)} obj - Value to check for observable API
211
- * @returns {boolean}
212
- * @alias module:@lumjs/core/events/observable.isObservable
213
- */
214
- function isObservable(obj)
215
- {
216
- return (isComplex(obj)
217
- && typeof obj.trigger === F
218
- && typeof obj.on === F);
219
- }
220
-
221
- // Undocumented alias for the sake of compatibility.
222
- def(makeObservable, 'is', isObservable);
223
-
224
- /**
225
- * Does a value implement the Observable interface?
226
- * @name module:@lumjs/core/types.doesObservable
227
- * @function
228
- * @param {*} v - The expected object/function to test.
229
- * @returns {boolean}
230
- * @see module:@lumjs/core/events/observable.isObservable
231
- */
232
-
233
- /**
234
- * Extension type for the {@link module:@lumjs/core/observable~API} interface.
235
- * @memberof module:@lumjs/core/types.TYPES
236
- * @member {string} OBSERV - Implements the *Observable* interface.
237
- */
238
- TYPES.add('OBSERV', 'observable', isObservable, 'doesObservable');
239
-
240
- module.exports =
241
- {
242
- makeObservable, setupEvent, setupListener, isObservable,
243
- }
8
+ module.exports = require('@lumjs/events-observable');
package/lib/index.js CHANGED
@@ -12,33 +12,34 @@
12
12
 
13
13
  /// see also: `docs/src/index.js`
14
14
 
15
+ const types = require('./types');
16
+ const {df,lazy} = require('./obj/df');
17
+
15
18
  // Get a bunch of properties from a submodule.
16
19
  function from(submod)
17
20
  {
18
21
  for (const key in submod)
19
22
  {
20
- def(exports, key, submod[key]);
23
+ df(exports, key, submod[key]);
21
24
  }
22
25
  }
23
26
 
24
- const types = require('./types');
25
- const {def,lazy} = types;
26
-
27
- def(exports, 'types', types);
28
- def(exports, 'def', def);
29
- def(exports, 'lazy', lazy);
27
+ df(exports, 'types', types);
28
+ df(exports, 'def', types.def);
29
+ df(exports, 'df', df);
30
+ df(exports, 'lazy', lazy);
30
31
 
31
- def(exports, 'context', require('./context'));
32
- def(exports, 'state', {value: require('./state')});
32
+ df(exports, 'context', require('./context'));
33
+ df(exports, 'state', {value: require('./state')});
33
34
 
34
35
  // ObjectID stuff is imported directly without registering a sub-module.
35
36
  from(require('./objectid'));
36
37
 
37
38
  // These are exported directly, but a meta sub-module also exists.
38
- // Unlike most sub-modules there is no `meta` property in the main library.
39
39
  const meta = require('./meta');
40
40
  from(meta);
41
- def(exports, 'AbstractClass',
41
+ df(exports, 'meta', meta);
42
+ df(exports, 'AbstractClass',
42
43
  {
43
44
  get() { return meta.AbstractClass; }
44
45
  });
@@ -50,7 +51,7 @@ lazy(exports, 'flags', () => require('./flags'));
50
51
  lazy(exports, 'obj', () => require('./obj'));
51
52
  lazy(exports, 'console', () => require('./console'));
52
53
  lazy(exports, 'traits', () => require('./traits'));
53
- lazy(exports, 'opt', () => require('./opt'), {def:{autoDesc: false}});
54
+ lazy(exports, 'opt', () => require('./opt'), {df:{autoDesc: false}});
54
55
  lazy(exports, 'Enum', () => require('./enum'));
55
56
  lazy(exports, 'observable', () => require('./observable'));
56
57
  lazy(exports, 'events', () => require('./events'));
package/lib/meta.js CHANGED
@@ -191,7 +191,7 @@ function wrapDepr(obj,prop,spec)
191
191
  if (typeof spec.get !== F)
192
192
  throw new TypeError("invalid init");
193
193
 
194
- return def(obj, prop,
194
+ return df(obj, prop,
195
195
  {
196
196
  get: () =>
197
197
  deprecated(spec.dep??prop, spec.rep, spec.get())
@@ -201,6 +201,6 @@ function wrapDepr(obj,prop,spec)
201
201
  exports.wrapDepr = wrapDepr;
202
202
 
203
203
  // This is near the bottom, but before any calls to wrapDepr.
204
- const def = require('./types/def');
204
+ const {df} = require('./obj/df');
205
205
 
206
206
  wrapDepr(exports, 'AbstractClass', () => require('./old/abstractclass'));