@nejs/basic-extensions 2.7.0 → 2.9.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 (271) hide show
  1. package/.vscode/settings.json +5 -0
  2. package/README.md +6250 -1574
  3. package/bin/version +100 -0
  4. package/dist/@nejs/basic-extensions.bundle.2.8.0.js +19 -0
  5. package/dist/@nejs/basic-extensions.bundle.2.8.0.js.map +7 -0
  6. package/dist/cjs/array.extensions.d.ts +39 -0
  7. package/dist/cjs/array.extensions.js +303 -0
  8. package/dist/cjs/array.extensions.js.map +1 -0
  9. package/dist/cjs/big.int.extension.d.ts +31 -0
  10. package/dist/cjs/big.int.extension.js +164 -0
  11. package/dist/cjs/big.int.extension.js.map +1 -0
  12. package/dist/cjs/{newClasses → classes}/asyncIterable.js +32 -44
  13. package/dist/cjs/classes/asyncIterable.js.map +1 -0
  14. package/dist/cjs/{newClasses → classes}/deferred.js +66 -138
  15. package/dist/cjs/classes/deferred.js.map +1 -0
  16. package/dist/cjs/{newClasses → classes}/descriptor.js +56 -90
  17. package/dist/cjs/classes/descriptor.js.map +1 -0
  18. package/dist/cjs/classes/index.d.ts +13 -0
  19. package/dist/cjs/classes/index.js +57 -0
  20. package/dist/cjs/classes/index.js.map +1 -0
  21. package/dist/cjs/classes/introspector.d.ts +20 -0
  22. package/dist/cjs/classes/introspector.js +130 -0
  23. package/dist/cjs/classes/introspector.js.map +1 -0
  24. package/dist/cjs/{newClasses → classes}/iterable.js +42 -63
  25. package/dist/cjs/classes/iterable.js.map +1 -0
  26. package/dist/cjs/classes/param.parser.d.ts +227 -0
  27. package/dist/cjs/classes/param.parser.js +242 -0
  28. package/dist/cjs/classes/param.parser.js.map +1 -0
  29. package/dist/cjs/classes/pluggable.proxy.d.ts +152 -0
  30. package/dist/cjs/classes/pluggable.proxy.js +444 -0
  31. package/dist/cjs/classes/pluggable.proxy.js.map +1 -0
  32. package/dist/cjs/{newClasses → classes}/refmap.js +18 -30
  33. package/dist/cjs/classes/refmap.js.map +1 -0
  34. package/dist/cjs/{newClasses → classes}/refset.js +28 -47
  35. package/dist/cjs/classes/refset.js.map +1 -0
  36. package/dist/cjs/classes/symkeys.d.ts +292 -0
  37. package/dist/cjs/classes/symkeys.js +424 -0
  38. package/dist/cjs/classes/symkeys.js.map +1 -0
  39. package/dist/cjs/classes/type.d.ts +56 -0
  40. package/dist/cjs/classes/type.js +405 -0
  41. package/dist/cjs/classes/type.js.map +1 -0
  42. package/dist/cjs/function.extensions.js +757 -0
  43. package/dist/cjs/function.extensions.js.map +1 -0
  44. package/dist/cjs/global.this.js +261 -0
  45. package/dist/cjs/global.this.js.map +1 -0
  46. package/dist/cjs/index.d.ts +4 -3
  47. package/dist/cjs/index.js +62 -32
  48. package/dist/cjs/index.js.map +1 -1
  49. package/dist/cjs/json.extensions.d.ts +2 -0
  50. package/dist/cjs/json.extensions.js +108 -0
  51. package/dist/cjs/json.extensions.js.map +1 -0
  52. package/dist/{mjs/mapextensions.d.ts → cjs/map.extensions.d.ts} +1 -0
  53. package/dist/cjs/map.extensions.js +142 -0
  54. package/dist/cjs/map.extensions.js.map +1 -0
  55. package/dist/cjs/number.extension.d.ts +44 -0
  56. package/dist/cjs/number.extension.js +260 -0
  57. package/dist/cjs/number.extension.js.map +1 -0
  58. package/dist/cjs/object.extensions.d.ts +62 -0
  59. package/dist/cjs/object.extensions.js +1128 -0
  60. package/dist/cjs/object.extensions.js.map +1 -0
  61. package/dist/cjs/proxy.extensions.d.ts +2 -0
  62. package/dist/cjs/proxy.extensions.js +207 -0
  63. package/dist/cjs/proxy.extensions.js.map +1 -0
  64. package/dist/cjs/reflect.extensions.js +316 -0
  65. package/dist/cjs/reflect.extensions.js.map +1 -0
  66. package/dist/cjs/regular.expression.extensions.d.ts +2 -0
  67. package/dist/cjs/regular.expression.extensions.js +423 -0
  68. package/dist/cjs/regular.expression.extensions.js.map +1 -0
  69. package/dist/cjs/set.extensions.d.ts +40 -0
  70. package/dist/cjs/{setextensions.js → set.extensions.js} +150 -2
  71. package/dist/cjs/set.extensions.js.map +1 -0
  72. package/dist/cjs/string.extensions.js +661 -0
  73. package/dist/cjs/string.extensions.js.map +1 -0
  74. package/dist/{mjs/symbolextensions.d.ts → cjs/symbol.extensions.d.ts} +1 -0
  75. package/dist/cjs/symbol.extensions.js +380 -0
  76. package/dist/cjs/symbol.extensions.js.map +1 -0
  77. package/dist/cjs/{weakrefextensions.js → weakref.extensions.js} +1 -1
  78. package/dist/cjs/weakref.extensions.js.map +1 -0
  79. package/dist/mjs/array.extensions.d.ts +39 -0
  80. package/dist/mjs/array.extensions.js +300 -0
  81. package/dist/mjs/array.extensions.js.map +1 -0
  82. package/dist/mjs/big.int.extension.d.ts +31 -0
  83. package/dist/mjs/big.int.extension.js +161 -0
  84. package/dist/mjs/big.int.extension.js.map +1 -0
  85. package/dist/mjs/classes/asyncIterable.js.map +1 -0
  86. package/dist/mjs/classes/deferred.js.map +1 -0
  87. package/dist/mjs/{newClasses → classes}/descriptor.js +7 -4
  88. package/dist/mjs/classes/descriptor.js.map +1 -0
  89. package/dist/mjs/classes/index.d.ts +13 -0
  90. package/dist/mjs/classes/index.js +40 -0
  91. package/dist/mjs/classes/index.js.map +1 -0
  92. package/dist/mjs/classes/introspector.d.ts +20 -0
  93. package/dist/mjs/classes/introspector.js +126 -0
  94. package/dist/mjs/classes/introspector.js.map +1 -0
  95. package/dist/mjs/classes/iterable.js.map +1 -0
  96. package/dist/mjs/classes/param.parser.d.ts +227 -0
  97. package/dist/mjs/classes/param.parser.js +238 -0
  98. package/dist/mjs/classes/param.parser.js.map +1 -0
  99. package/dist/mjs/classes/pluggable.proxy.d.ts +152 -0
  100. package/dist/mjs/classes/pluggable.proxy.js +438 -0
  101. package/dist/mjs/classes/pluggable.proxy.js.map +1 -0
  102. package/dist/mjs/{newClasses → classes}/refmap.js +3 -3
  103. package/dist/mjs/classes/refmap.js.map +1 -0
  104. package/dist/mjs/classes/refset.js.map +1 -0
  105. package/dist/mjs/classes/symkeys.d.ts +292 -0
  106. package/dist/mjs/classes/symkeys.js +420 -0
  107. package/dist/mjs/classes/symkeys.js.map +1 -0
  108. package/dist/mjs/classes/type.d.ts +56 -0
  109. package/dist/mjs/classes/type.js +401 -0
  110. package/dist/mjs/classes/type.js.map +1 -0
  111. package/dist/mjs/function.extensions.js +754 -0
  112. package/dist/mjs/function.extensions.js.map +1 -0
  113. package/dist/mjs/global.this.js +258 -0
  114. package/dist/mjs/global.this.js.map +1 -0
  115. package/dist/mjs/index.d.ts +4 -3
  116. package/dist/mjs/index.js +49 -19
  117. package/dist/mjs/index.js.map +1 -1
  118. package/dist/mjs/json.extensions.d.ts +2 -0
  119. package/dist/mjs/json.extensions.js +105 -0
  120. package/dist/mjs/json.extensions.js.map +1 -0
  121. package/dist/{cjs/mapextensions.d.ts → mjs/map.extensions.d.ts} +1 -0
  122. package/dist/mjs/map.extensions.js +139 -0
  123. package/dist/mjs/map.extensions.js.map +1 -0
  124. package/dist/mjs/number.extension.d.ts +44 -0
  125. package/dist/mjs/number.extension.js +257 -0
  126. package/dist/mjs/number.extension.js.map +1 -0
  127. package/dist/mjs/object.extensions.d.ts +62 -0
  128. package/dist/mjs/object.extensions.js +1124 -0
  129. package/dist/mjs/object.extensions.js.map +1 -0
  130. package/dist/mjs/proxy.extensions.d.ts +2 -0
  131. package/dist/mjs/proxy.extensions.js +204 -0
  132. package/dist/mjs/proxy.extensions.js.map +1 -0
  133. package/dist/mjs/reflect.extensions.js +313 -0
  134. package/dist/mjs/reflect.extensions.js.map +1 -0
  135. package/dist/mjs/regular.expression.extensions.d.ts +2 -0
  136. package/dist/mjs/regular.expression.extensions.js +420 -0
  137. package/dist/mjs/regular.expression.extensions.js.map +1 -0
  138. package/dist/mjs/set.extensions.d.ts +40 -0
  139. package/dist/mjs/{setextensions.js → set.extensions.js} +149 -1
  140. package/dist/mjs/set.extensions.js.map +1 -0
  141. package/dist/mjs/string.extensions.js +658 -0
  142. package/dist/mjs/string.extensions.js.map +1 -0
  143. package/dist/{cjs/symbolextensions.d.ts → mjs/symbol.extensions.d.ts} +1 -0
  144. package/dist/mjs/symbol.extensions.js +377 -0
  145. package/dist/mjs/symbol.extensions.js.map +1 -0
  146. package/dist/mjs/{weakrefextensions.js → weakref.extensions.js} +1 -1
  147. package/dist/mjs/weakref.extensions.js.map +1 -0
  148. package/docs/index.html +24452 -5692
  149. package/package.json +7 -5
  150. package/src/array.extensions.js +322 -0
  151. package/src/big.int.extension.js +163 -0
  152. package/src/{newClasses → classes}/descriptor.js +16 -12
  153. package/src/classes/index.js +51 -0
  154. package/src/classes/introspector.js +167 -0
  155. package/src/classes/param.parser.js +253 -0
  156. package/src/classes/pluggable.proxy.js +485 -0
  157. package/src/{newClasses → classes}/refmap.js +5 -3
  158. package/src/classes/symkeys.js +464 -0
  159. package/src/classes/type.js +427 -0
  160. package/src/function.extensions.js +818 -0
  161. package/src/global.this.js +304 -0
  162. package/src/index.js +56 -23
  163. package/src/json.extensions.js +109 -0
  164. package/src/map.extensions.js +144 -0
  165. package/src/number.extension.js +273 -0
  166. package/src/object.extensions.js +1237 -0
  167. package/src/proxy.extensions.js +229 -0
  168. package/src/reflect.extensions.js +346 -0
  169. package/src/regular.expression.extensions.js +451 -0
  170. package/src/{setextensions.js → set.extensions.js} +151 -2
  171. package/src/string.extensions.js +734 -0
  172. package/src/symbol.extensions.js +389 -0
  173. package/tests/newClasses/refmap.test.js +3 -2
  174. package/tsconfig.base.json +5 -3
  175. package/tsconfig.cjs.json +2 -2
  176. package/tsconfig.esm.json +2 -2
  177. package/dist/@nejs/basic-extensions.bundle.2.6.0.js +0 -17
  178. package/dist/@nejs/basic-extensions.bundle.2.6.0.js.map +0 -7
  179. package/dist/cjs/arrayextensions.d.ts +0 -10
  180. package/dist/cjs/arrayextensions.js +0 -73
  181. package/dist/cjs/arrayextensions.js.map +0 -1
  182. package/dist/cjs/functionextensions.js +0 -202
  183. package/dist/cjs/functionextensions.js.map +0 -1
  184. package/dist/cjs/globals.js +0 -166
  185. package/dist/cjs/globals.js.map +0 -1
  186. package/dist/cjs/mapextensions.js +0 -32
  187. package/dist/cjs/mapextensions.js.map +0 -1
  188. package/dist/cjs/newClasses/asyncIterable.js.map +0 -1
  189. package/dist/cjs/newClasses/deferred.js.map +0 -1
  190. package/dist/cjs/newClasses/descriptor.js.map +0 -1
  191. package/dist/cjs/newClasses/iterable.js.map +0 -1
  192. package/dist/cjs/newClasses/refmap.js.map +0 -1
  193. package/dist/cjs/newClasses/refset.js.map +0 -1
  194. package/dist/cjs/objectextensions.d.ts +0 -11
  195. package/dist/cjs/objectextensions.js +0 -232
  196. package/dist/cjs/objectextensions.js.map +0 -1
  197. package/dist/cjs/reflectextensions.js +0 -111
  198. package/dist/cjs/reflectextensions.js.map +0 -1
  199. package/dist/cjs/setextensions.d.ts +0 -2
  200. package/dist/cjs/setextensions.js.map +0 -1
  201. package/dist/cjs/stringextensions.js +0 -158
  202. package/dist/cjs/stringextensions.js.map +0 -1
  203. package/dist/cjs/symbolextensions.js +0 -69
  204. package/dist/cjs/symbolextensions.js.map +0 -1
  205. package/dist/cjs/weakrefextensions.js.map +0 -1
  206. package/dist/mjs/arrayextensions.d.ts +0 -10
  207. package/dist/mjs/arrayextensions.js +0 -70
  208. package/dist/mjs/arrayextensions.js.map +0 -1
  209. package/dist/mjs/functionextensions.js +0 -199
  210. package/dist/mjs/functionextensions.js.map +0 -1
  211. package/dist/mjs/globals.js +0 -163
  212. package/dist/mjs/globals.js.map +0 -1
  213. package/dist/mjs/mapextensions.js +0 -29
  214. package/dist/mjs/mapextensions.js.map +0 -1
  215. package/dist/mjs/newClasses/asyncIterable.js.map +0 -1
  216. package/dist/mjs/newClasses/deferred.js.map +0 -1
  217. package/dist/mjs/newClasses/descriptor.js.map +0 -1
  218. package/dist/mjs/newClasses/iterable.js.map +0 -1
  219. package/dist/mjs/newClasses/refmap.js.map +0 -1
  220. package/dist/mjs/newClasses/refset.js.map +0 -1
  221. package/dist/mjs/objectextensions.d.ts +0 -11
  222. package/dist/mjs/objectextensions.js +0 -229
  223. package/dist/mjs/objectextensions.js.map +0 -1
  224. package/dist/mjs/reflectextensions.js +0 -108
  225. package/dist/mjs/reflectextensions.js.map +0 -1
  226. package/dist/mjs/setextensions.d.ts +0 -2
  227. package/dist/mjs/setextensions.js.map +0 -1
  228. package/dist/mjs/stringextensions.js +0 -155
  229. package/dist/mjs/stringextensions.js.map +0 -1
  230. package/dist/mjs/symbolextensions.js +0 -66
  231. package/dist/mjs/symbolextensions.js.map +0 -1
  232. package/dist/mjs/weakrefextensions.js.map +0 -1
  233. package/src/arrayextensions.js +0 -75
  234. package/src/functionextensions.js +0 -225
  235. package/src/globals.js +0 -196
  236. package/src/mapextensions.js +0 -32
  237. package/src/objectextensions.js +0 -256
  238. package/src/reflectextensions.js +0 -118
  239. package/src/stringextensions.js +0 -166
  240. package/src/symbolextensions.js +0 -69
  241. /package/dist/cjs/{newClasses → classes}/asyncIterable.d.ts +0 -0
  242. /package/dist/cjs/{newClasses → classes}/deferred.d.ts +0 -0
  243. /package/dist/cjs/{newClasses → classes}/descriptor.d.ts +0 -0
  244. /package/dist/cjs/{newClasses → classes}/iterable.d.ts +0 -0
  245. /package/dist/cjs/{newClasses → classes}/refmap.d.ts +0 -0
  246. /package/dist/cjs/{newClasses → classes}/refset.d.ts +0 -0
  247. /package/dist/cjs/{functionextensions.d.ts → function.extensions.d.ts} +0 -0
  248. /package/dist/cjs/{globals.d.ts → global.this.d.ts} +0 -0
  249. /package/dist/cjs/{reflectextensions.d.ts → reflect.extensions.d.ts} +0 -0
  250. /package/dist/cjs/{stringextensions.d.ts → string.extensions.d.ts} +0 -0
  251. /package/dist/cjs/{weakrefextensions.d.ts → weakref.extensions.d.ts} +0 -0
  252. /package/dist/mjs/{newClasses → classes}/asyncIterable.d.ts +0 -0
  253. /package/dist/mjs/{newClasses → classes}/asyncIterable.js +0 -0
  254. /package/dist/mjs/{newClasses → classes}/deferred.d.ts +0 -0
  255. /package/dist/mjs/{newClasses → classes}/deferred.js +0 -0
  256. /package/dist/mjs/{newClasses → classes}/descriptor.d.ts +0 -0
  257. /package/dist/mjs/{newClasses → classes}/iterable.d.ts +0 -0
  258. /package/dist/mjs/{newClasses → classes}/iterable.js +0 -0
  259. /package/dist/mjs/{newClasses → classes}/refmap.d.ts +0 -0
  260. /package/dist/mjs/{newClasses → classes}/refset.d.ts +0 -0
  261. /package/dist/mjs/{newClasses → classes}/refset.js +0 -0
  262. /package/dist/mjs/{functionextensions.d.ts → function.extensions.d.ts} +0 -0
  263. /package/dist/mjs/{globals.d.ts → global.this.d.ts} +0 -0
  264. /package/dist/mjs/{reflectextensions.d.ts → reflect.extensions.d.ts} +0 -0
  265. /package/dist/mjs/{stringextensions.d.ts → string.extensions.d.ts} +0 -0
  266. /package/dist/mjs/{weakrefextensions.d.ts → weakref.extensions.d.ts} +0 -0
  267. /package/src/{newClasses → classes}/asyncIterable.js +0 -0
  268. /package/src/{newClasses → classes}/deferred.js +0 -0
  269. /package/src/{newClasses → classes}/iterable.js +0 -0
  270. /package/src/{newClasses → classes}/refset.js +0 -0
  271. /package/src/{weakrefextensions.js → weakref.extensions.js} +0 -0
