2015-10-29 71 views
1

我正在努力與nashornwith塊。我想通過從HashMap從Java通過'上下文',並在我的代碼中使用它。但是,我無法得到這個工作。下面我準備的短類來說明我面對錯誤Nashorn和'with'上下文傳自Java

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

當你說print(ctx.foo);它的工作原理是因爲ctx是一個特殊的Java對象Map,似乎Nashorn處理這種特殊情況。但它不認爲foo是該對象的實際屬性。因此,當您使用Object.bindProperties時,它不會將foo作爲屬性轉讓。但是,你的第二個例子似乎起作用的原因是它實際上將地圖的toString()方法作爲函數進行傳輸。因此,在打印對象o時,您會看到MaptoString()方法的輸出,就好像所有映射都已被複制一樣。

當您運行下面的程序

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); }"); 

這將創建具有特殊犀牛功能__noSuchProperty__將被調用處理缺席屬性和調用get(…)方法,我們得到了一個對象從我們的案例Map。因此,print(foo + bar);將在上面的示例中打印10