AST 技巧:使用 AST 自动打印函数执行路径
大家好,今天分享一个使用 AST 自动打印函数执行路径的方法。
函数执行日志
在扣代码的时候,我遇到过很多次因为环境或者其他问题导致 JS 代码在 nodejs
下面的执行路径和浏览器中不一致,导致最终的计算结果是错误的。
正常来说,想要获取函数的执行堆栈,要么是使用报错法,让函数在某个位置报错并且从错误日志中获取堆栈信息,这种方式不适合调试扣出来的代码,因为我们的目的是让它能正常运行,而不是报错。要么就是在每个函数调用时,添加日志输出当前被调用的函数叫什么名字,这么做当然没问题,问题就是函数调用太多了,一个一个的手动新增肯定不现实,所以使用 AST 的方法来新增就很有必要了。
AST 输出函数名
为了让每个函数能输出函数名,需要遍历所有的函数,并且在函数体的开头添加一个打印当前函数名字的日志,打开 AST 网站,开始分析。
它的函数体只有一条,并且函数体在 FunctionDeclaration
节点的 body
属性的 BlockStatement
节点下面,是一个数组类型。和上篇文章的思路一样,只需要在函数体的 body
数组中添加一条日志语句即可,别忘了先获取一下当前函数的名字,名字在 id
属性中。
函数的名字是一个 Identifier
类型,只需要取到它的 name
属性即可。
开始编码
1 | traverse(ast, { |
根据思路写出以上代码,运行一下试试:
发现好像不太对,输出的是函数本身的引用,也就是说默认会调用函数的 toString
方法,这不是我们想要的效果。
这是为什么呢?因为在输出的时候,直接将函数名输出了,正常来说应该输出函数名字符串才对,来改一下代码:
1 | traverse(ast, { |
运行一下看看效果:
现在正常了,输出的都是正常的函数名字符串了。
运行一下代码看看添加日志后的效果:
除了我打印的一些输出外,每次函数被调用的时候都会打印一次函数名。
那如何对比本地执行的函数和浏览器中执行的效果是否一致呢?将同样的代码在浏览器和本地都运行一遍,然后对比打印的日志即可。
总结
以上就是使用 AST 的方式自动给函数调用添加日志输出的方法了,目前的方案只打印了函数名,只能对比函数的调用次数和顺序是不是对的,其实还可以深入一些,打印一下函数的参数和返回值,可以更加精细的对比函数的调用过程,这个就留给大家自己实现了。
本文章首发于个人博客 LLLibra146’s blog
本文作者:LLLibra146
更多文章请关注公众号 (LLLibra146):
版权声明:本博客所有文章除特别声明外,均采用 © BY-NC-ND 许可协议。非商用转载请注明出处!严禁商业转载!