@@ -0,0 +1,818 @@
1
+ import { Patch } from '@nejs/extension'
2
+
3
+ /**
4
+ * The `FunctionExtensions` class is a patch applied to the built-in JavaScript
5
+ * `Function` constructor. It extends `Function` with additional utility methods
6
+ * for determining the specific type or nature of function-like objects. These
7
+ * methods allow developers to distinguish between classes, regular functions,
8
+ * async functions, and arrow functions in a more intuitive and straightforward
9
+ * manner. This class is part of the `@nejs/extension` library and enhances the
10
+ * capabilities of function handling and introspection in JavaScript.
11
+ */
12
+ export const FunctionExtensions = new Patch(Function, {
13
+ [Patch.kMutablyHidden]: {
14
+ /**
15
+ * Retrieves the properties of a function and its prototype.
16
+ *
17
+ * This method uses the `Reflect.ownKeys` function to get all the keys
18
+ * (including non-enumerable and symbol keys) of the function and its
19
+ * prototype. It then uses `Object.getOwnPropertyDescriptor` to get the
20
+ * property descriptors for each key. The descriptors include information
21
+ * about the property's value, writability, enumerability, and
22
+ * configurability.
23
+ *
24
+ * @param {Function} fn - The function whose properties are to be retrieved.
25
+ * @returns {Array} An array containing the function itself, its property
26
+ * descriptors, its prototype, and the prototype's property descriptors.
27
+ *
28
+ * @example
29
+ * function MyFunction() {}
30
+ * MyFunction.myProp = 'hello';
31
+ * MyFunction.prototype.myProtoProp = 'world';
32
+ *
33
+ * const result = getClassProperties(MyFunction);
34
+ * console.log(result);
35
+ * // Output: [MyFunction, { myProp: { value: 'hello', writable: true,
36
+ * // enumerable: true, configurable: true } }, MyFunction.prototype,
37
+ * // { myProtoProp: { value: 'world', writable: true, enumerable: true,
38
+ * // configurable: true } }]
39
+ */
40
+ getClassProperties(fn) {
41
+ const descriptors = Reflect.ownKeys(fn).reduce((acc, key) => {
42
+ acc[key] = Object.getOwnPropertyDescriptor(fn, key)
43
+ return acc
44
+ }, {})
45
+
46
+ const prototypeDescriptors = Reflect.ownKeys(fn.prototype).reduce(
47
+ (acc, key) => {
48
+ acc[key] = Object.getOwnPropertyDescriptor(fn.prototype, key)
49
+ return acc
50
+ }, {}
51
+ )
52
+
53
+ return [fn, descriptors, fn.prototype, prototypeDescriptors]
54
+ },
55
+
56
+ /**
57
+ * Determines if a given value is an asynchronous function. It checks if the
58
+ * value is an instance of `Function` and if its string representation
59
+ * includes the keyword 'Async'. This method is particularly useful for
60
+ * identifying async functions.
61
+ *
62
+ * @param {*} value - The value to be checked.
63
+ * @returns {boolean} Returns `true` if the value is an async function,
64
+ * otherwise `false`.
65
+ */
66
+ isAsync(value) {
67
+ const stringTag = /(\w+)]/g.exec(Object.prototype.toString.call(value))[1]
68
+ return (
69
+ value instanceof Function &&
70
+ stringTag.includes('Async')
71
+ )
72
+ },
73
+
74
+ /**
75
+ * The `ifAsync` function checks if a given value is an async function and
76
+ * returns one of two provided values based on the result. This function is
77
+ * a convenience method for performing conditional operations based on the
78
+ * type of a value.
79
+ *
80
+ * @param {*} value - The value to be checked. If this is an async function,
81
+ * `thenValue` is returned, otherwise `elseValue` is returned.
82
+ * @param {*} thenValue - The value to be returned if `value` is an async
83
+ * function.
84
+ * @param {*} elseValue - The value to be returned if `value` is not an
85
+ * async function.
86
+ * @returns {*} Returns `thenValue` if `value` is an async function,
87
+ * otherwise returns `elseValue`.
88
+ * @see {@link isThenElse}
89
+ *
90
+ * @example
91
+ * // Suppose we have an async function and a regular function
92
+ * async function asyncFunc() { return 'I am async'; }
93
+ * function regularFunc() { return 'I am regular'; }
94
+ *
95
+ * // Using ifAsync
96
+ * console.log(Function.ifAsync(asyncFunc, 'Async', 'Not Async'));
97
+ * // Output: 'Async'
98
+ * console.log(Function.ifAsync(regularFunc, 'Async', 'Not Async'));
99
+ * // Output: 'Not Async'
100
+ */
101
+ ifAsync(value, thenValue, elseValue) {
102
+ return isThenElse(this.isAsync(value), thenValue, elseValue)
103
+ },
104
+
105
+ /**
106
+ * The function checks if a given value is an async generator function
107
+ *
108
+ * @param {any} value - The `value` parameter is the value that we want to
109
+ * check if it is a generator function.
110
+ * @returns {boolean} `true` if the value is an instance of a function and
111
+ * its string tag is 'AsyncGeneratorFunction', otherwise it returns `false`.
112
+ */
113
+ isAsyncGenerator(value) {
114
+ const stringTag = getStringTag(value)
115
+
116
+ return (
117
+ value instanceof Function &&
118
+ stringTag == 'AsyncGeneratorFunction'
119
+ )
120
+ },
121
+
122
+ /**
123
+ * The `ifAsyncGenerator` function checks if a given value is an async
124
+ * generator function and returns one of two provided values based on the
125
+ * result. This function is a convenience method for performing conditional
126
+ * operations based on the type of a value.
127
+ *
128
+ * @param {*} value - The value to be checked. If this is an async
129
+ * generator function, `thenValue` is returned, otherwise `elseValue` is
130
+ * returned.
131
+ * @param {*} thenValue - The value to be returned if `value` is an async
132
+ * generator function.
133
+ * @param {*} elseValue - The value to be returned if `value` is not an
134
+ * async generator function.
135
+ * @returns {*} Returns `thenValue` if `value` is an async generator
136
+ * function, otherwise returns `elseValue`.
137
+ *
138
+ * @example
139
+ * // Suppose we have an async generator function and a regular function
140
+ * async function* asyncGenFunc() { yield 'I am async'; }
141
+ * function regularFunc() { return 'I am regular'; }
142
+ *
143
+ * // Using ifAsyncGenerator
144
+ * console.log(Function.ifAsyncGenerator(asyncGenFunc, 'Async', 'Not Async'));
145
+ * // Output: 'Async'
146
+ * console.log(Function.ifAsyncGenerator(regularFunc, 'Async', 'Not Async'));
147
+ * // Output: 'Not Async'
148
+ */
149
+ ifAsyncGenerator(value, thenValue, elseValue) {
150
+ return isThenElse(this.isAsyncGenerator(value), thenValue, elseValue)
151
+ },
152
+
153
+ /**
154
+ * Checks if a given value is an arrow function. It verifies if the value is
155
+ * an instance of `Function`, if its string representation includes the '=>'
156
+ * symbol, and if it lacks a prototype, which is a characteristic of arrow
157
+ * functions in JavaScript.
158
+ *
159
+ * @param {*} value - The value to be checked.
160
+ * @returns {boolean} Returns `true` if the value is an arrow function,
161
+ * otherwise `false`.
162
+ */
163
+ isBigArrow(value) {
164
+ return (
165
+ value instanceof Function &&
166
+ String(value).includes('=>') &&
167
+ !String(value).startsWith('bound') &&
168
+ !Reflect.has(value, 'prototype')
169
+ );
170
+ },
171
+
172
+ /**
173
+ * The `ifBigArrow` function checks if a given value is an arrow function
174
+ * and returns one of two provided values based on the result. This function
175
+ * is a convenience method for performing conditional operations based on
176
+ * the type of a value.
177
+ *
178
+ * @param {*} value - The value to be checked. If this is an arrow function,
179
+ * `thenValue` is returned, otherwise `elseValue` is returned.
180
+ * @param {*} thenValue - The value to be returned if `value` is an arrow
181
+ * function.
182
+ * @param {*} elseValue - The value to be returned if `value` is not an
183
+ * arrow function.
184
+ * @returns {*} Returns `thenValue` if `value` is an arrow function,
185
+ * otherwise returns `elseValue`.
186
+ *
187
+ * @example
188
+ * // Suppose we have an arrow function and a regular function
189
+ * const arrowFunc = () => 'I am an arrow function';
190
+ * function regularFunc() { return 'I am a regular function'; }
191
+ *
192
+ * // Using ifBigArrow
193
+ * console.log(Function.ifBigArrow(arrowFunc, 'Arrow', 'Not Arrow'));
194
+ * // Output: 'Arrow'
195
+ * console.log(Function.ifBigArrow(regularFunc, 'Arrow', 'Not Arrow'));
196
+ * // Output: 'Not Arrow'
197
+ */
198
+ ifBigArrow(value, thenValue, elseValue) {
199
+ return isThenElse(this.isBigArrow(value), thenValue, elseValue)
200
+ },
201
+
202
+ /**
203
+ * Determines if a given value is a bound function. Bound functions are
204
+ * created using the `Function.prototype.bind` method, which allows setting
205
+ * the `this` value at the time of binding. This method checks if the value
206
+ * is an instance of `Function`, if its string representation starts with
207
+ * 'bound', and if it lacks a `prototype` property. These characteristics
208
+ * are indicative of bound functions in JavaScript.
209
+ *
210
+ * @param {*} value - The value to be checked, typically a function.
211
+ * @returns {boolean} Returns `true` if the value is a bound function,
212
+ * otherwise `false`. Bound functions have a specific format in their
213
+ * string representation and do not have their own `prototype` property.
214
+ */
215
+ isBound(value) {
216
+ return (
217
+ value instanceof Function &&
218
+ String(value).startsWith('bound') &&
219
+ !Reflect.has(value, 'prototype')
220
+ )
221
+ },
222
+
223
+ /**
224
+ * The `ifBound` function checks if a given value is a bound function and
225
+ * returns one of two provided values based on the result. This function
226
+ * is a convenience method for performing conditional operations based on
227
+ * the type of a value.
228
+ *
229
+ * @param {*} value - The value to be checked. If this is a bound function,
230
+ * `thenValue` is returned, otherwise `elseValue` is returned.
231
+ * @param {*} thenValue - The value to be returned if `value` is a bound
232
+ * function.
233
+ * @param {*} elseValue - The value to be returned if `value` is not a
234
+ * bound function.
235
+ * @returns {*} Returns `thenValue` if `value` is a bound function,
236
+ * otherwise returns `elseValue`.
237
+ *
238
+ * @example
239
+ * // Suppose we have a bound function and a regular function
240
+ * const boundFunc = function() { return this.x }.bind({x: 'I am bound'});
241
+ * function regularFunc() { return 'I am a regular function'; }
242
+ *
243
+ * // Using ifBound
244
+ * console.log(Function.ifBound(boundFunc, 'Bound', 'Not Bound'));
245
+ * // Output: 'Bound'
246
+ * console.log(Function.ifBound(regularFunc, 'Bound', 'Not Bound'));
247
+ * // Output: 'Not Bound'
248
+ */
249
+ ifBound(value, thenValue, elseValue) {
250
+ return isThenElse(this.isBound(value), thenValue, elseValue)
251
+ },
252
+
253
+ /**
254
+ * Determines if a given value is a class. It checks if the value is an
255
+ * instance of `Function` and if its string representation includes the
256
+ * keyword 'class'. This method is useful for distinguishing classes from
257
+ * other function types in JavaScript.
258
+ *
259
+ * @param {*} value - The value to be checked.
260
+ * @returns {boolean} Returns `true` if the value is a class, otherwise
261
+ * `false`.
262
+ */
263
+ isClass(value) {
264
+ return value instanceof Function && !!/^class\s/.exec(String(value))
265
+ },
266
+
267
+ /**
268
+ * The `ifClass` function checks if a given value is a class and returns
269
+ * one of two provided values based on the result. This function is a
270
+ * convenience method for performing conditional operations based on the
271
+ * type of a value.
272
+ *
273
+ * @param {*} value - The value to be checked. If this is a class,
274
+ * `thenValue` is returned, otherwise `elseValue` is returned.
275
+ * @param {*} thenValue - The value to be returned if `value` is a class.
276
+ * @param {*} elseValue - The value to be returned if `value` is not a
277
+ * class.
278
+ * @returns {*} Returns `thenValue` if `value` is a class, otherwise returns
279
+ * `elseValue`.
280
+ *
281
+ * @example
282
+ * // Suppose we have a class and a regular function
283
+ * class MyClass {}
284
+ * function myFunction() {}
285
+ *
286
+ * // Using ifClass
287
+ * console.log(Function.ifClass(MyClass, 'Class', 'Not Class'));
288
+ * // Output: 'Class'
289
+ * console.log(Function.ifClass(myFunction, 'Class', 'Not Class'));
290
+ * // Output: 'Not Class'
291
+ */
292
+ ifClass(value, thenValue, elseValue) {
293
+ return isThenElse(this.isClass(value), thenValue, elseValue)
294
+ },
295
+
296
+ /**
297
+ * Checks if a given value is a regular function. This method verifies if
298
+ * the value is an instance of `Function`, which includes regular functions,
299
+ * classes, and async functions but excludes arrow functions.
300
+ *
301
+ * @param {*} value - The value to be checked.
302
+ * @returns {boolean} Returns `true` if the value is a regular function,
303
+ * otherwise `false`.
304
+ */
305
+ isFunction(value) {
306
+ return value instanceof Function && !Function.isClass(value);
307
+ },
308
+
309
+ /**
310
+ * The `ifFunction` method checks if a given value is a regular function
311
+ * and returns one of two provided values based on the result. This method
312
+ * is a convenience for performing conditional operations based on the
313
+ * type of a value.
314
+ *
315
+ * @param {*} value - The value to be checked. If this is a function,
316
+ * `thenValue` is returned, otherwise `elseValue` is returned.
317
+ * @param {*} thenValue - The value to be returned if `value` is a function.
318
+ * @param {*} elseValue - The value to be returned if `value` is not a
319
+ * function.
320
+ * @returns {*} Returns `thenValue` if `value` is a function, otherwise
321
+ * returns `elseValue`.
322
+ *
323
+ * @example
324
+ * // Suppose we have a function and a non-function value
325
+ * function myFunction() {}
326
+ * let notFunction = "I'm not a function";
327
+ *
328
+ * // Using ifFunction
329
+ * console.log(Function.ifFunction(myFunction, 'Function', 'Not Function'));
330
+ * // Output: 'Function'
331
+ * console.log(Function.ifFunction(notFunction, 'Function', 'Not Function'));
332
+ * // Output: 'Not Function'
333
+ */
334
+ ifFunction(value, thenValue, elseValue) {
335
+ return isThenElse(this.isFunction(value), thenValue, elseValue)
336
+ },
337
+
338
+ /**
339
+ * The function checks if a given value is a generator function
340
+ *
341
+ * @param {any} value - The `value` parameter is the value that we want to
342
+ * check if it is a generator function.
343
+ * @returns {boolean} `true` if the value is an instance of a function and
344
+ * its string tag is 'GeneratorFunction', otherwise it returns `false`.
345
+ */
346
+ isGenerator(value) {
347
+ const stringTag = getStringTag(value)
348
+
349
+ return (
350
+ value instanceof Function &&
351
+ stringTag == 'GeneratorFunction'
352
+ )
353
+ },
354
+
355
+ /**
356
+ * The `ifGenerator` method checks if a given value is a generator function
357
+ * and returns one of two provided values based on the result. This method
358
+ * is a convenience for performing conditional operations based on the
359
+ * type of a value.
360
+ *
361
+ * @param {*} value - The value to be checked. If this is a generator
362
+ * function, `thenValue` is returned, otherwise `elseValue` is returned.
363
+ * @param {*} thenValue - The value to be returned if `value` is a generator
364
+ * function.
365
+ * @param {*} elseValue - The value to be returned if `value` is not a
366
+ * generator function.
367
+ * @returns {*} Returns `thenValue` if `value` is a generator function,
368
+ * otherwise returns `elseValue`.
369
+ *
370
+ * @example
371
+ * // Suppose we have a generator function and a non-generator function
372
+ * function* myGenerator() {}
373
+ * function myFunction() {}
374
+ *
375
+ * // Using ifGenerator
376
+ * console.log(Function.ifGenerator(myGenerator, 'Generator', 'Not Generator'));
377
+ * // Output: 'Generator'
378
+ * console.log(Function.ifGenerator(myFunction, 'Generator', 'Not Generator'));
379
+ * // Output: 'Not Generator'
380
+ */
381
+ ifGenerator(value, thenValue, elseValue) {
382
+ return isThenElse(this.isGenerator(value), thenValue, elseValue)
383
+ },
384
+
385
+ /**
386
+ * This method modifies the behavior of the `instanceof` operator for a
387
+ * given class. It does this by defining a custom `Symbol.hasInstance`
388
+ * method on the class. The custom method checks if the string tag of the
389
+ * instance matches the name of the class or if the instance is part of
390
+ * the prototype chain of the class.
391
+ *
392
+ * @param {Function} Class - The class for which to modify the behavior
393
+ * of the `instanceof` operator.
394
+ *
395
+ * @example
396
+ * // Suppose we have a class `MyClass`
397
+ * class MyClass {}
398
+ *
399
+ * // And an instance of the class
400
+ * const myInstance = new MyClass();
401
+ *
402
+ * // Before applying `StringTagHasInstance`, `instanceof` works as usual
403
+ * console.log(myInstance instanceof MyClass); // Output: true
404
+ *
405
+ * // Now we apply `StringTagHasInstance` to `MyClass`
406
+ * FunctionExtensions.patches.StringTagHasInstance(MyClass);
407
+ *
408
+ * // `instanceof` now checks the string tag and the prototype chain
409
+ * console.log(myInstance instanceof MyClass); // Output: true
410
+ */
411
+ StringTagHasInstance(Class) {
412
+ Object.defineProperty(Class, Symbol.hasInstance, {
413
+ value: function stringTagAwareHasInstance(fn) {
414
+ const protoChain = getPrototypeChainEntries(fn)
415
+ return (
416
+ fn[Symbol.toStringTag] === this.name ||
417
+ fn instanceof this
418
+ )
419
+ }
420
+ })
421
+ },
422
+ },
423
+ })
424
+
425
+ const {
426
+ isAsyncGenerator: pIsAsyncGenerator, ifAsyncGenerator: pIfAsyncGenerator,
427
+ isAsync: pIsAsync, ifAsync: pIfAsync,
428
+ isBigArrow: pIsBigArrow, ifBigArrow: pIfBigArrow,
429
+ isBound: pIsBound, ifBound: pIfBound,
430
+ isClass: pIsClass, ifClass: pIfClass,
431
+ isFunction: pIsFunction, ifFunction: pIfFunction,
432
+ isGenerator: pIsGenerator, ifGenerator: pIfGenerator,
433
+ } = FunctionExtensions.patches
434
+
435
+ export const FunctionPrototypeExtensions = new Patch(Function.prototype, {
436
+ [Patch.kMutablyHidden]: {
437
+ /**
438
+ * Determines if a given value is an asynchronous function. It checks if the
439
+ * value is an instance of `Function` and if its string representation
440
+ * includes the keyword 'Async'. This method is particularly useful for
441
+ * identifying async functions.
442
+ *
443
+ * @returns {boolean} Returns `true` if the value is an async function,
444
+ * otherwise `false`.
445
+ */
446
+ get isAsync() {
447
+ return pIsAsync(this)
448
+ },
449
+
450
+ /**
451
+ * The `ifAsync` method checks if the current function is asynchronous and
452
+ * returns one of two provided values based on the result. This method is
453
+ * a convenience for performing conditional operations based on the
454
+ * type of a function.
455
+ *
456
+ * @param {*} thenValue - The value to be returned if the function is
457
+ * asynchronous.
458
+ * @param {*} elseValue - The value to be returned if the function is not
459
+ * asynchronous.
460
+ * @returns {*} Returns `thenValue` if the function is asynchronous,
461
+ * otherwise returns `elseValue`.
462
+ * @see {@link Function.ifAsync}
463
+ *
464
+ * @example
465
+ * // Suppose we have an async function and a non-async function
466
+ * async function myAsyncFunction() {}
467
+ * function myFunction() {}
468
+ *
469
+ * // Using ifAsync
470
+ * console.log(myAsyncFunction.ifAsync('Async', 'Not Async'));
471
+ * // Output: 'Async'
472
+ * console.log(myFunction.ifAsync('Async', 'Not Async'));
473
+ * // Output: 'Not Async'
474
+ */
475
+ ifAsync(thenValue, elseValue) {
476
+ return pIfAsync(this, thenValue, elseValue)
477
+ },
478
+
479
+ /**
480
+ * The function checks if a given value is an async generator function
481
+ *
482
+ * @returns {boolean} `true` if the value is an instance of a function and
483
+ * its string tag is 'AsyncGeneratorFunction', otherwise it returns `false`.
484
+ */
485
+ get isAsyncGenerator() {
486
+ return pIsAsyncGenerator(this)
487
+ },
488
+
489
+ /**
490
+ * The `ifAsyncGenerator` method checks if the current function is an
491
+ * asynchronous generator and returns one of two provided values based on
492
+ * the result. This method is a convenience for performing conditional
493
+ * operations based on the type of a function.
494
+ *
495
+ * @param {*} thenValue - The value to be returned if the function is an
496
+ * asynchronous generator.
497
+ * @param {*} elseValue - The value to be returned if the function is not
498
+ * an asynchronous generator.
499
+ * @returns {*} Returns `thenValue` if the function is an asynchronous
500
+ * generator, otherwise returns `elseValue`.
501
+ * @see {@link Function.ifAsyncGenerator}
502
+ *
503
+ * @example
504
+ * // Suppose we have an async generator function and a non-async function
505
+ * async function* myAsyncGeneratorFunction() {}
506
+ * function myFunction() {}
507
+ *
508
+ * // Using ifAsyncGenerator
509
+ * console.log(myAsyncGeneratorFunction.ifAsyncGenerator(
510
+ * 'Async Generator', 'Not Async Generator'
511
+ * ));
512
+ * // Output: 'Async Generator'
513
+ * console.log(myFunction.ifAsyncGenerator(
514
+ * 'Async Generator', 'Not Async Generator'
515
+ * ));
516
+ * // Output: 'Not Async Generator'
517
+ */
518
+ ifAsyncGenerator(thenValue, elseValue) {
519
+ return pIfAsyncGenerator(this, thenValue, elseValue)
520
+ },
521
+
522
+ /**
523
+ * Checks if a given value is an arrow function. It verifies if the value is
524
+ * an instance of `Function`, if its string representation includes the '=>'
525
+ * symbol, and if it lacks a prototype, which is a characteristic of arrow
526
+ * functions in JavaScript.
527
+ *
528
+ * @returns {boolean} Returns `true` if the value is an arrow function,
529
+ * otherwise `false`.
530
+ */
531
+ get isBigArrow() {
532
+ return pIsBigArrow(this)
533
+ },
534
+
535
+ /**
536
+ * Checks if the current function is a "big arrow" function and
537
+ * returns one of two provided values based on the result.
538
+ *
539
+ * A "big arrow" function is an arrow function that is not bound
540
+ * to a specific context and does not have its own `this` value.
541
+ *
542
+ * @param {*} thenValue - The value to be returned if the function
543
+ * is a "big arrow" function.
544
+ * @param {*} elseValue - The value to be returned if the function
545
+ * is not a "big arrow" function.
546
+ * @returns {*} Returns `thenValue` if the function is a "big arrow"
547
+ * function, otherwise returns `elseValue`.
548
+ *
549
+ * @example
550
+ * // Suppose we have a "big arrow" function and a regular function
551
+ * const bigArrowFn = () => {}
552
+ * function regularFn() {}
553
+ *
554
+ * // Using ifBigArrow
555
+ * console.log(bigArrowFn.ifBigArrow('Big Arrow', 'Not Big Arrow'))
556
+ * // Output: 'Big Arrow'
557
+ * console.log(regularFn.ifBigArrow('Big Arrow', 'Not Big Arrow'))
558
+ * // Output: 'Not Big Arrow'
559
+ */
560
+ ifBigArrow(thenValue, elseValue) {
561
+ return pIfBigArrow(this, thenValue, elseValue)
562
+ },
563
+
564
+ /**
565
+ * Determines if a given value is a bound function. Bound functions are
566
+ * created using the `Function.prototype.bind` method, which allows setting
567
+ * the `this` value at the time of binding. This method checks if the value
568
+ * is an instance of `Function`, if its string representation starts with
569
+ * 'bound', and if it lacks a `prototype` property. These characteristics
570
+ * are indicative of bound functions in JavaScript.
571
+ *
572
+ * @returns {boolean} Returns `true` if the value is a bound function,
573
+ * otherwise `false`. Bound functions have a specific format in their
574
+ * string representation and do not have their own `prototype` property.
575
+ */
576
+ get isBound() {
577
+ return pIsBound(this)
578
+ },
579
+
580
+ /**
581
+ * Checks if the current function is bound and returns one of two
582
+ * provided values based on the result.
583
+ *
584
+ * A bound function is a function that has a fixed `this` value and
585
+ * may have preset arguments. It is created using the
586
+ * `Function.prototype.bind` method.
587
+ *
588
+ * @param {*} thenValue - The value to be returned if the function
589
+ * is bound.
590
+ * @param {*} elseValue - The value to be returned if the function
591
+ * is not bound.
592
+ * @returns {*} Returns `thenValue` if the function is bound,
593
+ * otherwise returns `elseValue`.
594
+ *
595
+ * @example
596
+ * // Suppose we have a bound function and a regular function
597
+ * const boundFn = function() {}.bind(null)
598
+ * function regularFn() {}
599
+ *
600
+ * // Using ifBound
601
+ * console.log(boundFn.ifBound('Bound', 'Not Bound'))
602
+ * // Output: 'Bound'
603
+ * console.log(regularFn.ifBound('Bound', 'Not Bound'))
604
+ * // Output: 'Not Bound'
605
+ */
606
+ ifBound(thenValue, elseValue) {
607
+ return pIfBound(this, thenValue, elseValue)
608
+ },
609
+
610
+ /**
611
+ * Determines if a given value is a class. It checks if the value is an
612
+ * instance of `Function` and if its string representation includes the
613
+ * keyword 'class'. This method is useful for distinguishing classes from
614
+ * other function types in JavaScript.
615
+ *
616
+ * @returns {boolean} Returns `true` if the value is a class, otherwise
617
+ * `false`.
618
+ */
619
+ get isClass() {
620
+ return pIsClass(this)
621
+ },
622
+
623
+ /**
624
+ * Checks if the current function is a class and returns one of two
625
+ * provided values based on the result.
626
+ *
627
+ * A class is a special type of function in JavaScript that is
628
+ * defined using the `class` keyword. It serves as a blueprint for
629
+ * creating objects and encapsulates data and behavior.
630
+ *
631
+ * @param {any} thenValue - The value to be returned if the function
632
+ * is a class.
633
+ * @param {any} elseValue - The value to be returned if the function
634
+ * is not a class.
635
+ * @returns {any} Returns `thenValue` if the function is a class,
636
+ * otherwise returns `elseValue`.
637
+ *
638
+ * @example
639
+ * // Suppose we have a class and a regular function
640
+ * class MyClass {}
641
+ * function myFunction() {}
642
+ *
643
+ * // Using ifClass
644
+ * console.log(MyClass.ifClass('Class', 'Not Class'))
645
+ * // Output: 'Class'
646
+ * console.log(myFunction.ifClass('Class', 'Not Class'))
647
+ * // Output: 'Not Class'
648
+ */
649
+ ifClass(thenValue, elseValue) {
650
+ return pIfClass(this, thenValue, elseValue)
651
+ },
652
+
653
+ /**
654
+ * Checks if a given value is a regular function. This method verifies if
655
+ * the value is an instance of `Function`, which includes regular functions,
656
+ * classes, and async functions but excludes arrow functions.
657
+ *
658
+ * @returns {boolean} Returns `true` if the value is a regular function,
659
+ * otherwise `false`.
660
+ */
661
+ get isFunction() {
662
+ return pIsFunction(this)
663
+ },
664
+
665
+ /**
666
+ * Checks if the current function is a regular function and returns
667
+ * one of two provided values based on the result.
668
+ *
669
+ * A regular function is an instance of `Function`, which includes
670
+ * regular functions, classes, and async functions but excludes
671
+ * arrow functions.
672
+ *
673
+ * @param {any} thenValue - The value to be returned if the function
674
+ * is a regular function.
675
+ * @param {any} elseValue - The value to be returned if the function
676
+ * is not a regular function.
677
+ * @returns {any} Returns `thenValue` if the function is a regular
678
+ * function, otherwise returns `elseValue`.
679
+ *
680
+ * @example
681
+ * // Suppose we have a regular function and an arrow function
682
+ * function regularFunction() {}
683
+ * const arrowFunction = () => {}
684
+ *
685
+ * // Using ifFunction
686
+ * console.log(regularFunction.ifFunction('Regular', 'Not Regular'))
687
+ * // Output: 'Regular'
688
+ * console.log(arrowFunction.ifFunction('Regular', 'Not Regular'))
689
+ * // Output: 'Not Regular'
690
+ */
691
+ ifFunction(thenValue, elseValue) {
692
+ return pIfFunction(this, thenValue, elseValue)
693
+ },
694
+
695
+ /**
696
+ * The function checks if a given value is a generator function
697
+ *
698
+ * @returns {boolean} `true` if the value is an instance of a function and
699
+ * its string tag is 'GeneratorFunction', otherwise it returns `false`.
700
+ */
701
+ get isGenerator() {
702
+ return pIsGenerator(this)
703
+ },
704
+
705
+ /**
706
+ * Checks if the current function is a generator function and
707
+ * returns one of two provided values based on the result.
708
+ *
709
+ * A generator function is a special type of function that can be
710
+ * paused and resumed, allowing it to yield multiple values over
711
+ * time rather than returning a single value.
712
+ *
713
+ * @param {any} thenValue - The value to be returned if the
714
+ * function is a generator function.
715
+ * @param {any} elseValue - The value to be returned if the
716
+ * function is not a generator function.
717
+ * @returns {any} Returns `thenValue` if the function is a
718
+ * generator function, otherwise returns `elseValue`.
719
+ *
720
+ * @example
721
+ * // Suppose we have a generator function and a regular function
722
+ * function* generatorFunction() {
723
+ * yield 1
724
+ * yield 2
725
+ * yield 3
726
+ * }
727
+ * function regularFunction() {}
728
+ *
729
+ * // Using ifGenerator
730
+ * console.log(generatorFunction.ifGenerator('Generator', 'Regular'))
731
+ * // Output: 'Generator'
732
+ * console.log(regularFunction.ifGenerator('Generator', 'Regular'))
733
+ * // Output: 'Regular'
734
+ */
735
+ ifGenerator(thenValue, elseValue) {
736
+ return pIfGenerator(this, thenValue, elseValue)
737
+ },
738
+
739
+ /**
740
+ * Retrieves the properties of the current function and its prototype.
741
+ *
742
+ * This method uses the `getClassProperties` function from the
743
+ * `FunctionExtensions.patches` object to get all the properties of the
744
+ * current function and its prototype. The properties include both
745
+ * enumerable and non-enumerable properties, as well as properties
746
+ * defined with symbols.
747
+ *
748
+ * @returns {Array} An array containing the function itself, its property
749
+ * descriptors, its prototype, and the prototype's property descriptors.
750
+ *
751
+ * @example
752
+ * // Suppose we have a function with a property and a prototype property
753
+ * function MyFunction() {}
754
+ * MyFunction.myProp = 'hello';
755
+ * MyFunction.prototype.myProtoProp = 'world';
756
+ *
757
+ * // Using getClassProperties
758
+ * const result = MyFunction.getClassProperties();
759
+ * console.log(result);
760
+ * // Output: [MyFunction, { myProp: { value: 'hello', writable: true,
761
+ * // enumerable: true, configurable: true } }, MyFunction.prototype,
762
+ * // { myProtoProp: { value: 'world', writable: true, enumerable: true,
763
+ * // configurable: true } }]
764
+ */
765
+ getClassProperties() {
766
+ return FunctionExtensions.patches.getClassProperties(this)
767
+ },
768
+ },
769
+ })
770
+
771
+ // NOTE to self; this is repeated here otherwise a circular reference from
772
+ // Object<->Function<->Global occurs. See original source in global.this.js
773
+ // {@see globalThis.isThenElse}
774
+ function isThenElse(bv, tv, ev) {
775
+ if (arguments.length > 1) {
776
+ var _then = isFunction(tv) ? tv(bv) : tv; if (arguments.length > 2) {
777
+ var _else = isFunction(ev) ? tv(bv) : ev; return bv ? _then : _else
778
+ } return bv || _then;
779
+ } return bv
780
+ }
781
+
782
+ function hasStringTag(value) {
783
+ return Object.isObject(value) && Reflect.has(value, Symbol.toStringTag)
784
+ }
785
+
786
+ function getStringTag(value, strict = false) {
787
+ if (Object.hasStringTag(value)) {
788
+ return value[Symbol.toStringTag]
789
+ }
790
+
791
+ if (strict) {
792
+ return undefined
793
+ }
794
+
795
+ if (value && (typeof value === 'function')) {
796
+ return value.name
797
+ }
798
+
799
+ return /\s(.+)]/.exec(Object.prototype.toString.call(value))[1];
800
+ }
801
+
802
+ function getPrototypeChainEntries(object) {
803
+ const entries = []
804
+
805
+ let prototype = Object.getPrototypeOf(object)
806
+ while (prototype) {
807
+ const descriptors = Reflect.ownKeys(prototype).reduce((acc, key) => {
808
+ acc[key] = Object.getOwnPropertyDescriptor(prototype, key)
809
+ return acc
810
+ }, {})
811
+
812
+ entries.push([prototype, descriptors])
813
+
814
+ prototype = Object.getPrototypeOf(prototype)
815
+ }
816
+
817
+ return entries
818
+ }