Core traversal algorithms for walking JavaScript ASTs with different callback patterns and state management approaches. These functions provide the foundation for analyzing and transforming Abstract Syntax Trees.
Performs a simple walk over an AST, calling visitor functions for matching node types. The walker traverses the entire tree and calls the appropriate visitor for each node.
/**
* Performs a simple walk over AST calling visitor functions for matching node types
* @param node - AST node to walk
* @param visitors - Object mapping node types to visitor functions
* @param baseVisitor - Optional custom recursive walker (defaults to base)
* @param state - Optional initial state
* @param override - Optional node type override
*/
function simple<TState>(
node: Node,
visitors: SimpleVisitors<TState>,
baseVisitor?: RecursiveVisitors<TState>,
state?: TState,
override?: string
): void;Usage Example:
import * as acorn from "acorn";
import { simple } from "acorn-walk";
const ast = acorn.parse("let x = 10; function test() { return x + 5; }");
simple(ast, {
Literal(node) {
console.log(`Found literal: ${node.value}`);
},
Identifier(node) {
console.log(`Found identifier: ${node.name}`);
},
FunctionDeclaration(node) {
console.log(`Found function: ${node.id.name}`);
}
});Walks the AST while building up an array of ancestor nodes, passing the ancestor array to callbacks as the third parameter. Useful for context-aware analysis.
/**
* Walk with ancestor array passed to callbacks as third parameter
* @param node - AST node to walk
* @param visitors - Object mapping node types to visitor functions
* @param baseVisitor - Optional custom recursive walker (defaults to base)
* @param state - Optional initial state
* @param override - Optional node type override
*/
function ancestor<TState>(
node: Node,
visitors: AncestorVisitors<TState>,
baseVisitor?: RecursiveVisitors<TState>,
state?: TState,
override?: string
): void;Usage Example:
import * as acorn from "acorn";
import { ancestor } from "acorn-walk";
const ast = acorn.parse("function outer() { function inner() { return 42; } }");
ancestor(ast, {
FunctionDeclaration(node, state, ancestors) {
console.log(`Function ${node.id.name} has ${ancestors.length - 1} ancestors`);
console.log("Ancestor types:", ancestors.map(n => n.type));
}
});A recursive walk where visitor functions control their own traversal. Functions can modify state and decide how to walk child nodes by calling the continuation function.
/**
* Recursive walk where functions control their own traversal
* @param node - AST node to walk
* @param state - Initial state
* @param functions - Object mapping node types to recursive walker functions
* @param baseVisitor - Optional fallback walker (defaults to base)
* @param override - Optional node type override
*/
function recursive<TState>(
node: Node,
state: TState,
functions: RecursiveVisitors<TState>,
baseVisitor?: RecursiveVisitors<TState>,
override?: string
): void;Usage Example:
import * as acorn from "acorn";
import { recursive } from "acorn-walk";
const ast = acorn.parse("let a = 1; let b = a + 2;");
recursive(ast, { depth: 0 }, {
VariableDeclaration(node, state, c) {
console.log(`Variable declaration at depth ${state.depth}`);
for (let decl of node.declarations) {
c(decl, { ...state, depth: state.depth + 1 });
}
},
Identifier(node, state, c) {
console.log(`Identifier '${node.name}' at depth ${state.depth}`);
}
});Triggers a callback on every single node in the AST. The callback receives the node, state, and node type.
/**
* Full walk triggering callback on each node
* @param node - AST node to walk
* @param callback - Function called for each node with (node, state, type)
* @param baseVisitor - Optional custom walker (defaults to base)
* @param state - Optional initial state
* @param override - Optional node type override
*/
function full<TState>(
node: Node,
callback: FullWalkerCallback<TState>,
baseVisitor?: RecursiveVisitors<TState>,
state?: TState,
override?: string
): void;Usage Example:
import * as acorn from "acorn";
import { full } from "acorn-walk";
const ast = acorn.parse("let x = 10;");
full(ast, (node, state, type) => {
console.log(`Node: ${type} at ${node.start}-${node.end}`);
});Combines full walk with ancestor tracking, calling the callback for every node while maintaining the ancestor array.
/**
* Full walk with ancestor array passed to callback
* @param node - AST node to walk
* @param callback - Function called for each node with (node, state, ancestors, type)
* @param baseVisitor - Optional custom walker (defaults to base)
* @param state - Optional initial state
*/
function fullAncestor<TState>(
node: Node,
callback: FullAncestorWalkerCallback<TState>,
baseVisitor?: RecursiveVisitors<TState>,
state?: TState
): void;Usage Example:
import * as acorn from "acorn";
import { fullAncestor } from "acorn-walk";
const ast = acorn.parse("function test() { let x = 1; }");
fullAncestor(ast, (node, state, ancestors, type) => {
console.log(`${type} node has ${ancestors.length - 1} ancestors`);
if (ancestors.length > 1) {
console.log(`Parent: ${ancestors[ancestors.length - 2].type}`);
}
});type SimpleWalkerFn<TState> = (node: Node, state: TState) => void;
type AncestorWalkerFn<TState> = (
node: Node,
state: TState | Node[],
ancestors: Node[]
) => void;
type RecursiveWalkerFn<TState> = (
node: Node,
state: TState,
callback: WalkerCallback<TState>
) => void;
type FullWalkerCallback<TState> = (
node: Node,
state: TState,
type: string
) => void;
type FullAncestorWalkerCallback<TState> = (
node: Node,
state: TState | Node[],
ancestors: Node[],
type: string
) => void;
type SimpleVisitors<TState> = {
[type: string]: SimpleWalkerFn<TState>;
};
type AncestorVisitors<TState> = {
[type: string]: AncestorWalkerFn<TState>;
};
type RecursiveVisitors<TState> = {
[type: string]: RecursiveWalkerFn<TState>;
};
type WalkerCallback<TState> = (node: Node, state: TState) => void;