🎩 You're Invited:Meet the Socket team at Black Hat in Las Vegas, August 3-6.RSVP
Sign In

ast-walker-scope

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ast-walker-scope - npm Package Compare versions

Comparing version
0.7.1
to
0.8.0
+34
-20
dist/index.d.ts

@@ -1,29 +0,32 @@

import { ParserPlugin, ParseResult } from '@babel/parser';
import { Node, Function, Identifier, File, VariableDeclaration } from '@babel/types';
import { ParseResult, ParserPlugin } from "@babel/parser";
import { File, Function, Identifier, Node, VariableDeclaration } from "@babel/types";
//#region src/types.d.ts
interface ParseOptions {
filename?: string;
parserPlugins?: ParserPlugin[];
filename?: string;
parserPlugins?: ParserPlugin[];
}
type Scope = Record<string, Node>;
interface WalkerContext {
skip: () => void;
remove: () => void;
replace: (node: Node) => void;
skip: () => void;
remove: () => void;
replace: (node: Node) => void;
}
interface ScopeContext {
parent: Node | undefined | null;
key: string | undefined | null;
index: number | undefined | null;
scope: Scope;
scopes: Scope[];
level: number;
parent: Node | undefined | null;
key: string | undefined | null;
index: number | undefined | null;
scope: Scope;
scopes: Scope[];
level: number;
}
interface WalkerHooks {
enter?: (this: WalkerContext & ScopeContext, node: Node) => void;
enterAfter?: (this: ScopeContext, node: Node) => void;
leave?: (this: WalkerContext & ScopeContext, node: Node) => void;
leaveAfter?: (this: ScopeContext, node: Node) => void;
enter?: (this: WalkerContext & ScopeContext, node: Node) => void;
enterAfter?: (this: ScopeContext, node: Node) => void;
leave?: (this: WalkerContext & ScopeContext, node: Node) => void;
leaveAfter?: (this: ScopeContext, node: Node) => void;
}
//#endregion
//#region src/utils/babel.d.ts
declare const isNewScope: (node: Node | undefined | null) => boolean;

@@ -36,6 +39,17 @@ declare function walkFunctionParams(node: Function, onIdent: (id: Identifier) => void): void;

