README
estree-toolkit
Tools for working with ESTree AST
Installation
npm i estree-toolkit
# or
yarn add estree-toolkit
Basic operations
Traversing an AST
const { traverse } = require('estree-toolkit');
traverse(ast, {
Program(path) {
// Do something with the path
}
});
Building Nodes
const { builders: b } = require('estree-toolkit');
b.identifier('x'); // => { type: 'Identifier', name: 'x' }
Checking node types
const { traverse, is } = require('estree-toolkit');
const { parseModule } = require('meriyah');
const ast = parseModule(`x = 0`);
traverse(ast, {
AssignmentExpression(path) {
if (is.identifier(path.node.left, { name: 'x' })) {
// `left` is an identifier with name `x`
}
}
});
Replacing a node
const { traverse, builders: b } = require('estree-toolkit');
const { parseModule } = require('meriyah');
const ast = parseModule('a = b');
traverse(ast, {
Identifier(path) {
if (path.node.name === 'a') {
path.replaceWith(b.identifier('c'));
}
}
});
// Now the AST represents - `c = b`
Collecting scope information
const { traverse } = require('estree-toolkit');
traverse(ast, {
// Enable scope
$: { scope: true },
Program(path) {
// `path.scope` is now available in all paths
}
});
Checking if a binding is available
const { traverse } = require('estree-toolkit');
const { parseModule } = require('meriyah');
const ast = parseModule(`
import { a } from 'source';
const { b, c: [d, { e }] } = a;
`);
traverse(ast, {
$: { scope: true },
Program(path) {
path.scope.hasBinding('a') // => true
path.scope.hasBinding('b') // => true
path.scope.hasBinding('c') // => false
path.scope.hasBinding('d') // => true
path.scope.hasBinding('e') // => true
}
});
Getting all references of a binding
const { traverse } = require('estree-toolkit');
const { parseModule } = require('meriyah');
const ast = parseModule(`
import { a } from 'source';
fn(a);
s = a;
let obj = { a };
`);
traverse(ast, {
$: { scope: true },
Program(path) {
// Returns all the paths that reference the binding `a`
path.scope.getBinding('a').references // => [NodePath, NodePath, NodePath]
}
});
Checking if a global have been used
const { traverse } = require('estree-toolkit');
const { parseModule } = require('meriyah');
const ast = parseModule(`
const fx = require('fx-mod');
`);
traverse(ast, {
$: { scope: true },
Program(path) {
path.hasGlobalBinding('require') // => true
}
});
Utilities
There are several static utilities that you can use.
evaluate
Evaluates the given path. For now it only supports evaluation of logical, binary and unary operations.const { utils: u } = require('estree-toolkit'); // We are using `meriyah` but you can use any parser (like `acorn`) const { parseModule } = require('meriyah'); traverse(parseModule(`1 + 2`), { BinaryExpression(path) { u.evaluate(path) // => { value: 3 } } }); traverse(parseModule(`1 === 2`), { BinaryExpression(path) { u.evaluate(path) // => { value: false } } }); traverse(parseModule(`iDoNotKnowWhatThisIs === 55`), { BinaryExpression(path) { u.evaluate(path) // => undefined } });
evaluateTruthy
Evaluates the path for truthiness and returnstrue
,false
orundefined
depending on evaluation result.hasBinding
Checks if any binding with the name is available in the containing scope.const { utils: u } = require('estree-toolkit'); const { parseModule } = require('meriyah'); const ast = parseModule(` { let a; { id1; } } id2; `); traverse(ast, { Identifier(path) { if (path.node.name === 'id1') { u.hasBinding(path, 'a') // => true } else if (path.node.name === 'id2') { u.hasBinding(path, 'a') // => false } } });
Documentation
The documentation is work in progress. You can find the documentation at https://estree-toolkit.netlify.app/
License
Licensed under the MIT License.