@nejs/basic-extensions 1.6.0 → 1.7.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 (139) hide show
  1. package/.esdoc.json +9 -0
  2. package/README.md +2025 -11
  3. package/bin/clean +6 -0
  4. package/dist/@nejs/basic-extensions.bundle.1.6.1.js +4 -0
  5. package/dist/@nejs/basic-extensions.bundle.1.6.1.js.map +7 -0
  6. package/dist/cjs/arrayextensions.js +1 -0
  7. package/dist/cjs/arrayextensions.js.map +1 -0
  8. package/dist/cjs/functionextensions.js +1 -0
  9. package/dist/cjs/functionextensions.js.map +1 -0
  10. package/dist/cjs/globals.js +2 -1
  11. package/dist/cjs/globals.js.map +1 -0
  12. package/dist/cjs/index.d.ts +10 -19
  13. package/dist/cjs/index.js +69 -76
  14. package/dist/cjs/index.js.map +1 -0
  15. package/dist/cjs/mapextensions.d.ts +2 -0
  16. package/dist/cjs/mapextensions.js +30 -0
  17. package/dist/cjs/mapextensions.js.map +1 -0
  18. package/dist/cjs/newClasses/asyncIterable.d.ts +123 -0
  19. package/dist/cjs/{asyncIterable.js → newClasses/asyncIterable.js} +7 -4
  20. package/dist/cjs/newClasses/asyncIterable.js.map +1 -0
  21. package/dist/cjs/newClasses/descriptor.d.ts +401 -0
  22. package/dist/cjs/{descriptor.js → newClasses/descriptor.js} +150 -80
  23. package/dist/cjs/newClasses/descriptor.js.map +1 -0
  24. package/dist/cjs/newClasses/iterable.d.ts +125 -0
  25. package/dist/cjs/{iterable.js → newClasses/iterable.js} +36 -10
  26. package/dist/cjs/newClasses/iterable.js.map +1 -0
  27. package/dist/cjs/newClasses/refmap.d.ts +238 -0
  28. package/dist/cjs/newClasses/refmap.js +433 -0
  29. package/dist/cjs/newClasses/refmap.js.map +1 -0
  30. package/dist/cjs/newClasses/refset.d.ts +186 -0
  31. package/dist/cjs/{refset.js → newClasses/refset.js} +18 -3
  32. package/dist/cjs/newClasses/refset.js.map +1 -0
  33. package/dist/cjs/objectextensions.d.ts +7 -6
  34. package/dist/cjs/objectextensions.js +85 -43
  35. package/dist/cjs/objectextensions.js.map +1 -0
  36. package/dist/cjs/reflectextensions.js +16 -12
  37. package/dist/cjs/reflectextensions.js.map +1 -0
  38. package/dist/cjs/stringextensions.js +1 -0
  39. package/dist/cjs/stringextensions.js.map +1 -0
  40. package/dist/cjs/symbolextensions.js +3 -1
  41. package/dist/cjs/symbolextensions.js.map +1 -0
  42. package/dist/cjs/weakrefextensions.js +1 -0
  43. package/dist/cjs/weakrefextensions.js.map +1 -0
  44. package/dist/mjs/arrayextensions.js +1 -0
  45. package/dist/mjs/arrayextensions.js.map +1 -0
  46. package/dist/mjs/functionextensions.js +1 -0
  47. package/dist/mjs/functionextensions.js.map +1 -0
  48. package/dist/mjs/globals.js +2 -1
  49. package/dist/mjs/globals.js.map +1 -0
  50. package/dist/mjs/index.d.ts +10 -19
  51. package/dist/mjs/index.js +67 -60
  52. package/dist/mjs/index.js.map +1 -0
  53. package/dist/mjs/mapextensions.d.ts +2 -0
  54. package/dist/mjs/mapextensions.js +27 -0
  55. package/dist/mjs/mapextensions.js.map +1 -0
  56. package/dist/mjs/newClasses/asyncIterable.d.ts +123 -0
  57. package/dist/mjs/{asyncIterable.js → newClasses/asyncIterable.js} +106 -105
  58. package/dist/mjs/newClasses/asyncIterable.js.map +1 -0
  59. package/dist/mjs/newClasses/descriptor.d.ts +401 -0
  60. package/dist/mjs/{descriptor.js → newClasses/descriptor.js} +129 -67
  61. package/dist/mjs/newClasses/descriptor.js.map +1 -0
  62. package/dist/mjs/newClasses/iterable.d.ts +125 -0
  63. package/dist/mjs/newClasses/iterable.js +199 -0
  64. package/dist/mjs/newClasses/iterable.js.map +1 -0
  65. package/dist/mjs/newClasses/refmap.d.ts +238 -0
  66. package/dist/mjs/newClasses/refmap.js +417 -0
  67. package/dist/mjs/newClasses/refmap.js.map +1 -0
  68. package/dist/mjs/newClasses/refset.d.ts +186 -0
  69. package/dist/mjs/{refset.js → newClasses/refset.js} +17 -3
  70. package/dist/mjs/newClasses/refset.js.map +1 -0
  71. package/dist/mjs/objectextensions.d.ts +7 -6
  72. package/dist/mjs/objectextensions.js +84 -42
  73. package/dist/mjs/objectextensions.js.map +1 -0
  74. package/dist/mjs/reflectextensions.js +16 -12
  75. package/dist/mjs/reflectextensions.js.map +1 -0
  76. package/dist/mjs/stringextensions.js +1 -0
  77. package/dist/mjs/stringextensions.js.map +1 -0
  78. package/dist/mjs/symbolextensions.js +3 -1
  79. package/dist/mjs/symbolextensions.js.map +1 -0
  80. package/dist/mjs/weakrefextensions.js +1 -0
  81. package/dist/mjs/weakrefextensions.js.map +1 -0
  82. package/docs/assets/anchor.js +350 -0
  83. package/docs/assets/bass-addons.css +12 -0
  84. package/docs/assets/bass.css +544 -0
  85. package/docs/assets/fonts/EOT/SourceCodePro-Bold.eot +0 -0
  86. package/docs/assets/fonts/EOT/SourceCodePro-Regular.eot +0 -0
  87. package/docs/assets/fonts/LICENSE.txt +93 -0
  88. package/docs/assets/fonts/OTF/SourceCodePro-Bold.otf +0 -0
  89. package/docs/assets/fonts/OTF/SourceCodePro-Regular.otf +0 -0
  90. package/docs/assets/fonts/TTF/SourceCodePro-Bold.ttf +0 -0
  91. package/docs/assets/fonts/TTF/SourceCodePro-Regular.ttf +0 -0
  92. package/docs/assets/fonts/WOFF/OTF/SourceCodePro-Bold.otf.woff +0 -0
  93. package/docs/assets/fonts/WOFF/OTF/SourceCodePro-Regular.otf.woff +0 -0
  94. package/docs/assets/fonts/WOFF/TTF/SourceCodePro-Bold.ttf.woff +0 -0
  95. package/docs/assets/fonts/WOFF/TTF/SourceCodePro-Regular.ttf.woff +0 -0
  96. package/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Bold.otf.woff2 +0 -0
  97. package/docs/assets/fonts/WOFF2/OTF/SourceCodePro-Regular.otf.woff2 +0 -0
  98. package/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Bold.ttf.woff2 +0 -0
  99. package/docs/assets/fonts/WOFF2/TTF/SourceCodePro-Regular.ttf.woff2 +0 -0
  100. package/docs/assets/fonts/source-code-pro.css +23 -0
  101. package/docs/assets/github.css +123 -0
  102. package/docs/assets/site.js +168 -0
  103. package/docs/assets/split.css +15 -0
  104. package/docs/assets/split.js +782 -0
  105. package/docs/assets/style.css +147 -0
  106. package/docs/index.html +13060 -0
  107. package/jsdoc-config.json +31 -0
  108. package/package.json +12 -3
  109. package/src/globals.js +1 -1
  110. package/src/index.js +75 -82
  111. package/src/mapextensions.js +30 -0
  112. package/src/{asyncIterable.js → newClasses/asyncIterable.js} +117 -117
  113. package/src/{descriptor.js → newClasses/descriptor.js} +137 -74
  114. package/src/newClasses/iterable.js +221 -0
  115. package/src/newClasses/refmap.js +483 -0
  116. package/src/{refset.js → newClasses/refset.js} +29 -16
  117. package/src/objectextensions.js +97 -46
  118. package/src/reflectextensions.js +16 -14
  119. package/src/symbolextensions.js +2 -1
  120. package/tests/index.test.js +1 -1
  121. package/tests/{asyncIterable.test.js → newClasses/asyncIterable.test.js} +3 -4
  122. package/tests/newClasses/descriptor.test.js +252 -0
  123. package/tests/{iterable.test.js → newClasses/iterable.test.js} +2 -4
  124. package/tests/newClasses/refmap.test.js +69 -0
  125. package/tests/{refset.test.js → newClasses/refset.test.js} +2 -4
  126. package/tests/objectextensions.test.js +128 -0
  127. package/tsconfig.base.json +2 -1
  128. package/dist/@nejs/basic-extensions.bundle.1.5.1.js +0 -2
  129. package/dist/@nejs/basic-extensions.bundle.1.5.1.js.map +0 -7
  130. package/dist/cjs/asyncIterable.d.ts +0 -3
  131. package/dist/cjs/descriptor.d.ts +0 -2
  132. package/dist/cjs/iterable.d.ts +0 -3
  133. package/dist/cjs/refset.d.ts +0 -2
  134. package/dist/mjs/asyncIterable.d.ts +0 -3
  135. package/dist/mjs/descriptor.d.ts +0 -2
  136. package/dist/mjs/iterable.d.ts +0 -3
  137. package/dist/mjs/iterable.js +0 -184
  138. package/dist/mjs/refset.d.ts +0 -2
  139. package/src/iterable.js +0 -203
