Web App Development

Parsing and modifying Javascript code with Esprima and Escodegen

Esprima is a Javascript parser, i.e., it generates a nested object to represent the code structure in a more easily processable way than the human-centered code. Escodegen is a code generator that can take the object generated by Esprima and turn it back into Javascript code.

Together they can be used to inject instructions into the code, for example to log values.

Both can be used in either the browser or Node.

Parsing with Esprima

To load Esprima in the browsers we need to include the esprima.js file in the html code.
With Node run npm install esprima --save and var esprima = require('esprima') to the top of your Javascript code.

Then use Esprima’s parse method to generate the syntax tree:

esprima.parse('console.log("Hello world!")')

The output follows the format of Mozilla’s SpiderMonkey parser (Spidermonkey is Firefox’s Javascript engine, like V8 for Chrome or Node):

{
    "type": "Program",
    "body": [{
        "type": "ExpressionStatement",
        "expression": {
            "type": "CallExpression",
            "callee": {
                "type": "MemberExpression",
                "computed": false,
                "object": {
                    "type": "Identifier",
                    "name": "console"
                },
                "property": {
                    "type": "Identifier",
                    "name": "log"
                }
            },
            "arguments": [{
                "type": "Literal",
                "value": "Hello world!"
            }]
        }
    }]
}

It’s quite verbose, but we can now more easily iterate over the instructions.

To parse arguments to Esprima pass an options object as a second parameter:

esprima.parse('console.log("Hello world!")', {range: true})

The range option will add a character index to all parse tree elements:

"type": "MemberExpression",
    "computed": false,
    "object": {
        "type": "Identifier",
        "name": "console",
        "range": [0, 7]
    },
    // ...
    "range": [0, 11]
}

Esprima has a tool that updates the syntax tree of entered code in real time , which also shows some of the other options that are available, such as loc to get line numbers and comment to include comments in the syntax tree.

Turning the syntax tree back into code using Escodegen

To get the browser version download the release and look for the escodegen.browser.js in the extracted folder.

On the server run npm install escodegen --save and load the library with var escodegen = require('escodegen').

Now to go full circle back to the original code call escodgen.generate witht the parse tree as the first argument.

var parsed = esprima.parse('console.log("Hello world!")');
escodegen.generate(parsed); // Returns "console.log('Hello world!')";

Injecting code

To inject code we modify the parse tree before passing it to Escodegen.

We can avoid having to deal with parse trees directly by passing the code we want to inject to esprima.parse before adding it to the parse tree:

var parsed = esprima.parse('console.log("Hello world!")')
parsed.body.unshift(esprima.parse('start()'))
parsed.body.push(esprima.parse('end()'))
var newCode = escodegen.generate(parsed)

Which gives us the original code wrapped by two function calls that we could use for example to log how long the function takes to execute:

start();
console.log('Hello world!');
end();

Follow me on Twitter