xcraft-core-utils 4.9.0 → 4.10.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.
- package/lib/reflect.js +118 -7
- package/package.json +1 -1
package/lib/reflect.js
CHANGED
|
@@ -1,12 +1,123 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
// Not compatible CommonJS
|
|
4
|
+
// https://github.com/sindresorhus/fn-args/blob/v6.0.0/index.js
|
|
5
|
+
|
|
6
|
+
function functionArguments(function_) {
|
|
7
|
+
if (typeof function_ !== 'function') {
|
|
8
|
+
throw new TypeError('Expected a function');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const commentRegex = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/gm;
|
|
12
|
+
const quotes = ['`', '"', "'"];
|
|
13
|
+
|
|
14
|
+
const functionSource = function_.toString().replace(commentRegex, ''); // Function with no comments
|
|
15
|
+
|
|
16
|
+
let functionWithNoDefaults = '';
|
|
17
|
+
let depth = 0; // () [] {}
|
|
18
|
+
let index = 0;
|
|
19
|
+
|
|
20
|
+
// To remove default values we can not use regexp because finite automaton can not handle such
|
|
21
|
+
// things as (potential) infinity-nested blocks (), [], {}
|
|
22
|
+
|
|
23
|
+
// Remove default values
|
|
24
|
+
for (
|
|
25
|
+
;
|
|
26
|
+
index < functionSource.length && functionSource.charAt(index) !== ')';
|
|
27
|
+
index += 1
|
|
28
|
+
) {
|
|
29
|
+
// Exiting if an arrow occurs. Needed when arrow function without '()'.
|
|
30
|
+
if (functionSource.startsWith('=>', index)) {
|
|
31
|
+
functionWithNoDefaults = functionSource;
|
|
32
|
+
index = functionSource.length;
|
|
33
|
+
break;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// If we found a default value - skip it
|
|
37
|
+
if (functionSource.charAt(index) === '=') {
|
|
38
|
+
for (
|
|
39
|
+
;
|
|
40
|
+
index < functionSource.length &&
|
|
41
|
+
((functionSource.charAt(index) !== ',' &&
|
|
42
|
+
functionSource.charAt(index) !== ')') ||
|
|
43
|
+
depth !== 0);
|
|
44
|
+
index += 1
|
|
45
|
+
) {
|
|
46
|
+
// Skip all quotes
|
|
47
|
+
let wasQuote = false;
|
|
48
|
+
|
|
49
|
+
for (const quote of quotes) {
|
|
50
|
+
if (functionSource.charAt(index) === quote) {
|
|
51
|
+
index += 1;
|
|
52
|
+
|
|
53
|
+
for (
|
|
54
|
+
;
|
|
55
|
+
index < functionSource.length &&
|
|
56
|
+
functionSource.charAt(index) !== quote;
|
|
57
|
+
|
|
58
|
+
) {
|
|
59
|
+
index += 1;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
wasQuote = true;
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// If any quote type was skipped, start the cycle again
|
|
68
|
+
if (wasQuote) {
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
switch (
|
|
73
|
+
functionSource.charAt(index) // Keeps correct depths of all types of parenthesises
|
|
74
|
+
) {
|
|
75
|
+
case '(':
|
|
76
|
+
case '[':
|
|
77
|
+
case '{':
|
|
78
|
+
depth += 1;
|
|
79
|
+
break;
|
|
80
|
+
case ')':
|
|
81
|
+
case ']':
|
|
82
|
+
case '}':
|
|
83
|
+
depth -= 1;
|
|
84
|
+
break;
|
|
85
|
+
default:
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (functionSource.charAt(index) === ',') {
|
|
90
|
+
functionWithNoDefaults += ',';
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (functionSource.charAt(index) === ')') {
|
|
94
|
+
// Quits from the cycle immediately
|
|
95
|
+
functionWithNoDefaults += ')';
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
} else {
|
|
99
|
+
functionWithNoDefaults += functionSource.charAt(index);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (index < functionSource.length && functionSource.charAt(index) === ')') {
|
|
104
|
+
functionWithNoDefaults += ')';
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// The first part matches parens-less arrow functions
|
|
108
|
+
// The second part matches the rest
|
|
109
|
+
const regexFnArguments = /^(?:async)?([^=()]+)=|\(([^)]+)\)/;
|
|
110
|
+
|
|
111
|
+
const match = regexFnArguments.exec(functionWithNoDefaults);
|
|
112
|
+
|
|
113
|
+
return match
|
|
114
|
+
? (match[1] || match[2])
|
|
115
|
+
.split(',')
|
|
116
|
+
.map((x) => x.trim())
|
|
117
|
+
.filter(Boolean)
|
|
118
|
+
: [];
|
|
119
|
+
}
|
|
5
120
|
|
|
6
121
|
exports.funcParams = (func) => {
|
|
7
|
-
|
|
8
|
-
const result = fnStr
|
|
9
|
-
.slice(fnStr.indexOf('(') + 1, fnStr.indexOf(')'))
|
|
10
|
-
.match(ARGUMENT_NAMES);
|
|
11
|
-
return result || [];
|
|
122
|
+
return functionArguments(func);
|
|
12
123
|
};
|