source: frontend/node_modules/static-eval/index.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 7.3 KB
Line 
1var unparse = require('escodegen').generate;
2
3module.exports = function (ast, vars, opts) {
4 if(!opts) opts = {};
5 var rejectAccessToMethodsOnFunctions = !opts.allowAccessToMethodsOnFunctions;
6
7 if (!vars) vars = {};
8 var FAIL = {};
9
10 var result = (function walk (node, noExecute) {
11 if (node.type === 'Literal') {
12 return node.value;
13 }
14 else if (node.type === 'UnaryExpression'){
15 var val = walk(node.argument, noExecute)
16 if (node.operator === '+') return +val
17 if (node.operator === '-') return -val
18 if (node.operator === '~') return ~val
19 if (node.operator === '!') return !val
20 return FAIL
21 }
22 else if (node.type === 'ArrayExpression') {
23 var xs = [];
24 for (var i = 0, l = node.elements.length; i < l; i++) {
25 var x = walk(node.elements[i], noExecute);
26 if (x === FAIL) return FAIL;
27 xs.push(x);
28 }
29 return xs;
30 }
31 else if (node.type === 'ObjectExpression') {
32 var obj = {};
33 for (var i = 0; i < node.properties.length; i++) {
34 var prop = node.properties[i];
35 var value = prop.value === null
36 ? prop.value
37 : walk(prop.value, noExecute)
38 ;
39 if (value === FAIL) return FAIL;
40 obj[prop.key.value || prop.key.name] = value;
41 }
42 return obj;
43 }
44 else if (node.type === 'BinaryExpression' ||
45 node.type === 'LogicalExpression') {
46 var op = node.operator;
47
48 if (op === '&&') {
49 var l = walk(node.left);
50 if (l === FAIL) return FAIL;
51 if (!l) return l;
52 var r = walk(node.right);
53 if (r === FAIL) return FAIL;
54 return r;
55 }
56 else if (op === '||') {
57 var l = walk(node.left);
58 if (l === FAIL) return FAIL;
59 if (l) return l;
60 var r = walk(node.right);
61 if (r === FAIL) return FAIL;
62 return r;
63 }
64
65 var l = walk(node.left, noExecute);
66 if (l === FAIL) return FAIL;
67 var r = walk(node.right, noExecute);
68 if (r === FAIL) return FAIL;
69
70 if (op === '==') return l == r;
71 if (op === '===') return l === r;
72 if (op === '!=') return l != r;
73 if (op === '!==') return l !== r;
74 if (op === '+') return l + r;
75 if (op === '-') return l - r;
76 if (op === '*') return l * r;
77 if (op === '/') return l / r;
78 if (op === '%') return l % r;
79 if (op === '<') return l < r;
80 if (op === '<=') return l <= r;
81 if (op === '>') return l > r;
82 if (op === '>=') return l >= r;
83 if (op === '|') return l | r;
84 if (op === '&') return l & r;
85 if (op === '^') return l ^ r;
86
87 return FAIL;
88 }
89 else if (node.type === 'Identifier') {
90 if ({}.hasOwnProperty.call(vars, node.name)) {
91 return vars[node.name];
92 }
93 else return FAIL;
94 }
95 else if (node.type === 'ThisExpression') {
96 if ({}.hasOwnProperty.call(vars, 'this')) {
97 return vars['this'];
98 }
99 else return FAIL;
100 }
101 else if (node.type === 'CallExpression') {
102 var callee = walk(node.callee, noExecute);
103 if (callee === FAIL) return FAIL;
104 if (typeof callee !== 'function') return FAIL;
105
106
107 var ctx = node.callee.object ? walk(node.callee.object, noExecute) : FAIL;
108 if (ctx === FAIL) ctx = null;
109
110 var args = [];
111 for (var i = 0, l = node.arguments.length; i < l; i++) {
112 var x = walk(node.arguments[i], noExecute);
113 if (x === FAIL) return FAIL;
114 args.push(x);
115 }
116
117 if (noExecute) {
118 return undefined;
119 }
120
121 return callee.apply(ctx, args);
122 }
123 else if (node.type === 'MemberExpression') {
124 var obj = walk(node.object, noExecute);
125 if((obj === FAIL) || (
126 (typeof obj == 'function') && rejectAccessToMethodsOnFunctions
127 )){
128 return FAIL;
129 }
130 if (node.property.type === 'Identifier' && !node.computed) {
131 if (isUnsafeProperty(node.property.name)) return FAIL;
132 return obj[node.property.name];
133 }
134 var prop = walk(node.property, noExecute);
135 if (prop === null || prop === FAIL) return FAIL;
136 if (isUnsafeProperty(prop)) return FAIL;
137 return obj[prop];
138 }
139 else if (node.type === 'ConditionalExpression') {
140 var val = walk(node.test, noExecute)
141 if (val === FAIL) return FAIL;
142 return val ? walk(node.consequent) : walk(node.alternate, noExecute)
143 }
144 else if (node.type === 'ExpressionStatement') {
145 var val = walk(node.expression, noExecute)
146 if (val === FAIL) return FAIL;
147 return val;
148 }
149 else if (node.type === 'ReturnStatement') {
150 return walk(node.argument, noExecute)
151 }
152 else if (node.type === 'FunctionExpression') {
153 var bodies = node.body.body;
154
155 // Create a "scope" for our arguments
156 var oldVars = {};
157 Object.keys(vars).forEach(function(element){
158 oldVars[element] = vars[element];
159 })
160
161 for(var i=0; i<node.params.length; i++){
162 var key = node.params[i];
163 if(key.type == 'Identifier'){
164 vars[key.name] = null;
165 }
166 else return FAIL;
167 }
168 for(var i in bodies){
169 if(walk(bodies[i], true) === FAIL){
170 return FAIL;
171 }
172 }
173 // restore the vars and scope after we walk
174 vars = oldVars;
175
176 var keys = Object.keys(vars);
177 var vals = keys.map(function(key) {
178 return vars[key];
179 });
180 return Function(keys.join(', '), 'return ' + unparse(node)).apply(null, vals);
181 }
182 else if (node.type === 'TemplateLiteral') {
183 var str = '';
184 for (var i = 0; i < node.expressions.length; i++) {
185 str += walk(node.quasis[i], noExecute);
186 str += walk(node.expressions[i], noExecute);
187 }
188 str += walk(node.quasis[i], noExecute);
189 return str;
190 }
191 else if (node.type === 'TaggedTemplateExpression') {
192 var tag = walk(node.tag, noExecute);
193 var quasi = node.quasi;
194 var strings = quasi.quasis.map(walk);
195 var values = quasi.expressions.map(walk);
196 return tag.apply(null, [strings].concat(values));
197 }
198 else if (node.type === 'TemplateElement') {
199 return node.value.cooked;
200 }
201 else return FAIL;
202 })(ast);
203
204 return result === FAIL ? undefined : result;
205};
206
207function isUnsafeProperty(name) {
208 return name === 'constructor' || name === '__proto__';
209}
Note: See TracBrowser for help on using the repository browser.