# Esprima Documentation

## Basic Usage

Esprima runs on web browsers (IE 6+, Firefox 1+, Safari 3+, Chrome 1+, Konqueror 4.6+, Opera 8+) as well as Rhino and Node.js.

### In a web browser

Just include the source file:

    <script src="esparse.js"></script>

The module `esprima` will be available as part of the global window object:

    var syntax = esprima.parse('var answer = 42');

Since Esprima supports AMD (Asynchronous Module Definition), it can be loaded via a module loader such as RequireJS:

    require(['esprima'], function (parser) {
        // Do something with parser, e.g.
        var syntax = parser.parse('var answer = 42');
        console.log(JSON.stringify(syntax, null, 4));
    });

Since Esprima is available as a Bower component, it can be installed with:

    bower install esprima

Obviously, it can be used with Yeoman as well:

    yeoman install esprima

### With Node.js

Esprima is available as a Node.js package, install it using npm:

    npm install esprima

Load the module with `require` and use it:

    var esprima = require('esprima');
    console.log(JSON.stringify(esprima.parse('var answer = 42'), null, 4));

### With Rhino

Load the source file from another script:

    load('/path/to/esprima.js');

The module `esprima` will be available as part of the global object:

    var syntax = esprima.parse('42');
    print(JSON.stringify(syntax, null, 2));

### Parsing Interface

Basic usage:

    esprima.parse(code, options);

The output of the parser is the syntax tree formatted in JSON, see the following Syntax Tree Format section.

Available options so far (by default, every option false):

Option | When set to true
--- | ---
loc | Nodes have line and column-based location info
range | Nodes have an index-based location range (array)
raw | Literals have extra property which stores the verbatim source
tokens | An extra array containing all found tokens
comment | An extra array containing all line and block comments

The easiest way to see the different output based on various option settings is to use the online parser demo.

## Examples

### Detect Nested Ternary Conditionals

The script `detectnestedternary.js` in the `examples/` subdirectory is using Esprima to look for a ternary conditional, i.e. operator ?:, which is immediately followed (in one of its code paths) by another ternary conditional. The script can be invoked from the command-line with Node.js:

    node detectnestedternary.js /some/path

An example code fragment which will be flagged by this script as having a nested ternary conditional:

    var str = (age < 1) ? "baby" :
        (age < 5) ? "toddler" :
        (age < 18) ? "child": "adult";

which will yield the following report:

      Line 1 : Nested ternary for "age < 1"
      Line 2 : Nested ternary for "age < 5"

### Find Possible Boolean Traps

The script `findbooleantrap.js` in the `examples/` subdirectory is using Esprima to detect some possible cases of Boolean trap, i.e. the use of Boolean literal which may lead to ambiguities and lack of readability. The script can be invoked from command-line with Node.js:

    node findbooleantrap.js /some/path

It will search for all files (recursively) in the given path, try to parse each file, and then look for signs of Boolean traps:

- Literal used with a non-setter function (assumption: setter starts with the "set" prefix):

    this.refresh(true);

- Literal used with a function whose name may have a double-negative interpretation:

    item.setHidden(false);

- Two different literals in a single function call:

    element.stop(true, false);

- Multiple literals in a single function invocation:

    event.initKeyEvent("keypress", true, true, null, null,
        false, false, false, false, 9, 0);

- Ambiguous Boolean literal as the last argument:

    return getSomething(obj, false);

For some more info, read also the blog post on Boolean trap.

## Syntax Tree Format

The output of the parser is expected to be compatible with Mozilla SpiderMonkey Parser API. The best way to understand various different constructs is the online parser demo which shows the syntax tree (formatted with JSON.stringify) corresponding to the typed code. The simplest example is as follows. If the following code is executed:

    esprima.parse('var answer = 42;');

then the return value will be (JSON formatted):

    {
        type: 'Program',
        body: [
            {
                type: 'VariableDeclaration',
                declarations: [
                    {
                        type: 'AssignmentExpression',
                        operator: =,
                        left: {
                            type: 'Identifier',
                            name: 'answer'
                        },
                        right: {
                            type: 'Literal',
                            value: 42
                        }
                    }
                ]
            }
        ]
    }

## Contribution Guide

### Guidelines

Contributors are mandated to follow the guides described in the following sections. Any contribution which do not conform to the guides may be rejected.

#### Laundry list

Before creating pull requests, make sure the following applies.

There is a corresponding issue. If there is no issue yet, create one in the issue tracker.

The commit log links the corresponding issue (usually as the last line).

No functional regression. Run all unit tests.

No coverage regression. Run the code coverage analysis.

Each commit must be granular. Big changes should be splitted into smaller commits.

Write understandable code. No need to be too terse (or even obfuscated).

JSLint does not complain.

A new feature must be accompanied with unit tests. No compromise.

A new feature should not cause performance loss. Verify with the benchmark tests.

