estree-toolkit
Table of Contents

Utilities

These are basic utilities that you can use as helper functions

const { utils: u } = require('estree-toolkit');

evaluate(path)

  • path: <NodePath> The path that you want to evaluate
  • Returns: { value: any } | undefined The evaluation result

Evaluates the given path and returns the evaluated result. If it's sure about the evaluation it would return an object with the evaluated value stored in value property. If it's not sure about the evaluation it would return undefined.

These AST Nodes are supported for now

  • Identifier - with undefined as value
  • Literal
  • BinaryExpression - except instanceof operator
  • UnaryExpression - except delete operator
  • LogicalExpression
  • ObjectExpression
  • ArrayExpression
const { utils: u, traverse } = require('estree-toolkit'); const { parseModule } = require('meriyah'); traverse(parseModule(`undefined`), { Identifier(path) { u.evaluate(path) // => { value: undefined } } }); traverse(parseModule(`'some string'`), { Literal(path) { u.evaluate(path) // => { value: 'some string' } } }); traverse(parseModule(`1 + 2`), { BinaryExpression(path) { u.evaluate(path) // => { value: 3 } } }); traverse(parseModule(`!(1 === 2)`), { UnaryExpression(path) { u.evaluate(path) // => { value: true } } }); traverse(parseModule(`false && unknown`), { LogicalExpression(path) { u.evaluate(path) // => { value: false } } }); traverse(parseModule(` ({ a: 1, b: 2, m: { c: 1 } }) `), { ObjectExpression(path) { if (path.parent.type !== 'ExpressionStatement') return; u.evaluate(path) // => { value: { a: 1, b: 2, m: { c: 1 } } } } }); traverse(parseModule(`[1, 2, '3']`), { ArrayExpression(path) { u.evaluate(path) // => { value: [1, 2, '3'] } } }); // Whenever unknown binding is involved, it returns `undefined` traverse(parseModule(`unknownVariable`), { Identifier(path) { u.evaluate(path) // => undefined } }); traverse(parseModule(`unknownVariable === 55`), { BinaryExpression(path) { u.evaluate(path) // => undefined } });

evaluateTruthy(path)

  • path: <NodePath> The path that you want to evaluate
  • Returns: true | false | undefined The evaluation result

It's just like evaluate(path) but it evaluates for truthiness. It returns true or false depending on the evaluation result, if it's sure. If it's not sure, it would return undefined.

const { utils: u, traverse } = require('estree-toolkit'); const { parseModule } = require('meriyah'); traverse(parseModule(`false && unknown`), { LogicalExpression(path) { u.evaluateTruthy(path) // => false } }); traverse(parseModule(`true || unknown`), { LogicalExpression(path) { u.evaluateTruthy(path) // => true } }); traverse(parseModule(`!0`), { UnaryExpression(path) { u.evaluateTruthy(path) // => true } });

hasBinding(path, name)

  • path: <NodePath> The path from where the searching should start
  • name: <string> The name of the binding
  • Returns: boolean If the binding is available in the current position

You can easily track scopes by enabling Scope when traversing. But if you need to check if a binding is available only one or two times, using Scope can be overkill, because scope builds all the graphs that you may not need. So using hasBinding in this case would be more preferable.

This function starts walking up the tree from the path and finds if there is any binding with the provided name. If there is any binding it returns true, if not then it returns false.

const { utils: u, traverse } = 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 } } });

getCommonAncestor(paths)

  • paths: <NodePath[]> The paths for which the ancestor should be common
  • Returns: <NodePath> The NodePath of the ancestor

Finds the closest common parent (or ancestor) for all the provided paths