My colleague Colin Walters has recently been working on automatically generating language bindings from the Java to C libraries based on the GObject system. (See http://live.gnome.org/JGIR.) One question that we were interested in is how well things would work for non-Java languages on the JVM. So, I spent some time yesterday trying it out with Rhino. It basically worked out of the box:
http://svn.gnome.org/viewvc/java-gobject-introspection/trunk/gtktest.js?view=markup Cool! But there was one aspect of the binding that I wasn't very happy with - how you connect to GObject "signals" (callbacks) ... so I wanted to throw out some ideas for small Rhino enhancements to make that better. In Java, the way you make a connection to a signal in JGIR (as in the existing Java GNOME hand-written bindings for the same libraries) looks like: button.connect(new Button.Clicked() { public void onClicked() { System.out.println("I was clicked"); } }); So it uses overloading on the passed in interface to tell which signal to connect to. This translates over to: button.connect(Button.Clicked({ onClicked: function () { print("I was clicked"); }})); Which isn't bad, but there's a lot of extra noise there. One idea I had was that this could be simplified if Rhino allowed passing a function rather than an object when building an interface if with a single method, so: button.connect(Button.Clicked( function () { print("I was clicked"); })); Removing some of the excess noise. This seems like something that would be highly compatible with existing programs and convenient in any case where you had an overload on one-function interfaces (I think there are standard Java methods that take either Callable or Runnable) The other possibility would be to extend JGIR a little bit to have a second way of connecting signals generically avoiding the overload, so there was: interface Invokable { Object invoke(Object[] args); } public long connect(String signalName, Invokable callback); Then you could *almost* use the existing Rhino function => single function interface mapping. It doesn't quite work because the Object[] will get mapped to an array. You would need to do: widget.connect("MouseDown", function(args) { print(args[0].x, args[0].y); // args[0] is the event object }); My first thought was, what if Rhino automatically "de-boxed" a method with a single Object[] argument? It's not crazy behavior, but it's a little magic, and maybe not compatible enough. The second thought was that varargs methods are actually flagged in the bytecode. So, if we modified Invokable a bit to have: interface Invokable { Object invoke(Object args...); } And Rhino automatically turned Java varargs into the Javascript concept of calling with varargs (the argument list is just a list of arguments), then everything would work out perfectly. widget.connect("MouseDown", function(event) { print(event.x, event.y); }); Only disadvantages I see: there might be a few programs out there depending on the current behavior, and maybe it's a little weird to make the mapping depend on something that is not, strictly speaking, part of the method signature. Reactions to either of the above? Other ideas? - Owen _______________________________________________ dev-tech-js-engine-rhino mailing list [email protected] https://lists.mozilla.org/listinfo/dev-tech-js-engine-rhino
