UNPKG

@alu0101350158/constant-folding

Version:
184 lines (170 loc) 5.27 kB
// 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"); const { Console } = require("console"); "use strict"; module.exports = constantFolding; /** * A function that takes js code in a string * and applies constant folding to transform it * @param {string} code A string containing the js code * * @returns {string} Returns the transformed code as a string */ function constantFolding(code) { const t = espree.parse(code, { ecmaVersion: 6, loc: false }); estraverse.traverse(t, { leave: function (n) { if ( n.type == "MemberExpression" && n.object.type == "ArrayExpression") { if (n.property.name == "length" ) { replaceByArrayLength(n); } else if (n.property.type == "Literal" || n.property.type == "BinaryExpression") { replaceByArraySquare(n); } } if ( n.type == "CallExpression" && n.callee.type == "MemberExpression" && n.callee.object.type == "ArrayExpression" ) { if (n.callee.property.name == "concat" ) { replaceByArrayConcat(n); } else if (n.callee.property.name == "join") { if (n.arguments[0] != null) { replaceByArrayJoin(n, n.arguments[0].value); } else { replaceByArrayJoin(n); } } else if (n.callee.property.name == "pop") { replaceByArrayPop(n); } } if ( n.type == "BinaryExpression" && n.left.type == "Literal" && n.right.type == "Literal" ) { replaceByLiteral(n); } }, }); deb(t); let c = escodegen.generate(t); return c; } /** * A function that takes an ast node and evaluates * it's binary expresion in order to replace it with * it's value * * @param code An ast node */ function replaceByLiteral(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; } /** * A function that takes an ast node and evaluates * it's member expresion in order to replace it with * it's value * In this case the member expression is array.length * @param code An ast node */ function replaceByArrayLength(n) { n.type = "Literal"; n.value = n.object.elements.length; n.raw = String(n.value); delete n.object; delete n.property; } /** * A function that takes an ast node and evaluates * it's member expresion in order to replace it with * it's value * In this case the member expression is array.join(). * @param code An ast node */ function replaceByArrayJoin(n, separator = ',') { n.type = "Literal" let resultstring = ""; for (let i = 0; i < n.callee.object.elements.length; i++) { resultstring += n.callee.object.elements[i].value; if (i >= n.callee.object.elements.length - 1) break; resultstring += separator; } n.value = resultstring; n.raw = String(resultstring); } /** * A function that takes an ast node and evaluates * it's member expresion in order to replace it with * it's value * In this case the member expression is array[]. * @param code An ast node */ function replaceByArraySquare(n){ n.type = "Literal"; let position = 0; if (n.property.type == "BinaryExpression") { position = eval(`${n.property.left.raw} ${n.property.operator} ${n.property.right.raw}`); } else { position = n.property.value; } for (let i = 0; i < n.object.elements.length; i++){ if(i == position) { n.value = n.object.elements[i].value; } } n.raw = String(n.value); delete n.object delete n.property; } /** * A function that takes an ast node and evaluates * it's member expresion in order to replace it with * it's value * In this case the member expression is array.pop(). * @param code An ast node */ function replaceByArrayPop(n) { n.type = n.callee.object.elements[n.callee.object.elements.length -1].type; if(n.type == "Identifier") { n.name = n.callee.object.elements[n.callee.object.elements.length -1].name; } else if (n.type == "Literal") { n.value = n.callee.object.elements[n.callee.object.elements.length -1].value; n.raw = String(n.value); } delete n.callee; delete n.arguments; } /** * A function that takes an ast node and evaluates * it's member expresion in order to replace it with * it's value * In this case the member expression is array.concat(). * @param code An ast node */ function replaceByArrayConcat(n) { n.type = "ArrayExpression"; let elements = []; for (let i = 0; i < n.callee.object.elements.length; i++) { //console.log(n.callee.object.elements[i].raw) elements.push(n.callee.object.elements[i]); } for (let i = 0; i < n.arguments.length; i++) { if(n.arguments[i].type == "ArrayExpression") { for (let j = 0; j < n.arguments[i].elements.length; j++) { elements.push(n.arguments[i].elements[j]); } } else { elements.push(n.arguments[i]); } } n.elements = elements; delete n.callee; delete n.arguments; }