Graal 在 java 中嵌入了 java 脚本,如何从 java 调用 list/array 上的地图?可能吗?

Graal embedded javascript in java, how to call map on list/array from java? Is it possible?

我正在使用 Graal 运行 javascript 作为来宾语言,想知道是否可以使用 javascript Array.map 功能主机 (Java) 对象或代理。演示 Kotlin 代码如下,但应该足够接近 Java 代码。

fun main() {
    val context = Context.newBuilder().build()
    val javaOutputList = mutableListOf<Integer>()
    val javaList = listOf(2, 2, 3, 4, 5)
    val proxyJavaList = ProxyArray.fromList(javaList)

    context.polyglotBindings.apply {
        putMember("javaOutputList", javaOutputList)
        putMember("javaList", javaList)
        putMember("proxyJavaList", proxyJavaList)
    }

    val script = """
        var javaOutputList = Polyglot.import('javaOutputList');
        var javaList = Polyglot.import('javaList');
        var proxyJavaList = Polyglot.import('proxyJavaList');

        var abc = [1, 2, 3];
        abc.forEach(x => javaOutputList.add(x));      // WORKS

        //abc.map(x => x + 1)             // WORKS
        //javaList.map(x => x + 1)        // DOES NOT WORK (map not a method on list)
        proxyJavaList.map(x => x + 1)     // DOES NOT WORK (message not supported: INVOKE)
    """.trimIndent()

    val result = context.eval("js", script)

    val resultList = result.`as`(List::class.java)
    println("result: $resultList")
    println("javaOutputList: $javaOutputList")

}

使用 ProxyArray 对我来说看起来是最有前途的,但我仍然无法让它工作。预计会支持此功能吗?

编辑:接受的答案代码有效,这里是感兴趣的更改:

    val context = Context.newBuilder()
            //.allowExperimentalOptions(true)  // doesn't seem to be needed
            .option("js.experimental-foreign-object-prototype", "true")
            .build()

问题的根源在于类数组的非JavaScript 对象在默认情况下其原型链上没有Array.prototype。因此,使用 javaList.map/proxyJavaList.map 语法无法访问 Array.prototype.map

您可以像 Array.prototype.map.call(javaList, x => x+1) 一样直接调用 Array.prototype.map,也可以使用实验性选项 js.experimental-foreign-object-prototype=true(我们最近添加)在原型链上添加 Array.prototype所有类似数组的对象。 javaList.map/proxyJavaList.map 届时可用。