-
Notifications
You must be signed in to change notification settings - Fork 41
/
Copy pathresolveDefiniteMemberExpressions.js
36 lines (34 loc) · 1.27 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
35
36
import {badValue} from '../config.js';
import {Sandbox} from '../utils/sandbox.js';
import {evalInVm} from '../utils/evalInVm.js';
/**
* 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;
const relevantNodes = [
...(arb.ast[0].typeMap.MemberExpression || []),
];
for (let i = 0; i < relevantNodes.length; i++) {
const n = relevantNodes[i];
if (!['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;
}
export default resolveDefiniteMemberExpressions;