declare function walk(code: string, walkHooks: WalkerHooks, { filename, parserPlugins }?: ParseOptions): ParseResult<File>;
declare function walkAST(node: Node | Node[], { enter, leave, enterAfter, leaveAfter }: WalkerHooks): void;
//#endregion
//#region src/index.d.ts
declare function walk(code: string, walkHooks: WalkerHooks, {
filename,
parserPlugins
}?: ParseOptions): ParseResult<File>;
declare function walkAST(node: Node | Node[], {
enter,
leave,
enterAfter,
leaveAfter
}: WalkerHooks): void;
declare function getRootScope(nodes: Node[]): Scope;
export { type ParseOptions, type Scope, type ScopeContext, type WalkerContext, type WalkerHooks, babelParse, extractIdentifiers, getRootScope, isNewScope, walk, walkAST, walkFunctionParams, walkNewIdentifier, walkVariableDeclaration };
//#endregion
export { ParseOptions, Scope, ScopeContext, WalkerContext, WalkerHooks, babelParse, extractIdentifiers, getRootScope, isNewScope, walk, walkAST, walkFunctionParams, walkNewIdentifier, walkVariableDeclaration };
{
"name": "ast-walker-scope",
"version": "0.7.1",
"version": "0.8.0",
"description": "Traverse Babel AST with scope information.",

@@ -24,6 +24,3 @@ "type": "module",

"exports": {
".": {
"require": "./dist/index.cjs",
"import": "./dist/index.js"
},
".": "./dist/index.js",
"./*": "./*"

@@ -35,23 +32,22 @@ },

"dependencies": {
"@babel/parser": "^7.26.9",
"ast-kit": "^1.4.0"
"@babel/parser": "^7.27.2",
"ast-kit": "^1.4.3"
},
"devDependencies": {
"@babel/types": "^7.26.9",
"@sxzz/eslint-config": "^5.2.0",
"@sxzz/prettier-config": "^2.2.0",
"@types/node": "^22.13.9",
"bumpp": "^10.0.3",
"eslint": "^9.21.0",
"@babel/types": "^7.27.1",
"@sxzz/eslint-config": "^7.0.0",
"@sxzz/prettier-config": "^2.2.1",
"@types/node": "^22.15.17",
"bumpp": "^10.1.0",
"eslint": "^9.26.0",
"magic-string": "^0.30.17",
"oxc-transform": "^0.55.0",
"prettier": "^3.5.3",
"tsdown": "^0.6.3",
"tsx": "^4.19.3",
"typescript": "^5.8.2",
"vite": "^6.2.0",
"vitest": "^3.0.7"
"tsdown": "^0.11.1",
"tsx": "^4.19.4",
"typescript": "^5.8.3",
"vite": "^6.3.5",
"vitest": "^3.1.3"
},
"engines": {
"node": ">=18.12.0"
"node": ">=20.18.0"
},

@@ -58,0 +54,0 @@ "prettier": "@sxzz/prettier-config",

"use strict";
//#region rolldown:runtime
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
const ast_kit = __toESM(require("ast-kit"));
const __babel_parser = __toESM(require("@babel/parser"));
//#region src/utils/babel.ts
const NEW_SCOPE = [
"CatchClause",
"ForInStatement",
"ForOfStatement"
];
const isNewScope = (node) => node && NEW_SCOPE.includes(node.type) || (0, ast_kit.isFunctionType)(node);
function walkFunctionParams(node, onIdent) {
for (const p of node.params) for (const id of extractIdentifiers(p)) onIdent(id);
}
function extractIdentifiers(param, nodes = []) {
switch (param.type) {
case "Identifier":
nodes.push(param);
break;
case "MemberExpression": {
let object = param;
while (object.type === "MemberExpression") object = object.object;
nodes.push(object);
break;
}
case "ObjectPattern":
for (const prop of param.properties) if (prop.type === "RestElement") extractIdentifiers(prop.argument, nodes);
else extractIdentifiers(prop.value, nodes);
break;
case "ArrayPattern":
param.elements.forEach((element) => {
if (element) extractIdentifiers(element, nodes);
});
break;
case "RestElement":
extractIdentifiers(param.argument, nodes);
break;
case "AssignmentPattern":
extractIdentifiers(param.left, nodes);
break;
}
return nodes;
}
function babelParse(code, filename, parserPlugins = []) {
const plugins = parserPlugins || [];
if (filename) {
if (/\.tsx?$/.test(filename)) plugins.push("typescript");
if (filename.endsWith("x")) plugins.push("jsx");
}
const ast = (0, __babel_parser.parse)(code, {
sourceType: "module",
plugins
});
return ast;
}
function walkVariableDeclaration(stmt, register) {
if (stmt.declare) return;
for (const decl of stmt.declarations) for (const id of extractIdentifiers(decl.id)) register(id);
}
function walkNewIdentifier(node, register) {
if (node.type === "ExportNamedDeclaration" && node.declaration) node = node.declaration;
if (node.type === "VariableDeclaration") walkVariableDeclaration(node, register);
else if (node.type === "FunctionDeclaration" || node.type === "ClassDeclaration") {
if (node.declare || !node.id) return;
register(node.id);
} else if (node.type === "ExportNamedDeclaration" && node.declaration && node.declaration.type === "VariableDeclaration") walkVariableDeclaration(node.declaration, register);
}
//#endregion
//#region src/index.ts
function walk(code, walkHooks, { filename, parserPlugins } = {}) {
const ast = babelParse(code, filename, parserPlugins);
walkAST(ast.program, walkHooks);
return ast;
}
function walkAST(node, { enter, leave, enterAfter, leaveAfter }) {
let currentScope = {};
const scopeStack = [currentScope];
const ast = Array.isArray(node) ? {
type: "Program",
body: node
} : node;
(0, ast_kit.walkAST)(ast, {
enter(node$1, parent, ...args) {
const { scopeCtx, walkerCtx, isSkip, isRemoved, getNode } = getHookContext(this, node$1, [parent, ...args]);
enter?.call({
...scopeCtx(),
...walkerCtx
}, node$1);
node$1 = getNode();
if (!isSkip() && !isRemoved()) {
enterNode(node$1, parent);
enterAfter?.call(scopeCtx(), node$1);
}
},
leave(node$1, parent, ...args) {
const { scopeCtx, walkerCtx, isSkip, isRemoved, getNode } = getHookContext(this, node$1, [parent, ...args]);
leave?.call({
...scopeCtx(),
...walkerCtx
}, node$1);
node$1 = getNode();
if (!isSkip() && !isRemoved()) {
leaveNode(node$1, parent);
leaveAfter?.call(scopeCtx(), node$1);
}
}
});
function getHookContext(ctx, node$1, [parent, key, index]) {
const scopeCtx = () => ({
parent,
key,
index,
scope: scopeStack.reduce((prev, curr) => ({
...prev,
...curr
}), {}),
scopes: scopeStack,
level: scopeStack.length
});
let isSkip = false;
let isRemoved = false;
let newNode = node$1;
const walkerCtx = {
skip() {
isSkip = true;
ctx.skip();
},
replace(node$2) {
newNode = node$2;
},
remove() {
isRemoved = true;
}
};
return {
scopeCtx,
walkerCtx,
isSkip: () => isSkip,
isRemoved: () => isRemoved,
getNode: () => newNode
};
}
function enterNode(node$1, parent) {
if (isNewScope(node$1) || node$1.type === "BlockStatement" && !isNewScope(parent)) scopeStack.push(currentScope = {});
if ((0, ast_kit.isFunctionType)(node$1)) walkFunctionParams(node$1, registerBinding);
else if (node$1.type === "CatchClause" && node$1.param && node$1.param.type === "Identifier") registerBinding(node$1.param);
if (node$1.type === "BlockStatement" || node$1.type === "Program") {
for (const stmt of node$1.body) if (stmt.type === "VariableDeclaration" && stmt.kind === "var") walkVariableDeclaration(stmt, registerBinding);
else if (stmt.type === "FunctionDeclaration" && stmt.id) registerBinding(stmt.id);
}
}
function leaveNode(node$1, parent) {
if (isNewScope(node$1) || node$1.type === "BlockStatement" && !isNewScope(parent)) {
scopeStack.pop();
currentScope = scopeStack.at(-1);
}
walkNewIdentifier(node$1, registerBinding);
}
function registerBinding(id) {
if (currentScope) currentScope[id.name] = id;
else error("registerBinding called without active scope, something is wrong.", id);
}
function error(msg, node$1) {
const e = new Error(msg);
e.node = node$1;
throw e;
}
}
function getRootScope(nodes) {
const scope = {};
for (const node of nodes) walkNewIdentifier(node, (id) => {
scope[id.name] = id;
});
return scope;
}
//#endregion
exports.babelParse = babelParse
exports.extractIdentifiers = extractIdentifiers
exports.getRootScope = getRootScope
exports.isNewScope = isNewScope
exports.walk = walk
exports.walkAST = walkAST
exports.walkFunctionParams = walkFunctionParams
exports.walkNewIdentifier = walkNewIdentifier
exports.walkVariableDeclaration = walkVariableDeclaration
import { ParserPlugin, ParseResult } from '@babel/parser';
import { Node, Function, Identifier, File, VariableDeclaration } from '@babel/types';
interface ParseOptions {
filename?: string;
parserPlugins?: ParserPlugin[];
}
type Scope = Record<string, Node>;
interface WalkerContext {
skip: () => void;
remove: () => void;
replace: (node: Node) => void;
}
interface ScopeContext {
parent: Node | undefined | null;
key: string | undefined | null;
index: number | undefined | null;
scope: Scope;
scopes: Scope[];
level: number;
}
interface WalkerHooks {
enter?: (this: WalkerContext & ScopeContext, node: Node) => void;
enterAfter?: (this: ScopeContext, node: Node) => void;
leave?: (this: WalkerContext & ScopeContext, node: Node) => void;
leaveAfter?: (this: ScopeContext, node: Node) => void;
}
declare const isNewScope: (node: Node | undefined | null) => boolean;
declare function walkFunctionParams(node: Function, onIdent: (id: Identifier) => void): void;
declare function extractIdentifiers(param: Node, nodes?: Identifier[]): Identifier[];
declare function babelParse(code: string, filename?: string, parserPlugins?: ParserPlugin[]): ParseResult<File>;
declare function walkVariableDeclaration(stmt: VariableDeclaration, register: (id: Identifier) => void): void;
declare function walkNewIdentifier(node: Node, register: (id: Identifier) => void): void;
declare function walk(code: string, walkHooks: WalkerHooks, { filename, parserPlugins }?: ParseOptions): ParseResult<File>;
declare function walkAST(node: Node | Node[], { enter, leave, enterAfter, leaveAfter }: WalkerHooks): void;
declare function getRootScope(nodes: Node[]): Scope;
export { type ParseOptions, type Scope, type ScopeContext, type WalkerContext, type WalkerHooks, babelParse, extractIdentifiers, getRootScope, isNewScope, walk, walkAST, walkFunctionParams, walkNewIdentifier, walkVariableDeclaration };