@nejs/basic-extensions 2.9.0 → 2.11.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.
Files changed (176) hide show
  1. package/dist/@nejs/basic-extensions.bundle.2.11.0.js +19 -0
  2. package/dist/@nejs/basic-extensions.bundle.2.11.0.js.map +7 -0
  3. package/dist/cjs/array.extensions.js +174 -0
  4. package/dist/cjs/array.extensions.js.map +1 -1
  5. package/dist/cjs/big.int.extension.js +1 -0
  6. package/dist/cjs/big.int.extension.js.map +1 -1
  7. package/dist/cjs/classes/descriptor.d.ts +67 -155
  8. package/dist/cjs/classes/descriptor.js +185 -278
  9. package/dist/cjs/classes/descriptor.js.map +1 -1
  10. package/dist/cjs/classes/index.d.ts +1 -0
  11. package/dist/cjs/classes/index.js +3 -0
  12. package/dist/cjs/classes/index.js.map +1 -1
  13. package/dist/cjs/classes/iterable.d.ts +44 -0
  14. package/dist/cjs/classes/iterable.js +64 -0
  15. package/dist/cjs/classes/iterable.js.map +1 -1
  16. package/dist/cjs/classes/param.parser.d.ts +10 -10
  17. package/dist/cjs/classes/property.d.ts +86 -0
  18. package/dist/cjs/classes/property.js +284 -0
  19. package/dist/cjs/classes/property.js.map +1 -0
  20. package/dist/cjs/classes/symkeys.d.ts +68 -11
  21. package/dist/cjs/classes/symkeys.js +103 -17
  22. package/dist/cjs/classes/symkeys.js.map +1 -1
  23. package/dist/cjs/classes/type.d.ts +4 -4
  24. package/dist/cjs/function.extensions.js +1 -0
  25. package/dist/cjs/function.extensions.js.map +1 -1
  26. package/dist/cjs/global.this.js +29 -0
  27. package/dist/cjs/global.this.js.map +1 -1
  28. package/dist/cjs/index.d.ts +3 -0
  29. package/dist/cjs/index.js +19 -0
  30. package/dist/cjs/index.js.map +1 -1
  31. package/dist/cjs/json.extensions.js +19 -18
  32. package/dist/cjs/json.extensions.js.map +1 -1
  33. package/dist/cjs/map.extensions.js +1 -0
  34. package/dist/cjs/map.extensions.js.map +1 -1
  35. package/dist/cjs/number.extension.js +1 -0
  36. package/dist/cjs/number.extension.js.map +1 -1
  37. package/dist/cjs/object.extensions.d.ts +0 -29
  38. package/dist/cjs/object.extensions.js +218 -255
  39. package/dist/cjs/object.extensions.js.map +1 -1
  40. package/dist/cjs/set.extensions.js +1 -0
  41. package/dist/cjs/set.extensions.js.map +1 -1
  42. package/dist/cjs/string.extensions.js +474 -469
  43. package/dist/cjs/string.extensions.js.map +1 -1
  44. package/dist/cjs/symbol.extensions.js +387 -32
  45. package/dist/cjs/symbol.extensions.js.map +1 -1
  46. package/dist/cjs/utils/copy.object.d.ts +408 -0
  47. package/dist/cjs/utils/copy.object.js +720 -0
  48. package/dist/cjs/utils/copy.object.js.map +1 -0
  49. package/dist/cjs/utils/descriptor.utils.d.ts +146 -0
  50. package/dist/cjs/utils/descriptor.utils.js +614 -0
  51. package/dist/cjs/utils/descriptor.utils.js.map +1 -0
  52. package/dist/cjs/utils/index.d.ts +60 -0
  53. package/dist/cjs/utils/index.js +52 -0
  54. package/dist/cjs/utils/index.js.map +1 -0
  55. package/dist/cjs/utils/toolkit.d.ts +1898 -0
  56. package/dist/cjs/utils/toolkit.js +1378 -0
  57. package/dist/cjs/utils/toolkit.js.map +1 -0
  58. package/dist/mjs/array.extensions.js +174 -0
  59. package/dist/mjs/array.extensions.js.map +1 -1
  60. package/dist/mjs/big.int.extension.js +1 -0
  61. package/dist/mjs/big.int.extension.js.map +1 -1
  62. package/dist/mjs/classes/descriptor.d.ts +67 -155
  63. package/dist/mjs/classes/descriptor.js +185 -278
  64. package/dist/mjs/classes/descriptor.js.map +1 -1
  65. package/dist/mjs/classes/index.d.ts +1 -0
  66. package/dist/mjs/classes/index.js +3 -0
  67. package/dist/mjs/classes/index.js.map +1 -1
  68. package/dist/mjs/classes/iterable.d.ts +44 -0
  69. package/dist/mjs/classes/iterable.js +64 -0
  70. package/dist/mjs/classes/iterable.js.map +1 -1
  71. package/dist/mjs/classes/param.parser.d.ts +10 -10
  72. package/dist/mjs/classes/property.d.ts +86 -0
  73. package/dist/mjs/classes/property.js +280 -0
  74. package/dist/mjs/classes/property.js.map +1 -0
  75. package/dist/mjs/classes/symkeys.d.ts +68 -11
  76. package/dist/mjs/classes/symkeys.js +103 -17
  77. package/dist/mjs/classes/symkeys.js.map +1 -1
  78. package/dist/mjs/classes/type.d.ts +4 -4
  79. package/dist/mjs/function.extensions.js +1 -0
  80. package/dist/mjs/function.extensions.js.map +1 -1
  81. package/dist/mjs/global.this.js +6 -0
  82. package/dist/mjs/global.this.js.map +1 -1
  83. package/dist/mjs/index.d.ts +3 -0
  84. package/dist/mjs/index.js +5 -0
  85. package/dist/mjs/index.js.map +1 -1
  86. package/dist/mjs/json.extensions.js +19 -18
  87. package/dist/mjs/json.extensions.js.map +1 -1
  88. package/dist/mjs/map.extensions.js +1 -0
  89. package/dist/mjs/map.extensions.js.map +1 -1
  90. package/dist/mjs/number.extension.js +1 -0
  91. package/dist/mjs/number.extension.js.map +1 -1
  92. package/dist/mjs/object.extensions.d.ts +0 -29
  93. package/dist/mjs/object.extensions.js +215 -251
  94. package/dist/mjs/object.extensions.js.map +1 -1
  95. package/dist/mjs/set.extensions.js +1 -0
  96. package/dist/mjs/set.extensions.js.map +1 -1
  97. package/dist/mjs/string.extensions.js +474 -469
  98. package/dist/mjs/string.extensions.js.map +1 -1
  99. package/dist/mjs/symbol.extensions.js +387 -32
  100. package/dist/mjs/symbol.extensions.js.map +1 -1
  101. package/dist/mjs/utils/copy.object.d.ts +408 -0
  102. package/dist/mjs/utils/copy.object.js +702 -0
  103. package/dist/mjs/utils/copy.object.js.map +1 -0
  104. package/dist/mjs/utils/descriptor.utils.d.ts +146 -0
  105. package/dist/mjs/utils/descriptor.utils.js +606 -0
  106. package/dist/mjs/utils/descriptor.utils.js.map +1 -0
  107. package/dist/mjs/utils/index.d.ts +60 -0
  108. package/dist/mjs/utils/index.js +36 -0
  109. package/dist/mjs/utils/index.js.map +1 -0
  110. package/dist/mjs/utils/toolkit.d.ts +1898 -0
  111. package/dist/mjs/utils/toolkit.js +1373 -0
  112. package/dist/mjs/utils/toolkit.js.map +1 -0
  113. package/package.json +29 -37
  114. package/repl.bootstrap.js +12 -1
  115. package/src/array.extensions.js +191 -1
  116. package/src/big.int.extension.js +3 -1
  117. package/src/classes/descriptor.js +206 -305
  118. package/src/classes/index.js +4 -0
  119. package/src/classes/iterable.js +74 -0
  120. package/src/classes/property.js +333 -0
  121. package/src/classes/symkeys.js +120 -19
  122. package/src/function.extensions.js +2 -0
  123. package/src/global.this.js +8 -0
  124. package/src/index.js +6 -0
  125. package/src/json.extensions.js +18 -19
  126. package/src/map.extensions.js +3 -1
  127. package/src/number.extension.js +3 -1
  128. package/src/object.extensions.js +240 -277
  129. package/src/set.extensions.js +3 -1
  130. package/src/string.extensions.js +512 -506
  131. package/src/symbol.extensions.js +413 -30
  132. package/src/utils/copy.object.js +780 -0
  133. package/src/utils/descriptor.utils.js +707 -0
  134. package/src/utils/index.js +74 -0
  135. package/src/utils/toolkit.js +1473 -0
  136. package/tests/arrayextensions.test.js +2 -0
  137. package/tests/index.test.js +1 -0
  138. package/tests/newClasses/asyncIterable.test.js +2 -0
  139. package/tests/newClasses/deferred.test.js +5 -3
  140. package/tests/newClasses/descriptor.test.js +6 -8
  141. package/tests/newClasses/iterable.test.js +2 -0
  142. package/tests/newClasses/refmap.test.js +2 -1
  143. package/tests/newClasses/refset.test.js +2 -0
  144. package/tests/objectextensions.test.js +2 -0
  145. package/tests/setextensions.test.js +2 -0
  146. package/tests/stringextensions.test.js +1 -0
  147. package/tests/utils/toolkit.test.js +223 -0
  148. package/tsconfig.base.json +1 -1
  149. package/vitest.config.js +7 -0
  150. package/dist/@nejs/basic-extensions.bundle.2.8.0.js +0 -19
  151. package/dist/@nejs/basic-extensions.bundle.2.8.0.js.map +0 -7
  152. package/docs/assets/anchor.js +0 -350
  153. package/docs/assets/bass-addons.css +0 -12
  154. package/docs/assets/bass.css +0 -544
  155. package/docs/assets/fonts/EOT/SourceCodePro-Bold.eot +0 -0
  156. package/docs/assets/fonts/EOT/SourceCodePro-Regular.eot +0 -0
  157. package/docs/assets/fonts/LICENSE.txt +0 -93
  158. package/docs/assets/fonts/OTF/SourceCodePro-Bold.otf +0 -0
  159. package/docs/assets/fonts/OTF/SourceCodePro-Regular.otf +0 -0
  160. package/docs/assets/fonts/TTF/SourceCodePro-Bold.ttf +0 -0
  161. package/docs/assets/fonts/TTF/SourceCodePro-Regular.ttf +0 -0
  162. package/docs/assets/fonts/WOFF/OTF/SourceCodePro-Bold.otf.woff +0 -0
  163. package/docs/assets/fonts/WOFF/OTF/SourceCodePro-Regular.otf.woff +0 -0
  164. package/docs/assets/fonts/WOFF/TTF/SourceCodePro-Bold.ttf.woff +0 -0
  165. package/docs/assets/fonts/WOFF/TTF/SourceCodePro-Regular.ttf.woff +0 -0
  166. package/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Bold.otf.woff2 +0 -0
  167. package/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Regular.otf.woff2 +0 -0
  168. package/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Bold.ttf.woff2 +0 -0
  169. package/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Regular.ttf.woff2 +0 -0
  170. package/docs/assets/fonts/source-code-pro.css +0 -23
  171. package/docs/assets/github.css +0 -123
  172. package/docs/assets/site.js +0 -168
  173. package/docs/assets/split.css +0 -15
  174. package/docs/assets/split.js +0 -782
  175. package/docs/assets/style.css +0 -147
  176. package/docs/index.html +0 -35485
