从主持人语言注入的成员将以来宾语言类型到达来宾语言

时间:2018-08-06 11:54:11

标签: graalvm

该问题与以下内容有关: GraalVM - Using Polyglot Value without a context

在我的应用程序中,以来宾语言运行的代码片段不需要知道注入的参数(通过绑定的成员)是Java参数。相反,对于使用来宾语言开发的人,参数应该看起来像来宾语言本身的另一个参数。

例如,我希望以这种方式从Java宿主语言向JS来宾脚本中注入一个数组:

Value guestLanguageBindings = context.getBindings(scriptData.getLanguage().toString());

guestLanguageBindings.putMember(argumentName, argumentValue);

作为JS数组“到达”来宾语言,而不是作为java.util.ArrayList来“到达”来宾语言。

当前,我通过将每个非原始类型(我注意到String,int等作为JS“类型”到达JS)转换为JSON并转换为来宾语言来解决此问题。

这行得通,但是我想知道是否有更合适的方法来做,或者确实使用绑定是正确的方法?

谢谢!

2 个答案:

答案 0 :(得分:4)

  

这行得通,但是我想知道是否有更合适的方法来做,或者确实使用绑定是正确的方法?

正如您所注意到的,当您将Java对象放入多语言时,对于用户而言,它们将看起来像Java对象,而不是JavaScript对象。为了使它们模仿来宾语言对象,您可以使用Polyglot Proxy API。

JS对象的示例(由HashMap支持)

try (Context context = Context.create("js")) {
    Map<String, Object> backingMap = new HashMap<>();
    backingMap.put("foo", "bar");
    context.getBindings("js").putMember("hostObject", ProxyObject.fromMap(backingMap));
    assert "bar".equals(context.eval("js", "hostObject.foo").asString());
    backingMap.put("foo", "baz");
    assert "baz".equals(context.eval("js", "hostObject.foo").asString());
}

JS数组示例(由Java数组支持):

try (Context context = Context.create("js")) {
    Object[] backingArray = new Object[42];
    backingArray[0] = 42;
    context.getBindings("js").putMember("hostObject", ProxyArray.fromArray(backingArray));
    assert 42 == context.eval("js", "hostObject[0]").asInt();
    backingArray[0] = 43;
    assert 43 == context.eval("js", "hostObject[0]").asInt();
}

函数示例(由Lambda支持)

try (Context context = Context.create("js")) {
    ProxyExecutable executable = (arguments) -> arguments[0];
    context.getBindings("js").putMember("hostObject",executable);
    assert 42 == context.eval("js", "hostObject(42)").asInt();
    assert 43 == context.eval("js", "hostObject(43)").asInt();
}

您还可以直接实现ProxyObject和ProxyArray来自定义行为,例如如果要提供只读对象或数组。

这是另一个代理示例:http://www.graalvm.org/docs/graalvm-as-a-platform/embed/#computed-arrays-using-polyglot-proxies

代理Javadoc:http://www.graalvm.org/sdk/javadoc/org/graalvm/polyglot/proxy/package-summary.html

答案 1 :(得分:0)

@Christian Humer提供的答案表明使用ProxyArray是一个很好的答案,它说明了如何正确组合ProxyArray并给出了很好的解释。

但是,我的要求是要能够将数组参数(使用顶级绑定设置)呈现为一种来宾语言数据类型。 ProxyArray仅使我半途而废,结果数据类型是Java类型,而不是JS类型。

为了完全实现上述目标,由于我控制着Java主机端,因此我在主机端使用Context创建了一个JS数组,并在其中复制了Java ArrayList的内容。 。调用访客代码时,我只需在绑定中设置JS数组,该绑定已经是功能齐全的JS数组。

    Value jsArray = context.eval("js", "new Array();");

    jsArray.setArrayElement(0, 1001); //array will grow automatically, JS semantics
    jsArray.setArrayElement(1, 1002);
    jsArray.setArrayElement(2, 1003);

    guestLanguageBindings.putMember("variable", jsArray);
    context.eval("js", "print(variable);");

当我提交上述评论中提到的错误报告时,向我on Github建议了这种方法。