UNPKG

1.74 kBJavaScriptView Raw
1'use strict';
2
3const t = require('babel-types');
4
5function canEvaluate(staticNamespace, exprNode) {
6 // exprNode is a template literal and all expressions in the template literal can be evaluated
7 if (t.isTemplateLiteral(exprNode)) {
8 for (let idx = -1, len = exprNode.expressions.length; ++idx < len; ) {
9 const expr = exprNode.expressions[idx];
10 if (!canEvaluate(staticNamespace, expr)) {
11 return false;
12 }
13 }
14 return true;
15 }
16
17 // exprNode is a string, int, or null
18 if (t.isLiteral(exprNode)) {
19 return true;
20 }
21
22 // exprNode is minus whatever
23 if (t.isUnaryExpression(exprNode) && exprNode.operator === '-') {
24 return canEvaluate(staticNamespace, exprNode.argument);
25 }
26
27 // exprNode is a variable
28 if (t.isIdentifier(exprNode)) {
29 return (
30 typeof staticNamespace === 'object' &&
31 staticNamespace !== null &&
32 staticNamespace.hasOwnProperty(exprNode.name)
33 );
34 }
35
36 // exprNode is a member expression (object.property or object['property'])
37 if (t.isMemberExpression(exprNode)) {
38 return (
39 // object is in the provided namespace
40 canEvaluate(staticNamespace, exprNode.object) &&
41 // property is either an identifier specified with dot notation...
42 ((t.isIdentifier(exprNode.property) && !exprNode.computed) ||
43 // ...or it's specified with bracket notation and can be evaluated
44 canEvaluate(staticNamespace, exprNode.property))
45 );
46 }
47
48 // exprNode is a binary expression and both sides can be evaluated
49 if (t.isBinaryExpression(exprNode)) {
50 return (
51 canEvaluate(staticNamespace, exprNode.left) &&
52 canEvaluate(staticNamespace, exprNode.right)
53 );
54 }
55 return false;
56}
57
58module.exports = canEvaluate;