burrito
=======

Burrito makes it easy to do crazy stuff with the javascript AST.

This is super useful if you want to roll your own stack traces or build a code
coverage tool.

[![build status](https://secure.travis-ci.org/substack/node-burrito.png)](http://travis-ci.org/substack/node-burrito)

![node.wrap("burrito")](http://substack.net/images/burrito.png)

examples
========

microwave
---------

examples/microwave.js

````javascript
var burrito = require('burrito');

var res = burrito.microwave('Math.sin(2)', function (node) {
    if (node.name === 'num') node.wrap('Math.PI / %s');
});

console.log(res); // sin(pi / 2) == 1
````

output:

    1

wrap
----

examples/wrap.js

````javascript
var burrito = require('burrito');

var src = burrito('f() && g(h())\nfoo()', function (node) {
    if (node.name === 'call') node.wrap('qqq(%s)');
});

console.log(src);
````

output:

    qqq(f()) && qqq(g(qqq(h())));

    qqq(foo());

methods
=======

    var burrito = require('burrito');

burrito(code, cb)
-----------------

Given some source `code` and a function `trace`, walk the ast by expression.

The `cb` gets called with a node object described below.

If `code` is an Array then it is assumbed to be an AST which you can generate
yourself with `burrito.parse()`. The AST must be annotated, so make sure to
`burrito.parse(src, false, true)`.

burrito.microwave(code, context={}, cb)
---------------------------------------

Like `burrito()` except the result is run using
`vm.runInNewContext(res, context)`.

node object
===========

node.name
---------

Name is a string that contains the type of the expression as named by uglify.

node.wrap(s)
------------

Wrap the current expression in `s`.

If `s` is a string, `"%s"` will be replaced with the stringified current
expression.

If `s` is a function, it is called with the stringified current expression and
should return a new stringified expression.

If the `node.name === "binary"`, you get the subterms "%a" and "%b" to play with
too. These subterms are applied if `s` is a function too: `s(expr, a, b)`.

Protip: to insert multiple statements you can use javascript's lesser-known block
syntax that it gets from C:

````javascript
if (node.name === 'stat') node.wrap('{ foo(); %s }')
````

node.node
---------

raw ast data generated by uglify

node.value
----------

`node.node.slice(1)` to skip the annotations

node.start
----------

The start location of the expression, like this:

````javascript
{ type: 'name',
  value: 'b',
  line: 0,
  col: 3,
  pos: 3,
  nlb: false,
  comments_before: [] }
````

node.end
--------

The end  location of the expression, formatted the same as `node.start`.

node.state
----------

The state of the traversal using traverse.

node.source()
-------------

Returns a stringified version of the expression.

node.parent()
-------------

Returns the parent `node` or `null` if the node is the root element.

node.label()
------------

Return the label of the present node or `null` if there is no label.

Labels are returned for "call", "var", "defun", and "function" nodes.

Returns an array for "var" nodes since `var` statements can
contain multiple labels in assignment.

install
=======

With [npm](http://npmjs.org) you can just:

    npm install burrito

in the browser
==============

Burrito works in browser with
[browserify](https://github.com/substack/node-browserify).

It has been tested against:

* Internet Explorer 5.5, 6.0, 7.0, 8.0, 9.0
* Firefox 3.5
* Chrome 6.0
* Opera 10.6
* Safari 5.0

kudos
=====

Heavily inspired by (and previously mostly lifted outright from) isaacs's nifty
tmp/instrument.js thingy from uglify-js.
