您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > javascript

JavaScript黑科技:实现一个AST解释器

时间:2022-04-19 09:29:42  来源:  作者:修丹道的程序猿

JAVAScript黑科技:直接运行AST(抽象语法树)

实现一个AST解释器

一段JavaScript代码,经过语法分析、语法分析等编译过程之后,会形成一个对应的AST(抽象语法树),形如:

JavaScript黑科技:实现一个AST解释器

 

AST是一个JSON格式的大字符串,包含有代码相关信息,如:成员表达式调用、参数、标识符、字符串字面量等等。如:

{"type":"File","program":{"type":"Program","body":[{"type":"ExpressionStatement","expression":{"type":"CallExpression","callee":{"type":"MemberExpression","object":{"type":"Identifier","name":"console"},"property":{"type":"Identifier","name":"log"}},"arguments":[{"type":"StringLiteral","value":"jshaman"}]}}]}}

上面,是一段AST。

本文将要实现的目标的:直接运行这段AST。

先展示运行效果,如下:

JavaScript黑科技:实现一个AST解释器

 

即,运行后,输出一了个字符串。

功能意义

其实,如果直接要输出这样一个字符串,在JavaScript中是极为简单的,只需简单的一句:console.log('jshaman')。

那么,为什么要转化为复杂的AST,再执行AST呢?

其意义在于:我们将要实现一个AST解释器,引申而言,实现一个JavaScript解释器。在很多场景中,具有非常实用的意义。

比如,在小程序中屏蔽了Eval函数,而如果我们自己实现解释器,将可突破这个限制。

又比如,JShaman研发团队中,将它用于JavaScript代码加密。

JavaScript黑科技:实现一个AST解释器

 

Tip:JShaman是国内专业的JavaScript代码保护研究团队,拥有众多自主的JS代码加密方案,此为其一。

实现方案

要让这个AST能被执行,即要依JavaScript代码标准解释AST。

首先,尝试理解console.log('jshaman')这句代码的AST。通过astexplorer查看:

JavaScript黑科技:实现一个AST解释器

 

可以看到,这一句代码转成的AST中,包含7个节点。

那么,要执行这个AST,就要能正确处理这7种节点类型。

由于AST是JSON结构,处理时,可遍历其所有的成员节点。参考astexplorer展示的节点,分别处理:File、Program、ExpressionStatement、CallExpression等,代码如下:

JavaScript黑科技:实现一个AST解释器

 

当遇到CallExpression时,获取其对应的参数、方法名等,如下图:

JavaScript黑科技:实现一个AST解释器

 

并用Apply的方式进行执行,以返回结果。

原理即如此。

编码时,对照着AST节点类型,完成相应的操作即可,为方便调试,可输出节点类型加以分析,如下图:

JavaScript黑科技:实现一个AST解释器

 

完整源码

完整源码如下,保存为JS,在NodeJS环境中即可运行。也可在浏览器中直接运行代码,更为方便。

//各节点处理器
var visitors = {
//File节点,JS代码AST的根节点
File(node, scope) {
ast_excute(node.program, scope);
},
//File的次节点,其Body下对应各行JS代码
Program(program, scope) {
for (i=0; i< program.body.length;i++) {
//执行各行代码的AST
ast_excute(program.body[i], scope);
}
},
//Call调用AST之外会包裹有一层表达式语句结构
ExpressionStatement(node, scope) {
return ast_excute(node.expression, scope);
},
//Call调用
CallExpression(node, scope){
//遍历callee获取函数体
var func = ast_excute(node.callee, scope);
//获取参数
var args = node.arguments.map( function(arg){
return ast_excute(arg, scope)
});

var value;
if (node.callee.type === 'MemberExpression') {
value = ast_excute(node.callee.object, scope);
}
//返回函数运行结果
return func.apply(value, args)
},
//成员表达式
MemberExpression(node, scope){
//获取对象,如console
var obj = ast_excute(node.object, scope);
//获取对象的方法,如log
var name = node.property.name
//返回表达式,如console.log
return obj[name]
},
//标识符
Identifier(node, scope) {
return scope[node.name];
},
//字符串字面量
StringLiteral(node) {
return node.value;
},
};
//执行
function ast_excute(node, scope) {
var _evalute = visitors[node.type];
if (!_evalute) {
throw new Error("未知的AST类型:" , node.type);
}
// 递归调用
return _evalute(node, scope);
}
var ast = {"type":"File","program":{"type":"Program","body":[{"type":"ExpressionStatement","expression":{"type":"CallExpression","callee":{"type":"MemberExpression","object":{"type":"Identifier","name":"console"},"property":{"type":"Identifier","name":"log"}},"arguments":[{"type":"StringLiteral","value":"jshaman"}]}}]}};
ast_excute(ast, {console});

