source: trip-planner-front/node_modules/webpack/lib/javascript/BasicEvaluatedExpression.js@ 59329aa

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

initial commit

  • Property mode set to 100644
File size: 10.1 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8/** @typedef {import("estree").Node} EsTreeNode */
9/** @typedef {import("./JavascriptParser").VariableInfoInterface} VariableInfoInterface */
10
11const TypeUnknown = 0;
12const TypeUndefined = 1;
13const TypeNull = 2;
14const TypeString = 3;
15const TypeNumber = 4;
16const TypeBoolean = 5;
17const TypeRegExp = 6;
18const TypeConditional = 7;
19const TypeArray = 8;
20const TypeConstArray = 9;
21const TypeIdentifier = 10;
22const TypeWrapped = 11;
23const TypeTemplateString = 12;
24const TypeBigInt = 13;
25
26class BasicEvaluatedExpression {
27 constructor() {
28 this.type = TypeUnknown;
29 /** @type {[number, number]} */
30 this.range = undefined;
31 /** @type {boolean} */
32 this.falsy = false;
33 /** @type {boolean} */
34 this.truthy = false;
35 /** @type {boolean | undefined} */
36 this.nullish = undefined;
37 /** @type {boolean} */
38 this.sideEffects = true;
39 /** @type {boolean | undefined} */
40 this.bool = undefined;
41 /** @type {number | undefined} */
42 this.number = undefined;
43 /** @type {bigint | undefined} */
44 this.bigint = undefined;
45 /** @type {RegExp | undefined} */
46 this.regExp = undefined;
47 /** @type {string | undefined} */
48 this.string = undefined;
49 /** @type {BasicEvaluatedExpression[] | undefined} */
50 this.quasis = undefined;
51 /** @type {BasicEvaluatedExpression[] | undefined} */
52 this.parts = undefined;
53 /** @type {any[] | undefined} */
54 this.array = undefined;
55 /** @type {BasicEvaluatedExpression[] | undefined} */
56 this.items = undefined;
57 /** @type {BasicEvaluatedExpression[] | undefined} */
58 this.options = undefined;
59 /** @type {BasicEvaluatedExpression | undefined} */
60 this.prefix = undefined;
61 /** @type {BasicEvaluatedExpression | undefined} */
62 this.postfix = undefined;
63 this.wrappedInnerExpressions = undefined;
64 /** @type {string | undefined} */
65 this.identifier = undefined;
66 /** @type {VariableInfoInterface} */
67 this.rootInfo = undefined;
68 /** @type {() => string[]} */
69 this.getMembers = undefined;
70 /** @type {EsTreeNode} */
71 this.expression = undefined;
72 }
73
74 isUnknown() {
75 return this.type === TypeUnknown;
76 }
77
78 isNull() {
79 return this.type === TypeNull;
80 }
81
82 isUndefined() {
83 return this.type === TypeUndefined;
84 }
85
86 isString() {
87 return this.type === TypeString;
88 }
89
90 isNumber() {
91 return this.type === TypeNumber;
92 }
93
94 isBigInt() {
95 return this.type === TypeBigInt;
96 }
97
98 isBoolean() {
99 return this.type === TypeBoolean;
100 }
101
102 isRegExp() {
103 return this.type === TypeRegExp;
104 }
105
106 isConditional() {
107 return this.type === TypeConditional;
108 }
109
110 isArray() {
111 return this.type === TypeArray;
112 }
113
114 isConstArray() {
115 return this.type === TypeConstArray;
116 }
117
118 isIdentifier() {
119 return this.type === TypeIdentifier;
120 }
121
122 isWrapped() {
123 return this.type === TypeWrapped;
124 }
125
126 isTemplateString() {
127 return this.type === TypeTemplateString;
128 }
129
130 /**
131 * Is expression a primitive or an object type value?
132 * @returns {boolean | undefined} true: primitive type, false: object type, undefined: unknown/runtime-defined
133 */
134 isPrimitiveType() {
135 switch (this.type) {
136 case TypeUndefined:
137 case TypeNull:
138 case TypeString:
139 case TypeNumber:
140 case TypeBoolean:
141 case TypeBigInt:
142 case TypeWrapped:
143 case TypeTemplateString:
144 return true;
145 case TypeRegExp:
146 case TypeArray:
147 case TypeConstArray:
148 return false;
149 default:
150 return undefined;
151 }
152 }
153
154 /**
155 * Is expression a runtime or compile-time value?
156 * @returns {boolean} true: compile time value, false: runtime value
157 */
158 isCompileTimeValue() {
159 switch (this.type) {
160 case TypeUndefined:
161 case TypeNull:
162 case TypeString:
163 case TypeNumber:
164 case TypeBoolean:
165 case TypeRegExp:
166 case TypeConstArray:
167 case TypeBigInt:
168 return true;
169 default:
170 return false;
171 }
172 }
173
174 /**
175 * Gets the compile-time value of the expression
176 * @returns {any} the javascript value
177 */
178 asCompileTimeValue() {
179 switch (this.type) {
180 case TypeUndefined:
181 return undefined;
182 case TypeNull:
183 return null;
184 case TypeString:
185 return this.string;
186 case TypeNumber:
187 return this.number;
188 case TypeBoolean:
189 return this.bool;
190 case TypeRegExp:
191 return this.regExp;
192 case TypeConstArray:
193 return this.array;
194 case TypeBigInt:
195 return this.bigint;
196 default:
197 throw new Error(
198 "asCompileTimeValue must only be called for compile-time values"
199 );
200 }
201 }
202
203 isTruthy() {
204 return this.truthy;
205 }
206
207 isFalsy() {
208 return this.falsy;
209 }
210
211 isNullish() {
212 return this.nullish;
213 }
214
215 /**
216 * Can this expression have side effects?
217 * @returns {boolean} false: never has side effects
218 */
219 couldHaveSideEffects() {
220 return this.sideEffects;
221 }
222
223 asBool() {
224 if (this.truthy) return true;
225 if (this.falsy || this.nullish) return false;
226 if (this.isBoolean()) return this.bool;
227 if (this.isNull()) return false;
228 if (this.isUndefined()) return false;
229 if (this.isString()) return this.string !== "";
230 if (this.isNumber()) return this.number !== 0;
231 if (this.isBigInt()) return this.bigint !== BigInt(0);
232 if (this.isRegExp()) return true;
233 if (this.isArray()) return true;
234 if (this.isConstArray()) return true;
235 if (this.isWrapped()) {
236 return (this.prefix && this.prefix.asBool()) ||
237 (this.postfix && this.postfix.asBool())
238 ? true
239 : undefined;
240 }
241 if (this.isTemplateString()) {
242 const str = this.asString();
243 if (typeof str === "string") return str !== "";
244 }
245 return undefined;
246 }
247
248 asNullish() {
249 const nullish = this.isNullish();
250
251 if (nullish === true || this.isNull() || this.isUndefined()) return true;
252
253 if (nullish === false) return false;
254 if (this.isTruthy()) return false;
255 if (this.isBoolean()) return false;
256 if (this.isString()) return false;
257 if (this.isNumber()) return false;
258 if (this.isBigInt()) return false;
259 if (this.isRegExp()) return false;
260 if (this.isArray()) return false;
261 if (this.isConstArray()) return false;
262 if (this.isTemplateString()) return false;
263 if (this.isRegExp()) return false;
264
265 return undefined;
266 }
267
268 asString() {
269 if (this.isBoolean()) return `${this.bool}`;
270 if (this.isNull()) return "null";
271 if (this.isUndefined()) return "undefined";
272 if (this.isString()) return this.string;
273 if (this.isNumber()) return `${this.number}`;
274 if (this.isBigInt()) return `${this.bigint}`;
275 if (this.isRegExp()) return `${this.regExp}`;
276 if (this.isArray()) {
277 let array = [];
278 for (const item of this.items) {
279 const itemStr = item.asString();
280 if (itemStr === undefined) return undefined;
281 array.push(itemStr);
282 }
283 return `${array}`;
284 }
285 if (this.isConstArray()) return `${this.array}`;
286 if (this.isTemplateString()) {
287 let str = "";
288 for (const part of this.parts) {
289 const partStr = part.asString();
290 if (partStr === undefined) return undefined;
291 str += partStr;
292 }
293 return str;
294 }
295 return undefined;
296 }
297
298 setString(string) {
299 this.type = TypeString;
300 this.string = string;
301 this.sideEffects = false;
302 return this;
303 }
304
305 setUndefined() {
306 this.type = TypeUndefined;
307 this.sideEffects = false;
308 return this;
309 }
310
311 setNull() {
312 this.type = TypeNull;
313 this.sideEffects = false;
314 return this;
315 }
316
317 setNumber(number) {
318 this.type = TypeNumber;
319 this.number = number;
320 this.sideEffects = false;
321 return this;
322 }
323
324 setBigInt(bigint) {
325 this.type = TypeBigInt;
326 this.bigint = bigint;
327 this.sideEffects = false;
328 return this;
329 }
330
331 setBoolean(bool) {
332 this.type = TypeBoolean;
333 this.bool = bool;
334 this.sideEffects = false;
335 return this;
336 }
337
338 setRegExp(regExp) {
339 this.type = TypeRegExp;
340 this.regExp = regExp;
341 this.sideEffects = false;
342 return this;
343 }
344
345 setIdentifier(identifier, rootInfo, getMembers) {
346 this.type = TypeIdentifier;
347 this.identifier = identifier;
348 this.rootInfo = rootInfo;
349 this.getMembers = getMembers;
350 this.sideEffects = true;
351 return this;
352 }
353
354 setWrapped(prefix, postfix, innerExpressions) {
355 this.type = TypeWrapped;
356 this.prefix = prefix;
357 this.postfix = postfix;
358 this.wrappedInnerExpressions = innerExpressions;
359 this.sideEffects = true;
360 return this;
361 }
362
363 setOptions(options) {
364 this.type = TypeConditional;
365 this.options = options;
366 this.sideEffects = true;
367 return this;
368 }
369
370 addOptions(options) {
371 if (!this.options) {
372 this.type = TypeConditional;
373 this.options = [];
374 this.sideEffects = true;
375 }
376 for (const item of options) {
377 this.options.push(item);
378 }
379 return this;
380 }
381
382 setItems(items) {
383 this.type = TypeArray;
384 this.items = items;
385 this.sideEffects = items.some(i => i.couldHaveSideEffects());
386 return this;
387 }
388
389 setArray(array) {
390 this.type = TypeConstArray;
391 this.array = array;
392 this.sideEffects = false;
393 return this;
394 }
395
396 setTemplateString(quasis, parts, kind) {
397 this.type = TypeTemplateString;
398 this.quasis = quasis;
399 this.parts = parts;
400 this.templateStringKind = kind;
401 this.sideEffects = parts.some(p => p.sideEffects);
402 return this;
403 }
404
405 setTruthy() {
406 this.falsy = false;
407 this.truthy = true;
408 this.nullish = false;
409 return this;
410 }
411
412 setFalsy() {
413 this.falsy = true;
414 this.truthy = false;
415 return this;
416 }
417
418 setNullish(value) {
419 this.nullish = value;
420 return this;
421 }
422
423 setRange(range) {
424 this.range = range;
425 return this;
426 }
427
428 setSideEffects(sideEffects = true) {
429 this.sideEffects = sideEffects;
430 return this;
431 }
432
433 setExpression(expression) {
434 this.expression = expression;
435 return this;
436 }
437}
438
439/**
440 * @param {string} flags regexp flags
441 * @returns {boolean} is valid flags
442 */
443BasicEvaluatedExpression.isValidRegExpFlags = flags => {
444 const len = flags.length;
445
446 if (len === 0) return true;
447 if (len > 4) return false;
448
449 // cspell:word gimy
450 let remaining = 0b0000; // bit per RegExp flag: gimy
451
452 for (let i = 0; i < len; i++)
453 switch (flags.charCodeAt(i)) {
454 case 103 /* g */:
455 if (remaining & 0b1000) return false;
456 remaining |= 0b1000;
457 break;
458 case 105 /* i */:
459 if (remaining & 0b0100) return false;
460 remaining |= 0b0100;
461 break;
462 case 109 /* m */:
463 if (remaining & 0b0010) return false;
464 remaining |= 0b0010;
465 break;
466 case 121 /* y */:
467 if (remaining & 0b0001) return false;
468 remaining |= 0b0001;
469 break;
470 default:
471 return false;
472 }
473
474 return true;
475};
476
477module.exports = BasicEvaluatedExpression;
Note: See TracBrowser for help on using the repository browser.