elearning/Frontend-Learner/node_modules/oxc-walker/README.md
2026-01-13 10:48:02 +07:00

225 lines
6.5 KiB
Markdown

# oxc-walker
[![npm version][npm-version-src]][npm-version-href]
[![npm downloads][npm-downloads-src]][npm-downloads-href]
[![Github Actions][github-actions-src]][github-actions-href]
[![Codecov][codecov-src]][codecov-href]
A strongly-typed ESTree AST walker built on top of [oxc-parser](https://github.com/oxc-project/oxc).
## Usage
Install package:
```sh
# npm
npm install oxc-walker
# pnpm
pnpm install oxc-walker
```
### Walk a parsed AST
```ts
import { parseSync } from 'oxc-parser'
import { walk } from 'oxc-walker'
const ast = parseSync('example.js', 'const x = 1')
walk(ast.program, {
enter(node, parent, ctx) {
// ...
},
})
```
### Parse and walk directly
```js
import { parseAndWalk } from 'oxc-walker'
parseAndWalk('const x = 1', 'example.js', (node, parent, ctx) => {
// ...
})
```
## ⚙️ API
### `walk(ast, options)`
Walk an AST.
```ts
// options
interface WalkOptions {
/**
* The function to be called when entering a node.
*/
enter?: (node: Node, parent: Node | null, ctx: CallbackContext) => void
/**
* The function to be called when leaving a node.
*/
leave?: (node: Node, parent: Node | null, ctx: CallbackContext) => void
/**
* The instance of `ScopeTracker` to use for tracking declarations and references.
*/
scopeTracker?: ScopeTracker
}
interface CallbackContext {
/**
* The key of the current node within its parent node object, if applicable.
*/
key: string | number | symbol | null | undefined
/**
* The zero-based index of the current node within its parent's children array, if applicable.
*/
index: number | null
/**
* The full Abstract Syntax Tree (AST) that is being walked, starting from the root node.
*/
ast: Program | Node
}
```
#### `this.skip()`
When called inside an `enter` callback, prevents the node's children from being walked.
It is not available in `leave`.
#### `this.replace(newNode)`
Replaces the current node with `newNode`. When called inside `enter`, the **new node's children** will be walked.
The leave callback will still be called with the original node.
> ⚠️ When a `ScopeTracker` is provided, calling `this.replace()` will not update its declarations.
#### `this.remove()`
Removes the current node from its parent. When called inside `enter`, the removed node's children
will not be walked.
_This has a higher precedence than `this.replace()`, so if both are called, the node will be removed._
> ⚠️ When a `ScopeTracker` is provided, calling `this.remove()` will not update its declarations.
### `parseAndWalk(source, filename, callback, options?)`
Parse the source code using `oxc-parser`, walk the resulting AST and return the `ParseResult`.
Overloads:
- `parseAndWalk(code, filename, enter)`
- `parseAndWalk(code, filename, options)`
```ts
interface ParseAndWalkOptions {
/**
* The function to be called when entering a node.
*/
enter?: (node: Node, parent: Node | null, ctx: CallbackContext) => void
/**
* The function to be called when leaving a node.
*/
leave?: (node: Node, parent: Node | null, ctx: CallbackContext) => void
/**
* The instance of `ScopeTracker` to use for tracking declarations and references.
*/
scopeTracker?: ScopeTracker
/**
* The options for `oxc-parser` to use when parsing the code.
*/
parseOptions?: ParserOptions
}
```
### `ScopeTracker`
A utility to track scopes and declarations while walking an AST. It is designed to be used with the `walk`
function from this library.
```ts
interface ScopeTrackerOptions {
/**
* If true, the scope tracker will preserve exited scopes in memory.
* @default false
*/
preserveExitedScopes?: boolean
}
```
#### Example usage:
```ts
import { parseAndWalk, ScopeTracker } from 'oxc-walker'
const scopeTracker = new ScopeTracker()
parseAndWalk('const x = 1; function foo() { console.log(x) }', 'example.js', {
scopeTracker,
enter(node, parent) {
if (node.type === 'Identifier' && node.name === 'x' && parent?.type === 'CallExpression') {
const declaration = scopeTracker.getDeclaration(node.name)
console.log(declaration) // ScopeTrackerVariable
}
},
})
```
```ts
import { parseAndWalk, ScopeTracker, walk } from 'oxc-walker'
const code = `
function foo() {
console.log(a)
}
const a = 1
`
const scopeTracker = new ScopeTracker({
preserveExitedScopes: true,
})
// pre-pass to collect hoisted declarations
const { program } = parseAndWalk(code, 'example.js', {
scopeTracker,
})
// freeze the scope tracker to prevent further modifications
// and prepare it for second pass
scopeTracker.freeze()
// main pass to analyze references
walk(program, {
scopeTracker,
enter(node) {
if (node.type === 'CallExpression' && node.callee.type === 'MemberExpression' /* ... */) {
const declaration = scopeTracker.getDeclaration('a')
console.log(declaration) // ScopeTrackerVariable; would be `null` without the pre-pass
}
}
})
```
#### Helpers:
- `scopeTracker.isDeclared(name: string): boolean` - check if an identifier is declared in reference to the current scope
- `scopeTracker.getDeclaration(name: string): ScopeTrackerNode | null` - get the scope tracker node with metadata for a given identifier name in reference to the current scope
- `scopeTracker.freeze()` - freeze the scope tracker to prevent further modifications and prepare for second pass (useful for multi-pass analysis)
- `scopeTracker.getCurrentScope(): string` - get the key of the current scope (a unique identifier for the scope, do not rely on its format)
- `scopeTracker.isCurrentScopeUnder(scopeKey: string): boolean` - check if the current scope is a child of the given scope key
## 💻 Development
- Clone this repository
- Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable`
- Install dependencies using `pnpm install`
- Run interactive tests using `pnpm dev`
## License
Made with ❤️
Published under [MIT License](./LICENCE).
<!-- Badges -->
[npm-version-src]: https://img.shields.io/npm/v/oxc-walker?style=flat-square
[npm-version-href]: https://npmjs.com/package/oxc-walker
[npm-downloads-src]: https://img.shields.io/npm/dm/oxc-walker?style=flat-square
[npm-downloads-href]: https://npm.chart.dev/oxc-walker
[github-actions-src]: https://img.shields.io/github/actions/workflow/status/danielroe/oxc-walker/ci.yml?branch=main&style=flat-square
[github-actions-href]: https://github.com/danielroe/oxc-walker/actions?query=workflow%3Aci
[codecov-src]: https://img.shields.io/codecov/c/gh/danielroe/oxc-walker/main?style=flat-square
[codecov-href]: https://codecov.io/gh/danielroe/oxc-walker