1 | "use strict";
|
2 | exports.__esModule = true;
|
3 | var parser_1 = require("@babel/parser");
|
4 | var b = require("@babel/types");
|
5 | var binaryOperation_1 = require("./binaryOperation");
|
6 | function expressionToConstant(expression, options) {
|
7 | if (options === void 0) { options = {}; }
|
8 | var constant = true;
|
9 | function toConstant(expression) {
|
10 | if (!constant)
|
11 | return;
|
12 | if (b.isArrayExpression(expression)) {
|
13 | var result_1 = [];
|
14 | for (var i = 0; constant && i < expression.elements.length; i++) {
|
15 | var element = expression.elements[i];
|
16 | if (b.isSpreadElement(element)) {
|
17 | var spread = toConstant(element.argument);
|
18 | if (!(isSpreadable(spread) && constant)) {
|
19 | constant = false;
|
20 | }
|
21 | else {
|
22 | result_1.push.apply(result_1, spread);
|
23 | }
|
24 | }
|
25 | else if (b.isExpression(element)) {
|
26 | result_1.push(toConstant(element));
|
27 | }
|
28 | else {
|
29 | constant = false;
|
30 | }
|
31 | }
|
32 | return result_1;
|
33 | }
|
34 | if (b.isBinaryExpression(expression)) {
|
35 | var left = toConstant(expression.left);
|
36 | var right = toConstant(expression.right);
|
37 | return constant && binaryOperation_1["default"](expression.operator, left, right);
|
38 | }
|
39 | if (b.isBooleanLiteral(expression)) {
|
40 | return expression.value;
|
41 | }
|
42 | if (b.isCallExpression(expression)) {
|
43 | var args = [];
|
44 | for (var i = 0; constant && i < expression.arguments.length; i++) {
|
45 | var arg = expression.arguments[i];
|
46 | if (b.isSpreadElement(arg)) {
|
47 | var spread = toConstant(arg.argument);
|
48 | if (!(isSpreadable(spread) && constant)) {
|
49 | constant = false;
|
50 | }
|
51 | else {
|
52 | args.push.apply(args, spread);
|
53 | }
|
54 | }
|
55 | else if (b.isExpression(arg)) {
|
56 | args.push(toConstant(arg));
|
57 | }
|
58 | else {
|
59 | constant = false;
|
60 | }
|
61 | }
|
62 | if (!constant)
|
63 | return;
|
64 | if (b.isMemberExpression(expression.callee)) {
|
65 | var object = toConstant(expression.callee.object);
|
66 | if (!object || !constant) {
|
67 | constant = false;
|
68 | return;
|
69 | }
|
70 | var member = expression.callee.computed
|
71 | ? toConstant(expression.callee.property)
|
72 | : b.isIdentifier(expression.callee.property)
|
73 | ? expression.callee.property.name
|
74 | : undefined;
|
75 | if (member === undefined && !expression.callee.computed) {
|
76 | constant = false;
|
77 | }
|
78 | if (!constant)
|
79 | return;
|
80 | if (canCallMethod(object, '' + member)) {
|
81 | return object[member].apply(object, args);
|
82 | }
|
83 | }
|
84 | else {
|
85 | if (!b.isExpression(expression.callee)) {
|
86 | constant = false;
|
87 | return;
|
88 | }
|
89 | var callee = toConstant(expression.callee);
|
90 | if (!constant)
|
91 | return;
|
92 | return callee.apply(null, args);
|
93 | }
|
94 | }
|
95 | if (b.isConditionalExpression(expression)) {
|
96 | var test = toConstant(expression.test);
|
97 | return test
|
98 | ? toConstant(expression.consequent)
|
99 | : toConstant(expression.alternate);
|
100 | }
|
101 | if (b.isIdentifier(expression)) {
|
102 | if (options.constants &&
|
103 | {}.hasOwnProperty.call(options.constants, expression.name)) {
|
104 | return options.constants[expression.name];
|
105 | }
|
106 | }
|
107 | if (b.isLogicalExpression(expression)) {
|
108 | var left = toConstant(expression.left);
|
109 | var right = toConstant(expression.right);
|
110 | if (constant && expression.operator === '&&') {
|
111 | return left && right;
|
112 | }
|
113 | if (constant && expression.operator === '||') {
|
114 | return left || right;
|
115 | }
|
116 | }
|
117 | if (b.isMemberExpression(expression)) {
|
118 | var object = toConstant(expression.object);
|
119 | if (!object || !constant) {
|
120 | constant = false;
|
121 | return;
|
122 | }
|
123 | var member = expression.computed
|
124 | ? toConstant(expression.property)
|
125 | : b.isIdentifier(expression.property)
|
126 | ? expression.property.name
|
127 | : undefined;
|
128 | if (member === undefined && !expression.computed) {
|
129 | constant = false;
|
130 | }
|
131 | if (!constant)
|
132 | return;
|
133 | if ({}.hasOwnProperty.call(object, '' + member) && member[0] !== '_') {
|
134 | return object[member];
|
135 | }
|
136 | }
|
137 | if (b.isNullLiteral(expression)) {
|
138 | return null;
|
139 | }
|
140 | if (b.isNumericLiteral(expression)) {
|
141 | return expression.value;
|
142 | }
|
143 | if (b.isObjectExpression(expression)) {
|
144 | var result_2 = {};
|
145 | for (var i = 0; constant && i < expression.properties.length; i++) {
|
146 | var property = expression.properties[i];
|
147 | if (b.isObjectProperty(property)) {
|
148 | if (property.shorthand) {
|
149 | constant = false;
|
150 | return;
|
151 | }
|
152 | var key = property.computed
|
153 | ? toConstant(property.key)
|
154 | : b.isIdentifier(property.key)
|
155 | ? property.key.name
|
156 | : b.isStringLiteral(property.key)
|
157 | ? property.key.value
|
158 | : undefined;
|
159 | if (!key || key[0] === '_') {
|
160 | constant = false;
|
161 | }
|
162 | if (!constant)
|
163 | return;
|
164 | if (b.isExpression(property.value)) {
|
165 | var value = toConstant(property.value);
|
166 | if (!constant)
|
167 | return;
|
168 | result_2[key] = value;
|
169 | }
|
170 | else {
|
171 | constant = false;
|
172 | }
|
173 | }
|
174 | else if (b.isObjectMethod(property)) {
|
175 | constant = false;
|
176 | }
|
177 | else if (b.isSpreadProperty(property)) {
|
178 | var argument = toConstant(property.argument);
|
179 | if (!argument)
|
180 | constant = false;
|
181 | if (!constant)
|
182 | return;
|
183 | Object.assign(result_2, argument);
|
184 | }
|
185 | }
|
186 | return result_2;
|
187 | }
|
188 | if (b.isParenthesizedExpression(expression)) {
|
189 | return toConstant(expression.expression);
|
190 | }
|
191 | if (b.isRegExpLiteral(expression)) {
|
192 | return new RegExp(expression.pattern, expression.flags);
|
193 | }
|
194 | if (b.isSequenceExpression(expression)) {
|
195 | for (var i = 0; i < expression.expressions.length - 1 && constant; i++) {
|
196 | toConstant(expression.expressions[i]);
|
197 | }
|
198 | return toConstant(expression.expressions[expression.expressions.length - 1]);
|
199 | }
|
200 | if (b.isStringLiteral(expression)) {
|
201 | return expression.value;
|
202 | }
|
203 |
|
204 | if (b.isTemplateLiteral(expression)) {
|
205 | var result_3 = '';
|
206 | for (var i = 0; i < expression.quasis.length; i++) {
|
207 | var quasi = expression.quasis[i];
|
208 | result_3 += quasi.value.cooked;
|
209 | if (i < expression.expressions.length) {
|
210 | result_3 += '' + toConstant(expression.expressions[i]);
|
211 | }
|
212 | }
|
213 | return result_3;
|
214 | }
|
215 | if (b.isUnaryExpression(expression)) {
|
216 | var argument = toConstant(expression.argument);
|
217 | if (!constant) {
|
218 | return;
|
219 | }
|
220 | switch (expression.operator) {
|
221 | case '-':
|
222 | return -argument;
|
223 | case '+':
|
224 | return +argument;
|
225 | case '!':
|
226 | return !argument;
|
227 | case '~':
|
228 | return ~argument;
|
229 | case 'typeof':
|
230 | return typeof argument;
|
231 | case 'void':
|
232 | return void argument;
|
233 | }
|
234 | }
|
235 | constant = false;
|
236 | }
|
237 | var result = toConstant(expression);
|
238 | return constant ? { constant: true, result: result } : { constant: false };
|
239 | }
|
240 | exports.expressionToConstant = expressionToConstant;
|
241 | function isSpreadable(value) {
|
242 | return (typeof value === 'string' ||
|
243 | Array.isArray(value) ||
|
244 | (typeof Set !== 'undefined' && value instanceof Set) ||
|
245 | (typeof Map !== 'undefined' && value instanceof Map));
|
246 | }
|
247 | function shallowEqual(a, b) {
|
248 | if (a === b)
|
249 | return true;
|
250 | if (a && b && typeof a === 'object' && typeof b === 'object') {
|
251 | for (var key in a) {
|
252 | if (a[key] !== b[key]) {
|
253 | return false;
|
254 | }
|
255 | }
|
256 | for (var key in b) {
|
257 | if (a[key] !== b[key]) {
|
258 | return false;
|
259 | }
|
260 | }
|
261 | return true;
|
262 | }
|
263 | return false;
|
264 | }
|
265 | function canCallMethod(object, member) {
|
266 | switch (typeof object) {
|
267 | case 'boolean':
|
268 | switch (member) {
|
269 | case 'toString':
|
270 | return true;
|
271 | default:
|
272 | return false;
|
273 | }
|
274 | case 'number':
|
275 | switch (member) {
|
276 | case 'toExponential':
|
277 | case 'toFixed':
|
278 | case 'toPrecision':
|
279 | case 'toString':
|
280 | return true;
|
281 | default:
|
282 | return false;
|
283 | }
|
284 | case 'string':
|
285 | switch (member) {
|
286 | case 'charAt':
|
287 | case 'charCodeAt':
|
288 | case 'codePointAt':
|
289 | case 'concat':
|
290 | case 'endsWith':
|
291 | case 'includes':
|
292 | case 'indexOf':
|
293 | case 'lastIndexOf':
|
294 | case 'match':
|
295 | case 'normalize':
|
296 | case 'padEnd':
|
297 | case 'padStart':
|
298 | case 'repeat':
|
299 | case 'replace':
|
300 | case 'search':
|
301 | case 'slice':
|
302 | case 'split':
|
303 | case 'startsWith':
|
304 | case 'substr':
|
305 | case 'substring':
|
306 | case 'toLowerCase':
|
307 | case 'toUpperCase':
|
308 | case 'trim':
|
309 | return true;
|
310 | default:
|
311 | return false;
|
312 | }
|
313 | default:
|
314 | if (object instanceof RegExp) {
|
315 | switch (member) {
|
316 | case 'test':
|
317 | case 'exec':
|
318 | return true;
|
319 | default:
|
320 | return false;
|
321 | }
|
322 | }
|
323 | return {}.hasOwnProperty.call(object, member) && member[0] !== '_';
|
324 | }
|
325 | }
|
326 | var EMPTY_OBJECT = {};
|
327 | var lastSrc = '';
|
328 | var lastConstants = EMPTY_OBJECT;
|
329 | var lastOptions = EMPTY_OBJECT;
|
330 | var lastResult = null;
|
331 | var lastWasConstant = false;
|
332 | function isConstant(src, constants, options) {
|
333 | if (constants === void 0) { constants = EMPTY_OBJECT; }
|
334 | if (options === void 0) { options = EMPTY_OBJECT; }
|
335 | if (lastSrc === src &&
|
336 | shallowEqual(lastConstants, constants) &&
|
337 | shallowEqual(lastOptions, options)) {
|
338 | return lastWasConstant;
|
339 | }
|
340 | lastSrc = src;
|
341 | lastConstants = constants;
|
342 | var ast;
|
343 | try {
|
344 | ast = parser_1.parseExpression(src, options);
|
345 | }
|
346 | catch (ex) {
|
347 | return (lastWasConstant = false);
|
348 | }
|
349 | var _a = expressionToConstant(ast, { constants: constants }), result = _a.result, constant = _a.constant;
|
350 | lastResult = result;
|
351 | return (lastWasConstant = constant);
|
352 | }
|
353 | exports.isConstant = isConstant;
|
354 | function toConstant(src, constants, options) {
|
355 | if (constants === void 0) { constants = EMPTY_OBJECT; }
|
356 | if (options === void 0) { options = EMPTY_OBJECT; }
|
357 | if (!isConstant(src, constants, options)) {
|
358 | throw new Error(JSON.stringify(src) + ' is not constant.');
|
359 | }
|
360 | return lastResult;
|
361 | }
|
362 | exports.toConstant = toConstant;
|
363 | exports["default"] = isConstant;
|
364 | module.exports = isConstant;
|
365 | module.exports["default"] = isConstant;
|
366 | module.exports.expressionToConstant = expressionToConstant;
|
367 | module.exports.isConstant = isConstant;
|
368 | module.exports.toConstant = toConstant;
|