npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

estree-walkie

v0.0.4

Published

Walks a JavaScript AST compatible with ESTree.

Downloads

1

Readme

estree-walkie

Latest version Dependency status Coverage

Walks a JavaScript AST compatible with ESTree.

  • ESM, CJS and UMD modules offering an API for programmatic usage in Node.js, Deno and web browser.
  • Ignores keys pointing to the parent node. (Often cause of stack overflows.)
  • Includes TypeScript types.
  • No dependencies.
  • Tiny size - 926 B minified, 435 B gzipped, 390 B brotlied.
  • Blazingly fast.

Synopsis

import { parse } from 'meriyah'
import { walk } from 'estree-walkie'

const program = parse('...', { module: true, next: true })
const identifiers = []

walk(program, {
  Identifier(node) {
    identifiers.push(node.name)
  }
})

API

Exported methods:

walk(node, visitor, fallback, state)
walkAtOffset(node, offset, visitor, fallback, state)
walkAtPosition(node, line, column, visitor, fallback, state)
walkInRange(node, start, end, visitor, fallback, state)
walkBetweenLines(node, first, last, visitor, fallback, state)

Arguments:

  • node - AST node to start walking with
  • visitor - object with visiting handlers named by node types
  • fallback - handler for nodes not matched by the visitor (optional)
  • state - custom value passed to each handler (optional)
  • offset - source code character offset to walk the AST around
  • start and ens - source code character range to walk the AST within
  • line and column - source code position to walk the AST around
  • first and last - source code line range to walk the AST within

Visiting handler:

handler(node, state, parent) => boolean?
{ enter?: handler, exit?: handler }
  • node - currently visited AST node
  • state - custom value passed to the walking method (optional)
  • node - parent of the currently visited AST node

If an object with enter and/or exit methods is used as a visiting handler, enter will be caled before visiting children and exit after visiting children of the current node.

If a handler retuns false children of the current node will not be visited.

Walking can be interrupted by throwing an error and ignoring the thrown type in error handling.

Examples

Collect only identifiers used in the outer scope:

import { parse } from 'meriyah'
import { walk } from 'estree-walkie'

const program = parse('...', { module: true, next: true })
const identifiers = []

const avoid = () => false
walk(program, {
  FunctionDeclaration: avoid,
  ClassDeclaration: avoid,
  CallExpression: avoid,
  FunctionExpression: avoid,
  ArrowFunctionExpression: avoid,
  Identifier(node) {
    identifiers.push(node.name)
  }
})

Collect variables declared at all scopes and assign node.parent to all nodes:

import { parse } from 'meriyah'
import { walk } from 'estree-walkie'

const program = parse('...', { module: true, next: true, loc: true })
const variables = []

const assignParent = (node, parent) => node.parent = parent
walk(astRoot, line, column, {
  VariableDeclarator(node, state, parent) {
    if (node.type !== 'Identifier') {
      throw new Error(`unsupported declarator at ${node.loc.start.line}:${node.loc.start.column + 1}`)
    }
    state.push(node.name)
    assignParent(node, parent)
  }
}, (node, _state, parent) => assignParent(node, parent), variables)

Check if there is an identifier at a specific position and remember its parent:

import { parse } from 'meriyah'
import { walk } from 'estree-walkie'

const program = parse('...', { module: true, next: true, loc: true })
let identified

try {
  walkAtLocation(astRoot, line, column, {
    Identifier(node, _state, parent) {
      identified = parent
      throw 0
    }
  });
} catch (err) {
  if (typeof err !== 'number') throw err
}

Node.js usage

Make sure that you use Node.js >= 8.3. Install the estree-walkie package locally using your favourite package manager:

npm i estree-walkie
pnpm i estree-walkie
yarn add estree-walkie

Either import methods from the API using the CJS module:

const { walk, walkAtOffset, walkAtPosition, walkInRange, walkBetweenLines } = require('estree-walkie')
...

Or import methods from the API using the ESM module:

import { walk, walkAtOffset, walkAtPosition, walkInRange, walkBetweenLines } from 'estree-walkie'
...

Browser usage

You can either compile this module to your application bundle, or load it directly to the browser. For the former, you would install this package and import methods from the API in the same way as for the Node.js usage. For the latter, you would either refer to the module installed locally, or to the module from the UNPKG CDN, for example:

node_modules/estree-walkie/dist/index.umd.min.js
https://unpkg.com/[email protected]/dist/index.min.mjs

The following modules are available in the dist directory:

| Name | Type | | ------------------ | -------------------------- | | index.cjs | CJS module, not minified | | index.mjs | ESM module, not minified | | index.min.mjs | ESM module, minified | | index.umd.js | UMD module, not minified | | index.umd.min.js | UMD module, minified |

Either import methods from the API using the ESM module:

<script type=module>
  import { walk, walkAtOffset, walkAtPosition, walkInRange, walkBetweenLines }
    from 'https://unpkg.com/[email protected]/dist/index.min.mjs'
  ...
</script>

Or import methods from the API using the UMD module, which will set a global object estree-walkie:

<script src=https://unpkg.com/[email protected]/dist/index.umd.min.js></script>
<script>
  (() => {
    const { walk, walkAtOffset, walkAtPosition, walkInRange, walkBetweenLines } = estreeWalkie
    ...
  })()
</script>

If an AMD module loader is detected, the UMD module will return exports es expected:

<script>
  require(['https://unpkg.com/[email protected]/dist/index.umd.min.js'],
    ({ walk, walkAtOffset, walkAtPosition, walkInRange, walkBetweenLines }) => {
      ...
    })
</script>

Performance

Comparison with other libraries, which allow visiting AST nodes by their types:

$ cd bench && pnpm i && node walk

Validation:
  ✔ @babel/traverse (46,955 identifiers)
  ✔ estree-walker (46,955 identifiers)
  ✔ estree-walk (46,955 identifiers)
  ✔ estree-visitor (46,955 identifiers)
  ✘ acorn-walk (26,662 identifiers)
  ✔ ast-types (46,955 identifiers)
  ✔ astray (46,955 identifiers)
  ✔ estree-walkie (46,955 identifiers)

Benchmark:
  @babel/traverse x 8.18 ops/sec ±7.00% (25 runs sampled)
  estree-walker   x 95.59 ops/sec ±2.63% (69 runs sampled)
  estree-walk     x 46.53 ops/sec ±1.57% (60 runs sampled)
  estree-visitor  x 61.86 ops/sec ±1.87% (64 runs sampled)
  acorn-walk      x 78.81 ops/sec ±0.92% (68 runs sampled)
  ast-types       x 3.65 ops/sec ±8.24% (14 runs sampled)
  astray          x 98.37 ops/sec ±0.93% (72 runs sampled)
  estree-walkie   x 131 ops/sec ±0.99% (76 runs sampled)

Contributing

In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. Lint and test your code using npm test.

License

Copyright (c) 2022 Ferdinand Prantl

Licensed under the MIT license.