Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Hooking a scope object's get() and put() / Calling a superclass's method in a JavaAdapter

100 views
Skip to first unread message

tlrobinson

unread,
Sep 22, 2008, 10:14:50 PM9/22/08
to
I'm trying to create Rhino context (in JS code running in Rhino) with
a scope object that reports to me whenever a property is set or
accessed. I've tried a number of things, but can't seem to find the
right combination.

Here's what I was hoping would work, but I couldn't find any way to
call a Java superclass's method from within a JavaAdapter's method
implementation. Is it possible?

var cx = Packages.org.mozilla.javascript.Context.enter();
var scope = new Packages.org.mozilla.javascript.ScriptableObject({
className : function() {
return "HookedScriptableObject";
},
put : function(name, start, value) {
java.lang.System.out.println("putting: " + name);
// need equivalent to "super.put(name, start, value)"
}
});
scope = cx.initStandardObjects(scope);


I also tried subclassing ScriptableObject directly in Java. This sort
of worked when I just instantiated it directly:

js> a = new Packages.HookedScriptableObject()
Default for class java.lang.String
test4567
js> a.asdf = "1234"
Putting: asdf => 1234
1234
js> a.asdf
Getting: asdf
1234

But when calling initStandardObjects I get "Can't find method
org.mozilla.javascript.Context.initStandardObjects(object)":

var cx = Packages.org.mozilla.javascript.Context.enter();
scope = cx.initStandardObjects(new
Packages.HookedScriptableObject());

Here's HookedScriptableObject.java:

import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.ScriptableObject;

class HookedScriptableObject extends ScriptableObject
{
public HookedScriptableObject()
{
super();
}

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

public Object getDefaultValue(Class typeHint)
{
System.out.println("Default for " + typeHint);
return "test4567";
}

public Object get(int index, Scriptable start)
{
System.out.println("Getting index: " + index);
return super.get(index, start);
}

public Object get(String name, Scriptable start)
{
System.out.println("Getting: " + name);
return super.get(name, start);
}

public void put(String name, Scriptable start, Object value)
{
System.out.println("Putting: " + name + " => " + value);
super.put(name, start, value);
}

public void put(int index, Scriptable start, Object value)
{
System.out.println("Putting index: " + index + " => " +
value);
super.put(index,start, value);
}
}

I feel like there must be a way to do this pretty easily, I'm just
missing something...

Ideally the code would be entirely in JavaScript, but some Java is
ok. This portion of the code should be in JavaScript, if possible:

var cx = Packages.org.mozilla.javascript.Context.enter();
scope = cx.initStandardObjects(whatever);

Thanks in advance.

-Tom

Hannes Wallnoefer

unread,
Sep 23, 2008, 8:27:20 AM9/23/08
to
On Sep 23, 4:14 am, tlrobinson <yacht...@gmail.com> wrote:
> I'm trying to create Rhino context (in JS code running in Rhino) with
> a scope object that reports to me whenever a property is set or
> accessed. I've tried a number of things, but can't seem to find the
> right combination.
>
> Here's what I was hoping would work, but I couldn't find any way to
> call a Java superclass's method from within a JavaAdapter's method
> implementation. Is it possible?

Yes, use super$methodName() to invoke super methods. This should be
documented at
http://www.mozilla.org/rhino/ScriptingJava.html#javaAdapter

>     var cx = Packages.org.mozilla.javascript.Context.enter();

Note that you don't need to call Context.enter() as you are already
running in a rhino context. You may just use
Context.getCurrentContext() instead.

>     var scope = new Packages.org.mozilla.javascript.ScriptableObject({
>         className : function() {
>             return "HookedScriptableObject";
>         },
>         put : function(name, start, value) {
>             java.lang.System.out.println("putting: " + name);
>             // need equivalent to "super.put(name, start, value)"
>         }
>     });
>     scope = cx.initStandardObjects(scope);

Neat idea, but it won't work that way, as the JavaAdapter will be
wrapped as java object.

> I also tried subclassing ScriptableObject directly in Java. This sort
> of worked when I just instantiated it directly:
>
>         js> a = new Packages.HookedScriptableObject()
>         Default for class java.lang.String
>         test4567
>         js> a.asdf = "1234"
>         Putting: asdf => 1234
>         1234
>         js> a.asdf
>         Getting: asdf
>         1234
>
> But when calling initStandardObjects I get "Can't find method
> org.mozilla.javascript.Context.initStandardObjects(object)":
>
>     var cx = Packages.org.mozilla.javascript.Context.enter();
>     scope = cx.initStandardObjects(new
> Packages.HookedScriptableObject());

This is a bug in the java method lookup code. I filed a bug for this:
https://bugzilla.mozilla.org/show_bug.cgi?id=456546

The following will work (with the fix for bug 456546 above):

var rhino = org.mozilla.javascript;
var cx = rhino.Context.currentContext;

var scope = new JavaAdapter(rhino.NativeObject, {
getClassName: function() { return "Foo"; },
put: function(name, start, value) {
this.super$put(name, this, value);
},
});

scope = rhino.Context.currentContext.jsToJava(scope,
rhino.Scriptable);
scope.__proto__ = Object.prototype;
cx.initStandardObjects(scope);


Be careful not to calling value.toString() in the put function, as it
will dive into infinite recursion while the scope is being
initialized.

hannes

> -Tom

tlrobinson

unread,
Sep 23, 2008, 1:28:16 PM9/23/08
to
Thanks. So there's no way to get this working until that bug is fixed?

Maybe push more of the code (i.e. currentContext and
initStandardObjects) into Java, to eliminate the JavaAdapter use?


-Tom

On Sep 23, 5:27 am, Hannes Wallnoefer <hann...@gmail.com> wrote:
> On Sep 23, 4:14 am, tlrobinson <yacht...@gmail.com> wrote:
>
> > I'm trying to create Rhino context (in JS code running in Rhino) with
> > a scope object that reports to me whenever a property is set or
> > accessed. I've tried a number of things, but can't seem to find the
> > right combination.
>
> > Here's what I was hoping would work, but I couldn't find any way to
> > call a Java superclass's method from within a JavaAdapter's method
> > implementation. Is it possible?
>
> Yes, use super$methodName() to invoke super methods. This should be

> documented athttp://www.mozilla.org/rhino/ScriptingJava.html#javaAdapter

0 new messages