babel
npm install @babel/parse
npm install @babel/core
npm install @babel/generator
npm install @babel/traverse
npm install @babel/types
工具基础使用方法
- generator: 将 AST 转化回 js 代码
- parse: 将 js 代码转化为 AST
- traverse: 节点遍历操作的方便功能
- types: 提供一个与格式相关的对象合集,可以操作从而生成节点
// 导入解析工具
const {parse} = require("@babel/parser")
// 导入生成工具
const generator = require("@babel/generator").default
// 对js代码进行解析
var ast_code = parse('var a; a = "This is a test"')
// 尝试修改节点
ast_code.program.body[0].declarations[0].id.name ='b';
// 转换ast_code为js代码
js_code = generator(ast_code).code;
console.log(js_code);
parse 用法
const {parse} = require("@babel/parser");
var js_code = `
var a =1;
var b 10;
`
let ast_code = parse(js_code,{
sourceType : "module", //不加这句话的时候,如果解析的AsT里面包含import等一些写法的话,会报错
})
// console.log(ast_code);
generator 用法
const generator = require("@babel/generator").default;
const js_code_out = generator(ast_code,{
retainLines : true, // 是否保留行号
// comment:false, // 是否保留注释
// compact:false, // 代码压缩正常压,保留完整分号
// minified:true, // 代码压缩高压 删掉全部无用,硬压缩。混淆常用参数
// concise:false, // 代码压缩低压一行,基本空格等基本会保留
// jsescoption:{} // 日后再议
}).code
console.log(js_code_out)
traverse 用法
遍历都是深度优先
// traverse是遍历操作,babel为我们提供了很多的API去处理类似的问题。使得我们不需要手写遍历即可目的
const traverse = require("@babel/traverse").default;
const visitor = {
// 遍历节点
ExpressionStatement(path){
console.log(path.node)
}
}
traverse(ast_code,visitor)
高级(ES6)遍历写法
const visitor = {
// 遍历节点 两种都会遍历
"ExpressionStatement|AssignmentExpression"(path){
console.log(path.node)
}
}
停止遍历
const visitor = {
// 遍历节点 两种都会遍历
"ExpressionStatement|AssignmentExpression"(path){
enter(path){
console.log(path.toString())
path.stop()
}
}
}
types 用法
- is 开头判断
- assert 断言
生成节点
types.valueToNode("123456")
path 用法
节点替换
- replacewith 替换的是节点 1 对 1
- replacewithMultiple 替换的是节点 1 对多
- replaceInline 自动识别,包含了以上两种方法。~所以直接用这个吧
- replacewithsourcestring 节点替换成源码的字符串【也蛮常用。相当于强制替换一波】
停止遍历
- path.stop()
删除节点
- path.remove()
插入节点
- path.insertBefore()
- path.insertAfter()
获取对象
-
path.parent 【父节点的 path 对象】
-
path.parentPath 【父节点的 nodepath 对象】
向上遍历父节点,直到满足回调函数
- path.findParent(function(result){return result.isVariableDeclaration()})
向上遍历父节点,包含当前节点
- path.find
向上找函数
- path.getFunctionParent()
向上遍历语法树,找到父节点为止(包含当前节点)
- path.getStatementParent()
返回所在容器节点
- path. container
返回节点所在容器索引
- path.key 【对象返回键,数组返回索引】
- path.listkey
判断容器是否为数组
- path.inList
获取同级节点的第几个 key 的 path
- path.getsibling(index)
获取下一个同级节点
- path.getsibling(path. key+1)
获取当前作用域的引用值
- path. evaluate()
模拟解混淆
// 导入解析工具
const {parse} = require("@babel/parser")
// 导入生成工具
const generator = require("@babel/generator").default
const traverse = require("@babel/traverse").default
js_code = `function hi(){console['\x6c\x6f\x67']('\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21');}hi();`
var ast_code = parse(js_code)
// console.log(ast_code)
const visitor = {
// 遍历节点
StringLiteral(path){
path.node.extra.raw = '\'' + path.node.extra.rawValue + '\''
// console.log(path.node.extra)
}
}
traverse(ast_code,visitor)
jscode = generator(ast_code, {}).code
console.log(jscode)
Comments NOTHING