-
Notifications
You must be signed in to change notification settings - Fork 41
/
Copy pathunwrapFunctionShells.js
36 lines (35 loc) · 1.4 KB
/
unwrapFunctionShells.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
/**
* Remove functions which only return another function.
* If params or id on the outer scope are used in the inner function - replace them on the inner function.
* E.g.
* function a(x) {
* return function() {return x + 3}
* }
* // will be replaced with
* function a(x) {return x + 3}
* @param {Arborist} arb
* @param {Function} candidateFilter (optional) a filter to apply on the candidates list
* @return {Arborist}
*/
function unwrapFunctionShells(arb, candidateFilter = () => true) {
const relevantNodes = [
...(arb.ast[0].typeMap.FunctionExpression || []),
...(arb.ast[0].typeMap.FunctionDeclaration || []),
];
for (let i = 0; i < relevantNodes.length; i++) {
const n = relevantNodes[i];
if (['FunctionDeclaration', 'FunctionExpression'].includes(n.type) &&
n.body?.body?.[0]?.type === 'ReturnStatement' &&
(n.body.body[0].argument?.callee?.property?.name || n.body.body[0].argument?.callee?.property?.value) === 'apply' &&
n.body.body[0].argument.arguments?.length === 2 &&
n.body.body[0].argument.callee.object.type === 'FunctionExpression' &&
candidateFilter(n)) {
const replacementNode = n.body.body[0].argument.callee.object;
if (n.id && !replacementNode.id) replacementNode.id = n.id;
if (n.params.length && !replacementNode.params.length) replacementNode.params.push(...n.params);
arb.markNode(n, replacementNode);
}
}
return arb;
}
export default unwrapFunctionShells;