js_reverse/AST抽象语法树
2023-08-28 14:47:00 +08:00
..
1.AST概述 AST概述 2023-07-16 23:28:17 +08:00
2.AST基础知识-nodejs安装-babel源代码解析 2.AST基础知识-nodejs安装-babel源代码解析 2023-07-17 12:13:30 +08:00
3.AST结构说明-节点类型-在线解析网站 3.AST结构说明-节点类型-在线解析网站 2023-07-17 12:13:47 +08:00
4.AST初次尝试-读取js-转换成ast-遍历ast-节点操作-转成js 4.AST初次尝试-读取js-转换成ast-遍历ast-节点操作-转成js 2023-07-17 12:14:16 +08:00
5.AST操作之API用法-path路径-path属性-path方法 AST操作之API用法-path路径-path属性-path方法 2023-07-18 14:56:08 +08:00
6.AST操作之API用法-node节点 AST操作之API用法-node节点 2023-07-18 14:56:03 +08:00
7.AST操作之API用法-path.scope属性和方法 AST操作之API用法-path.scope属性和方法 2023-07-18 16:41:38 +08:00
8.AST操作之获得当前节点的源代码 8.AST操作之获得当前节点的源代码 2023-08-22 11:01:12 +08:00
9.AST操作之构造节点信息 AST操作之构造节点信息 2023-07-18 18:43:49 +08:00
10.AST操作之template构建节点 AST操作之template构建节点 2023-07-20 00:28:22 +08:00
11.AST操作之删除节点-pop-delete-remove 11.AST操作之删除节点-pop-delete-remove 2023-08-22 11:01:01 +08:00
12.AST操作之如何插入节点-insertAfter-insertBefore 12.AST操作之如何插入节点-insertAfter-insertBefore 2023-08-22 12:20:08 +08:00
13.AST遍历方式enter和exit的区别 13.AST遍历方式enter和exit的区别 2023-08-22 16:06:44 +08:00
14.AST编写的插件报错该怎么定位和处理 14.AST编写的插件报错该怎么定位和处理 2023-08-25 11:51:28 +08:00
15.AST代码还原案例 15.AST代码还原案例 2023-08-25 16:31:03 +08:00
README.md ast readme 2023-08-28 14:47:00 +08:00

参考文档

深入学习 JavaScript 转译器 Babel AST还原混淆代码

https://blog.csdn.net/weixin_52057903/article/details/129131582

babel文档

https://babeljs.io/docs/babel-types

Babel 插件开发手册(官方)

https://blog.csdn.net/weixin_33826609/article/details/93164633#toc-visitors

操作AST语法树babel库中path全部方法和属性

path 属性

path属性相关的源代码在如下js文件中

\node_modules\@babel\traverse\lib\path

下面是一些常见的path对象的属性API

api 功能
path.node 获取当前路径对应的节点。
path.parent 获取当前路径对应节点的父节点。
path.parentPath 获取当前路径对应节点的父路径。
path.scope 表示当前path下的作用域这个也是写插件经常会用到的。
path.container 用于获取当前path下的所有兄弟节点(包括自身)。
path.type 获取当前path的节点类型。
path.key 获取当前path的key值key通常用于path.get函数。

path.scope相关的源代码在这个js文件中

node_modules\@babel\traverse\lib\scope\index.js
api 说明
scope.block 表示当前作用域下的所有node参考上面的 this.block = node;
scope.dump() 输出当前每个变量的作用域信息。调用后直接打印,不需要加打印函数
scope.crawl() 重构scope在某种情况下会报错不过还是建议在每一个插件的最后一行加上。
scope.rename(oldName, newName, block) 修改当前作用域下的的指定的变量名oldname、newname表示替换前后的变量名为字符串。注意oldName需要有binding否则无法重命名。
scope.traverse(node, opts, state) 遍历当前作用域下的某些(个)插件。和全局的traverse用法一样。
scope.getBinding(name) 获取某个变量的binding可以理解为其生命周期。包含引用修改之类的信息

binding常用方法及属性总结

node_modules\@babel\traverse\lib\scope\binding.js

目前我看到的只有 变量定义 和 函数定义 拥有binding其他的获取binding都是undefined。

let binding = scope.getBinding(name);

例如:

var a = 123; 这里的 a 就拥有 binding。 而 function test(a,b,c) {}; 函数名test以及形参abc均拥有 binding。

