首页 > 解决方案 > 使用 graal.js 通过 Java 访问 JavaScript 数组

问题描述

我正在将一个项目从 Nashorn 迁移到 graal.js。该项目使用了大量脚本(超过 3,400 个),并且在 Java 端有一个调用方法的函数;该方法返回一个 JavaScript 对象列表。

function filterList(ob)
{
    var list = [];
    var arr = ob.toArray();

    for(var i = 0; i < arr.length; i++)
    {
        if(global.isValid(arr[i]))
        {
            list.push(arr[i]);
        }
    }

    return list;
}

以前使用 ScriptUtils 在 Nashorn 上运行良好。这段代码是在我拿起它之前由从事该项目的开发人员编写的:

try {
    Object p = iv.invokeFunction("filterList", this.getList());

    if(p != null) {
        List<MyObj> lObj = new ArrayList<>(((Map<String, MyObj>)(ScriptUtils.convert(p, Map.class))).values());
        return lObj;
    }
} catch (ScriptException | NoSuchMethodException ex) {
    ex.printStackTrace();
}

如何使用 graal.js 通过 Java 访问数组?我试过使用Value.asValue(p)as(MyObj[])无济于事。我还尝试遵循 Nashorn 迁移指南,他们建议将对象转换为 List 或 Map,但也无济于事。

我知道一个解决方案,我必须重写脚本以仅使用new Java.type('java.util.ArrayList');并返回 aList而不是数组 - 但是有成千上万的脚本,重写所有脚本将非常乏味。

标签: javagraalvmgraaljs

解决方案


您可以使用 Value.getArraySize() 和 Value.getArrayElement(index):

Context context = Context.newBuilder("js").build();
Value result = context.eval("js", "var list=[1,2,'foo',true]; list;");
if (result.hasArrayElements()) {
    for (int i=0;i<result.getArraySize();i++) {
        System.out.println(result.getArrayElement(i));
    }
}

您可以在https://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/Value.html中找到 Value 类的完整 JavaDoc

最好的,克里斯蒂安


推荐阅读