AST简化

以上代码中,使用的是简化过的AST。astexplorer默认生成的AST,内容较多,如下图:

JavaScript黑科技:实现一个AST解释器

 

其包含有代码行号、起始、结束等位置信息:

JavaScript黑科技:实现一个AST解释器

 

但这些冗长的位置信息对于执行是无用的,可以将其去除,实现简化的AST:

JavaScript黑科技:实现一个AST解释器

 

这样就成为了代码中使用的、较简短的AST。



Tags:JavaScript   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
JavaScript的异步编程常见模式
在JavaScript中,异步编程是一种处理长时间运行操作(如网络请求或I/O操作)的常见方式。它允许程序在等待这些操作完成时继续执行其他任务,从而提高应用程序的响应性和性能。JavaS...【详细内容】
2024-04-12  Search: JavaScript  点击:(9)  评论:(0)  加入收藏
17 个你需要知道的 JavaScript 优化技巧
你可能一直在使用JavaScript搞开发,但很多时候你可能对它提供的最新功能并不感冒,尽管这些功能在无需编写额外代码的情况下就可以解决你的问题。作为前端开发人员,我们必须了解...【详细内容】
2024-04-03  Search: JavaScript  点击:(7)  评论:(0)  加入收藏
你不可不知的 15 个 JavaScript 小贴士
在掌握如何编写JavaScript代码之后,那么就进阶到实践&mdash;&mdash;如何真正地解决问题。我们需要更改JS代码使其更简单、更易于阅读,因为这样的程序更易于团队成员之间紧密协...【详细内容】
2024-03-21  Search: JavaScript  点击:(29)  评论:(0)  加入收藏
构建一个通用灵活的JavaScript插件系统?看完你也会!
在软件开发中,插件系统为应用程序提供了巨大的灵活性和可扩展性。它们允许开发者在不修改核心代码的情况下扩展和定制应用程序的功能。本文将详细介绍如何构建一个灵活的Java...【详细内容】
2024-03-20  Search: JavaScript  点击:(23)  评论:(0)  加入收藏
对JavaScript代码压缩有什么好处?
对JavaScript代码进行压缩主要带来以下好处: 减小文件大小:通过移除代码中的空白符、换行符、注释,以及缩短变量名等方式,可以显著减小JavaScript文件的大小。这有助于减少网页...【详细内容】
2024-03-13  Search: JavaScript  点击:(8)  评论:(0)  加入收藏
跨端轻量JavaScript引擎的实现与探索
一、JavaScript 1.JavaScript语言JavaScript是ECMAScript的实现,由ECMA 39(欧洲计算机制造商协会39号技术委员会)负责制定ECMAScript标准。ECMAScript发展史: 2.JavaScript...【详细内容】
2024-03-12  Search: JavaScript  点击:(7)  评论:(0)  加入收藏
面向AI工程的五大JavaScript工具
令许多人惊讶的是,一向在Web开发领域中大放异彩的JavaScript在开发使用大语言模型(LLM)的应用程序方面同样大有价值。我们在本文中将介绍面向AI工程的五大工具,并为希望将LLM...【详细内容】
2024-02-06  Search: JavaScript  点击:(58)  评论:(0)  加入收藏
18个JavaScript技巧:编写简洁高效的代码
本文翻译自 18 JavaScript Tips : You Should Know for Clean and Efficient Code,作者:Shefali, 略有删改。在这篇文章中,我将分享18个JavaScript技巧,以及一些你应该知道的示例...【详细内容】
2024-01-30  Search: JavaScript  点击:(79)  评论:(0)  加入收藏
使用 JavaScript 清理我的 200GB iCloud,有了一个意外发现!
本文作者在综合成本因素之下,决定用 Java 脚本来清理一下自己的 iCloud,结果却有了一个意外发现,即在 iCloud 中上传同一个视频和删除此视频之后,iCloud 的空间并不一致,这到底是...【详细内容】
2024-01-11  Search: JavaScript  点击:(111)  评论:(0)  加入收藏
JavaScript前端框架2024年展望
Angular、Next.js、React和Solid的维护者和创作者们展望2024年,分享了他们计划中的改进。译自2024 Predictions by JavaScript Frontend Framework Maintainers,作者 Loraine...【详细内容】
2024-01-05  Search: JavaScript  点击:(98)  评论:(0)  加入收藏
▌简易百科推荐
JavaScript的异步编程常见模式
在JavaScript中,异步编程是一种处理长时间运行操作(如网络请求或I/O操作)的常见方式。它允许程序在等待这些操作完成时继续执行其他任务,从而提高应用程序的响应性和性能。JavaS...【详细内容】
2024-04-12  靳国梁    Tags:JavaScript   点击:(9)  评论:(0)  加入收藏
17 个你需要知道的 JavaScript 优化技巧
你可能一直在使用JavaScript搞开发,但很多时候你可能对它提供的最新功能并不感冒,尽管这些功能在无需编写额外代码的情况下就可以解决你的问题。作为前端开发人员,我们必须了解...【详细内容】
2024-04-03  前端新世界  微信公众号  Tags:JavaScript   点击:(7)  评论:(0)  加入收藏
你不可不知的 15 个 JavaScript 小贴士
在掌握如何编写JavaScript代码之后,那么就进阶到实践&mdash;&mdash;如何真正地解决问题。我们需要更改JS代码使其更简单、更易于阅读,因为这样的程序更易于团队成员之间紧密协...【详细内容】
2024-03-21  前端新世界  微信公众号  Tags:JavaScript   点击:(29)  评论:(0)  加入收藏
又出新JS运行时了!JS运行时大盘点
Node.js是基于Google V8引擎的JavaScript运行时,以非阻塞I/O和事件驱动架构为特色,实现全栈开发。它跨平台且拥有丰富的生态系统,但也面临安全性、TypeScript支持和性能等挑战...【详细内容】
2024-03-21  前端充电宝  微信公众号  Tags:JS   点击:(29)  评论:(0)  加入收藏
构建一个通用灵活的JavaScript插件系统?看完你也会!
在软件开发中,插件系统为应用程序提供了巨大的灵活性和可扩展性。它们允许开发者在不修改核心代码的情况下扩展和定制应用程序的功能。本文将详细介绍如何构建一个灵活的Java...【详细内容】
2024-03-20  前端历险记  微信公众号  Tags:JavaScript   点击:(23)  评论:(0)  加入收藏
对JavaScript代码压缩有什么好处?
对JavaScript代码进行压缩主要带来以下好处: 减小文件大小:通过移除代码中的空白符、换行符、注释,以及缩短变量名等方式,可以显著减小JavaScript文件的大小。这有助于减少网页...【详细内容】
2024-03-13  WangLiwen    Tags:JavaScript   点击:(8)  评论:(0)  加入收藏
跨端轻量JavaScript引擎的实现与探索
一、JavaScript 1.JavaScript语言JavaScript是ECMAScript的实现,由ECMA 39(欧洲计算机制造商协会39号技术委员会)负责制定ECMAScript标准。ECMAScript发展史: 2.JavaScript...【详细内容】
2024-03-12  京东云开发者    Tags:JavaScript   点击:(7)  评论:(0)  加入收藏
面向AI工程的五大JavaScript工具
令许多人惊讶的是,一向在Web开发领域中大放异彩的JavaScript在开发使用大语言模型(LLM)的应用程序方面同样大有价值。我们在本文中将介绍面向AI工程的五大工具,并为希望将LLM...【详细内容】
2024-02-06    51CTO  Tags:JavaScript   点击:(58)  评论:(0)  加入收藏
JS小知识,使用这6个小技巧,避免过多的使用 if 语句
最近在重构我的代码时,我注意到早期的代码使用了太多的 if 语句,达到了我以前从未见过的程度。这就是为什么我认为分享这些可以帮助我们避免使用过多 if 语句的简单技巧很重要...【详细内容】
2024-01-30  前端达人  今日头条  Tags:JS   点击:(62)  评论:(0)  加入收藏
18个JavaScript技巧:编写简洁高效的代码
本文翻译自 18 JavaScript Tips : You Should Know for Clean and Efficient Code,作者:Shefali, 略有删改。在这篇文章中,我将分享18个JavaScript技巧,以及一些你应该知道的示例...【详细内容】
2024-01-30  南城大前端  微信公众号  Tags:JavaScript   点击:(79)  评论:(0)  加入收藏
站内最新
站内热门
站内头条