@@ -1,5 +1,15 @@
1
1
  import { Extension } from '@nejs/extension'
2
2
 
3
+ import {
4
+ accessor as uAccessor,
5
+ data as uData,
6
+ isDescriptor as uIsDescriptor,
7
+ kAccessorDescriptorKeys,
8
+ kDataDescriptorKeys,
9
+ kDescriptorKeys,
10
+ kSharedDescriptorKeys
11
+ } from '../utils/descriptor.utils.js'
12
+
3
13
  export class Descriptor {
4
14
  /**
5
15
  * The default private descriptor value is that of `enigmatic`
@@ -7,7 +17,7 @@ export class Descriptor {
7
17
  * @private
8
18
  * @type {object}
9
19
  */
10
- #desc = undefined
20
+ _desc = undefined
11
21
 
12
22
  /**
13
23
  * An optionally associated object, usually the parent from which
@@ -16,7 +26,7 @@ export class Descriptor {
16
26
  *
17
27
  * @type {object}
18
28
  */
19
- #object = undefined
29
+ _object = undefined
20
30
 
21
31
  /**
22
32
  * Constructs a Descriptor instance which wraps and manages an object
@@ -35,26 +45,38 @@ export class Descriptor {
35
45
  * valid.
36
46
  */
37
47
  constructor(object, key) {
38
- if ((object ?? key) === undefined) {
39
- this.#desc = Descriptor.enigmatic
48
+ if (arguments.length === 0) {
49
+ this._desc = Descriptor.enigmatic
40
50
  }
51
+
41
52
  else if (Descriptor.isDescriptor(object)) {
42
- this.#desc = object
43
- this.#object = isObject(key) ? key : undefined
53
+ this._desc = object
54
+ this._object = isObject(key) ? key : undefined
44
55
  }
56
+
45
57
  else if (isObject(object) && isValidKey(key)) {
46
- this.#desc = Object.getOwnPropertyDescriptor(object, key)
47
- this.#object = object
58
+ console.log('new Descriptor(%o, %o)', object, key)
59
+ this._desc = Object.getOwnPropertyDescriptor(object, key)
60
+ this._object = object
48
61
  }
49
62
 
50
63
  if (!this.isDescriptor) {
64
+ const objectMsg = object === globalThis
65
+ ? '[GLOBAL]'
66
+ : (typeof key === 'object' ? JSON.stringify(object) : String(object));
67
+
68
+ const keyMsg = key === globalThis
69
+ ? '[GLOBAL]'
70
+ : (typeof key === 'object' ? JSON.stringify(key) : String(key));
71
+
51
72
  console.error(`
52
- Descriptor(object,key) FAILED:
53
- object: ${object === globalThis ? '[GLOBAL]' : (typeof key === 'object' ? JSON.stringify(object) : String(object))}
54
- key: ${key === globalThis ? '[GLOBAL]' : (typeof key === 'object' ? JSON.stringify(key) : String(key))}
55
- descriptor: `, this.#desc
73
+ Descriptor(object: ${object}, key: ${key}) FAILED:
74
+ object: ${objectMsg}
75
+ key: ${keyMsg}
76
+ descriptor: `, this._desc
56
77
  )
57
- throw new Error(`Not a valid descriptor:`, this.#desc)
78
+
79
+ throw new Error(`Not a valid descriptor:`, this._desc)
58
80
  }
59
81
  }
60
82
 
@@ -65,7 +87,7 @@ export class Descriptor {
65
87
  * a data descriptor
66
88
  */
67
89
  get isAccessor() {
68
- return Descriptor.isAccessor(this.#desc)
90
+ return uIsDescriptor(this._desc, true).isAccessor
69
91
  }
70
92
 
71
93
  /**
@@ -75,7 +97,7 @@ export class Descriptor {
75
97
  * an accessor descriptor
76
98
  */
77
99
  get isData() {
78
- return Descriptor.isData(this.#desc)
100
+ return uIsDescriptor(this._desc, true).isData
79
101
  }
80
102
 
81
103
  /**
@@ -84,106 +106,7 @@ export class Descriptor {
84
106
  * @returns {boolean} true if this descriptor store is a valid descriptor
85
107
  */
86
108
  get isDescriptor() {
87
- return Descriptor.isDescriptor(this.#desc)
88
- }
89
-
90
- /**
91
- * Getter around the `configurable` object descriptor property of
92
- * this instance of Descriptor.
93
- *
94
- * @returns {boolean} a boolean value or undefined if the internal
95
- * descriptor store is invalid.
96
- */
97
- get configurable() {
98
- return !!this.#desc?.configurable
99
- }
100
-
101
- /**
102
- * Sets the `configurable` value of this object. If the internal descriptor
103
- * store store is invalid, the value is thrown away
104
- *
105
- * @param {boolean} value the value to set for the `configurable` descriptor
106
- * property. If this value is not a `boolean` it will be converted to one
107
- */
108
- set configurable(value) {
109
- (this.#desc || {}).configurable = !!value
110
- }
111
-
112
- /**
113
- * Getter around the `enumerable` object descriptor property of
114
- * this instance of Descriptor.
115
- *
116
- * @returns {boolean} a boolean value or undefined if the internal
117
- * descriptor store is invalid.
118
- */
119
- get enumerable() {
120
- return this.#desc?.enumerable
121
- }
122
-
123
- /**
124
- * Sets the `enumerable` value of this object. If the internal descriptor
125
- * store is invalid, the value is thrown away
126
- *
127
- * @param {boolean} value the value to set for the `enumerable` descriptor
128
- * property. If this value is not a `boolean` it will be converted to one
129
- */
130
- set enumerable(value) {
131
- (this.#desc || {}).enumerable = value
132
- }
133
-
134
- /**
135
- * Getter around the `writable` object descriptor property of
136
- * this instance of Descriptor.
137
- *
138
- * @returns {boolean} a boolean value or undefined if the internal
139
- * descriptor store is invalid.
140
- */
141
- get writable() {
142
- return this.#desc?.writable
143
- }
144
-
145
- /**
146
- * Sets the `writable` value of this object. If the internal descriptor
147
- * store is invalid, the value is thrown away
148
- *
149
- * @param {boolean} value the value to set for the `writable` descriptor
150
- * property. If this value is not a `boolean` it will be converted to one
151
- */
152
- set writable(value) {
153
- (this.#desc || {}).writable = value
154
- }
155
-
156
- /**
157
- * Getter around the `value` object descriptor property of
158
- * this instance of Descriptor.
159
- *
160
- * @returns {any} any value stored in this descriptor
161
- */
162
- get value() {
163
- return this.#desc?.value
164
- }
165
-
166
- /**
167
- * Sets the `value` value of this object. If the internal descriptor
168
- * store is invalid, the value is thrown away
169
- *
170
- * @param {any} value the value to set for the `value` descriptor
171
- * property.
172
- */
173
- set value(value) {
174
- (this.#desc || {}).value = value
175
- }
176
-
177
- /**
178
- * Getter around the `get` object descriptor property of
179
- * this instance of Descriptor.
180
- *
181
- * @returns {function} a function if the getter for this descriptor is
182
- * defined or `undefined` if the internal descriptor object or the getter
183
- * is undefined.
184
- */
185
- get get() {
186
- return this.#desc?.get
109
+ return uIsDescriptor(this._desc)
187
110
  }
188
111
 
189
112
  /**
@@ -195,29 +118,7 @@ export class Descriptor {
195
118
  * getter will be bound the associated and previously set `object`.
196
119
  */
197
120
  get boundGet() {
198
- return (isObject(this.#object) ? this.get?.bind(this.#object) : this.get)
199
- }
200
-
201
- /**
202
- * Sets the `get` value of this object. If the internal descriptor
203
- * store is invalid, the value is thrown away
204
- *
205
- * @param {function} value the getter function for this descriptor
206
- */
207
- set get(value) {
208
- (this.#desc || {}).get = value
209
- }
210
-
211
- /**
212
- * Getter around the `set` object descriptor property of
213
- * this instance of Descriptor.
214
- *
215
- * @returns {function} a function if the setter for this descriptor is
216
- * defined or `undefined` if the internal descriptor object or the setter
217
- * is undefined.
218
- */
219
- get set() {
220
- return (this.#desc || {}).set
121
+ return (isObject(this._object) ? this.get?.bind(this._object) : this.get)
221
122
  }
222
123
 
223
124
  /**
@@ -229,17 +130,7 @@ export class Descriptor {
229
130
  * setter will be bound the associated and previously set `object`.
230
131
  */
231
132
  get boundSet() {
232
- return (isObject(this.#object) ? this.set?.bind(this.#object) : this.set)
233
- }
234
-
235
- /**
236
- * Sets the `set` value of this object. If the internal descriptor
237
- * store is invalid, the value is thrown away
238
- *
239
- * @param {function} value the setter function for this descriptor
240
- */
241
- set set(value) {
242
- (this.#desc || {}).set = value
133
+ return (isObject(this._object) ? this.set?.bind(this._object) : this.set)
243
134
  }
244
135
 
245
136
  /**
@@ -249,7 +140,7 @@ export class Descriptor {
249
140
  * @returns {boolean} `true` if the `object` property has been set,
250
141
  * `false` otherwise
251
142
  */
252
- get hasObject() { return isObject(this.#object) }
143
+ get hasObject() { return isObject(this._object) }
253
144
 
254
145
  /**
255
146
  * Returns the descriptor's associated `object` value. This is usually the
@@ -259,7 +150,7 @@ export class Descriptor {
259
150
  * @returns {object} the associated object for this descriptor or undefined
260
151
  * if it has not yet been set.
261
152
  */
262
- get object() { return this.#object }
153
+ get object() { return this._object }
263
154
 
264
155
  /**
265
156
  * Sets the descriptor's associated `object` value. This is usually the
@@ -268,49 +159,7 @@ export class Descriptor {
268
159
  * @param {object} value sets the object for which this descriptor is to
269
160
  * be associated with.
270
161
  */
271
- set object(value) { this.#object = Object(value) }
272
-
273
- /**
274
- * The function returns a string representation of a descriptor object with
275
- * additional information about its type when used in the NodeJS repl.
276
- *
277
- * @param {number} depth - The `depth` parameter is used to specify the
278
- * maximum depth to which nested objects and arrays will be formatted. If
279
- * the depth is exceeded, the output will be truncated with ellipses.
280
- * @param {object} options - The `options` parameter is an object that
281
- * contains various configuration options for the `inspect` function.
282
- * These options can be used to customize the output of the inspection.
283
- * @param {function} inspect - The `inspect` parameter is a function that
284
- * is used to convert an object into a string representation. It is
285
- * typically used for debugging purposes or when displaying an object's
286
- * properties.
287
- * @returns a string that represents a descriptor. The string includes the
288
- * type of the descriptor (either "Accessor" or "Data") and the result of
289
- * inspecting the descriptor object using the provided options and depth.
290
- */
291
- [Symbol.for('nodejs.util.inspect.custom')](depth, options, inspect) {
292
- const type = this.isAccessor ? ' (Accessor)' : this.isData ? ' (Data)' : ''
293
- return `Descriptor${type} ${inspect(this.#desc, {...options, depth})}`
294
- }
295
-
296
- /**
297
- * Shorthand for Object.getOwnPropertyDescriptor()
298
- *
299
- * @param {object} object a non-null object instance
300
- * @param {string|symbol} key a symbol or string referencing which key on the
301
- * object to return a descriptor for.
302
- * @returns an object descriptor for the requested field or null
303
- */
304
- static for(object, key, wrap = false) {
305
- if (!isObject(object) || !isValidKey(key) || !Reflect.has(object, key)) {
306
- return null
307
- }
308
-
309
- return (wrap
310
- ? new Descriptor(Object.getOwnPropertyDescriptor(object, key))
311
- : Object.getOwnPropertyDescriptor(object, key)
312
- )
313
- }
162
+ set object(value) { this._object = Object(value) }
314
163
 
315
164
  /**
316
165
  * Take the descriptor defined by this objects values and apply them to
@@ -342,7 +191,7 @@ export class Descriptor {
342
191
  * a descriptor.
343
192
  */
344
193
  toObject(bindAccessors = false) {
345
- let descriptor = { ...this.#desc }
194
+ let descriptor = { ...this._desc }
346
195
 
347
196
  if (bindAccessors && this.isAccessor) {
348
197
  if (this.hasObject) {
@@ -364,6 +213,29 @@ export class Descriptor {
364
213
  return descriptor
365
214
  }
366
215
 
216
+ /**
217
+ * The function returns a string representation of a descriptor object with
218
+ * additional information about its type when used in the NodeJS repl.
219
+ *
220
+ * @param {number} depth - The `depth` parameter is used to specify the
221
+ * maximum depth to which nested objects and arrays will be formatted. If
222
+ * the depth is exceeded, the output will be truncated with ellipses.
223
+ * @param {object} options - The `options` parameter is an object that
224
+ * contains various configuration options for the `inspect` function.
225
+ * These options can be used to customize the output of the inspection.
226
+ * @param {function} inspect - The `inspect` parameter is a function that
227
+ * is used to convert an object into a string representation. It is
228
+ * typically used for debugging purposes or when displaying an object's
229
+ * properties.
230
+ * @returns a string that represents a descriptor. The string includes the
231
+ * type of the descriptor (either "Accessor" or "Data") and the result of
232
+ * inspecting the descriptor object using the provided options and depth.
233
+ */
234
+ [Symbol.for('nodejs.util.inspect.custom')](depth, options, inspect) {
235
+ const type = this.isAccessor ? ' (Accessor)' : this.isData ? ' (Data)' : ''
236
+ return `Descriptor${type} ${inspect(this._desc, {...options, depth})}`
237
+ }
238
+
367
239
  /**
368
240
  * Converts this descriptor object into a base representation
369
241
  *
@@ -375,18 +247,20 @@ export class Descriptor {
375
247
  switch (hint) {
376
248
  case 'string':
377
249
  if (this.isAccessor) {
378
- const hasGetter = Reflect.has(this.#desc, 'get') ? `getter` : ''
379
- const hasSetter = Reflect.has(this.#desc, 'set') ? `setter` : ''
380
- const separator = hasGetter && hasSetter ? ', ' : ''
250
+ const props = []
381
251
 
382
- return `Accessor (${hasGetter}${separator}${hasSetter})`
252
+ if (Reflect.has(this._desc, 'get')) props.push('getter')
253
+ if (Reflect.has(this._desc, 'set')) props.push('setter')
254
+
255
+ return `Accessor (${props.join(', ')})`
383
256
  }
384
257
  else if (this.isData) {
385
- const hasGetter = Reflect.has(this.#desc, 'value') ? `value` : ''
386
- const hasSetter = Reflect.has(this.#desc, 'writable') ? `writable` : ''
387
- const separator = hasGetter && hasSetter ? ', ' : ''
258
+ const props = []
259
+
260
+ if (Reflect.has(this._desc, 'value')) props.push('value')
261
+ if (Reflect.has(this._desc, 'writable')) props.push('writable')
388
262
 
389
- return `Data (${hasGetter}${separator}${hasSetter})`
263
+ return `Data (${props.join(', ')})`
390
264
  }
391
265
  break
392
266
 
@@ -498,17 +372,8 @@ export class Descriptor {
498
372
  * @returns an object with properties "get", "set", "enumerable", and
499
373
  * "configurable".
500
374
  */
501
- static accessor(
502
- getter,
503
- setter,
504
- { enumerable, configurable } = Descriptor.base()
505
- ) {
506
- return {
507
- get: getter,
508
- set: setter,
509
- enumerable,
510
- configurable
511
- }
375
+ static accessor() {
376
+ return uAccessor(...arguments)
512
377
  }
513
378
 
514
379
  /**
@@ -528,14 +393,28 @@ export class Descriptor {
528
393
  static data(
529
394
  value,
530
395
  writable = true,
531
- { enumerable, configurable } = Descriptor.base()
396
+ { enumerable, configurable } = { configurable: true, enumerable: true }
532
397
  ) {
533
- return {
534
- value,
535
- enumerable,
536
- writable,
537
- configurable
398
+ return uData(value, writable, enumerable, configurable)
399
+ }
400
+
401
+ /**
402
+ * Shorthand for Object.getOwnPropertyDescriptor()
403
+ *
404
+ * @param {object} object a non-null object instance
405
+ * @param {string|symbol} key a symbol or string referencing which key on the
406
+ * object to return a descriptor for.
407
+ * @returns an object descriptor for the requested field or null
408
+ */
409
+ static for(object, key, wrap = false) {
410
+ if (!isObject(object) || !isValidKey(key) || !Reflect.has(object, key)) {
411
+ return null
538
412
  }
413
+
414
+ return (wrap
415
+ ? new Descriptor(Object.getOwnPropertyDescriptor(object, key))
416
+ : Object.getOwnPropertyDescriptor(object, key)
417
+ )
539
418
  }
540
419
 
541
420
  /**
@@ -545,127 +424,113 @@ export class Descriptor {
545
424
  * or set). Technically, any object could serve as a descriptor but this
546
425
  * function only returns true if known descriptor keys are found.
547
426
  *
548
- * @param object - The `object` parameter is the object that we want to
549
- * check if it is a descriptor.
550
- * @returns a boolean value.
427
+ * @param {any} object - Any value we want to check for being a descriptor.
428
+ * @param {boolean} returnStatsInstead defaults to false, but if the value
429
+ * is `true` then an object with reasoning behind the decision of whether
430
+ * or not the
431
+ * @returns {IsDescriptorResponse} either a {@link boolean} value or
432
+ * an object conforming to {@link IsDescriptorStats} if `returnStatsInstead`
433
+ * is `true`
434
+ *
435
+ * @see {@link DescriptorUtils.isDescriptor}
551
436
  */
552
- static isDescriptor(object) {
553
- const knownKeys = [
554
- ...Descriptor.SHARED_KEYS,
555
- ...Descriptor.ACCESSOR_KEYS,
556
- ...Descriptor.DATA_KEYS,
557
- ]
558
-
559
- return hasSome(object, knownKeys)
437
+ static isDescriptor(object, returnStatsInstead = false) {
438
+ return uIsDescriptor(object, returnStatsInstead)
560
439
  }
561
440
 
562
441
  /**
563
- * The function checks if a given property or descriptor is a data property.
564
- *
565
- * brie
442
+ * The function checks if a given property descriptor or property of an
443
+ * object is an accessor.
566
444
  *
567
- * @param descriptor_orProp - The `descriptor_orProp` parameter can be
568
- * either a descriptor or a property name.
569
- * @param object - The `object` parameter is the object that you want to
570
- * check for data properties.
571
- * @returns a boolean value. It returns `true` if the `descriptor` object
572
- * has any keys that match the `DATA_KEYS` array, otherwise it returns
573
- * `false`.
445
+ * @param {object} objectOrDescriptor - The `objectOrDescriptor` parameter
446
+ * can be either a descriptor object or a property name.
447
+ * @param {(string|number|symbol)?} property the property name you wish to
448
+ * check the validity as an accessor descriptor. Only expected if the
449
+ * `objectOrDescriptor` parameter is the object that would contain this
450
+ * property.
451
+ * @returns {@link Boolean} returning `true` if the `descriptor` object
452
+ * has any keys that match the {@link Descriptor.ACCESSOR_KEYS} array,
453
+ * otherwise it returns `false`.
574
454
  */
575
- static isData(object_orProp, property) {
576
- const needsDescriptor = (
577
- ((typeof object_orProp === 'object') || object_orProp instanceof Object) &&
578
- property instanceof String
579
- )
580
-
581
- const descriptor = (needsDescriptor
582
- ? Descriptor.for(object_orProp, property)
583
- : object_orProp
584
- )
455
+ static isAccessor(objectOrDescriptor, property) {
456
+ const needsDescriptor =
457
+ objectOrDescriptor &&
458
+ property &&
459
+ isObject(objectOrDescriptor) &&
460
+ isValidKey(property);
585
461
 
586
- const { DATA_KEYS } = this
587
- let validData = false
462
+ const descriptor = needsDescriptor
463
+ ? Descriptor.for(objectOrDescriptor, property)
464
+ : objectOrDescriptor
588
465
 
589
- if (hasSome(descriptor, DATA_KEYS)) {
590
- validData = true
591
- }
592
-
593
- return validData
466
+ return uIsDescriptor(descriptor, true).isAccessor
594
467
  }
595
468
 
596
469
  /**
597
- * The function checks if a given property descriptor or property of an
598
- * object is an accessor.
470
+ * The function checks if a given property or descriptor is a data property.
599
471
  *
600
- * @param object_orProp - The `descriptor_orProp` parameter can be either a
601
- * descriptor object or a property name.
602
- * @param property - The `object` parameter is the object that you want to
603
- * check for accessor properties.
604
- * @returns a boolean value. It returns true if the descriptor or property
605
- * passed as an argument is an accessor descriptor, and false otherwise.
606
- */
607
- static isAccessor(object_orProp, property) {
608
- const needsDescriptor = (
609
- (object_orProp && property) &&
610
- ((typeof object_orProp === 'object') || object_orProp instanceof Object) &&
611
- (property instanceof String || (typeof property === 'symbol'))
612
- )
613
-
614
- const descriptor = (needsDescriptor
615
- ? Descriptor.for(object_orProp, property)
616
- : object_orProp)
617
-
618
- const { ACCESSOR_KEYS } = this
619
- let validAccessor = false
472
+ * @param {object} objectOrDescriptor - The `objectOrDescriptor` parameter
473
+ * can be either a descriptor object or a property name.
474
+ * @param {(string|number|symbol)?} property the property name you wish to
475
+ * check the validity as an accessor descriptor. Only expected if the
476
+ * `objectOrDescriptor` parameter is the object that would contain this
477
+ * property.
478
+ * @returns {@link Boolean} returning `true` if the `descriptor` object
479
+ * has any keys that match the {@link Descriptor.DATA_KEYS} array, otherwise
480
+ * it returns `false`.
481
+ */
482
+ static isData(objectOrDescriptor, property) {
483
+ const needsDescriptor =
484
+ objectOrDescriptor &&
485
+ property &&
486
+ isObject(objectOrDescriptor) &&
487
+ isValidKey(property);
620
488
 
621
- if (hasSome(descriptor, ACCESSOR_KEYS)) {
622
- validAccessor = true
623
- }
489
+ const descriptor = needsDescriptor
490
+ ? Descriptor.for(objectOrDescriptor, property)
491
+ : objectOrDescriptor
624
492
 
625
- return validAccessor
493
+ return uIsDescriptor(descriptor, true).isData
626
494
  }
627
495
 
628
496
  /**
629
497
  * A base descriptor (new for each read) that is both enumerable and
630
498
  * configurable
631
499
  *
632
- * @returns The method `flexible` is returning the result of calling the
633
- * `base` method with the arguments `true` and `true`.
500
+ * @returns `{ enumerable: true, configurable: true }`
634
501
  */
635
502
  static get flexible() {
636
- return this.base(true, true)
503
+ return { enumerable: true, configurable: true }
637
504
  }
638
505
 
639
506
  /**
640
507
  * A base descriptor (new for each read) that is not enumerable but is
641
508
  * configurable
642
509
  *
643
- * @returns The method `enigmatic` is returning the result of calling
644
- * the `base` method with the arguments `false` and `true`.
510
+ * @returns `{ enumerable: false, configurable: true }`
645
511
  */
646
512
  static get enigmatic() {
647
- return this.base(false, true)
513
+ return { enumerable: false, configurable: true }
648
514
  }
649
515
 
650
516
  /**
651
517
  * A base descriptor (new for each read) that is neither enumerable
652
- * nor configurable
518
+ * nor configurable.
653
519
  *
654
- * @returns The code is returning the result of calling the `base` method with
655
- * the arguments `false` and `false`.
520
+ * @returns `{ enumerable: false, configurable: false }`
656
521
  */
657
522
  static get intrinsic() {
658
- return this.base(false, false)
523
+ return { enumerable: false, configurable: false }
659
524
  }
660
525
 
661
526
  /**
662
- * A base descriptor (new for each read) that enumerable but not configurable
527
+ * A base descriptor (new for each read) that is enumerable but
528
+ * not configurable
663
529
  *
664
- * @returns The method is returning the result of calling the `base`
665
- * method with the arguments `true` and `false`.
530
+ * @returns `{ enumerable: true, configurable: false }`
666
531
  */
667
532
  static get transparent() {
668
- return this.base(true, false)
533
+ return { enumerable: true, configurable: false }
669
534
  }
670
535
 
671
536
  /**
@@ -674,7 +539,7 @@ export class Descriptor {
674
539
  * @returns An array containing the strings 'configurable' and 'enumerable'.
675
540
  */
676
541
  static get SHARED_KEYS() {
677
- return ['configurable', 'enumerable']
542
+ return kSharedDescriptorKeys
678
543
  }
679
544
 
680
545
  /**
@@ -683,7 +548,7 @@ export class Descriptor {
683
548
  * @returns An array containing the strings 'get' and 'set' is being returned.
684
549
  */
685
550
  static get ACCESSOR_KEYS() {
686
- return ['get', 'set']
551
+ return kAccessorDescriptorKeys
687
552
  }
688
553
 
689
554
  /**
@@ -693,17 +558,53 @@ export class Descriptor {
693
558
  * returned.
694
559
  */
695
560
  static get DATA_KEYS() {
696
- return ['value', 'writable']
561
+ return kDataDescriptorKeys
562
+ }
563
+
564
+ static {
565
+ for (const key of kDescriptorKeys) {
566
+ Object.defineProperties(Descriptor.prototype, {
567
+ [key]: uAccessor(
568
+ function getMaker(storage) { return function get() {
569
+ return this._desc[key]
570
+ }},
571
+ function setMaker(storage) { return function set(value) {
572
+ this._desc[key] = value
573
+ }},
574
+ )
575
+ })
576
+ }
697
577
  }
698
578
  }
699
579
 
700
580
  export const DescriptorExtensions = new Extension(Descriptor)
701
581
 
702
- function isObject(o) { return o && typeof o === 'object' }
703
- function isValidKey(o) { return ['string','symbol'].some(t => typeof o === t) }
704
- function hasSome(object, ...keys) {
582
+ function typeOrType(type, Class, notNullish = true) {
583
+ return (value) => (
584
+ (!notNullish || (notNullish && value !== null && value !== undefined)) &&
585
+ (typeof value === type || (value && value instanceof Class))
586
+ )
587
+ }
588
+
589
+ function isObject(o) { return typeOrType('object', Object)(o) }
590
+ function isString(o) { return typeOrType('string', String)(o) }
591
+ function isNumber(o) { return typeOrType('number', Number)(o) }
592
+ function isSymbol(o) { return typeOrType('symbol', Symbol)(o) }
593
+ function isFunction(o) { return typeOrType('function', Function)(o) }
594
+ function isValidKey(o) { return isString(o) || isNumber(o) || isSymbol(o) }
595
+
596
+ function hasAll(object, ...keys) { return hasQuantity('every', object, keys) }
597
+ function hasSome(object, ...keys) { return hasQuantity('some', object, keys) }
598
+ function hasQuantity(quantityFn, object, keys) {
599
+ return isObject(object) && (keys.flat(Infinity)
600
+ .map(key => Reflect.has(object, key))
601
+ [quantityFn](has => has)
602
+ )
603
+ }
604
+ function hasOne(object, ...keys) {
705
605
  return isObject(object) && (keys.flat(Infinity)
706
606
  .map(key => Reflect.has(object, key))
707
- .some(has => has)
607
+ .filter(has => has)
608
+ .length === 1
708
609
  )
709
610
  }