@lumjs/core 1.0.0-beta.2 → 1.0.0-beta.4
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/README.md +7 -2
- package/TODO.md +18 -5
- package/docs/changelogs/1.0-beta.md +69 -0
- package/jsdoc.json +33 -0
- package/lib/arrays.js +66 -0
- package/lib/context.js +4 -2
- package/lib/enum.js +6 -3
- package/lib/index.js +10 -20
- package/lib/lazy.js +29 -33
- package/lib/meta.js +29 -2
- package/lib/modules.js +16 -4
- package/lib/obj/clone.js +148 -131
- package/lib/obj/index.js +8 -3
- package/lib/obj/lock.js +3 -4
- package/lib/observable.js +3 -2
- package/lib/types/basics.js +142 -0
- package/lib/types/def.js +180 -0
- package/lib/types/index.js +38 -0
- package/lib/types/isa.js +193 -0
- package/lib/types/js.js +12 -0
- package/lib/types/needs.js +112 -0
- package/lib/types/root.js +94 -0
- package/lib/types/typelist.js +104 -0
- package/package.json +6 -1
- package/test/arrays.js +19 -0
- package/test/meta.js +17 -0
- package/test/types.js +5 -11
- package/CHANGELOG.md +0 -25
- package/lib/descriptors.js +0 -243
- package/lib/prop.js +0 -170
- package/lib/types.js +0 -545
package/lib/obj/clone.js
CHANGED
|
@@ -1,21 +1,37 @@
|
|
|
1
1
|
// Import *most* required bits here.
|
|
2
2
|
const {B,N,F, isObj, isComplex, def} = require('../types');
|
|
3
3
|
const Enum = require('../enum');
|
|
4
|
-
const {getDescriptor, DESC} = require('../descriptors');
|
|
5
4
|
const copyProps = require('./copyprops');
|
|
6
5
|
|
|
7
6
|
/**
|
|
8
7
|
* An enum of supported modes for the `clone` method.
|
|
9
8
|
*
|
|
10
|
-
*
|
|
11
|
-
* `
|
|
12
|
-
*
|
|
13
|
-
*
|
|
9
|
+
* - **P** = All properties. If unchecked, enumerable properties only.
|
|
10
|
+
* - **A** = Uses `Array.slice()` shortcut for shallow Array cloning.
|
|
11
|
+
* - **R** = Recursive (deep) cloning of nested objects.
|
|
12
|
+
*
|
|
13
|
+
* | Mode | P | A | R | Notes |
|
|
14
|
+
* | ---- | - | - | - | ----- |
|
|
15
|
+
* | `CLONE.DEF` | × | ✓ | × | Default mode for cloning functions. |
|
|
16
|
+
* | `CLONE.DEEP` | × | × | ✓ | |
|
|
17
|
+
* | `CLONE.FULL` | ✓ | ✓ | × | |
|
|
18
|
+
* | `CLONE.ALL` | ✓ | × | × | |
|
|
19
|
+
* | `CLONE.ENTIRE` | ✓ | × | ✓ | |
|
|
20
|
+
* | `CLONE.JSON` | × | × | ✓ | Uses JSON, so no `function` or `symbol` support. |
|
|
14
21
|
*
|
|
15
22
|
*/
|
|
16
|
-
const CLONE = Enum(['DEF','
|
|
23
|
+
const CLONE = Enum(['DEF','FULL','ALL','DEEP','ENTIRE','JSON']);
|
|
17
24
|
|
|
18
25
|
exports.CLONE = CLONE;
|
|
26
|
+
|
|
27
|
+
// A list of modes that should use the array.slice shallow shortcut.
|
|
28
|
+
const SLICE_ARRAYS = [CLONE.DEF, CLONE.FULL];
|
|
29
|
+
|
|
30
|
+
// A list of modes that should get *all* properties.
|
|
31
|
+
const ALL_PROPS = [CLONE.FULL, CLONE.ALL, CLONE.DEEP];
|
|
32
|
+
|
|
33
|
+
// A list of modes that should do recursive cloning of objects.
|
|
34
|
+
const RECURSIVE = [CLONE.DEEP, CLONE.ENTIRE];
|
|
19
35
|
|
|
20
36
|
/**
|
|
21
37
|
* Clone an object or function.
|
|
@@ -23,10 +39,7 @@ const copyProps = require('./copyprops');
|
|
|
23
39
|
* @param {object|function} obj - The object we want to clone.
|
|
24
40
|
* @param {object} [opts={}] - Options for the cloning process.
|
|
25
41
|
*
|
|
26
|
-
* @param {number} [opts.mode=
|
|
27
|
-
*
|
|
28
|
-
* For any mode that doesn't saay "Arrays included", Array objects will
|
|
29
|
-
* use a shortcut technique of `obj.slice()` to create the clone.
|
|
42
|
+
* @param {number} [opts.mode=CLONE.DEF] - One of the `CLONE.*` enum values.
|
|
30
43
|
*
|
|
31
44
|
* Note: The `CLONE` enum is also aliased as `clone.MODE` as an alternative.
|
|
32
45
|
*
|
|
@@ -46,88 +59,92 @@ const copyProps = require('./copyprops');
|
|
|
46
59
|
*
|
|
47
60
|
* @return {object} - The clone of the object.
|
|
48
61
|
*/
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
62
|
+
function clone(obj, opts={})
|
|
63
|
+
{
|
|
64
|
+
//console.debug("Lum~clone()", obj, opts);
|
|
65
|
+
|
|
66
|
+
if (!isComplex(obj))
|
|
67
|
+
{ // Doesn't need cloning.
|
|
68
|
+
//console.debug("no cloning required");
|
|
69
|
+
return obj;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!isObj(opts))
|
|
73
|
+
{ // Opts has to be a valid object.
|
|
74
|
+
opts = {};
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const mode = typeof opts.mode === N ? opts.mode : CLONE.DEF;
|
|
78
|
+
const reclone = typeof opts.addClone === B ? opts.addClone : false;
|
|
79
|
+
const relock = typeof opts.addLock === B ? opts.addLock : false;
|
|
80
|
+
|
|
81
|
+
let copy;
|
|
82
|
+
|
|
83
|
+
//console.debug("::clone", {mode, reclone, relock});
|
|
84
|
+
|
|
85
|
+
if (mode === CLONE.JSON)
|
|
86
|
+
{ // Deep clone enumerable properties using JSON trickery.
|
|
87
|
+
//console.debug("::clone using JSON cloning");
|
|
88
|
+
copy = JSON.parse(JSON.stringify(obj));
|
|
89
|
+
}
|
|
90
|
+
else if (Array.isArray(obj) && SLICE_ARRAYS.includes(mode))
|
|
91
|
+
{ // Make a shallow copy using slice.
|
|
92
|
+
//console.debug("::clone using Array.slice()");
|
|
93
|
+
copy = obj.slice();
|
|
94
|
+
}
|
|
95
|
+
else
|
|
96
|
+
{ // Build a clone using a simple loop.
|
|
97
|
+
//console.debug("::clone using simple loop");
|
|
98
|
+
copy = {};
|
|
99
|
+
|
|
100
|
+
let props;
|
|
101
|
+
if (ALL_PROPS.includes(mode))
|
|
102
|
+
{ // All object properties.
|
|
103
|
+
//console.debug("::clone getting all properties");
|
|
104
|
+
props = Object.getOwnPropertyNames(obj);
|
|
105
|
+
}
|
|
106
|
+
else
|
|
107
|
+
{ // Enumerable properties.
|
|
108
|
+
//console.debug("::clone getting enumerable properties");
|
|
109
|
+
props = Object.keys(obj);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
//console.debug("::clone[props]", props);
|
|
113
|
+
|
|
114
|
+
for (const prop of props)
|
|
115
|
+
{
|
|
116
|
+
let val = obj[prop];
|
|
117
|
+
if (isObj(val) && RECURSIVE.includes(mode))
|
|
118
|
+
{ // Deep cloning.
|
|
119
|
+
val = clone(val, {mode});
|
|
120
|
+
}
|
|
121
|
+
copy[prop] = val;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (reclone)
|
|
126
|
+
{ // Add the clone() method to the clone, with the passed opts as defaults.
|
|
127
|
+
addClone(copy, opts);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (opts.copy)
|
|
131
|
+
{ // Pass the clone through the copyProps() function as well.
|
|
132
|
+
copyProps(obj, copy, opts.copy);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (relock)
|
|
136
|
+
{ // Add the lock() method to the clone.
|
|
137
|
+
addLock(copy, opts);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return copy;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Alias the CLONE enum as clone.MODE
|
|
144
|
+
def(clone, 'MODE', CLONE);
|
|
145
|
+
|
|
146
|
+
// Export the clone here.
|
|
147
|
+
exports.clone = clone;
|
|
131
148
|
|
|
132
149
|
/**
|
|
133
150
|
* Add a clone() method to an object.
|
|
@@ -141,26 +158,26 @@ const copyProps = require('./copyprops');
|
|
|
141
158
|
*
|
|
142
159
|
* @method Lum._.addClone
|
|
143
160
|
*/
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
161
|
+
function addClone(obj, defOpts=null)
|
|
162
|
+
{
|
|
163
|
+
if (!isObj(defOpts))
|
|
164
|
+
{ // Assign a default set of defaults.
|
|
165
|
+
defOpts = {mode: CLONE.DEF, addClone: true, addLock: false};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const defDesc = defOpts.cloneDesc ?? {};
|
|
169
|
+
|
|
170
|
+
defDesc.value = function (opts)
|
|
171
|
+
{
|
|
172
|
+
if (!isObj(opts))
|
|
173
|
+
opts = defOpts;
|
|
174
|
+
return clone(obj, opts);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return def(obj, 'clone', defDesc);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
exports.addClone = addClone;
|
|
164
181
|
|
|
165
182
|
/**
|
|
166
183
|
* Clone an object if it's not extensible (locked, sealed, frozen, etc.)
|
|
@@ -177,25 +194,25 @@ const copyProps = require('./copyprops');
|
|
|
177
194
|
*
|
|
178
195
|
* @method Lum._.cloneIfLocked
|
|
179
196
|
*/
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
197
|
+
function cloneIfLocked(obj, opts)
|
|
198
|
+
{
|
|
199
|
+
if (!Object.isExtensible(obj))
|
|
200
|
+
{
|
|
201
|
+
if (typeof obj.clone === F)
|
|
202
|
+
{ // Use the object's clone() method.
|
|
203
|
+
return obj.clone(opts);
|
|
204
|
+
}
|
|
205
|
+
else
|
|
206
|
+
{ // Use our own clone method.
|
|
207
|
+
return clone(obj, opts);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Return the object itself, it's fine.
|
|
212
|
+
return obj;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
exports.cloneIfLocked = cloneIfLocked;
|
|
199
216
|
|
|
200
217
|
// Import `addLock()` here *after* assigning the clone methods.
|
|
201
218
|
const {addLock} = require('./lock');
|
package/lib/obj/index.js
CHANGED
|
@@ -8,11 +8,16 @@ const copyProps = require('./copyprops');
|
|
|
8
8
|
const {CLONE,clone,addClone,cloneIfLocked} = require('./clone');
|
|
9
9
|
const {lock,addLock} = require('./lock');
|
|
10
10
|
const {mergeNested,syncNested} = require('./merge');
|
|
11
|
-
const
|
|
11
|
+
const ns = require('./ns');
|
|
12
|
+
const
|
|
13
|
+
{
|
|
14
|
+
getObjectPath,setObjectPath,
|
|
15
|
+
getNamespace,setNamespace,
|
|
16
|
+
} = ns;
|
|
12
17
|
|
|
13
18
|
module.exports =
|
|
14
19
|
{
|
|
15
20
|
CLONE, clone, addClone, cloneIfLocked, lock, addLock,
|
|
16
|
-
mergeNested, syncNested,
|
|
17
|
-
getObjectPath, setObjectPath,
|
|
21
|
+
mergeNested, syncNested, copyProps, copyAll, ns,
|
|
22
|
+
getObjectPath, setObjectPath, getNamespace, setNamespace,
|
|
18
23
|
}
|
package/lib/obj/lock.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
// Import *most* required bits here.
|
|
2
2
|
const {B, isObj, def} = require('../types');
|
|
3
|
-
const {getDescriptor, DESC} = require('../descriptors');
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Lock an object using Object.freeze()
|
|
@@ -47,14 +46,14 @@ const {getDescriptor, DESC} = require('../descriptors');
|
|
|
47
46
|
*/
|
|
48
47
|
function addLock(obj, opts)
|
|
49
48
|
{
|
|
50
|
-
const defDesc =
|
|
51
|
-
defDesc.
|
|
49
|
+
const defDesc = opts.lockDesc ?? {};
|
|
50
|
+
defDesc.value = function(obj, cloneable, cloneOpts, useSeal)
|
|
52
51
|
{
|
|
53
52
|
if (typeof cloneable !== B) clonable = opts.addClone ?? true;
|
|
54
53
|
if (!isObj(cloneOpts)) cloneOpts = opts; // Yup, just a raw copy.
|
|
55
54
|
if (typeof useSeal !== B) useSeal = opts.useSeal ?? false;
|
|
56
55
|
return lock(obj, cloneable, cloneOpts, useSeal);
|
|
57
|
-
}
|
|
56
|
+
}
|
|
58
57
|
return def(obj, 'lock', defDesc);
|
|
59
58
|
}
|
|
60
59
|
|
package/lib/observable.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// This library was original based on the observable library from riot.js,
|
|
2
2
|
// but has been refactored and expanded a lot since then.
|
|
3
3
|
|
|
4
|
-
const
|
|
4
|
+
const types = require('./types');
|
|
5
|
+
const {B,F,S,def,isObj,isComplex} = types;
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Make an object support the observable API.
|
|
@@ -289,4 +290,4 @@ function isObservable(obj)
|
|
|
289
290
|
def(observable, 'is', isObservable);
|
|
290
291
|
|
|
291
292
|
// And make it available as `types.doesObservable`
|
|
292
|
-
|
|
293
|
+
types.doesObservable = isObservable;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
const {O, F, S, SY} = require('./js');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* See if a value is a non-null `object`.
|
|
5
|
+
* @param {*} v - The value we're testing.
|
|
6
|
+
* @returns {boolean}
|
|
7
|
+
*/
|
|
8
|
+
function isObj(v) { return (typeof v === O && v !== null); }
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* See if a value is *complex* (i.e. either `object` or `function`).
|
|
12
|
+
* Like `isObj()`, `null` does not count as an `object`.
|
|
13
|
+
* @param {*} v - The value we're testing.
|
|
14
|
+
* @returns {boolean}
|
|
15
|
+
*/
|
|
16
|
+
function isComplex(v) { return (typeof v === F || isObj(v)); }
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* See if a value is *nil* (i.e. either `null` or `undefined`).
|
|
20
|
+
* @param {*} v - The value we're testing.
|
|
21
|
+
* @returns {boolean}
|
|
22
|
+
*/
|
|
23
|
+
function isNil(v) { return (v === undefined || v === null); }
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* See if a value is not *nil* (i.e. neither `null` nor `undefined`).
|
|
27
|
+
* @param {*} v - The value we're testing.
|
|
28
|
+
* @returns {boolean}
|
|
29
|
+
*/
|
|
30
|
+
function notNil(v) { return (v !== undefined && v !== null); }
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* See if a value is a scalar.
|
|
34
|
+
* For the purposes of this, a scalar is any value which
|
|
35
|
+
* is neither *nil* nor *complex*.
|
|
36
|
+
* @param {*} v - The value we're testing.
|
|
37
|
+
* @returns {boolean}
|
|
38
|
+
*/
|
|
39
|
+
function isScalar(v) { return (notNil(v) && !isComplex(v)); }
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* See if a value is an `Array` object.
|
|
43
|
+
* This is literally just a copy of `Array.isArray`.
|
|
44
|
+
* @param {*} v - The value we're testing.
|
|
45
|
+
* @returns {boolean}
|
|
46
|
+
*/
|
|
47
|
+
const isArray = Array.isArray;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* See if a value is a `TypedArray` object.
|
|
51
|
+
* @param {*} v - The value we're testing.
|
|
52
|
+
* @returns {boolean}
|
|
53
|
+
*/
|
|
54
|
+
function isTypedArray(v)
|
|
55
|
+
{
|
|
56
|
+
return (ArrayBuffer.isView(v) && !(v instanceof DataView));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* See if a value is a non-empty Array.
|
|
61
|
+
* @param {*} v - The value we're testing.
|
|
62
|
+
* @param {boolean} [typed=false] If `true` we want a `TypedArray`.
|
|
63
|
+
* If `false` (default) we want a regular `Array`.
|
|
64
|
+
* @returns {boolean}
|
|
65
|
+
*/
|
|
66
|
+
function nonEmptyArray(v, typed=false)
|
|
67
|
+
{
|
|
68
|
+
if (typed)
|
|
69
|
+
return (isTypedArray(v) && v.length > 0);
|
|
70
|
+
else
|
|
71
|
+
return (isArray(v) && v.length > 0);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* See if a value is an `arguments` object.
|
|
76
|
+
* @param {*} v - The value we're testing.
|
|
77
|
+
* @returns {boolean}
|
|
78
|
+
*/
|
|
79
|
+
function isArguments(v)
|
|
80
|
+
{
|
|
81
|
+
return Object.prototype.toString.call(v) === '[object Arguments]';
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* See if a value is a Property name.
|
|
86
|
+
* @param {*} v - The value we're testing.
|
|
87
|
+
* @returns {boolean}
|
|
88
|
+
*/
|
|
89
|
+
function isProperty(v)
|
|
90
|
+
{
|
|
91
|
+
const t = typeof v;
|
|
92
|
+
return (t === S || t === SY);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* See if an object can be used as a valid descriptor.
|
|
97
|
+
*
|
|
98
|
+
* Basically in order to be considered a valid descriptor,
|
|
99
|
+
* one of the the following sets of rules must be true:
|
|
100
|
+
*
|
|
101
|
+
* - A Data Descriptor:
|
|
102
|
+
* - Has a `value` property.
|
|
103
|
+
* - Does not have a `get` property.
|
|
104
|
+
* - Does not have a `set` property.
|
|
105
|
+
* - An Accessor Descriptor:
|
|
106
|
+
* - Has a `get` and/or `set` property.
|
|
107
|
+
* - Does not have a `value` property.
|
|
108
|
+
* - Does not have a `writable` property.
|
|
109
|
+
*
|
|
110
|
+
* @param {object} obj - The object we are testing.
|
|
111
|
+
* @returns {boolean} - Is the object a valid descriptor?
|
|
112
|
+
*/
|
|
113
|
+
function doesDescriptor(obj)
|
|
114
|
+
{
|
|
115
|
+
if (isObj(obj))
|
|
116
|
+
{
|
|
117
|
+
const hasValue = (obj.value !== undefined);
|
|
118
|
+
const hasGetter = (typeof obj.get === F);
|
|
119
|
+
const hasSetter = (typeof obj.set === F);
|
|
120
|
+
const hasWritable = (obj.writable !== undefined);
|
|
121
|
+
|
|
122
|
+
if (hasValue && !hasGetter && !hasSetter)
|
|
123
|
+
{ // We have a value, and no getter or setter.
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
else if ((hasGetter || hasSetter) && !hasValue && !hasWritable)
|
|
127
|
+
{ // We have a getter or setter, and no value or writable properties.
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Nothing matched, not a valid descriptor rule.
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Now export those.
|
|
137
|
+
module.exports =
|
|
138
|
+
{
|
|
139
|
+
isObj, isComplex, isNil, notNil, isScalar, isArray, isTypedArray,
|
|
140
|
+
nonEmptyArray, isArguments, isProperty, doesDescriptor,
|
|
141
|
+
}
|
|
142
|
+
|