Сражавам се nashorn
и with
блок. Бих искал да премине "контекст" от Java с HashMap
и го използвайте в моя код. Въпреки това, аз не съм в състояние да получи тази работа.
JS за оценка
with(ctx) {
return a+b;
}
Картата на Java трябва да бъде "прехвърлена"
Map<Object, Object> ctx = new HashMap<>();
ctx.put("a", 5)
ctx.put("b", 5)
По-долу подготвих кратък клас, за да покажа грешките, пред които съм изправен.
public class Test {
public static void main(String[] args) throws ScriptException {
Map<Object, Object> ctx = new HashMap<>();
ctx.put("foo", 5);
eval("print("1st - :)"); ctx = {"foo":"bar"}; with(ctx) {print(foo);}", new HashMap<>());
// No exception with "with", o seems to be properly "in context"..
eval("print("2nd - :)"); var o = {}; print(o); with(Object.bindProperties(o, ctx)) { print(o); } print(o)", ctx);
try {
// ..But it is not
eval("print("3rd - :("); var o = {}; with(Object.bindProperties(o, ctx)) {print(foo);}", ctx);
} catch (Exception e) {
e.printStackTrace();
}
try {
// "with" failure - context was not event bound
eval("print("4th - :("); with(ctx) {print(foo);}", ctx);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void eval(String code, Map<Object, Object> ctx) throws ScriptException {
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.getContext().setAttribute("ctx", ctx, ScriptContext.ENGINE_SCOPE);
engine.eval(code);
}
}
Благодаря ви за помощта.
Отговори:
2 за отговор № 1Когато кажеш print(ctx.foo);
работи, защото ctx
е специален Java обект, който се изпълнява Map
и изглежда, че Nashorn се справя с този специален случай. Но това не се взема предвид foo
да бъде действително свойство на обекта. Така че, когато използвате Object.bindProperties
, не се прехвърля foo
като собственост. Но причината, вашият втори пример изглежда да работи, е, че тя действително прехвърли toString()
метод на картата като функция. Така че при отпечатване на обекта o
, виждате изхода на Map
'с toString()
метод, както ако всички копия са копирани.
Когато стартирате следната програма
Map<Object, Object> ctx = new HashMap<>();
ctx.put("foo", 5);
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.getContext().setAttribute("ctx", ctx, ScriptContext.ENGINE_SCOPE);
engine.eval("print(ctx.foo);"
+ "with(Object.bindProperties({}, ctx)) {"
+ " print(toString());"
+ " print(get("foo"));"
+ " print(foo); }");
Вие получавате
5
{foo=5}
5
Exception in thread "main" javax.script.ScriptException: ReferenceError: "foo" …
посочва, че методите са прехвърлени, но не и псевдо собствеността foo
, Но наличието на методите в обекта отваря възможност за работа:
Map<Object, Object> ctx = new HashMap<>();
ctx.put("foo", 3);
ctx.put("bar", 7);
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.getContext().setAttribute("ctx", ctx, ScriptContext.ENGINE_SCOPE);
engine.eval(
"var o={ __noSuchProperty__: function(n) { return this.get(n); } };"
+ "with(Object.bindProperties(o, ctx)) { print( foo + bar ); }");
Това създава обект със специална функция на Nashorn __noSuchProperty__
които ще бъдат извикани за обработване на липсващи имоти и извиква get(…)
метод, който получихме от Map
в нашия случай. Следователно, print( foo + bar );
ще отпечата 10
в горния пример.