Utility functions for creating custom walkers and accessing the default base walker containing handlers for all ESTree node types. These utilities enable advanced customization of AST traversal behavior.
Creates a custom walker by combining user-defined functions with a base walker. Missing node type handlers are filled in from the base walker.
/**
* Create custom walker by combining functions with base walker
* @param functions - Object mapping node types to walker functions
* @param baseVisitor - Optional base walker (defaults to base)
* @returns Combined walker object
*/
function make<TState>(
functions: RecursiveVisitors<TState>,
baseVisitor?: RecursiveVisitors<TState>
): RecursiveVisitors<TState>;Usage Examples:
import * as acorn from "acorn";
import { make, base, recursive } from "acorn-walk";
// Create custom walker for counting nodes
const counter = make({
FunctionDeclaration(node, state, c) {
state.functions++;
// Continue with default traversal
base.FunctionDeclaration(node, state, c);
},
VariableDeclaration(node, state, c) {
state.variables++;
// Continue with default traversal
base.VariableDeclaration(node, state, c);
}
}, base);
const ast = acorn.parse("function test() { let x = 1; let y = 2; }");
const counts = { functions: 0, variables: 0 };
recursive(ast, counts, counter);
console.log(counts); // { functions: 1, variables: 2 }Advanced Custom Walker Example:
import { make, base } from "acorn-walk";
// Custom walker that tracks scope depth
const scopeTracker = make({
Program(node, state, c) {
console.log("Entering program scope");
state.depth = 0;
base.Program(node, state, c);
},
FunctionDeclaration(node, state, c) {
console.log(`Entering function '${node.id.name}' at depth ${state.depth}`);
state.depth++;
base.FunctionDeclaration(node, { ...state }, c);
state.depth--;
console.log(`Exiting function '${node.id.name}'`);
},
BlockStatement(node, state, c) {
if (state.depth > 0) {
console.log(`Block at depth ${state.depth}`);
}
base.BlockStatement(node, state, c);
}
});The default walker object containing functions for all ESTree node types. Each function defines how to traverse that specific node type.
/**
* Default walker object containing functions for all ESTree node types
*/
const base: RecursiveVisitors<any>;Note: The base constant is exported from the source code but is missing from the official TypeScript definitions.
The base walker contains handlers for all standard ESTree node types:
Statement Handlers:
Program, BlockStatement - Walk statement bodiesExpressionStatement - Walk the expressionIfStatement - Walk test, consequent, alternateWhileStatement, DoWhileStatement - Walk test and bodyForStatement - Walk init, test, update, bodyForInStatement, ForOfStatement - Walk left, right, bodySwitchStatement - Walk discriminant and casesTryStatement - Walk block, handler, finalizerFunctionDeclaration - Walk as functionVariableDeclaration - Walk declaratorsReturnStatement, ThrowStatement - Walk argumentBreakStatement, ContinueStatement - No-op walkersExpression Handlers:
ArrayExpression - Walk elementsObjectExpression - Walk propertiesFunctionExpression, ArrowFunctionExpression - Walk as functionCallExpression, NewExpression - Walk callee and argumentsMemberExpression - Walk object and computed propertyBinaryExpression, LogicalExpression - Walk left and rightUnaryExpression, UpdateExpression - Walk argumentConditionalExpression - Walk test, consequent, alternateSequenceExpression - Walk expressionsTemplateLiteral - Walk quasis and expressionsPattern and Declaration Handlers:
ArrayPattern - Walk elementsObjectPattern - Walk propertiesRestElement - Walk argumentAssignmentPattern - Walk left and rightModule Handlers:
ImportDeclaration - Walk specifiers and sourceExportNamedDeclaration, ExportDefaultDeclaration - Walk declaration and sourceExportAllDeclaration - Walk exported and sourceUsage Examples:
import { base } from "acorn-walk";
// Access specific node handler
console.log(typeof base.FunctionDeclaration); // "function"
// Use base walker directly in custom function
const customWalker = {
FunctionDeclaration(node, state, c) {
console.log(`Custom handling for function: ${node.id.name}`);
// Delegate to base implementation
base.FunctionDeclaration(node, state, c);
}
};Extending Base Walker:
import { make, base } from "acorn-walk";
// Create walker that logs all identifier access
const identifierLogger = make({
Identifier(node, state, c) {
if (state.inExpression) {
console.log(`Accessing identifier: ${node.name}`);
}
// base.Identifier is a no-op, but call it for consistency
base.Identifier(node, state, c);
},
Expression(node, state, c) {
// Mark that we're in an expression context
base.Expression(node, { ...state, inExpression: true }, c);
}
}, base);Traversal Control:
// Custom walker that skips function bodies
const skipFunctions = make({
FunctionDeclaration(node, state, c) {
// Process function declaration but don't traverse body
console.log(`Function declared: ${node.id.name}`);
// Don't call base.FunctionDeclaration to skip traversal
},
FunctionExpression(node, state, c) {
console.log("Anonymous function expression");
// Skip body traversal
}
}, base);State Transformation:
// Walker that transforms state for nested scopes
const scopeWalker = make({
FunctionDeclaration(node, state, c) {
const newState = {
...state,
scope: state.scope + 1,
functionName: node.id.name
};
base.FunctionDeclaration(node, newState, c);
}
}, base);type RecursiveWalkerFn<TState> = (
node: Node,
state: TState,
callback: WalkerCallback<TState>
) => void;
type RecursiveVisitors<TState> = {
[type: string]: RecursiveWalkerFn<TState>;
};
type WalkerCallback<TState> = (node: Node, state: TState) => void;