2017-05-28 74 views
0

我最近問這個問題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錯誤。 :(

+0

我在JDK JIRA中發現了https://bugs.openjdk.java.net/browse/JDK-8154720,它表示Object.keys()不適用於Java對象,但請注意在這種情況下的區別是我的班級正在實施JSObject,這意味着它應該是兼容的。 – deinspanjer

+0

我還發現https://bugs.openjdk.java.net/browse/JDK-8015830觸及類似的區域,並實施了一個修復程序,但修復程序不包括JSObject接口本身。 – deinspanjer

回答

2

理想的情況下,用戶實現的JSObject對象應該完全等同於腳本對象,但用戶實現JSObjects是幾乎腳本對象 - 但不太這是記錄在這裏 - >https://wiki.openjdk.java.net/display/Nashorn/Nashorn+jsr223+engine+notes

Object.keys就是這樣的一個情況下它打破但是,如果你只是想的for..in迭代的JavaScript支持你的對象,你可以在你的類實現JSObject.keySet

示例代碼:。

import javax.script.*; 
import jdk.nashorn.api.scripting.*; 
import java.util.*; 

public class Main { 
    public static void main(String[] args) throws Exception { 
     ScriptEngineManager m = new ScriptEngineManager(); 
     ScriptEngine e = m.getEngineByName("nashorn"); 

     // This JSObject wraps the following Properties object 
     Properties props = System.getProperties(); 

     JSObject jsObj = new AbstractJSObject() { 
      @Override 
      public Set<String> keySet() { 
       return props.stringPropertyNames(); 
      } 

      @Override 
      public Object getMember(String name) { 
       return props.getProperty(name); 
      } 
     }; 

     e.put("obj", jsObj); 
     e.eval("for (i in obj) print(i, ' = ', obj[i])"); 
    } 
} 
+0

不幸的是,我打電話到正在使用Object.keys()的第三方代碼中,所以我沒有選擇將它交換出來。對於jdk9來說,爲了讓Object.keys測試JSObject而不是僅僅使用ScriptObjectMirror,是否值得將RFE放入? – deinspanjer

+0

是的,請對openjdk提出bug/rfe。 –

+0

RFE提交,內部審查ID:9049306 – deinspanjer

相關問題