Friday, December 22, 2006

JavaScript Support in Java 6 is WORSE than old Rhino 1.6

Java 6 is out, and with it, it includes built-in support for the Rhino JavaScript interpreter, warts and all. I've had a lot of problems with the Rhino JS interpreter, but astoundingly, the Rhino built-in to Java 6 is actually worse than the Rhino you can download from mozilla.org.

How, you ask?

Exceptions don't work

Well, first, it's got all of the problems you'll find in standard Rhino. The most annoying problem you'll encounter is that exceptions don't work. Here, eval this (in either Rhino 1.6R5 or Java 6):

try { throw new Error("urk"); } catch (e) { throw e; }

To eval this in Rhino, put this text in a file called "bug.js", run Rhino with "java -jar js.jar" and type "load('bug.js')".

"bug.js", line 4: exception from uncaught JavaScript throw: [object Error]

There's two things very wrong with this, one more serious than the other. The first thing wrong with it is that it's reporting the error on the wrong line number. The error was thrown from line 2, but rethrown in line 4. The stacktrace should show the source of the original throw (line 2), not the source of the rethrow (line 4). You'll find this as bug 363543 in Rhino's bugzilla. (I'd suggest that you vote for it, but you can't vote for bugs in Rhino!)

But the second problem is actually way more serious: it's missing the error message of the exception ("urk")! That's bug 351664 (recently patched, but not yet released in any official Rhino release). Since the JS interpreter didn't get the line numbers right either, you now know nothing about the cause of the exception!

Unfortunately, bug 351664 doesn't just apply to rethrown exceptions... it applies to regular old thrown exceptions, too. Here, eval this:

throw new Error("oh no!");

All you get is "[object Error]"... no hint of the error message.

Java 6 won't compile JS into .class files

The coolest feature of Rhino, IMO, was its tight integration with Java classes; you could compile JS directly to .class files that you could run directly in the JVM. (The IKVM guys used this trick to run JS on Mono.)

While Java 6 provides new support for a Compiler API, it doesn't even provide built-in support for compiling a string (you have to roll your own classes for that little convenience), and absolutely no integration with any other compiler, including the Rhino compiler. That means no JS files as classes.

Java 6 has no JavaScript debugger

But aside from inheriting all of the problems in the Rhino implementation, you'll soon find that Java 6 is lacking a critical feature present in Rhino. Rhino includes a JavaScript debugger, allowing you to set breakpoints, step in, step over and step return throughout your code, as well as set up watch expressions, observe the state of local variables, and so on.

But the new JSR 223 scripting API includes no debugger support. There's no way to stop on line 2330 of a long JavaScript file, set breakpoints, observe script-level variables, etc. The Java 6 scripting engine is just a black box with an eval function.

1 comment:

Adam said...

Okay, tell me whether I'm going crazy, or if this could be another rhino exceptions bug.

Code:
function chuck() {
throw "chucked!";
};
function catches() {
try {
var v = chuck();
return v;
} catch (e) {
return "caught!";
}
};
try {
jot.out.write(catches());
} catch (e) {
jot.out.write("uncaught:" + e);
}

Result: "caught!";

Code:


function chuck() {
throw "chucked!";
};
function catches() {
try {
return chuck();
} catch (e) {
return "caught!";
}
};
try {
jot.out.write(catches());
} catch (e) {
jot.out.write("uncaught:" + e);
}

Result: "uncaught:chucked!"