Thursday, 18 April 2013

Nashorn Thoughts

Recently, we ran a HackDay on Nashorn as part of Devoxx UK.

Nashorn (pronounced NAS-horn, not NASH-horn) is a new implementation of Javascript that will ship with Java 8. It's very cool - all implemented with invokedynamic & passes the ECMAScript spec 100% (no other impl can do this).

It's already landed on OpenJDK 8 mainline & is in most cases, pretty solid. We found a couple of surprising things & minor bugs with it during the HackDay, but nothing major.

On the whole, it's pretty awesome - the Java interop is great, and it's a way of writing Javascript which doesn't feel too clunky.

In fact, I'd really like to start using Nashorn as a teaching aid to do outreach to web programmers who don't know the Java platform at all.

One slight problem is that jjs (the Nashorm shell) isn't actually a very good REPL. In particular, it doesn't handle multi-line cut & paste & has no history.

So, I decided that the simplest way to try to fix that was to use rlwrap (thanks to Richard Warburton for discussion of this point). This is a program which takes a command name (plus args) as arguments, and runs them through the readline library, thereby adding support for history, etc even to programs which don't support them out of the box.

rlwrap is, for example, often used by Oracle DBAs to add history support to sqlplus.

Here, then, is where this tale of woe truly begins.

Mac OS X does not ship rlwrap. In fact, it doesn't even ship the GNU Readline library on which rlwrap strongly depends. Instead, it ships a library which has the same name, but is not fully compatible.

All of this means that rlwrap will not build cleanly from source on OS X.

To fix this, I downloaded GNU Readline & compiled it as a static library (actually 2 static libs - libhistory.a & libreadline.a).

Then I set the include directory of rlwrap to ignore the bogus readline.h in /usr/include & instead use the correct one (contained in the source directory of GNU Readline).

Rerunning make from the rlwrap build directory now correctly compiled all of rlwrap, but the final link still failed (because it was attempting to use the bogus libreadline.dylib which OS X ships).

However, at this point, I could now take the final link command, and modify it - removing the -lreadline switch & instead adding in libreadline.a and libhistory.a as additional object files that just need to be included in the final binary. This results in a semi-statically linked rlwrap which actually works.

With all of this yak-shaving done (& yes, I do know that MacPorts ships an rlwrap, but I have been bitten by MacPorts way too many tines to trust it. I'd rather actually understand what was happening on my system - there are package managers I fully understand. MacPorts is not one of them), we were finally read to go:

rlwrap jjs

Aaaaaand - it fails. Well, it works correctly with history & so forth - but one of the critical features for me (multiline c&p) just doesn't work, even under rlwrap.

So, that's kind of back to the drawing board.
  • I'm sure we need a better REPL for interacting with Nashorn. 
  • I'm prepared to spend some cycles on it.
  • I think I have a decent starter set of use cases for it
  • I need some help
  • Especially from people who are approaching this from the POV of not knowing the Java platform or the JVM
  • Errr, that's it...
So - who wants to help? I think this could be quite a cool little project...


jgr said...


thank you for this post. I would like to know if you have considered the integration of jline2?
It's used in Rhino and would be a good candidate I think. I agree that I was disappointed by the jjs shell in jdk8 as it's really basic and first experience won't attract anybody to use it...

Ben said...

jgr - Thanks for the thought. jline2 looks reasonable - so when I get some cycles I'll try it out.