source: trip-planner-front/node_modules/@babel/traverse/lib/path/evaluation.js@ 6a80231

Last change on this file since 6a80231 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 9.0 KB
Line 
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.evaluateTruthy = evaluateTruthy;
7exports.evaluate = evaluate;
8const VALID_CALLEES = ["String", "Number", "Math"];
9const INVALID_METHODS = ["random"];
10
11function evaluateTruthy() {
12 const res = this.evaluate();
13 if (res.confident) return !!res.value;
14}
15
16function deopt(path, state) {
17 if (!state.confident) return;
18 state.deoptPath = path;
19 state.confident = false;
20}
21
22function evaluateCached(path, state) {
23 const {
24 node
25 } = path;
26 const {
27 seen
28 } = state;
29
30 if (seen.has(node)) {
31 const existing = seen.get(node);
32
33 if (existing.resolved) {
34 return existing.value;
35 } else {
36 deopt(path, state);
37 return;
38 }
39 } else {
40 const item = {
41 resolved: false
42 };
43 seen.set(node, item);
44
45 const val = _evaluate(path, state);
46
47 if (state.confident) {
48 item.resolved = true;
49 item.value = val;
50 }
51
52 return val;
53 }
54}
55
56function _evaluate(path, state) {
57 if (!state.confident) return;
58
59 if (path.isSequenceExpression()) {
60 const exprs = path.get("expressions");
61 return evaluateCached(exprs[exprs.length - 1], state);
62 }
63
64 if (path.isStringLiteral() || path.isNumericLiteral() || path.isBooleanLiteral()) {
65 return path.node.value;
66 }
67
68 if (path.isNullLiteral()) {
69 return null;
70 }
71
72 if (path.isTemplateLiteral()) {
73 return evaluateQuasis(path, path.node.quasis, state);
74 }
75
76 if (path.isTaggedTemplateExpression() && path.get("tag").isMemberExpression()) {
77 const object = path.get("tag.object");
78 const {
79 node: {
80 name
81 }
82 } = object;
83 const property = path.get("tag.property");
84
85 if (object.isIdentifier() && name === "String" && !path.scope.getBinding(name) && property.isIdentifier() && property.node.name === "raw") {
86 return evaluateQuasis(path, path.node.quasi.quasis, state, true);
87 }
88 }
89
90 if (path.isConditionalExpression()) {
91 const testResult = evaluateCached(path.get("test"), state);
92 if (!state.confident) return;
93
94 if (testResult) {
95 return evaluateCached(path.get("consequent"), state);
96 } else {
97 return evaluateCached(path.get("alternate"), state);
98 }
99 }
100
101 if (path.isExpressionWrapper()) {
102 return evaluateCached(path.get("expression"), state);
103 }
104
105 if (path.isMemberExpression() && !path.parentPath.isCallExpression({
106 callee: path.node
107 })) {
108 const property = path.get("property");
109 const object = path.get("object");
110
111 if (object.isLiteral() && property.isIdentifier()) {
112 const value = object.node.value;
113 const type = typeof value;
114
115 if (type === "number" || type === "string") {
116 return value[property.node.name];
117 }
118 }
119 }
120
121 if (path.isReferencedIdentifier()) {
122 const binding = path.scope.getBinding(path.node.name);
123
124 if (binding && binding.constantViolations.length > 0) {
125 return deopt(binding.path, state);
126 }
127
128 if (binding && path.node.start < binding.path.node.end) {
129 return deopt(binding.path, state);
130 }
131
132 if (binding != null && binding.hasValue) {
133 return binding.value;
134 } else {
135 if (path.node.name === "undefined") {
136 return binding ? deopt(binding.path, state) : undefined;
137 } else if (path.node.name === "Infinity") {
138 return binding ? deopt(binding.path, state) : Infinity;
139 } else if (path.node.name === "NaN") {
140 return binding ? deopt(binding.path, state) : NaN;
141 }
142
143 const resolved = path.resolve();
144
145 if (resolved === path) {
146 return deopt(path, state);
147 } else {
148 return evaluateCached(resolved, state);
149 }
150 }
151 }
152
153 if (path.isUnaryExpression({
154 prefix: true
155 })) {
156 if (path.node.operator === "void") {
157 return undefined;
158 }
159
160 const argument = path.get("argument");
161
162 if (path.node.operator === "typeof" && (argument.isFunction() || argument.isClass())) {
163 return "function";
164 }
165
166 const arg = evaluateCached(argument, state);
167 if (!state.confident) return;
168
169 switch (path.node.operator) {
170 case "!":
171 return !arg;
172
173 case "+":
174 return +arg;
175
176 case "-":
177 return -arg;
178
179 case "~":
180 return ~arg;
181
182 case "typeof":
183 return typeof arg;
184 }
185 }
186
187 if (path.isArrayExpression()) {
188 const arr = [];
189 const elems = path.get("elements");
190
191 for (const elem of elems) {
192 const elemValue = elem.evaluate();
193
194 if (elemValue.confident) {
195 arr.push(elemValue.value);
196 } else {
197 return deopt(elemValue.deopt, state);
198 }
199 }
200
201 return arr;
202 }
203
204 if (path.isObjectExpression()) {
205 const obj = {};
206 const props = path.get("properties");
207
208 for (const prop of props) {
209 if (prop.isObjectMethod() || prop.isSpreadElement()) {
210 return deopt(prop, state);
211 }
212
213 const keyPath = prop.get("key");
214 let key = keyPath;
215
216 if (prop.node.computed) {
217 key = key.evaluate();
218
219 if (!key.confident) {
220 return deopt(key.deopt, state);
221 }
222
223 key = key.value;
224 } else if (key.isIdentifier()) {
225 key = key.node.name;
226 } else {
227 key = key.node.value;
228 }
229
230 const valuePath = prop.get("value");
231 let value = valuePath.evaluate();
232
233 if (!value.confident) {
234 return deopt(value.deopt, state);
235 }
236
237 value = value.value;
238 obj[key] = value;
239 }
240
241 return obj;
242 }
243
244 if (path.isLogicalExpression()) {
245 const wasConfident = state.confident;
246 const left = evaluateCached(path.get("left"), state);
247 const leftConfident = state.confident;
248 state.confident = wasConfident;
249 const right = evaluateCached(path.get("right"), state);
250 const rightConfident = state.confident;
251
252 switch (path.node.operator) {
253 case "||":
254 state.confident = leftConfident && (!!left || rightConfident);
255 if (!state.confident) return;
256 return left || right;
257
258 case "&&":
259 state.confident = leftConfident && (!left || rightConfident);
260 if (!state.confident) return;
261 return left && right;
262 }
263 }
264
265 if (path.isBinaryExpression()) {
266 const left = evaluateCached(path.get("left"), state);
267 if (!state.confident) return;
268 const right = evaluateCached(path.get("right"), state);
269 if (!state.confident) return;
270
271 switch (path.node.operator) {
272 case "-":
273 return left - right;
274
275 case "+":
276 return left + right;
277
278 case "/":
279 return left / right;
280
281 case "*":
282 return left * right;
283
284 case "%":
285 return left % right;
286
287 case "**":
288 return Math.pow(left, right);
289
290 case "<":
291 return left < right;
292
293 case ">":
294 return left > right;
295
296 case "<=":
297 return left <= right;
298
299 case ">=":
300 return left >= right;
301
302 case "==":
303 return left == right;
304
305 case "!=":
306 return left != right;
307
308 case "===":
309 return left === right;
310
311 case "!==":
312 return left !== right;
313
314 case "|":
315 return left | right;
316
317 case "&":
318 return left & right;
319
320 case "^":
321 return left ^ right;
322
323 case "<<":
324 return left << right;
325
326 case ">>":
327 return left >> right;
328
329 case ">>>":
330 return left >>> right;
331 }
332 }
333
334 if (path.isCallExpression()) {
335 const callee = path.get("callee");
336 let context;
337 let func;
338
339 if (callee.isIdentifier() && !path.scope.getBinding(callee.node.name) && VALID_CALLEES.indexOf(callee.node.name) >= 0) {
340 func = global[callee.node.name];
341 }
342
343 if (callee.isMemberExpression()) {
344 const object = callee.get("object");
345 const property = callee.get("property");
346
347 if (object.isIdentifier() && property.isIdentifier() && VALID_CALLEES.indexOf(object.node.name) >= 0 && INVALID_METHODS.indexOf(property.node.name) < 0) {
348 context = global[object.node.name];
349 func = context[property.node.name];
350 }
351
352 if (object.isLiteral() && property.isIdentifier()) {
353 const type = typeof object.node.value;
354
355 if (type === "string" || type === "number") {
356 context = object.node.value;
357 func = context[property.node.name];
358 }
359 }
360 }
361
362 if (func) {
363 const args = path.get("arguments").map(arg => evaluateCached(arg, state));
364 if (!state.confident) return;
365 return func.apply(context, args);
366 }
367 }
368
369 deopt(path, state);
370}
371
372function evaluateQuasis(path, quasis, state, raw = false) {
373 let str = "";
374 let i = 0;
375 const exprs = path.get("expressions");
376
377 for (const elem of quasis) {
378 if (!state.confident) break;
379 str += raw ? elem.value.raw : elem.value.cooked;
380 const expr = exprs[i++];
381 if (expr) str += String(evaluateCached(expr, state));
382 }
383
384 if (!state.confident) return;
385 return str;
386}
387
388function evaluate() {
389 const state = {
390 confident: true,
391 deoptPath: null,
392 seen: new Map()
393 };
394 let value = evaluateCached(this, state);
395 if (!state.confident) value = undefined;
396 return {
397 confident: state.confident,
398 deopt: state.deoptPath,
399 value: value
400 };
401}
Note: See TracBrowser for help on using the repository browser.