acorn-walk vs estree-walker
JavaScript AST (Abstract Syntax Tree) Traversal Comparison
1 Year
acorn-walkestree-walkerSimilar Packages:
What's JavaScript AST (Abstract Syntax Tree) Traversal?

JavaScript AST (Abstract Syntax Tree) Traversal libraries are tools that allow developers to navigate and manipulate the structure of JavaScript code programmatically. These libraries parse JavaScript code into a tree-like structure, where each node represents a part of the code (such as a variable, function, or expression). By traversing this tree, developers can analyze, transform, or generate code, making these libraries essential for tasks like linting, code formatting, and building compilers or transpilers. acorn-walk is a simple and efficient AST walker for Acorn, a fast JavaScript parser, while estree-walker is a more flexible walker designed for ESTree-compliant ASTs, supporting various traversal patterns and allowing for easier integration with other tools in the JavaScript ecosystem.

Package Weekly Downloads Trend
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
acorn-walk52,902,40711,02252.3 kB1710 months agoMIT
estree-walker51,456,95641417.6 kB113 years agoMIT
Feature Comparison: acorn-walk vs estree-walker

AST Compatibility

  • acorn-walk:

    acorn-walk is specifically designed for the AST generated by the Acorn parser. It is optimized for this particular AST structure, making it highly efficient for projects that use Acorn for parsing.

  • estree-walker:

    estree-walker is designed to work with ESTree-compliant ASTs, which are a standardized format for representing JavaScript code. This makes estree-walker more versatile and compatible with a wider range of parsers and tools that adhere to the ESTree specification.

Traversal Flexibility

  • acorn-walk:

    acorn-walk provides a simple and straightforward API for traversing the AST. It supports depth-first and breadth-first traversal but lacks advanced features like custom node handling or asynchronous traversal.

  • estree-walker:

    estree-walker offers more flexibility in how traversal is performed. It supports custom walkers, allows for asynchronous traversal, and provides more control over the traversal process, making it suitable for complex use cases.

Integration with Other Tools

  • acorn-walk:

    acorn-walk is tightly integrated with the Acorn parser, making it a natural choice for projects that use Acorn. However, its integration with other tools and parsers is limited due to its specificity.

  • estree-walker:

    estree-walker is designed to be compatible with other ESTree-based tools and libraries, making it a better choice for projects that require interoperability with multiple parsers and tools in the JavaScript ecosystem.

Performance

  • acorn-walk:

    acorn-walk is lightweight and performs well for most traversal tasks, especially when working with smaller to medium-sized ASTs generated by Acorn.

  • estree-walker:

    estree-walker is also performant, but its flexibility and additional features may introduce some overhead. However, it is designed to handle large ASTs efficiently, making it suitable for more complex traversal tasks.

Ease of Use: Code Examples

  • acorn-walk:

    Simple AST Traversal with acorn-walk

    import { parse } from 'acorn';
    import { simple } from 'acorn-walk';
    
    const code = 'const x = 10;';
    const ast = parse(code);
    
    simple(ast, {
      VariableDeclaration(node) {
        console.log('Found a variable declaration:', node);
      },
    });
    
  • estree-walker:

    Flexible AST Traversal with estree-walker

    import { walk } from 'estree-walker';
    
    const ast = {
      type: 'Program',
      body: [
        { type: 'VariableDeclaration', declarations: [], kind: 'const' },
      ],
    };
    
    walk(ast, {
      enter(node) {
        console.log('Entering node:', node.type);
      },
      leave(node) {
        console.log('Leaving node:', node.type);
      },
    });
    
How to Choose: acorn-walk vs estree-walker
  • acorn-walk:

    Choose acorn-walk if you are working with the Acorn parser and need a lightweight, straightforward solution for traversing its AST. It is ideal for projects that require simple walking functionality without additional complexity.

  • estree-walker:

    Choose estree-walker if you need a more flexible and feature-rich walking solution that supports ESTree-compliant ASTs. It is suitable for projects that require advanced traversal capabilities, such as custom node handling, and is designed to work well with other ESTree-based tools.

README for acorn-walk

Acorn AST walker

An abstract syntax tree walker for the ESTree format.

Community

Acorn is open source software released under an MIT license.

You are welcome to report bugs or create pull requests on github.

Installation

The easiest way to install acorn is from npm:

npm install acorn-walk

Alternately, you can download the source and build acorn yourself:

git clone https://github.com/acornjs/acorn.git
cd acorn
npm install

Interface

An algorithm for recursing through a syntax tree is stored as an object, with a property for each tree node type holding a function that will recurse through such a node. There are several ways to run such a walker.

simple(node, visitors, base, state) does a 'simple' walk over a tree. node should be the AST node to walk, and visitors an object with properties whose names correspond to node types in the ESTree spec. The properties should contain functions that will be called with the node object and, if applicable the state at that point. The last two arguments are optional. base is a walker algorithm, and state is a start state. The default walker will simply visit all statements and expressions and not produce a meaningful state. (An example of a use of state is to track scope at each point in the tree.)

const acorn = require("acorn")
const walk = require("acorn-walk")

walk.simple(acorn.parse("let x = 10"), {
  Literal(node) {
    console.log(`Found a literal: ${node.value}`)
  }
})

ancestor(node, visitors, base, state) does a 'simple' walk over a tree, building up an array of ancestor nodes (including the current node) and passing the array to the callbacks as a third parameter.

const acorn = require("acorn")
const walk = require("acorn-walk")

walk.ancestor(acorn.parse("foo('hi')"), {
  Literal(_node, _state, ancestors) {
    console.log("This literal's ancestors are:", ancestors.map(n => n.type))
  }
})

recursive(node, state, functions, base) does a 'recursive' walk, where the walker functions are responsible for continuing the walk on the child nodes of their target node. state is the start state, and functions should contain an object that maps node types to walker functions. Such functions are called with (node, state, c) arguments, and can cause the walk to continue on a sub-node by calling the c argument on it with (node, state) arguments. The optional base argument provides the fallback walker functions for node types that aren't handled in the functions object. If not given, the default walkers will be used.

make(functions, base) builds a new walker object by using the walker functions in functions and filling in the missing ones by taking defaults from base.

full(node, callback, base, state) does a 'full' walk over a tree, calling the callback with the arguments (node, state, type) for each node

fullAncestor(node, callback, base, state) does a 'full' walk over a tree, building up an array of ancestor nodes (including the current node) and passing the array to the callbacks as a third parameter.

const acorn = require("acorn")
const walk = require("acorn-walk")

walk.full(acorn.parse("1 + 1"), node => {
  console.log(`There's a ${node.type} node at ${node.ch}`)
})

findNodeAt(node, start, end, test, base, state) tries to locate a node in a tree at the given start and/or end offsets, which satisfies the predicate test. start and end can be either null (as wildcard) or a number. test may be a string (indicating a node type) or a function that takes (nodeType, node) arguments and returns a boolean indicating whether this node is interesting. base and state are optional, and can be used to specify a custom walker. Nodes are tested from inner to outer, so if two nodes match the boundaries, the inner one will be preferred.

findNodeAround(node, pos, test, base, state) is a lot like findNodeAt, but will match any node that exists 'around' (spanning) the given position.

findNodeAfter(node, pos, test, base, state) is similar to findNodeAround, but will match all nodes after the given position (testing outer nodes before inner nodes).