@@ -1,14 +1,26 @@
1
1
  import { Patch } from '@nejs/extension';
2
2
 
3
3
  /**
4
- * `ObjectExtensions` is a patch for the JavaScript built-in `Object` class. It
5
- * adds utility methods to the `Object` class without modifying the global namespace
6
- * directly. This patch includes methods for key validation, object type checking,
7
- * and retrieving the string tag of an object. These methods are useful for
8
- * enhancing the capabilities of the standard `Object` class with additional
9
- * utility functions.
4
+ * `ObjectExtensions` is a patch for the JavaScript built-in `Object` class.
5
+ * It adds utility methods to the `Object` class without modifying the global
6
+ * namespace directly. This patch includes methods for key validation, object
7
+ * type checking, and retrieving the string tag of an object. These methods
8
+ * are useful for enhancing the capabilities of the standard `Object` class
9
+ * with additional utility functions.
10
10
  */
11
11
  export const ObjectExtensions = new Patch(Object, {
12
+ /**
13
+ * The function checks if a value is either `undefined` or `null`.
14
+ *
15
+ * @param {any} value - The parameter "value" is a variable that can hold
16
+ * any value.
17
+ * @returns {boolean} `true` if the value is either `undefined` or `null`,
18
+ * and `false` otherwise.
19
+ */
20
+ isNullDefined(value) {
21
+ return value === undefined || value === null
22
+ },
23
+
12
24
  /**
13
25
  * Checks to see if the supplied `value` is both an object, and has the
14
26
  * appropriate symbol defined.
@@ -22,19 +34,27 @@ export const ObjectExtensions = new Patch(Object, {
22
34
  },
23
35
 
24
36
  /**
25
- * Retrieves the string tag of an object. The string tag is a representation of
26
- * the object's type, as defined by its `Object.prototype.toString` method. This
27
- * utility method is helpful for getting a more descriptive type of an object than
28
- * what is returned by the `typeof` operator, especially for custom objects.
37
+ * Retrieves the string tag of an object. The string tag is a representation
38
+ * of the object's type, as defined by its `Object.prototype.toString`
39
+ * method. This utility method is helpful for getting a more descriptive
40
+ * type of an object than what is returned by the `typeof` operator,
41
+ * especially for custom objects.
29
42
  *
30
43
  * @param {*} value - The object whose string tag is to be retrieved.
44
+ * @param {boolean} strict - if this is set to true, undefined will be
45
+ * returned whenever a supplied object does not have a
46
+ * `Symbol.toStringTag` defined, period. if false, the default,
31
47
  * @returns {string} - The string tag of the object, indicating its type.
32
48
  */
33
- getStringTag(value) {
49
+ getStringTag(value, strict = false) {
34
50
  if (Object.hasStringTag(value)) {
35
51
  return value[Symbol.toStringTag]
36
52
  }
37
53
 
54
+ if (strict) {
55
+ return undefined
56
+ }
57
+
38
58
  if (value && (typeof value === 'function')) {
39
59
  return value.name
40
60
  }
@@ -54,13 +74,13 @@ export const ObjectExtensions = new Patch(Object, {
54
74
  *
55
75
  * @param {any} value - The value whose type is to be determined.
56
76
  * @param {object} [owner=globalThis] - The object in which to look up the
57
- * constructor corresponding to the string tag. Defaults to `globalThis`, which
58
- * covers global constructors like `Array`, `Object`, etc.
59
- * @returns {Function|object|null|undefined} - Returns the constructor or type
60
- * of the value based on its string tag. For 'Null' and 'Undefined', it returns
61
- * `null` and `undefined`, respectively. For other types, it returns the
62
- * corresponding constructor (e.g., `Array` for arrays) if available in the
63
- * `owner` object.
77
+ * constructor corresponding to the string tag. Defaults to `globalThis`,
78
+ * which covers global constructors like `Array`, `Object`, etc.
79
+ * @returns {Function|object|null|undefined} - Returns the constructor or
80
+ * type of the value based on its string tag. For 'Null' and 'Undefined',
81
+ * it returns `null` and `undefined`, respectively. For other types, it
82
+ * returns the corresponding constructor (e.g., `Array` for arrays) if
83
+ * available in the `owner` object.
64
84
  */
65
85
  getType(value, owner = globalThis) {
66
86
  const stringTag = Object.getStringTag(value)
@@ -74,13 +94,14 @@ export const ObjectExtensions = new Patch(Object, {
74
94
  },
75
95
 
76
96
  /**
77
- * Determines if the provided value is an object. This method checks whether the
78
- * value is an instance of `Object` or if its type is 'object'. It's a utility
79
- * method for type-checking, ensuring that a value is an object before performing
80
- * operations that are specific to objects.
97
+ * Determines if the provided value is an object. This method checks whether
98
+ * the value is an instance of `Object` or if its type is 'object'. It's a
99
+ * utility method for type-checking, ensuring that a value is an object
100
+ * before performing operations that are specific to objects.
81
101
  *
82
102
  * @param {*} value - The value to be checked.
83
- * @returns {boolean} - Returns `true` if the value is an object, otherwise `false`.
103
+ * @returns {boolean} - Returns `true` if the value is an object,
104
+ * otherwise `false`.
84
105
  */
85
106
  isObject(value) {
86
107
  return value && (value instanceof Object || typeof value === 'object');
@@ -115,13 +136,14 @@ export const ObjectExtensions = new Patch(Object, {
115
136
  },
116
137
 
117
138
  /**
118
- * Checks if the given value is a valid key for an object. In JavaScript, a valid
119
- * key can be either a string or a symbol. This method is useful for validating
120
- * object keys before using them in operations like setting or getting object properties.
139
+ * Checks if the given value is a valid key for an object. In JavaScript, a
140
+ * valid key can be either a string or a symbol. This method is useful for
141
+ * validating object keys before using them in operations like setting or
142
+ * getting object properties.
121
143
  *
122
144
  * @param {*} value - The value to be checked.
123
- * @returns {boolean} - Returns `true` if the value is a valid object key (string or symbol),
124
- * otherwise `false`.
145
+ * @returns {boolean} - Returns `true` if the value is a valid object key
146
+ * (string or symbol), otherwise `false`.
125
147
  */
126
148
  isValidKey(value) {
127
149
  return (typeof value === 'string' || typeof value === 'symbol');
@@ -134,37 +156,66 @@ export const ObjectExtensions = new Patch(Object, {
134
156
  * @param {object} object the object to pare down
135
157
  * @param {Array<string|symbol>} keys the keys that should appear in the
136
158
  * final reduced object
137
- * @param {boolean} [bindAccessors = true] if this value is true
138
- * then any accessors from the source object will continue to have their
139
- * `this` value bound to the source. If the getter or setter on that object
140
- * is defined using an arrow function, this will not work as intended.
141
- * @returns {object} an object containing only the keys and symbols specified
142
- * in the `keys` parameter.
159
+ * @param {boolean} [bindAccessors = true] if this value is true then any
160
+ * accessors from the source object will continue to have their `this`
161
+ * value bound to the source. If the getter or setter on that object is
162
+ * defined using an arrow function, this will not work as intended.
163
+ * @returns {object} an object containing only the keys and symbols
164
+ * specified in the `keys` parameter.
143
165
  */
144
166
  stripTo(object, keys, bindAccessors = true) {
145
- const result = {}
167
+ if (!object || typeof object !== 'object') {
168
+ throw new TypeError(
169
+ 'Object.stripTo requires an object to strip. Received',
170
+ object
171
+ );
172
+ }
173
+
174
+ const result = {};
146
175
 
147
176
  if (!Array.isArray(keys)) {
148
- return result
177
+ return result;
149
178
  }
150
179
 
151
180
  for (let key of keys) {
152
181
  if (Reflect.has(object, key)) {
153
- const descriptor = Object.getOwnPropertyDescriptor(object, key)
154
- if (Reflect.has(descriptor, 'get') || Reflect.has(descriptor, 'set')) {
182
+ const originalDescriptor = Object.getOwnPropertyDescriptor(object, key);
183
+ const descriptor = { ...originalDescriptor };
184
+
185
+ if (
186
+ typeof descriptor.get === 'function' ||
187
+ typeof descriptor.set === 'function'
188
+ ) {
155
189
  if (bindAccessors) {
156
- descriptor.get = descriptor?.get?.bind(object)
157
- descriptor.set = descriptor?.set?.bind(object)
190
+ descriptor.get = descriptor.get?.bind(object);
191
+ descriptor.set = descriptor.set?.bind(object);
158
192
  }
159
- Object.defineProperty(result, descriptor)
160
- }
161
- else {
162
- Object.defineProperty(result, descriptor)
163
193
  }
194
+
195
+ Object.defineProperty(result, key, descriptor);
164
196
  }
165
197
  }
166
198
 
167
- return result
199
+ return result;
168
200
  },
169
-
170
201
  });
202
+
203
+ export const ObjectPrototypeExtensions = new Patch(Object.prototype, {
204
+ /**
205
+ * Strips an object down to only the keys specified. Optionally, any
206
+ * accessors can be made to retain their context on the source object.
207
+ * This is a passthrough to the static {@link Object.stripTo} function
208
+ *
209
+ * @param {Array<string|symbol>} keys the keys that should appear in the
210
+ * final reduced object
211
+ * @param {boolean} [bindAccessors = true] if this value is true then any
212
+ * accessors from the source object will continue to have their `this`
213
+ * value bound to the source. If the getter or setter on that object is
214
+ * defined using an arrow function, this will not work as intended.
215
+ * @returns {object} an object containing only the keys and symbols
216
+ * specified in the `keys` parameter.
217
+ */
218
+ stripTo(keys, bindAccessors = true) {
219
+ return Object.stripTo(this, keys, bindAccessors)
220
+ }
221
+ })
@@ -1,6 +1,8 @@
1
1
  import { Patch } from '@nejs/extension'
2
2
  import { ObjectExtensions } from './objectextensions.js'
3
3
 
4
+ const { isObject } = ObjectExtensions.patches
5
+
4
6
  /**
5
7
  * The `ReflectExtensions` class is a patch applied to the built-in JavaScript
6
8
  * `Reflect` object. It extends `Reflect` with additional utility methods that
@@ -31,20 +33,22 @@ export const ReflectExtensions = new Patch(Reflect, {
31
33
  )
32
34
  },
33
35
 
36
+ /**
37
+ * Fetches all descriptors of an object, including those mapped to a
38
+ * symbol descriptor value.
39
+ *
40
+ * @param {object} object the object from whose descriptors need to be
41
+ * retrieved.
42
+ * @returns {object} with keys mapped to object descriptors
43
+ * @throws {TypeError} if the supplied `object` is null or not an object
44
+ * a TypeError exception will be thrown
45
+ */
34
46
  ownDescriptors(object) {
35
- const result = {}
36
- const revertOnDone = () => revertOnDone.doIt ? ObjectExtensions.revert() : ''
37
- revertOnDone.doIt = false
38
-
39
- if (!Object.isObject) {
40
- revertOnDone.doIt = true
41
- ObjectExtensions.apply()
47
+ if (!isObject(object)) {
48
+ throw new TypeError('The supplied object must be non-null and an object')
42
49
  }
43
50
 
44
- if (!Object.isObject(object)) {
45
- revertOnDone()
46
- return {}
47
- }
51
+ const result = {}
48
52
 
49
53
  const keys = Reflect.ownKeys(object)
50
54
 
@@ -52,8 +56,6 @@ export const ReflectExtensions = new Patch(Reflect, {
52
56
  result[key] = Object.getOwnPropertyDescriptor(key)
53
57
  }
54
58
 
55
- revertOnDone()
56
-
57
59
  return result
58
60
  },
59
61
 
@@ -69,7 +71,7 @@ export const ReflectExtensions = new Patch(Reflect, {
69
71
  * at least one of the keys provided as arguments exists in the given object.
70
72
  */
71
73
  hasSome(object, ...keys) {
72
- return Object.isObject(object) && (keys.flat(Infinity)
74
+ return isObject(object) && (keys.flat(Infinity)
73
75
  .map(key => Reflect.has(object, key))
74
76
  .some(has => has)
75
77
  )
@@ -60,7 +60,8 @@ export const SymbolExtensions = new Patch(Symbol, {
60
60
  * spec static symbols (`toStringTag`, `iterator`, etc...), and any symbols
61
61
  * created by passing a value directly to the `Symbol` function, such as
62
62
  * `Symbol('name')`
63
- * @returns
63
+ * @returns true if the `value` in question is both a `symbol` and has
64
+ * returns `undefined` if passed to `Symbol.keyFor`
64
65
  */
65
66
  isNonRegistered(value, allowOnlySymbols = false) {
66
67
  return !Symbol.isRegistered(value, allowOnlySymbols)
@@ -1,4 +1,4 @@
1
- const { enableAll, disableAll } = require('../dist/cjs/index.js')
1
+ const { Controls: { enableAll, disableAll } } = require('../dist/cjs/index.js')
2
2
 
3
3
  describe('Enabled extensions', () => {
4
4
  beforeEach(() => {
@@ -1,9 +1,8 @@
1
- const { enableAll, disableAll } = require('../dist/cjs/index.js')
1
+ const { Extensions } = require('../../dist/cjs/index.js')
2
+ const AsyncIterable = Extensions.AsyncIterable.class
3
+ const Iterable = Extensions.Iterable.class
2
4
 
3
5
  describe('AsyncIterable', () => {
4
- beforeAll(() => { enableAll() })
5
- afterAll(() => { disableAll() })
6
-
7
6
  test('should create an async iterable from an array of promises', async () => {
8
7
  const promises = [Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)];
9
8
  const asyncIterable = new AsyncIterable(promises);
@@ -0,0 +1,252 @@
1
+ const { Extensions } = require('../../dist/cjs/index.js')
2
+ const Descriptor = Extensions.Descriptor.class
3
+
4
+ describe('Descriptor', () => {
5
+ describe('constructor', () => {
6
+ test('should create a Descriptor from a property descriptor', () => {
7
+ const obj = { a: 1 };
8
+ const desc = new Descriptor(Object.getOwnPropertyDescriptor(obj, 'a'));
9
+ expect(desc.isData).toBe(true);
10
+ expect(desc.value).toBe(1);
11
+ });
12
+
13
+ test('should throw an error for invalid descriptors', () => {
14
+ expect(() => new Descriptor(5)).toThrow();
15
+ });
16
+ });
17
+
18
+ describe('isAccessor', () => {
19
+ test('should return true for accessor descriptors', () => {
20
+ const getter = () => {};
21
+ const setter = (value) => {};
22
+ const obj = {};
23
+ Object.defineProperty(obj, 'prop', { get: getter, set: setter });
24
+ const desc = new Descriptor(obj, 'prop');
25
+ expect(desc.isAccessor).toBe(true);
26
+ });
27
+
28
+ test('should return false for data descriptors', () => {
29
+ const obj = { a: 1 };
30
+ const desc = new Descriptor(obj, 'a');
31
+ expect(desc.isAccessor).toBe(false);
32
+ });
33
+ });
34
+
35
+ describe('isData', () => {
36
+ test('should return true for data descriptors', () => {
37
+ const obj = { a: 1 };
38
+ const desc = new Descriptor(obj, 'a');
39
+ expect(desc.isData).toBe(true);
40
+ });
41
+
42
+ test('should return false for accessor descriptors', () => {
43
+ const obj = {};
44
+ Object.defineProperty(obj, 'prop', {
45
+ get: () => {},
46
+ set: (value) => {}
47
+ });
48
+ const desc = new Descriptor(obj, 'prop');
49
+ expect(desc.isData).toBe(false);
50
+ });
51
+ });
52
+
53
+ describe('isDescriptor', () => {
54
+ test('should return true for valid descriptors', () => {
55
+ const desc = new Descriptor({ value: 10 });
56
+ expect(desc.isDescriptor).toBe(true);
57
+ });
58
+
59
+ test('should throw an error for invalid descriptors', () => {
60
+ expect(() => new Descriptor({})).toThrow()
61
+ });
62
+ });
63
+
64
+ describe('getters and setters', () => {
65
+ let desc;
66
+
67
+ beforeEach(() => {
68
+ desc = new Descriptor({ value: 10, writable: true, enumerable: true, configurable: true });
69
+ });
70
+
71
+ test('configurable getter and setter', () => {
72
+ expect(desc.configurable).toBe(true);
73
+ desc.configurable = false;
74
+ expect(desc.configurable).toBe(false);
75
+ });
76
+
77
+ test('enumerable getter and setter', () => {
78
+ expect(desc.enumerable).toBe(true);
79
+ desc.enumerable = false;
80
+ expect(desc.enumerable).toBe(false);
81
+ });
82
+
83
+ test('writable getter and setter', () => {
84
+ expect(desc.writable).toBe(true);
85
+ desc.writable = false;
86
+ expect(desc.writable).toBe(false);
87
+ });
88
+
89
+ test('value getter and setter', () => {
90
+ expect(desc.value).toBe(10);
91
+ desc.value = 20;
92
+ expect(desc.value).toBe(20);
93
+ });
94
+ });
95
+
96
+ describe('applyTo', () => {
97
+ test('should apply descriptor to an object', () => {
98
+ const obj = {};
99
+ const desc = new Descriptor({
100
+ configurable: true,
101
+ enumerable: true,
102
+ value: 10,
103
+ writable: true
104
+ });
105
+ desc.applyTo(obj, 'a');
106
+ expect(obj.a).toBe(10);
107
+ });
108
+
109
+ test('should throw error for non-object or invalid key', () => {
110
+ const desc = new Descriptor({ value: 10 });
111
+ expect(() => desc.applyTo(123, 'a')).toThrow();
112
+ expect(() => desc.applyTo({}, null)).toThrow();
113
+ });
114
+ });
115
+
116
+ describe('static methods', () => {
117
+ describe('getData', () => {
118
+ test('should return the value of a data property', () => {
119
+ const obj = { a: 10 };
120
+ expect(Descriptor.getData(obj, 'a')).toBe(10);
121
+ });
122
+
123
+ test('should return undefined for non-data properties', () => {
124
+ const obj = {};
125
+ Object.defineProperty(obj, 'prop', {
126
+ get: () => 20,
127
+ set: (value) => {}
128
+ });
129
+ expect(Descriptor.getData(obj, 'prop')).toBeNull();
130
+ });
131
+ });
132
+
133
+ describe('getAccessor', () => {
134
+ test('should return value of getter', () => {
135
+ const obj = {
136
+ get prop() { return 20 }
137
+ };
138
+ const accessedValue = Descriptor.getAccessor(obj, 'prop');
139
+ expect(accessedValue).toBe(20)
140
+ });
141
+
142
+ test('should return value getter when dependent on an adajcent value', () => {
143
+ const obj = {
144
+ age: 21,
145
+ get canDrink() { return this.age >= 21 }
146
+ };
147
+ const accessedValue = Descriptor.getAccessor(obj, 'canDrink');
148
+ expect(accessedValue).toBe(true)
149
+ });
150
+
151
+ test('should return null for non-accessor properties', () => {
152
+ const obj = { a: 10 };
153
+ expect(Descriptor.getAccessor(obj, 'a')).toBeNull();
154
+ });
155
+ });
156
+
157
+ describe('for', () => {
158
+ test('should return a descriptor for a given object property', () => {
159
+ const obj = { a: 10 };
160
+ const descriptor = Descriptor.for(obj, 'a');
161
+ expect(descriptor.value).toBe(10);
162
+ expect(descriptor.writable).toBe(true);
163
+ expect(descriptor.enumerable).toBe(true);
164
+ expect(descriptor.configurable).toBe(true);
165
+ });
166
+
167
+ test('should return null for invalid inputs', () => {
168
+ expect(Descriptor.for(null, 'a')).toBeNull();
169
+ expect(Descriptor.for({}, Symbol())).toBeNull();
170
+ });
171
+ });
172
+
173
+ describe('accessor', () => {
174
+ test('should create an accessor descriptor', () => {
175
+ const getter = () => 'get';
176
+ const setter = (value) => { /* Do nothing */ };
177
+ const descriptor = Descriptor.accessor(getter, setter);
178
+ expect(descriptor.get).toBe(getter);
179
+ expect(descriptor.set).toBe(setter);
180
+ expect(descriptor.enumerable).toBe(false);
181
+ expect(descriptor.configurable).toBe(false);
182
+ });
183
+
184
+ // Additional tests for variations in enumerable and configurable
185
+ });
186
+
187
+ describe('data', () => {
188
+ test('should create a data descriptor', () => {
189
+ const value = 10;
190
+ const descriptor = Descriptor.data(value);
191
+ expect(descriptor.value).toBe(value);
192
+ expect(descriptor.writable).toBe(true);
193
+ expect(descriptor.enumerable).toBe(false);
194
+ expect(descriptor.configurable).toBe(false);
195
+ });
196
+
197
+ // Additional tests for variations in writable, enumerable, and configurable
198
+ });
199
+
200
+ });
201
+
202
+ describe('Symbol methods', () => {
203
+ test('Symbol.for("nodejs.util.inspect.custom") should return custom inspect info', () => {
204
+ const desc = new Descriptor({ value: 10 });
205
+ expect(typeof desc[Symbol.for('nodejs.util.inspect.custom')]).toBe('function');
206
+ });
207
+
208
+ test('Symbol.toPrimitive should handle different hints', () => {
209
+ const dataDesc = new Descriptor({ value: 10 });
210
+ const accessorDesc = new Descriptor({
211
+ age: 18,
212
+ get canDrink() { return this.age >= 21 },
213
+ set canDrink(value) {
214
+ if (value)
215
+ this.age = Math.max(21, this.age)
216
+ else
217
+ this.age = Math.min(20, this.age)
218
+ },
219
+ }, 'canDrink')
220
+
221
+ expect(dataDesc[Symbol.toPrimitive]('string')).toBe('Data (value)');
222
+ dataDesc.writable = true
223
+ expect(dataDesc[Symbol.toPrimitive]('string')).toBe('Data (value, writable)')
224
+ expect(isNaN(dataDesc[Symbol.toPrimitive]('number'))).toBe(true);
225
+
226
+ expect(accessorDesc[Symbol.toPrimitive]('string')).toBe(
227
+ 'Accessor (getter, setter)'
228
+ )
229
+ expect(accessorDesc[Symbol.toPrimitive]('number')).toBe(NaN)
230
+ expect(accessorDesc.boundGet()).toBe(false)
231
+ expect(accessorDesc.hasObject).toBe(true)
232
+ expect(accessorDesc.set).toBeTruthy()
233
+ accessorDesc.boundSet?.(true)
234
+ expect(accessorDesc.boundGet()).toBe(true)
235
+ });
236
+ });
237
+
238
+ describe('static properties', () => {
239
+ test('SHARED_KEYS should contain expected keys', () => {
240
+ expect(Descriptor.SHARED_KEYS).toEqual(['configurable', 'enumerable']);
241
+ });
242
+
243
+ test('ACCESSOR_KEYS should contain expected keys', () => {
244
+ expect(Descriptor.ACCESSOR_KEYS).toEqual(['get', 'set']);
245
+ });
246
+
247
+ test('DATA_KEYS should contain expected keys', () => {
248
+ expect(Descriptor.DATA_KEYS).toEqual(['value', 'writable']);
249
+ });
250
+ });
251
+
252
+ });
@@ -1,9 +1,7 @@
1
- const { enableAll, disableAll } = require('../dist/cjs/index.js')
1
+ const { Extensions } = require('../../dist/cjs/index.js')
2
+ const Iterable = Extensions.Iterable.class
2
3
 
3
4
  describe('Iterable', () => {
4
- beforeAll(() => { enableAll() })
5
- afterAll(() => { disableAll() })
6
-
7
5
  test('should create an iterable from an array', () => {
8
6
  const array = [1, 2, 3];
9
7
  const iterable = new Iterable(array);
@@ -0,0 +1,69 @@
1
+ const { Extensions } = require('../../dist/cjs/index.js')
2
+ const RefMap = Extensions.RefMap.class
3
+
4
+ describe('RefMap', () => {
5
+ let refMap;
6
+
7
+ beforeEach(() => {
8
+ refMap = new RefMap();
9
+ });
10
+
11
+ // Test the constructor
12
+ test('should create an empty RefMap', () => {
13
+ expect(refMap.size).toBe(0);
14
+ });
15
+
16
+ // Test objectifying behavior
17
+ test('should toggle objectify values', () => {
18
+ refMap.objectifying(true);
19
+ expect(refMap.objectifyValues).toBe(true);
20
+ refMap.objectifying(false);
21
+ expect(refMap.objectifyValues).toBe(false);
22
+ });
23
+
24
+ // Test set and get methods
25
+ test('should set and get weakly referenced values', () => {
26
+ const obj = {};
27
+ refMap.set('key', obj);
28
+ expect(refMap.get('key')).toBe(obj);
29
+ expect(refMap.size).toBe(1);
30
+ });
31
+
32
+ // Test handling of primitives
33
+ test('should handle primitives when objectifying is true', () => {
34
+ refMap.objectifying(true);
35
+ refMap.set('number', 123);
36
+ expect(typeof refMap.get('number')).toBe('object');
37
+ });
38
+
39
+ // Test error handling
40
+ test('should throw error for invalid values in set', () => {
41
+ expect(() => refMap.set('key', undefined)).toThrow(TypeError);
42
+ });
43
+
44
+ // Test asObject method
45
+ test('asObject should return a regular object', () => {
46
+ const obj = {};
47
+ refMap.set('key', obj);
48
+ const regularObject = refMap.asObject();
49
+ expect(typeof regularObject).toBe('object');
50
+ expect(regularObject.key).toBe(obj);
51
+ });
52
+
53
+ // Test hasValue method
54
+ test('hasValue should correctly determine the presence of a value', () => {
55
+ const obj = {};
56
+ refMap.set('key', obj);
57
+ expect(refMap.hasValue(obj)).toBe(true);
58
+ expect(refMap.hasValue({})).toBe(false);
59
+ });
60
+
61
+ // Test forEach method
62
+ test('forEach should iterate over values', () => {
63
+ const mockCallback = jest.fn();
64
+ const obj = {};
65
+ refMap.set('key', obj);
66
+ refMap.forEach(mockCallback);
67
+ expect(mockCallback.mock.calls.length).toBe(1);
68
+ });
69
+ });
@@ -1,9 +1,7 @@
1
- const { enableAll, disableAll } = require('../dist/cjs/index.js')
1
+ const { Extensions } = require('../../dist/cjs/index.js')
2
+ const RefSet = Extensions.RefSet.class
2
3
 
3
4
  describe('RefSet', () => {
4
- beforeAll(() => { enableAll() })
5
- afterAll(() => { disableAll() })
6
-
7
5
  let refSet;
8
6
 
9
7
  beforeEach(() => {