1

我正在使用 Graal 将 javascript 作为访客语言运行,并且想知道是否有办法Array.map在主机 (Java) 对象或代理上使用 javascript 功能。演示 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()
4

1 回答 1

6

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

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

于 2019-04-04T16:27:17.543 回答