@lumjs/core 1.37.1 → 1.38.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.
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+
3
+ const def = require('../types/def');
4
+
5
+ /**
6
+ * Copy properties into a target object.
7
+ *
8
+ * Like Object.assign(), but it uses getOwnPropertyDescriptors()
9
+ * to get the properties to copy and type.def() to assign them.
10
+ *
11
+ * Basically a super simple, non-recursive replacement for my copyProps()
12
+ * and cp() functions that were overly complex and tried to do way too much.
13
+ *
14
+ * @param {object} target - The target object to copy properties into
15
+ * @param {...object} sources - Source objects to copy properties from
16
+ * @returns {object} the `target` object
17
+ *
18
+ * @alias module:@lumjs/core/obj.assignd
19
+ */
20
+ function assignd (target, ...sources)
21
+ {
22
+ for (const src of sources)
23
+ {
24
+ const descs = Object.getOwnPropertyDescriptors(src);
25
+ def(target, descs);
26
+ }
27
+ return target;
28
+ }
29
+
30
+ module.exports = assignd;
package/lib/obj/df.js ADDED
@@ -0,0 +1,213 @@
1
+ "use strict";
2
+
3
+ const {doesDescriptor,needObj,needType,lazy,B,TYPES} = require('../types');
4
+
5
+ const DEF_DESC = {configurable: true}
6
+ const DEF_OPTS = {autoDesc: true}
7
+
8
+ const cp = Object.assign;
9
+ const clone = (...args) => cp({}, ...args);
10
+ const dps = Object.defineProperties;
11
+
12
+ /**
13
+ * Handle populating descriptor objects for df() and family.
14
+ *
15
+ * Exported as `obj.df.descriptor`, but since jsdoc doesn't like
16
+ * properties attached to functions, I've listed it as internal.
17
+ *
18
+ * @param {object} desc - Descriptor object from df()
19
+ * @param {object} opts - Options from df();
20
+ *
21
+ * Will be checked for default descriptor options in the
22
+ * case where those options were not explicitly defined
23
+ * in the descriptor object.
24
+ *
25
+ * @param {boolean} [opts.configurable=true] configurable rule;
26
+ * this is the only option with a fallback default value.
27
+ *
28
+ * @param {boolean} [opts.enumerable] enumerable rule
29
+ *
30
+ * @param {boolean} [opts.writable] writable rule;
31
+ * only applies to data descriptors (ones with a `value` property),
32
+ * NOT to accessor descriptors.
33
+ *
34
+ * @returns {object} `desc`
35
+ * @alias module:@lumjs/core/obj~descriptor
36
+ */
37
+ function descriptor(desc, opts)
38
+ {
39
+ opts = clone(DEF_DESC, opts);
40
+
41
+ const dps = ['configurable', 'enumerable'];
42
+ if (desc.value) dps.push('writable');
43
+
44
+ for (const dp of dps)
45
+ {
46
+ if (typeof desc[dp] !== B && typeof opts[dp] === B)
47
+ {
48
+ desc[dp] = opts[dp];
49
+ }
50
+ }
51
+
52
+ return desc;
53
+ }
54
+
55
+ /**
56
+ * A replacement for `types.def()`, but MUCH simpler.
57
+ *
58
+ * Instead of one function where every argument has several different
59
+ * purposes depending on the type of value, there are now a bunch
60
+ * of functions, each one with a single purpose, and a single signature.
61
+ *
62
+ * This is the main one that all the rest use and is just a wrapper
63
+ * around Object.defineProperty() that simplifies its use a bit.
64
+ *
65
+ * @param {(object|function)} obj - Target to define property in
66
+ * @param {(string|symbol)} name - Property identifier
67
+ * @param {*} value - Value to assign
68
+ *
69
+ * If `opts.autoDesc` is `true` and this is an `object` that passes the
70
+ * {@link module:@lumjs/core/types.doesDescriptor} test, it will be
71
+ * used as the template descriptor to assign the property.
72
+ *
73
+ * In any other case, this will be used as the `value` property of
74
+ * a generated descriptor to be assigned.
75
+ *
76
+ * @param {object} [opts] Options
77
+ *
78
+ * @returns {object} `obj`
79
+ * @alias module:@lumjs/core/obj.df
80
+ */
81
+ function df(obj, name, value, opts)
82
+ {
83
+ const log = {obj,name,value,opts};
84
+ needObj(obj, {log, fun: true});
85
+ needType(TYPES.PROP, name, {log});
86
+
87
+ opts = clone(DEF_OPTS, opts);
88
+
89
+ const desc = descriptor(((opts.autoDesc && doesDescriptor(value))
90
+ ? value
91
+ : {value}), opts);
92
+
93
+ return Object.defineProperty(obj, name, desc);
94
+ }
95
+
96
+ // Sub-export
97
+ df(df, 'descriptor', descriptor);
98
+ df(df, 'lazy', lazy);
99
+
100
+ /**
101
+ * A wrapper around df() that defines multiple properties at once.
102
+ *
103
+ * @param {(object|function)} obj - Target to define property in
104
+ * @param {object} values
105
+ * All string-keyed enumerable properties will be passed to df()
106
+ * @param {object} [opts] See df() for details
107
+ *
108
+ * @returns {object} `obj`
109
+ * @alias module:@lumjs/core/obj.dfa
110
+ */
111
+ function dfa(obj, values, opts)
112
+ {
113
+ const log = {obj,values,opts};
114
+ needObj(values, {log});
115
+
116
+ for (const key in values)
117
+ {
118
+ df(obj, key, values[key], opts);
119
+ }
120
+
121
+ return obj;
122
+ }
123
+
124
+ /**
125
+ * Build magic closures to define properties using a chained syntax.
126
+ *
127
+ * This actually creates three closures, one around df(), another
128
+ * that wraps dfa(), and one that wraps the lazy() function.
129
+ * You can switch between them using magic properties.
130
+ *
131
+ * The closures when called will pass their arguments to the function
132
+ * they are wrapping, and in a bit of brain-melting recursion, the
133
+ * return value from each closure is the closure itself.
134
+ *
135
+ * Magic Properties that are added to both closures:
136
+ *
137
+ * - `one(name, value)` → A closure that wraps df()
138
+ * - `all(values)` → A closure that wraps dfa()
139
+ * - `update(opts)` → Update the options used by the closures.
140
+ * Uses Object.assign() to copy options from the specied object
141
+ * to the internal options object from the original dfc() call.
142
+ * This is a method call, NOT a closure function.
143
+ * - `opts` → The actual options object used by the closures.
144
+ * - `obj` → The target object used by the closures.
145
+ * - `next(obj)` → A wrapper method that will call dfc().
146
+ * When using this method, a *new set of closures* will be created,
147
+ * with the current options, but a new target object.
148
+ * If you use this in a chained statement, any calls after this
149
+ * will be using the new closures rather than the original ones.
150
+ *
151
+ * @param {(object|function)} obj - Target to define property in;
152
+ * available as the `obj` magic property on the closures.
153
+ *
154
+ * @param {object} [opts] Options - see df() for details;
155
+ * available as the `opts` magic property on the closures.
156
+ *
157
+ * @returns {function} The `one` closure.
158
+ */
159
+ function dfc(obj, opts={})
160
+ {
161
+ const fnOne = function (name, value)
162
+ {
163
+ df(obj, name, value, opts);
164
+ return fnOne;
165
+ }
166
+
167
+ const fnAll = function (values)
168
+ {
169
+ dfa(obj, values, opts);
170
+ return fnAll;
171
+ }
172
+
173
+ const fnLazy = function (name, initfunc)
174
+ {
175
+ lazy(obj, name, initfunc, opts);
176
+ return fnLazy;
177
+ }
178
+
179
+ const ctx =
180
+ {
181
+ obj: {value: obj},
182
+ opts: {value: opts},
183
+ one: {value: fnOne},
184
+ all: {value: fnAll},
185
+ update:
186
+ {
187
+ value()
188
+ {
189
+ cp(opts, ...arguments);
190
+ return this;
191
+ },
192
+ },
193
+ next:
194
+ {
195
+ value(newobj)
196
+ {
197
+ return dfc(newobj, opts);
198
+ },
199
+ },
200
+ }
201
+
202
+ dps(fnOne, ctx);
203
+ dps(fnAll, ctx);
204
+
205
+ return fnOne;
206
+ }
207
+
208
+
209
+
210
+ module.exports =
211
+ {
212
+ df, dfa, dfc, lazy,
213
+ }
package/lib/obj/index.js CHANGED
@@ -4,9 +4,11 @@
4
4
  */
