3

从0到1编写一个JS脚本引擎

 2 years ago
source link: https://segmentfault.com/a/1190000041734351
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

从0到1编写一个JS脚本引擎

发布于 4 月 20 日

使用Java实现JS脚本引擎

https://github.com/GitHub-Laz...

  • 支持解析js脚本生成语法树
  • 支持运行完整js脚本
  • 支持安全模式运行单行表达式
  • 支持设置超时时间

打包后命令行运行

git clone https://github.com/GitHub-Laziji/js-engine.git
cd js-engine
mvn package
cd target

java -jar ./js-engine-1.0-SNAPSHOT-jar-with-dependencies.jar ./test.js

或者安装后直接引入依赖

git clone https://github.com/GitHub-Laziji/js-engine.git
cd js-engine
mvn install
<dependency>
    <groupId>org.laziji.commons</groupId>
    <artifactId>js-engine</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

1. 生成语法树 并输出格式化代码

class Test{
    public static void main(String[] args){
        Top.init();
        DocNode doc = Top.compile("let      a=1+2,b=3,c=\"string\",d=a*(b+c/2),func=function(){};");
        System.out.println(doc);
    }
}
let a = 1 + 2, b = 3, c = "string", d = a * (b + c / 2), func = function () {

}

2. 运行完整脚本

以下示例为运行快排算法(运行环境线程隔离)

class Test{
    /**
     * function sort(arr, i, j) {
     *   if (i >= j) {
     *     return;
     *   }
     *   let p = i, q = j;
     *   let temp = arr[p];
     *   while (p < q) {
     *     while (p < q && arr[q] >= temp) {
     *       q-=1;
     *     }
     *     arr[p] = arr[q];
     *     while (p < q && arr[p] <= temp) {
     *       p+=1;
     *     }
     *     arr[q] = arr[p];
     *   }
     *   arr[q] = temp;
     *   sort(arr, i, q - 1);
     *   sort(arr, q + 1, j);
     * }
     *
     * let arr = [234, 57, 12, 123, 346, 1234, 2];
     *
     * sort(arr, 0, arr.length - 1);
     */
    public static void main(String[] args){
        Top.init();
        Top.eval("function sort(arr, i, j) {\n" +
                "    if (i >= j) {\n" +
                "        return;\n" +
                "    }\n" +
                "    let p = i, q = j;\n" +
                "    let temp = arr[p];\n" +
                "    while (p < q) {\n" +
                "        while (p < q && arr[q] >= temp) {\n" +
                "            q-=1;\n" +
                "        }\n" +
                "        arr[p] = arr[q];\n" +
                "        while (p < q && arr[p] <= temp) {\n" +
                "            p+=1;\n" +
                "        }\n" +
                "        arr[q] = arr[p];\n" +
                "    }\n" +
                "    arr[q] = temp;\n" +
                "    sort(arr, i, q - 1);\n" +
                "    sort(arr, q + 1, j);\n" +
                "}\n" +
                "\n" +
                "let arr = [234, 57, 12, 123, 346, 1234, 2];\n" +
                "\n" +
                "sort(arr, 0, arr.length - 1);");
        Top.loop();
        System.out.println(Top.getThreadLocalTop().getMainContexts().getContexts().peek().toSimpleString());
    }
}
arr: [2, 12, 57, 123, 234, 346, 1234]
sort: [object Object]

3. 运行单行表达式

该模式下只支持单行表达式 并且无法使用for、while、function、lambda、import关键字

class Test{
    public static void main(String[] args){
        Top.init();
        System.out.println(Top.exprEval("'hello '+(1*2*3*4)"));
    }
}
hello 24

4. 设置超时时间

通过Top.getThreadLocalTop().setOvertime(100L);设置超时时间,单位毫秒

class Test{
    public static void main(String[] args){
        Top.init();
        Top.getThreadLocalTop().setOvertime(100L);
        Top.addInternalModules("sys", new SystemModuleValue());
        Top.eval("import { print } from \"sys\";\n" +
                "\n" +
                "let i=1;\n" +
                "while(true){\n" +
                "    print(i++);\n" +
                "}");
        Top.loop();
    }
}
1
2
3
...

org.laziji.commons.js.exception.RunException: Run timeout.
...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK