我最近问这个问题How can I pass a proper method reference in so Nashorn can execute it?,得到了一个答案,帮助我进一步了解我的项目,但是我发现了一个限制,提供了一个我不知道如何解决的自定义JSObject实现。有没有办法使用Object.keys()来实现Nashorn JSObject的自定义实现?
鉴于这种简单的工作JSObject,能够处理大多数的方法JS将它援引如地图:
import javax.script.*;
import jdk.nashorn.api.scripting.*;
import java.util.*;
import java.util.function.*;
public class scratch_6 {
public static void main(String[] args) throws Exception {
ScriptEngineManager m = new ScriptEngineManager();
ScriptEngine e = m.getEngineByName("nashorn");
// The following JSObject wraps this list
List<Object> l = new ArrayList<>();
l.add("hello");
l.add("world");
l.add(true);
l.add(1);
JSObject jsObj = new AbstractJSObject() {
@Override
public Object getMember(String name) {
if (name.equals("map")) {
// return a functional interface object - nashorn will treat it like
// script function!
final Function<JSObject, Object> jsObjectObjectFunction = callback -> {
List<Object> res = new ArrayList<>();
for (Object obj : l) {
// call callback on each object and add the result to new list
res.add(callback.call(null, obj));
}
// return fresh list as result of map (or this could be another wrapper)
return res;
};
return jsObjectObjectFunction;
} else {
// unknown property
return null;
}
}
};
e.put("obj", jsObj);
// map each String to it's uppercase and print result of map
e.eval("print(obj.map(function(x) '\"'+x.toString()+'\"'))");
//PROBLEM
//e.eval("print(Object.keys(obj))");
}
}
如果取消注释最后一行,其中Object.keys(OBJ)被调用时,它会失败,错误为... is not an Object
。
这似乎是因为Object.keys()[NativeObject.java:376]仅检查对象是ScriptObject的还是ScriptObjectMirror的实例。如果它不是这些东西,它会抛出notAnObject错误。 :(
我在JDK JIRA中发现了https://bugs.openjdk.java.net/browse/JDK-8154720,它表示Object.keys()不适用于Java对象,但请注意在这种情况下的区别是我的班级正在实施JSObject,这意味着它应该是兼容的。 – deinspanjer
我还发现https://bugs.openjdk.java.net/browse/JDK-8015830触及类似的区域,并实施了一个修复程序,但修复程序不包括JSObject接口本身。 – deinspanjer