astify
Astify generates Abstract Syntax Trees from objects in live JS (as well as from source). Want to convert the entire global object to source? global.toAST().toSource()
. Beyond adding toAST
, astify also makes build AST (which is then convertable to code using toSource
) super simple to do. Frankenstein different pieces of objects and functions together to make new ones.
This is still experimental and unfinished.
This is a fork of the original astify, with the dependancies included and uploaded to npm.
Usage
It is currently set up for use in Node.js (will be combining for a browser build soon).
var astify = require('astify');
astify.install(global);
console.log(global.toAST().toSource());
API
- astify.install(context): Install the
toAST
prototype functions on a given global object, defaulting to the main global.
- anything.toAST(showHidden, identity)_: Builtins get specialized
toAST
methods. showHidden includes non-enumerable properties. identity labels an object which doesn't have a discernable name. By default a gensym is provided.
- astify.parseFile(filename): creates AST from sourcecode.
- astify.createNode(type, args...): creates an AST Node from scratch.
Selectors
To select nodes you can use css-like syntax (work in progress) using node.find(selector). Some examples:
function function function var
- descending selectors, this would filter to vars that are inside 3 nested functions.
function > id
- child selector requires nodes to be direct children
var.declarations
- select specific properties
function.params.id
- select multiple properties
function:scope
- select all the nodes in the current scope
method[kind = ""][key != "constructor"].value
- selects methods (es6) with no kind (normal) where key is notEqual to constructor, then selectos its value property (a function expression).
method[key = "constructor"].value:first
- selects the first method with the name "constructor" and returns its value (function expr)
ident:first-child
- selects all identifiers that are first-children
return:last-child
- select all return statements which are last children
call[callee = "super"]
- select functions calls where the function name is "super"
member[object=super]
- selects expressions that look like "super.prop"
Node Creation
An intro example to manually assembling nodes
var _ = astify.createNode;
var myAST = _('object', {
a: 50,
b: _('function').declare({
somevar: 5,
another: _('iife').append([
_('return', _('function', 'another'))
])
}),
c: function hi(){
return 'stuff';
},
get d(){ return this.b.name }
});
Which produces
console.log(myAST.toSource());
var myAST = {
a: 50,
b: function () {
var somevar = 5,
another = function () {
return function another() {
};
}();
},
c: function hi() {
return 'stuff';
},
get d() {
return this.b.name;
}
};
And the AST:
{ type: 'ObjectExpression',
properties:
[ { type: 'Property',
key: { type: 'Identifier', name: 'a' },
value: { type: 'Literal', value: 50 },
kind: 'init' },
{ type: 'Property',
key: { type: 'Identifier', name: 'b' },
value:
{ type: 'FunctionExpression',
params: [],
id: null,
body:
{ type: 'BlockStatement',
body:
[ { type: 'VariableDeclaration',
kind: 'var',
declarations:
[ { type: 'VariableDeclarator',
id: { type: 'Identifier', name: 'somevar' },
init: { type: 'Literal', value: 5 } },
{ type: 'VariableDeclarator',
id: { type: 'Identifier', name: 'another' },
init:
{ type: 'CallExpression',
callee:
{ type: 'FunctionExpression',
params: [],
id: null,
body:
{ type: 'BlockStatement',
body:
[ { type: 'ReturnStatement',
argument:
{ type: 'FunctionExpression',
params: [],
id: { type: 'Identifier', name: 'another' },
body: { type: 'BlockStatement', body: [] } } } ] } },
arguments: [] } } ] } ] } },
kind: 'init' },
{ type: 'Property',
key: { type: 'Identifier', name: 'c' },
value:
{ type: 'FunctionExpression',
id: { type: 'Identifier', name: 'hi' },
params: [],
body:
{ type: 'BlockStatement',
body:
[ { type: 'ReturnStatement',
argument: { type: 'Literal', value: 'stuff' } } ] } },
kind: 'init' },
{ type: 'Property',
key: { type: 'Identifier', name: 'd' },
value:
{ type: 'FunctionExpression',
id: { type: 'Identifier', name: 'd' },
params: [],
body:
{ type: 'BlockStatement',
body:
[ { type: 'ReturnStatement',
argument:
{ type: 'MemberExpression',
computed: false,
object:
{ type: 'MemberExpression',
computed: false,
object: { type: 'Identifier', name: 'this' },
property: { type: 'Identifier', name: 'b' } },
property: { type: 'Identifier', name: 'name' } } } ] } },
kind: 'get' } ] }
Node Types
The short name can be used to identify the when using astify.createNode
. Optional arguments are in [brackets].
- "assign" - AssignmentExpression(operator, left, right)
- "array" - ArrayExpression([elementArray])
- "block" - BlockStatement([bodyStatementsArray])
- "binary" - BinaryExpression(operator, left, right)
- "break" - BreakStatement([label])
- "call" - CallExpression(callee, [argsExpressionsArray])
- "catch" - CatchClause(param, [[bodyBlock])
- "conditional" - ConditionalExpression(test, consequentExpression, alternateExpression)
- "continue" - ContinueStatement([label])
- "dowhile" - DoWhileStatement(test, [bodyBlock])
- "debugger" - DebuggerStatement()
- "empty" - EmptyStatement()
- "expression" - ExpressionStatement(expression)
- "for" - ForStatement([init, test, update, bodyBlock])
- "forin" - ForInStatement(left, right, [bodyBlock])
- "functiondecl" - FunctionDeclaration(id, [bodyBlock, params])
- "function" - FunctionExpression([id, bodyBlock, params])
- "identifier" - Identifier(name)
- "if" - IfStatement(test, [consequentBlock, alternateBlock])
- "literal" - Literal(value)
- "labeled" - LabeledStatement(label, [bodyBlock])
- "logical" - LogicalExpression(operator, left, right)
- "member" - MemberExpression(object, property)
- "new" - NewExpression(callee, [argsArray])
- "object" - ObjectExpression([propertiesArray])
- "program" - Program([bodyBlock, comments])
- "property" - Property(kind, key, value)
- "return" - ReturnStatement([argument])
- "sequence" - SequenceExpression(expressionsArray)
- "switch" - SwitchStatement(descriminant, [casesArray])
- "case" - SwitchCase([test, consequent])
- "this" - ThisExpression()
- "throw" - ThrowStatement(argument)
- "try" - TryStatement([block, handlers, finalizer])
- "unary" - UnaryExpression(operator, argument)
- "update" - UpdateExpression(operator, argument, [isPrefix])
- "var" - VariableDeclaration(kind, [declarationsArray])
- "decl" - VariableDeclarator(id, [init])
- "while" - WhileStatement(test, [bodyBlock])
- "with" - WithStatement(object, [bodyBlock])
- "iife" - ImmediatelyInvokedFunctionExpression([func, argsArray])