123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353 |
- "use strict";
- exports.__esModule = true;
- var babylon_1 = require("babylon");
- var b = require("babel-types");
- var binaryOperation_1 = require("./binaryOperation");
- function expressionToConstant(expression, options) {
- if (options === void 0) { options = {}; }
- var constant = true;
- function toConstant(expression) {
- if (!constant)
- return;
- if (b.isArrayExpression(expression)) {
- var result_1 = [];
- for (var i = 0; constant && i < expression.elements.length; i++) {
- var element = expression.elements[i];
- if (b.isSpreadElement(element)) {
- var spread = toConstant(element.argument);
- if (!(isSpreadable(spread) && constant)) {
- constant = false;
- }
- else {
- result_1.push.apply(result_1, spread);
- }
- }
- else {
- result_1.push(toConstant(element));
- }
- }
- return result_1;
- }
- if (b.isBinaryExpression(expression)) {
- var left = toConstant(expression.left);
- var right = toConstant(expression.right);
- return constant && binaryOperation_1["default"](expression.operator, left, right);
- }
- if (b.isBooleanLiteral(expression)) {
- return expression.value;
- }
- if (b.isCallExpression(expression)) {
- var args = [];
- for (var i = 0; constant && i < expression.arguments.length; i++) {
- var arg = expression.arguments[i];
- if (b.isSpreadElement(arg)) {
- var spread = toConstant(arg.argument);
- if (!(isSpreadable(spread) && constant)) {
- constant = false;
- }
- else {
- args.push.apply(args, spread);
- }
- }
- else {
- args.push(toConstant(arg));
- }
- }
- if (!constant)
- return;
- if (b.isMemberExpression(expression.callee)) {
- var object = toConstant(expression.callee.object);
- if (!object || !constant) {
- constant = false;
- return;
- }
- var member = expression.callee.computed
- ? toConstant(expression.callee.property)
- : b.isIdentifier(expression.callee.property)
- ? expression.callee.property.name
- : undefined;
- if (member === undefined && !expression.callee.computed) {
- constant = false;
- }
- if (!constant)
- return;
- if (canCallMethod(object, '' + member)) {
- return object[member].apply(object, args);
- }
- }
- else {
- var callee = toConstant(expression.callee);
- if (!constant)
- return;
- return callee.apply(null, args);
- }
- }
- if (b.isConditionalExpression(expression)) {
- var test = toConstant(expression.test);
- return test
- ? toConstant(expression.consequent)
- : toConstant(expression.alternate);
- }
- if (b.isIdentifier(expression)) {
- if (options.constants &&
- {}.hasOwnProperty.call(options.constants, expression.name)) {
- return options.constants[expression.name];
- }
- }
- if (b.isLogicalExpression(expression)) {
- var left = toConstant(expression.left);
- var right = toConstant(expression.right);
- if (constant && expression.operator === '&&') {
- return left && right;
- }
- if (constant && expression.operator === '||') {
- return left || right;
- }
- }
- if (b.isMemberExpression(expression)) {
- var object = toConstant(expression.object);
- if (!object || !constant) {
- constant = false;
- return;
- }
- var member = expression.computed
- ? toConstant(expression.property)
- : b.isIdentifier(expression.property)
- ? expression.property.name
- : undefined;
- if (member === undefined && !expression.computed) {
- constant = false;
- }
- if (!constant)
- return;
- if ({}.hasOwnProperty.call(object, '' + member) && member[0] !== '_') {
- return object[member];
- }
- }
- if (b.isNullLiteral(expression)) {
- return null;
- }
- if (b.isNumericLiteral(expression)) {
- return expression.value;
- }
- if (b.isObjectExpression(expression)) {
- var result_2 = {};
- for (var i = 0; constant && i < expression.properties.length; i++) {
- var property = expression.properties[i];
- if (b.isObjectProperty(property)) {
- if (property.shorthand) {
- constant = false;
- return;
- }
- var key = property.computed
- ? toConstant(property.key)
- : b.isIdentifier(property.key)
- ? property.key.name
- : b.isStringLiteral(property.key)
- ? property.key.value
- : undefined;
- if (!key || key[0] === '_') {
- constant = false;
- }
- if (!constant)
- return;
- var value = toConstant(property.value);
- if (!constant)
- return;
- result_2[key] = value;
- }
- else if (b.isObjectMethod(property)) {
- constant = false;
- }
- else if (b.isSpreadProperty(property)) {
- var argument = toConstant(property.argument);
- if (!argument)
- constant = false;
- if (!constant)
- return;
- Object.assign(result_2, argument);
- }
- }
- return result_2;
- }
- if (b.isParenthesizedExpression(expression)) {
- return toConstant(expression.expression);
- }
- if (b.isRegExpLiteral(expression)) {
- return new RegExp(expression.pattern, expression.flags);
- }
- if (b.isSequenceExpression(expression)) {
- for (var i = 0; i < expression.expressions.length - 1 && constant; i++) {
- toConstant(expression.expressions[i]);
- }
- return toConstant(expression.expressions[expression.expressions.length - 1]);
- }
- if (b.isStringLiteral(expression)) {
- return expression.value;
- }
- // TODO: TaggedTemplateExpression
- if (b.isTemplateLiteral(expression)) {
- var result_3 = '';
- for (var i = 0; i < expression.quasis.length; i++) {
- var quasi = expression.quasis[i];
- result_3 += quasi.value.cooked;
- if (i < expression.expressions.length) {
- result_3 += '' + toConstant(expression.expressions[i]);
- }
- }
- return result_3;
- }
- if (b.isUnaryExpression(expression)) {
- var argument = toConstant(expression.argument);
- if (!constant) {
- return;
- }
- switch (expression.operator) {
- case '-':
- return -argument;
- case '+':
- return +argument;
- case '!':
- return !argument;
- case '~':
- return ~argument;
- case 'typeof':
- return typeof argument;
- case 'void':
- return void argument;
- }
- }
- constant = false;
- }
- var result = toConstant(expression);
- return constant ? { constant: true, result: result } : { constant: false };
- }
- exports.expressionToConstant = expressionToConstant;
- function isSpreadable(value) {
- return (typeof value === 'string' ||
- Array.isArray(value) ||
- (typeof Set !== 'undefined' && value instanceof Set) ||
- (typeof Map !== 'undefined' && value instanceof Map));
- }
- function shallowEqual(a, b) {
- if (a === b)
- return true;
- if (a && b && typeof a === 'object' && typeof b === 'object') {
- for (var key in a) {
- if (a[key] !== b[key]) {
- return false;
- }
- }
- for (var key in b) {
- if (a[key] !== b[key]) {
- return false;
- }
- }
- return true;
- }
- return false;
- }
- function canCallMethod(object, member) {
- switch (typeof object) {
- case 'boolean':
- switch (member) {
- case 'toString':
- return true;
- default:
- return false;
- }
- case 'number':
- switch (member) {
- case 'toExponential':
- case 'toFixed':
- case 'toPrecision':
- case 'toString':
- return true;
- default:
- return false;
- }
- case 'string':
- switch (member) {
- case 'charAt':
- case 'charCodeAt':
- case 'codePointAt':
- case 'concat':
- case 'endsWith':
- case 'includes':
- case 'indexOf':
- case 'lastIndexOf':
- case 'match':
- case 'normalize':
- case 'padEnd':
- case 'padStart':
- case 'repeat':
- case 'replace':
- case 'search':
- case 'slice':
- case 'split':
- case 'startsWith':
- case 'substr':
- case 'substring':
- case 'toLowerCase':
- case 'toUpperCase':
- case 'trim':
- return true;
- default:
- return false;
- }
- default:
- if (object instanceof RegExp) {
- switch (member) {
- case 'test':
- case 'exec':
- return true;
- default:
- return false;
- }
- }
- return {}.hasOwnProperty.call(object, member) && member[0] !== '_';
- }
- }
- var EMPTY_OBJECT = {};
- var lastSrc = '';
- var lastConstants = EMPTY_OBJECT;
- var lastOptions = EMPTY_OBJECT;
- var lastResult = null;
- var lastWasConstant = false;
- function isConstant(src, constants, options) {
- if (constants === void 0) { constants = EMPTY_OBJECT; }
- if (options === void 0) { options = EMPTY_OBJECT; }
- if (lastSrc === src &&
- shallowEqual(lastConstants, constants) &&
- shallowEqual(lastOptions, options)) {
- return lastWasConstant;
- }
- lastSrc = src;
- lastConstants = constants;
- var ast;
- try {
- ast = babylon_1.parseExpression(src, options);
- }
- catch (ex) {
- return (lastWasConstant = false);
- }
- var _a = expressionToConstant(ast, { constants: constants }), result = _a.result, constant = _a.constant;
- lastResult = result;
- return (lastWasConstant = constant);
- }
- exports.isConstant = isConstant;
- function toConstant(src, constants, options) {
- if (constants === void 0) { constants = EMPTY_OBJECT; }
- if (options === void 0) { options = EMPTY_OBJECT; }
- if (!isConstant(src, constants, options)) {
- throw new Error(JSON.stringify(src) + ' is not constant.');
- }
- return lastResult;
- }
- exports.toConstant = toConstant;
- exports["default"] = isConstant;
- module.exports = isConstant;
- module.exports["default"] = isConstant;
- module.exports.expressionToConstant = expressionToConstant;
- module.exports.isConstant = isConstant;
- module.exports.toConstant = toConstant;
|