私は最近、この質問をHow can I pass a proper method reference in so Nashorn can execute it?と尋ねました。私のプロジェクトにもっと役立つ答えを得ましたが、解決方法がわからないカスタムJSObject実装を提供することに限界があることがわかりました。Nashorn JSObjectのカスタム実装をObject.keys()で動作させる方法はありますか?
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)が呼び出され、最後の行のコメントを解除した場合、それがされます:JSは、そのようなマップとしてそれを呼び出します。メソッドのほとんどを処理することができ、この単純な作業のJSObjectを考えると
エラー... 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