我最近問這個問題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