Source: constant-folding.js

// 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;

/**
 * Receive a node that will be replaced by the evaluation of binary operation  
 * @param {Node} n Replace node
 */
function replaceBinary(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;
}
/**
* Receive a node that will be replaced by the evaluation of the length of an array
* @param {Node} n Replace node
*/
function replaceLength(n) {
  n.type = "Literal";

  n.value = eval(`${n.object.elements.length}`);
  n.raw = String(n.value);

}
/**
 * A function that reduce the code using constant folding
 * @param {string} code A JS code encapuslated in a String
 * @returns {string} Returns code reduced using costant folding
 */
/**
* Receive a node that will be replaced by the evaluation of the length of an array
* @param {Node} n Replace node
*/
function replaceAt(n) {
  Object.assign(n, n.object.elements[n.property.value])
  delete n.object
  delete n.property
}

/**
* Only puts the last item of an array
* @param {Node} n Replace node
* @param {Node} p Parent Node
*/
function replacePop(n, p) {
  Object.assign(p, n.object.elements.pop())
  delete p.callee
  delete p.arguments
}

/**
* Splice elements from elements array
* @param {Node} n Replace node
*/
function replaceSlice(n) {
  arrayAux = {
    type: "ArrayExpression",
    elements: null,
  }
  arrayAux.elements = n.callee.object.elements.slice(...n.arguments.map(x => x.value))

  Object.assign(n, arrayAux)
  delete n.callee
  delete n.object
  delete n.arguments
}


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"
      ) {
        replaceBinary(n);
      } else if (n.type === "MemberExpression") {
        if (n.object.type === "ArrayExpression") {
          if (n.property.type === "Identifier" && n.property.name === "length") {
            replaceLength(n);
          } else if (n.property.type === "Identifier" && n.property.name === "pop") {
            replacePop(n, p);

          } else if (n.property.type === "Literal") {
            replaceAt(n)
          }
        }
      } else if (n.type === "CallExpression") {
        if (n.callee.type === "MemberExpression"
          && n.callee.property.type === "Identifier"
          && n.callee.property.name === "slice") {
          if (n.arguments.every(x => x.type === "Literal"))
            replaceSlice(n)
        }
      }

    },
  });
  let output = escodegen.generate(t);
  /* ... */
  return output;
}