-
Notifications
You must be signed in to change notification settings - Fork 36
/
resolveDefiniteMemberExpressions.js
34 lines (32 loc) · 1.25 KB
/
resolveDefiniteMemberExpressions.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
const {badValue} = require(__dirname + '/../config');
const Sandbox = require(__dirname + '/../utils/sandbox');
const evalInVm = require(__dirname + '/../utils/evalInVm');
/**
* Replace definite member expressions with their intended value.
* E.g.
* '123'[0]; ==> '1';
* 'hello'.length ==> 5;
* @param {Arborist} arb
* @param {Function} candidateFilter (optional) a filter to apply on the candidates list
* @return {Arborist}
*/
function resolveDefiniteMemberExpressions(arb, candidateFilter = () => true) {
let sharedSb;
for (let i = 0; i < arb.ast.length; i++) {
const n = arb.ast[i];
if (n.type === 'MemberExpression' &&
!['UpdateExpression'].includes(n.parentNode.type) && // Prevent replacing (++[[]][0]) with (++1)
!(n.parentKey === 'callee') && // Prevent replacing obj.method() with undefined()
(n.property.type === 'Literal' ||
(n.property.name && !n.computed)) &&
['ArrayExpression', 'Literal'].includes(n.object.type) &&
(n.object?.value?.length || n.object?.elements?.length) &&
candidateFilter(n)) {
sharedSb = sharedSb || new Sandbox();
const replacementNode = evalInVm(n.src, sharedSb);
if (replacementNode !== badValue) arb.markNode(n, replacementNode);
}
}
return arb;
}
module.exports = resolveDefiniteMemberExpressions;