2009-03-25 10 views
3

Wie kann ein Hostobjekt in Rhino am besten an JavaScript zurückgegeben werden? Ich habe zwei Klassen wie folgt aus:Zurückgeben eines Hostobjekts in Rhino

public class Hosted extends org.mozilla.javascript.ScriptableObject { 
    private static final long serialVersionUID = 1; 
    public Hosted() {} 
    public void jsConstructor() {} 

    public String getClassName() { 
     return "Hosted"; 
    } 

    public Member jsGet_member() { 
     Member m = new Member(); 
     m.defineFunctionProperties(new String[] { "toString" }, m.getClass(), DONTENUM); 
     return m; 
    } 
} 

public class Member extends org.mozilla.javascript.ScriptableObject { 
    private static final long serialVersionUID = 2; 
    public Member() {} 
    public void jsConstructor() {} 

    public String getClassName() { 
     return "Member"; 
    } 

    public String toString() { 
     return "called toString()"; 
    } 
} 

Es funktioniert, in dem Sinne, dass ich die toString Methode aufrufen kann, aber das Element Objekt verhält sich nicht wie ich erwarten würde:

js> defineClass("Hosted"); 
js> defineClass("Member"); 
js> var h = new Hosted(); 
js> h.toString(); 
[object Hosted] 
js> h instanceof Hosted; 
true 
js> h.__proto__; 
[object Hosted] 
js> 
js> var m = h.member; 
js> m.toString(); 
called toString() 
js> m instanceof Member; // Should be true 
false 
js> m.__proto__; // Should be [object Member] 
null 

Wenn ich obwohl nennen Object.prototype.toString, es sagt, es ist ein Mitglied Objekt:

js> Object.prototype.toString.call(m); 
[object Member] 

ich habe versucht m.setPrototype und Context.javaToJS aufrufen.

Antwort

4
public Scriptable jsGet_member() { 
     Scriptable scope = ScriptableObject.getTopLevelScope(this); 
     Member m = new Member(); 
     m.setParentScope(scope); 
     // defineClass("Member") must have previously been called. 
     m.setPrototype(ScriptableObject.getClassPrototype(scope, "Member")); 
     m.defineFunctionProperties(new String[] { "toString" }, 
       m.getClass(), DONTENUM); 
     return m; 
    } 

js> defineClass("Member") 
js> defineClass("Hosted") 
js> var h = new Hosted(); 
js> var m = h.member; 
js> m.toString(); 
called toString() 
js> m instanceof Member; 
true 
js> m.__proto__; 
[object Member] 

bearbeiten: Das Verfahren kann auch geschrieben werden kann:

public Scriptable jsGet_member() { 
     Scriptable scope = ScriptableObject.getTopLevelScope(this); 
     Context cx = Context.getCurrentContext(); 
     Member m = (Member)cx.newObject(scope, "Member"); 
     m.defineFunctionProperties(new String[] { "toString" }, 
       m.getClass(), DONTENUM); 
     return m; 
    } 

die Member.jsConstructor nennen; es kann auch andere Unterschiede geben.

+0

Danke, das ist perfekt. –