Boa - Rust实现的Javascript引擎
更新日期:
Boa是Rust语言实现的实验性Javascript语言编译与执行引擎,参考实现EcmaScript规范。在Rust项目中引用的包名为boa_engine
, 当前版本为0.17.3
。Boa提供了基于WASM实现网页版playground,可动手实践,实时查看执行结果 https://boajs.dev/boa/playground/ 。
Boa_engine的基础用法
新建一个Rust项目后,然后添加依赖boa_engine
|
|
编辑src/main.js
,将生成的代码替换成如下内容,来自boa项目文档的示例。 先从boa_engine
引入类型, Source
用于处理JavaScript源代码,Context
是执行代码的上下文环境。如下代码直接从string来创建Source
对象, 然后使用context.eval()
执行。如果要从文件加载js代码,使用Source::from_filepath(Path::new('js_file_path.js'))
。
|
|
接下来编译并执行,项目输出结果为22
, 符合预期, 数值类型与字符类型相加结果为字符类型。
参考:
- Boa项目文档 https://docs.rs/boa_engine/latest/boa_engine/#
- Boa github https://github.com/boa-dev/boa
Boa引擎中注册全局变量
Boa中支持注册全局变量、回调方法,使用Context.register_global_property()
, Context.register_global_callable()
。
实现简单的ejs模板引擎
经试验, Boa支持ES6中的模板语法、正则表达式、JSON等,也有对模块语法import/export的支持。这里参考网络上对ejs模板的实现原理,尝试在Boa中实现ejs模板。
如下是一个简单的ejs模板,就是在html内容中使用标签嵌入js代码。个人理解, 主要是2类标签: 1)<% xx %>
用于流程控制,不输出内容; 2)<%= xx %>
一类主要用于输出的,包含<%=
html内容,<%_
去除空格, <%-
不转义html内容。
|
|
ejs模板引擎实现的基本原理,是将模板内容转换成可执行的javascript方法:模板中非标签的内容都转换成字符串用于直接输出, <%= xx %>
替换为变量,而<% xx %>
中的内容则直接作为编译后方法体中的语句。 如下是简单实现, 使用正则表达式进行替换:
|
|
前面ejs模板内容,在执行convert_to_js()
后,返回的内容如下:
|
|
接下来,将在Rust使用Boa执行这个简单的模板。一种简单的方式是将模板引擎方法、执行模板引擎过程写在同一个js文件中,然后在Boa引入文件内容执行。这里将采用一种复杂的方式,将引入模板引擎与执行模板引擎过程分开,目的是要复用引擎,一次引入后可以针对不同的模板内容多次执行。
将ejs模板引擎文件保存为ejs-convert.js, 将模板内容保存为hello.tpl。Rust代码如下:
|
|
2次执行模板方法的打印输出如下,说明执行成功。
|
|
参考:
- ejs模板的文档 https://ejs.co/#docs
- ejs github https://github.com/mde/ejs/blob/main/lib/ejs.js
- ejs实现原理 https://juejin.cn/post/6856763527160725512
后记
最近研究Rust中的Javascript引擎以及ejs模板, 出发点只是想将个人博客引擎使用的Hexo进行替换,而Hexo中使用的theme模板中使用了ejs。个人并不太想更改页面样式,于是开始了解是否有Rust库实现ejs,并进行了些尝试。github上有用golang实现ejs, 但没有Rust的实现。Boa只是Javascript引擎,要实现直接引用ejs项目代码的话,require
模块引用以及nodejs中fs
等模块缺失,要实现可用的ejs模板还要下一番功夫才行。
参考:
- sailfish,受ejs启发的rust模板 https://github.com/rust-sailfish/sailfish
- Hexo API, https://hexo.io/zh-cn/api/
- goejs, golang实现的ejs模板 https://github.com/lmmfy/goejs
- otto,golang实现的js引擎 https://github.com/robertkrimen/otto
- goja,golang实现ECMAScript https://github.com/dop251/goja
- go-ejs,goja的封装 https://github.com/rosbit/go-ejs