-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
index.js
90 lines (73 loc) · 2.53 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
export default function functionArguments(function_) {
if (typeof function_ !== 'function') {
throw new TypeError('Expected a function');
}
const commentRegex = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/gm;
const quotes = ['`', '"', '\''];
const functionSource = function_.toString().replace(commentRegex, ''); // Function with no comments
let functionWithNoDefaults = '';
let depth = 0; // () [] {}
let index = 0;
// To remove default values we can not use regexp because finite automaton can not handle such
// things as (potential) infinity-nested blocks (), [], {}
// Remove default values
for (; index < functionSource.length && functionSource.charAt(index) !== ')'; index += 1) {
// Exiting if an arrow occurs. Needed when arrow function without '()'.
if (functionSource.startsWith('=>', index)) {
functionWithNoDefaults = functionSource;
index = functionSource.length;
break;
}
// If we found a default value - skip it
if (functionSource.charAt(index) === '=') {
for (; index < functionSource.length && ((functionSource.charAt(index) !== ',' && functionSource.charAt(index) !== ')') || depth !== 0); index += 1) {
// Skip all quotes
let wasQuote = false;
for (const quote of quotes) {
if (functionSource.charAt(index) === quote) {
index += 1;
for (; index < functionSource.length && functionSource.charAt(index) !== quote;) {
index += 1;
}
wasQuote = true;
break;
}
}
// If any quote type was skipped, start the cycle again
if (wasQuote) {
continue;
}
switch (functionSource.charAt(index)) { // Keeps correct depths of all types of parenthesises
case '(':
case '[':
case '{':
depth += 1;
break;
case ')':
case ']':
case '}':
depth -= 1;
break;
default:
}
}
if (functionSource.charAt(index) === ',') {
functionWithNoDefaults += ',';
}
if (functionSource.charAt(index) === ')') { // Quits from the cycle immediately
functionWithNoDefaults += ')';
break;
}
} else {
functionWithNoDefaults += functionSource.charAt(index);
}
}
if (index < functionSource.length && functionSource.charAt(index) === ')') {
functionWithNoDefaults += ')';
}
// The first part matches parens-less arrow functions
// The second part matches the rest
const regexFnArguments = /^(?:async)?([^=()]+)=|\(([^)]+)\)/;
const match = regexFnArguments.exec(functionWithNoDefaults);
return match ? (match[1] || match[2]).split(',').map(x => x.trim()).filter(Boolean) : [];
}