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 79 80 81 82 83 84 85 86 87 88 | 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 7x 7x 7x 1x 1x | // See https://github.com/babel/minify/tree/master/packages/babel-plugin-minify-constant-folding
const fs = require("fs");
const deb = require('../src/deb.js');
const escodegen = require("escodegen");
const espree = require("espree");
const estraverse = require("estraverse");
"use strict";
module.exports = constantFolding;
/**
* This function gets passed by a Node and depending on its type will perform
* different operations.
* @param {Obect} elem Single subNode
* @returns
*/
function getValues(elem) {
let types = {
'Literal' : () => {return elem.raw},
'Identifier' : () => {return elem.name},
'ArrayExpression' : () => {return `${elem.elements.map(l => getValues(l))}`},
'BinaryExpression' : () => {return `${eval(`${elem.left.raw} ${elem.operator} ${elem.right.raw}`)}`}
}
return types[elem.type]();
}
/**
* This function gets passed two arguments and perform a transformation in the node
* depending different parameters. Then it creates a new node object that will substitute
* the passed one.
* @param {Object} n Node object in which constant folding will be applied
* @param {*} args Possible arguments this node has ex: [a].concat([b]), [b] are the args here
*/
function transNode(n, args) {
let argString = ""
let auxstring = "";
let a = n.expression;
if (args) {
a = n.expression.callee;
argString += `(${(args) ? args.map(arg => getValues(arg)) : ''})`;
}
if (a.property.type == 'Literal')
auxString = `[${a.object.elements.map(el => getValues(el))}][${getValues(a.property)}]` + argString;
else
auxString = `[${a.object.elements.map(el => getValues(el))}].${getValues(a.property)}` + argString;
n.expression = espree.parse(eval(auxString)).body[0].expression;
}
/**
* This Function takes a Node of type BinaryExpression and perform constant Folding on it
* @param {Object} n Node with a type of BinaryExpression
*/
function transLiteralNode(n) {
n.value = Number(getValues(n));
n.raw = String(n.value);
n.type = 'Literal';
delete n.left;
delete n.rigth;
}
/**
* This function get passed some code and then it forms an AST tree with it.
* After it traverses the tree doing constant folding in different nodes in
* which it is possible to perform it
* @param {string} code The javascript input code
* @returns {string} Generated js code from the resultant tree
*/
function constantFolding(code) {
let ast = espree.parse(code, {ecmaVersion: espree.latestEcmaVersion});
estraverse.traverse(ast, {
leave: function(node, parent) {
Iif (node.type == 'ExpressionStatement' && node.expression.type == 'CallExpression' && node.expression.callee.object.type == 'ArrayExpression') {
transNode(node, node.expression.arguments);
}
Iif (node.type == 'ExpressionStatement' && node.expression.type == 'MemberExpression' && node.expression.object.type == 'ArrayExpression') {
transNode(node);
}
if(node.type == 'BinaryExpression' && node.left.type == 'Literal' && node.right.type == 'Literal') {
transLiteralNode(node);
}
}
});
//deb(ast);
return escodegen.generate(ast);
} |