api 说明
binding.path 用于定位初始拥有binding的path;
binding.constant 用于判断当前变量是否被更改true表示未改变false表示有更改变量值。
binding.referenced 用于判断当前变量是否被引用true表示代码下面有引用该变量的地方false表示没有地方引用该变量。注意引用和改变是分开的。
binding.referencePaths 它是一个Array类型包含所有引用的path多用于替换。
binding.

path 方法

path方法相关的源代码在如下js文件中

node_modules\@babel\traverse\lib\path\index.js
\node_modules\@babel\traverse\lib\path

下面是一些常见的path对象的方法API

api 功能
path.get(key) 获取当前路径下指定属性名key对应的子路径。例如path.get("body") 获取当前路径下名为 "body" 的子路径。
path.getSibling(index) 获取当前路径对应节点的兄弟节点的路径。通过指定索引index可以获取相应的兄弟路径。
path.getFunctionParent() 获取当前路径对应节点的最近的函数父节点的路径。
path.getPrevSibling() 获取当前path的前一个兄弟节点返回的是path类型。
path.getAllPrevSiblings() 获取当前path的所有前兄弟节点返回的是Array类型其元素都是path类型。
path.getNextSibling() 获取当前path的后一个兄弟节点返回的是path类型。
path.getAllNextSiblings() 获取当前path的所有后兄弟节点返回的是Array类型其元素都是path类型。
path.evaluate() 用于计算表达式的值,大家可以参考 constantFold 插件的写法。
path.findParent() 向上查找满足回调函数特征的path即判断上级路径是否包含有XXX类型的节点。
path.find() 功能与 path.findParent 方法一样只不过从当前path开始进行遍历。
path.getFunctionParent() 获取函数类型父节点,如果不存在,返回 null。
path.getStatementParent() 获取Statement类型父节点这个基本上都会有返回值如果当前遍历的是 Program 或者 File 节点,则会报错。
path.getAncestry() 获取所有的祖先节点没有实参返回的是一个Array对象。
path.isAncestor(maybeDescendant) 判断当前遍历的节点是否为实参的祖先节点.
path.isDescendant(maybeAncestor) 判断当前遍历的节点是否为实参的子孙节点.
path.traverse(visitor) 遍历当前路径下的所有子节点,并应用指定的 visitor。
path.replaceWith(node) 用指定的节点替换当前路径对应的节点。
path.remove() 从 AST 中移除当前路径对应的节点。
path.insertBefore(nodes) 在当前路径对应节点之前插入一个或多个节点。
path.insertAfter(nodes) 在当前路径对应节点之后插入一个或多个节点。
path.toString() 用于将 AST 节点转换回对应的源代码字符串。

node 节点

看语法就可以猜到node就是path的一个属性

api 功能
path.node.type 获取当前节点的类型。
path.node.declarations 对于 VariableDeclaration 节点, 获取变量声明列表。
path.node.init.value 获取某个节点的值。
delete path.node.init; 删除节点,使用系统的 delete 方法。

AST 节点类型对照表

序号 类型原名称 中文名称 描述
1 Program 程序主体 整段代码的主体
2 VariableDeclaration 变量声明 声明一个变量,例如 var let const
3 FunctionDeclaration 函数声明 声明一个函数,例如 function
4 ExpressionStatement 表达式语句 通常是调用一个函数,例如 console.log()
5 BlockStatement 块语句 包裹在 {} 块内的代码,例如 if (condition){var a = 1;}
6 BreakStatement 中断语句 通常指 break
7 ContinueStatement 持续语句 通常指 continue
8 ReturnStatement 返回语句 通常指 return
9 SwitchStatement Switch 语句 通常指 Switch Case 语句中的 Switch
10 IfStatement If 控制流语句 控制流语句,通常指 if(condition){}else{}
11 Identifier 标识符 标识,例如声明变量时 var identi = 5 中的 identi
12 CallExpression 调用表达式 通常指调用一个函数,例如 console.log()
13 BinaryExpression 二进制表达式 通常指运算,例如 1+2
14 MemberExpression 成员表达式 通常指调用对象的成员,例如 console 对象的 log 成员
15 ArrayExpression 数组表达式 通常指一个数组,例如 [1, 3, 5]
16 NewExpression New 表达式 通常指使用 New 关键词
17 AssignmentExpression 赋值表达式 通常指将函数的返回值赋值给变量
18 UpdateExpression 更新表达式 通常指更新成员值,例如 i++
19 Literal 字面量 字面量
20 BooleanLiteral 布尔型字面量 布尔值,例如 true false
21 NumericLiteral 数字型字面量 数字,例如 100
22 StringLiteral 字符型字面量 字符串,例如 vansenb
23 SwitchCase Case 语句 通常指 Switch 语句中的 Case