5
5
 
6
6
  const apply = require('./apply');
7
+ const assignd = require('./assignd');
7
8
  const {copyAll,duplicateOne,duplicateAll} = require('./copyall');
8
9
  const copyProps = require('./copyprops');
9
10
  const {CLONE,clone,addClone,cloneIfLocked} = require('./clone');
11
+ const {df,dfa,dfc,lazy} = require('./df');
10
12
  const {flip, flipKeyVal, flipMap} = require('./flip');
11
13
  const {getMethods,signatureOf,MethodFilter} = require('./getmethods');
12
14
  const getProperty = require('./getproperty');
@@ -24,7 +26,8 @@ const
24
26
 
25
27
  module.exports =
26
28
  {
27
- cp, CLONE, clone, addClone, cloneIfLocked, lock, addLock,
29
+ assignd, cp, CLONE, clone, addClone, cloneIfLocked, lock, addLock,
30
+ df, dfa, dfc, lazy,
28
31
  mergeNested, syncNested, copyProps, copyAll, ns,
29
32
  getObjectPath, setObjectPath, getNamespace, setNamespace,
30
33
  getProperty, duplicateAll, duplicateOne, getMethods, signatureOf,
package/lib/types/def.js CHANGED
@@ -1,12 +1,20 @@
1
- // Thanks to CJS `require()` rules, recursive dependencies are possible.
2
- const unbound = require('./root').unbound;
3
- const {F, B} = require('./js');
4
- const {isObj, isNil, isProperty, doesDescriptor} = require('./basics');
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
  /**
8
8
  * A wrapper around `Object.defineProperty()` with added flair!
9
9
  *
10
+ * FUTURE DEPRECATION: When I release @lumjs/core 2.0, this function
11
+ * will be deprecated! It's gotten almost as convoluted as the old
12
+ * prop() method it replaced from my original Nano.js libraries.
13
+ * I have written new `obj.{df,dfa,dfc}` functions that will replace this
14
+ * function going forward. The related `types.lazy()` function will also
15
+ * be refactored to use the new functions, and moved to the `obj` module,
16
+ * although for the `2.x` lifetime an alias will remain in the `type` module.
17
+ *
10
18
  * @param {(object|function)} obj - The object to add a property to.
11
19
  *
12
20
  * @param {?(string|symbol|boolean|object)} name
@@ -73,8 +81,8 @@ const clone = (...args) => Object.assign({}, ...args);
73
81
  * directly, so any changes will be made on the original.
74
82
  *
75
83
  * @param {boolean} [opts.configurable=true] Default `configurable` value
76
- * @param {boolean} [opts.enumerable=false] Default `enumerable` value
77
- * @param {boolean} [opts.writable=false] Default `writable` value
84
+ * @param {boolean} [opts.enumerable] Default `enumerable` value
85
+ * @param {boolean} [opts.writable] Default `writable` value
78
86
  *
79
87
  * Only used with *data descriptors* and will be ignored with
80
88
  * *accessor* descriptors.
@@ -95,9 +103,10 @@ const clone = (...args) => Object.assign({}, ...args);
95
103
  */
96
104
  function def(obj, name, value, opts)
97
105
  {
98
- const isBound // Is this a 'bound' def function?
99
- = !unbound(this, true, true)
100
- && typeof this.bound === F;
106
+ const isBound
107
+ = isObj(this)
108
+ && typeof this.bound === F
109
+ && this.bound.$this === this;
101
110
 
102
111
  if (isNil(name) || typeof name === B)
103
112
  { // Binding of Isaac?
package/lib/types/lazy.js CHANGED
@@ -100,6 +100,12 @@ const {doesDescriptor} = require('./basics');
100
100
  *
101
101
  * This is an extension of the [def()]{@link module:@lumjs/core/types.def}
102
102
  * method, and indeed an alias called `def.lazy()` is also available.
103
+ *
104
+ * IMPORTANT: In version 2.x, this will be refactored to use the new
105
+ * [obj.df()]{@link module:@lumjs/core/obj.df} function that will replace
106
+ * def(). There's already an alias called `df.lazy()` available now.
107
+ * This will also be moved to the `obj` module, with an alias left
108
+ * in the `types` module for the duration of the 2.x lifecycle.
103
109
  *
104
110
  * @param {(object|function)} target - The object to add the property to.
105
111
  *
@@ -2,44 +2,103 @@ const {F, S, B} = require('./js');
2
2
  const {isType, isa} = require('./isa');
3
3
  const {isObj, isComplex} = require('./basics');
4
4
 
5
+ // Internal function used by both needObj and needType
6
+ function needOpts(opts, fn, bopt, ons)
7
+ {
8
+ if (isObj(opts))
9
+ {
10
+ if (opts.log)
11
+ { // Make a closure to handle the logging
12
+ const info = (opts.log === true) ? [opts]
13
+ : (Array.isArray(opts.log) ? opts.log : [opts.log]);
14
+ opts.$log = () => console.error(...info);
15
+ }
16
+ }
17
+ else if (typeof opts === S)
18
+ { // A message was passed.
19
+ opts =
20
+ {
21
+ msg: opts,
22
+ }
23
+ if (ons) ons(opts);
24
+ }
25
+ else if (typeof opts === B)
26
+ {
27
+ opts = {[bopt]: opts}
28
+ }
29
+ else
30
+ {
31
+ console.error('invalid options', {fn, opts});
32
+ opts = {};
33
+ }
34
+ return opts;
35
+ }
36
+
37
+ exports._needOptions = needOpts;
38
+
5
39
  /**
6
40
  * If a value is not an object, throw an error.
7
41
  *
8
42
  * @param {*} v - The value we're testing.
9
- * @param {(boolean|string)} [allowFunc=false] - Also accept `function`?
43
+ *
44
+ * @param {(object|boolean|string)} [opts] Options
45
+ *
46
+ * - If this is a string, it will be used as `opts.msg`,
47
+ * and `opts.fun` will be determined by the presence
48
+ * of the word 'function' (case-insensitive) in the message.
49
+ * - If this is a boolean, it will be used as `opts.fun`,
50
+ * and the default message will be used.
51
+ *
52
+ * @param {boolean} [opts.fun=false] Also accept `function`?
10
53
  *
11
54
  * By default this function uses `isObj()` to perform the
12
- * test. If `allowFunc` is `true` then it'll use `isComplex()` instead.
55
+ * test. If `opts.fun` is `true` then it'll use `isComplex()` instead.
56
+ *
57
+ * @param {(object|string|true)} [opts.log] Optional debugging information.
58
+ *
59
+ * This is a way to specify arguments to be sent to the
60
+ * console.error() method before the TypeError is thrown.
61
+ *
62
+ * If this is an `Array` object, it will be used as positional arguments.
13
63
  *
14
- * If this is a `string` then it'll be assigned to the `msg`
15
- * parameter, and `allowFunc` will be `true` if the word
16
- * `function` is found in the message, or `false` otherwise.
64
+ * If it is boolean `true`, the `opts` object itself will be used.
17
65
  *
18
- * @param {string} [msg] A custom error message.
66
+ * Any other value will be used as the sole argument.
19
67
  *
20
- * If not specified, a generic one will be used.
68
+ * @param {string} [opts.msg] The error message to use on failure.
69
+ *
70
+ * If not specified, a simple default message will be used.
71
+ *
72
+ * @param {?string} [msg=null] A positional version of `opts.msg`.
73
+ *
74
+ * Setting `opts.msg` as a named option will take precedence
75
+ * over this positional argument.
21
76
  *
22
77
  * @throws {TypeError} If the type check failed.
23
78
  * @alias module:@lumjs/core/types.needObj
24
79
  */
25
- function needObj (v, allowFunc=false, msg=null)
80
+ function needObj (v, opts={}, msg=null)
26
81
  {
27
- if (typeof allowFunc === S)
28
- { // A message was passed.
29
- msg = allowFunc;
30
- allowFunc = msg.toLowerCase().includes(F);
31
- }
82
+ opts = needOpts(opts, 'needObj', 'fun',
83
+ (o) => o.fun = o.msg.toLowerCase().includes(F));
32
84
 
33
- const ok = allowFunc ? isComplex(v) : isObj(v);
85
+ const ok = opts.fun ? isComplex(v) : isObj(v);
34
86
 
35
87
  if (!ok)
36
88
  { // Did not pass the test.
37
- if (typeof msg !== S)
89
+ if (typeof opts.msg === S)
90
+ {
91
+ msg = opts.msg;
92
+ }
93
+ else if (typeof msg !== S)
38
94
  { // Use a default message.
39
95
  msg = "Invalid object";
40
- if (allowFunc)
96
+ if (opts.fun)
41
97
  msg += " or function";
42
98
  }
99
+
100
+ if (opts.$log) opts.$log();
101
+
43
102
  throw new TypeError(msg);
44
103
  }
45
104
  }
@@ -51,28 +110,42 @@ exports.needObj = needObj;
51
110
  *
52
111
  * @param {string} type - The type name as per `isType()`.
53
112
  * @param {*} v - The value we're testing.
54
- * @param {string} [msg] A custom error message.
113
+ *
114
+ * @param {(object|string)} [opts] Options
115
+ *
116
+ * If this is a string, it will be used as `opts.msg`.
117
+ *
118
+ * @param {string} [opts.msg] See needObj() for details.
119
+ * @param {(object|string|true)} [opts.log] See needObj() for details.
120
+ *
121
+ * @param {?string} [msg=null] A positional version of `opts.msg`;
122
+ * handled the same was as needObj().
123
+ *
55
124
  * @throws {TypeError} If the type check failed.
56
125
  * @alias module:@lumjs/core/types.needType
57
126
  */
58
- function needType (type, v, msg, unused)
127
+ function needType (type, v, opts={}, msg=null)
59
128
  {
129
+ opts = needOpts(opts, 'needType', 'null');
130
+
131
+ if (typeof opts.null === B)
132
+ {
133
+ console.warn("needType(): 'allowNull' is no longer supported");
134
+ }
135
+
60
136
  if (!isType(type, v))
61
137
  {
62
- if (typeof msg === B)
138
+ if (typeof opts.msg === S)
63
139
  {
64
- console.warn("needType(): 'allowNull' is no longer supported");
65
- if (typeof unused === S)
66
- { // Compatibility with old code.
67
- msg = unused;
68
- }
140
+ msg = opts.msg;
69
141
  }
70
-
71
- if (typeof msg !== S)
142
+ else if (typeof msg !== S)
72
143
  { // Use a default message.
73
144
  msg = `Invalid ${type} value`;
74
145
  }
75
146
 
147
+ if (opts.$log) opts.$log();
148
+
76
149
  throw new TypeError(msg);
77
150
  }
78
151
  }
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 = typeof globalThis !== U ? globalThis
15
- : typeof global !== U ? global
16
- : typeof self !== U ? self
17
- : typeof window !== U ? window
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 list of objects to be considered unbound globally.
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
- * Always considers `null` and `undefined` as unbound.
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, rootIsUnbound=true, areUnbound=false)
60
+ function unbound(whatIsThis, opts=true, list)
39
61
  {
40
- if (areUnbound === true)
41
- { // If areUnbound is true, we use the unboundObjects
42
- areUnbound = unboundObjects;
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 (rootIsUnbound && whatIsThis === root) return true;
47
- if (isArray(areUnbound) && areUnbound.includes(whatIsThis)) return true;
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 magic methods to the `unbound` function.
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
- * @function
15
- * @param {(object|function)} obj - The object to be considered unbound.
16
- * @returns {boolean} Will be `false` if `obj` is already unbound.
17
- * @throws {TypeError} If `obj` was neither an `object` nor a `function`.
18
- * @name module:@lumjs/core/types.unbound.add
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 (unbound(obj, true, true))
24
- { // Item is already unbound.
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
- * @function
36
- * @param {(object|function)} obj - The object to be removed.
37
- * @returns {boolean} Will be `false` if the item was not in the list.
38
- * @throws {TypeError} If `obj` was neither an `object` nor a `function`.
39
- * @name module:@lumjs/core/types.unbound.remove
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
- return (removeFromArray(unboundObjects, obj) > 0);
39
+ unboundObjects.delete(obj);
40
+ return true;
45
41
  });
46
42
  }
@@ -1,2 +1,3 @@
1
1
  // Private storage, not exported outside the package.
2
- module.exports = [];
2
+ // TODO: remove this in 2.0
3
+ module.exports = new Set();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lumjs/core",
3
- "version": "1.37.1",
3
+ "version": "1.38.0",
4
4
  "main": "lib/index.js",
5
5
  "exports":
6
6
  {
@@ -17,6 +17,7 @@
17
17
  "./modules": "./lib/modules.js",
18
18
  "./obj": "./lib/obj/index.js",
19
19
  "./obj/cp": "./lib/obj/cp.js",
20
+ "./obj/df": "./lib/obj/df.js",
20
21
  "./observable": "./lib/observable.js",
21
22
  "./opt": "./lib/opt/index.js",
22
23
  "./opt/args": "./lib/opt/args.js",