Performance improvement should be backed up by actual conclusive speed-up in the benchmark suite.

#### Coding style

Indentation is 4 spaces.

Open curly brace is at the end of the line.

String literal uses single quote (') and not double quote (").

#### Commit message

Bad:

        Fix a problem with Firefox.

The above commit is too short and useless in the long term.

Good:

        Add support for labeled statement.

        It is covered in ECMAScript Language Specification Section 12.12.
        This also fixes parsing MooTools and JSLint code.

        Running the benchmarks suite show negligible performance loss.

        http://code.google.com/p/esprima/issues/detail?id=10
        http://code.google.com/p/esprima/issues/detail?id=15
        http://code.google.com/p/esprima/issues/detail?id=16

Important aspects:

- The first line is the short description, useful for per-line commit view and thus keep it under 80 characters.
- The next paragraphs should provide more explanation (if needed).
- Describe the testing situation (new unit/benchmark test, change in performance, etc).
- Put the link to the issues for cross-ref.

#### Baseline syntax tree as the expected result

The test suite contains a collection of a pair of code and its syntax tree. To generate the syntax tree suitably formatted for the test fixture, use the included helper script `tools/generate-test-fixture.js` (with Node.js), e.g.:

    node tools/generate-test-fixture.js "var answer = 42"

The syntax tree will be printed out to the console. This can be used in the test fixture.

### Test Workflow

#### Unit tests

Browser-based unit testing is available by opening `test/index.html` in the source tree. The online version is esprima.org/test.

Command-line testing using Node.js:

    npm test

#### Code coverage test

Note: you need to use Node.js 0.6 or later version.

Install node-cover:

    sudo npm install -g cover

Run it in Esprima source tree:

    cover run test/runner.js

Check the quick report:

    cover report

To get the detailed report:

    cover report html

and then open `cover_html/index.html` file and choose `esprima.js` from the list.

#### Benchmark tests

Available by opening `test/benchmarks.html` in the source tree. The online version is esprima.org/test/benchmarks.html.

Note: Because the corpus is fetched via XML HTTP Request, the benchmarks test needs to be served via a web server and not local file.

It is important to run this with various browsers to cover different JavaScript engines.

Command-line benchmark using Node.js:

    node test/benchmark.js

Command-line benchmark using V8 shell:

    /path/to/v8/shell test/benchmark.js

The current corpus for the benchmarks:

- jQuery (version 1.7.1 and 1.6.4)
- jQuery Mobile (version 1.0)
- Prototype (version 1.7.0.0 and 1.6.1)
- Ext Core (version 3.1.0 and 3.0.0)
- MooTools (version 1.4.1 and 1.3.2)
- Backbone (version 0.5.3)
- Underscore (version 1.2.3)

#### Speed comparison tests

Available by opening `test/compare.html`. The online version is esprima.org/test/compare.html.

Note: Because the corpus is fetched via XML HTTP Request, the benchmarks test needs to be served via a web server and not local file.

Warning: Since each parser has a different format for the syntax tree, the speed is not fully comparable (the cost of constructing different result is not taken into account). These tests exist only to ensure that Esprima parser is not ridiculously slow, e.g. one magnitude slower compare to other parsers.

The current corpus for the speed comparison tests:

- jQuery version 1.7.1
- Prototype version 1.7.0.0
- MooTools version 1.4.1
- Ext Core version 3.1.0

#### Manual tests

Code parser

Available by opening `demo/parse.html`.

In this demo, whatever is typed in the editor will be parsed. If it is a valid code, the syntax tree will be shown formatted using JSON.stringify.

Operator precedence

Available by opening `demo/precedence.html`.

The demo compares two expression and decides whether they are semantically equivalent or not. If not, the expression will be rewritten, with extra parentheses, to following the intended semantic of the original.

Regular expression collector

Available by opening `demo/collector.html`.

The demo finds all the regular expressions in the given code, along with the location for each regular expression.

Function tracing

Available by opening `demo/functiontrace.html`.

The demo inserts a function call at the beginning of every function block to log the number of times the function is executed.

## Related Projects

### Sister projects

Escodegen is a code generator which supports Esprima syntax tree. This is useful for source code transformation. The source can be parsed by Esprima and then regenerated using escodegen. Between the process, the syntax tree can be transformed.

Esmorph is a non-destructive source code morphing tool. It can tweak portions of the code without affecting the rest (hence the term non-destructive).

### Similar parsers

Narcissus is a metacircular implementation of JavaScript. Obviously it has a parsing capability. Check more at the code repo: github.com/mozilla/narcissus. Narcissus is likely the oldest JavaScript parser written in JavaScript.

UglifyJS is a minifier and obfuscator which has a parser called parse-js. It is pretty popular and widely used. Read more at its project page: github.com/mishoo/UglifyJS.

ZeParser, see github.com/qfox/ZeParser.

## License

Copyright (C) 2012, 2011 Ariya Hidayat and other contributors.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.