astify v0.0.4
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); //the toAST functions must be explicitly installed on a global object
console.log(global.toAST().toSource()); // anything can be converted to AST
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 childrenvar.declarations
- select specific propertiesfunction.params.id
- select multiple propertiesfunction:scope
- select all the nodes in the current scopemethod[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-childrenreturn:last-child
- select all return statements which are last childrencall[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;
// intermix explicit AST node definitions with regular functions, objects, and literals
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)