Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | 1x 1x 1x 1x 1x 1x 12x 12x 114x 5x 114x 2x 2x 114x 7x 7x 12x 5x 5x 5x 5x 5x 27x 9x 9x 9x | const escodegen = require("escodegen");
const espree = require("espree");
const estraverse = require("estraverse");
const { isConstant, newArrayNode, newNode, getValue } = require("./utils");
"use strict";
module.exports = constantFolding;
/**
* A function that does constant folding onto the code it receives
* @param {string} code A string containing the code to do the constant folding on
* @returns {string} Returns the resulting code
*/
function constantFolding(code) {
const t = espree.parse(code, { ecmaVersion: 6, loc: false });
estraverse.traverse(t, {
leave: function (n, p) {
if (
n.type == "BinaryExpression" &&
n.left.type == "Literal" && n.right.type == "Literal"
) {
binaryConstantFolding(n);
}
if (
(n.type === "MemberExpression") &&
(n.object.type === "ArrayExpression") &&
(p.type !== "CallExpression")
) {
let value = eval(arrayConstantFolding(n));
Object.assign(n, newNode(value));
}
if (
(n.type === "CallExpression") &&
(n.callee.object.type === "ArrayExpression") &&
isConstant(n.arguments) &&
isConstant(n.callee.object.elements)
) {
let value = arrayConstantFolding(n.callee, n.arguments);
Array.isArray(value) ?
Object.assign(n, newArrayNode(value)) :
Object.assign(n, newNode(value));
}
}
}
);
return escodegen.generate(t);
}
/**
* Does ConstantFolding on binaryExpression nodes. I.E. turns 2+3 into 5.
* @param {Object} n an AST node representing a binaryExpression.
*/
function binaryConstantFolding(n) {
n.type = "Literal";
n.value = eval(`${n.left.raw} ${n.operator} ${n.right.raw}`);
n.raw = String(n.value);
delete n.left;
delete n.right;
}
/**
* Does constant folding on Array operations.
* @param {Object} code an AST node containing the expression statement
* @param {Array} args arguments used on the function call. I.E. for [1].concat('d', 'e'), args = ['d', 'e']
* @returns {string} the resulting js code to be used by escodegen
*/
function arrayConstantFolding(code, args) {
let result = `[${code.object.elements.map(e => getValue(e))}]`;
result += code.property.type === "Literal" ? `[${getValue(code.property)}]` : `.${getValue(code.property)}`;
result += (args ? `(${args.map(e => getValue(e))})` : "");
return eval(result);
}
|