Example: console Calls Removal

The following Node.js script demonstrates the use of Esprima parser to remove every single expression that represents a console call. The script accepts the input from stdin and displays the result to stdout. The entire script comprises approximately 30 lines of code.

  1. const esprima = require('esprima');
  2. const readline = require('readline');
  3.  
  4. // console.log(x) or console['error'](y)
  5. function isConsoleCall(node) {
  6. return (node.type === 'CallExpression') &&
  7. (node.callee.type === 'MemberExpression') &&
  8. (node.callee.object.type === 'Identifier') &&
  9. (node.callee.object.name === 'console');
  10. }
  11.  
  12. function removeCalls(source) {
  13. const entries = [];
  14. esprima.parse(source, {}, function (node, meta) {
  15. if (isConsoleCall(node)) {
  16. entries.push({
  17. start: meta.start.offset,
  18. end: meta.end.offset
  19. });
  20. }
  21. });
  22. entries.sort((a, b) => { return b.end - a.end }).forEach(n => {
  23. source = source.slice(0, n.start) + source.slice(n.end);
  24. });
  25. return source;
  26. }
  27.  
  28. let source = '';
  29. readline.createInterface({ input: process.stdin, terminal: false })
  30. .on('line', line => { source += line + '\n' })
  31. .on('close', () => { console.log(removeCalls(source)) });

An example run is shown in the following screenshot (the script is called unconsole.js). Note that the single call to console.log is eliminated in the output.

Console removal

The script uses the readline module to read the input line-by-line, collecting each line to a buffer. Once there is no more input, it uses Esprima parser and utilizes the syntax delegate feature with a callback function that looks for a particular type of syntax node, i.e. a call expression with console object as the callee. The logic inside the isConsoleCall function is intended to match such a node. As an illustration, using the Esprima online demo to parse console.log("Hello") will reveal the following syntax tree:

Call expression

For each matched node, the node location is recorded. Once the parsing is completed, the list of the location of every matched call expression with console is used to modify the source, i.e. the portion of the source corresponding to the call expression is removed. When it is done repeatedly, the result is that every single console call will disappear. Note how this is done from the last one to the first one (reflected by the sorting in the reverse order) to maintain the correct offset throughout the process.