Blog


Spicing Up Embedded JavaScript

One thing that I absolutely adore is the sheer embeddability of JavaScript. It's a (comparatively) simple language that is fiercely flexible. I tend to liken JavaScript to water - alone it's painfully simple but it can take the form of its container - and mixing it with anything enhances its flavor.

Since JavaScript, alone, is so dumb (we've become spoiled by browsers which provide DOM, setTimeout/setInterval, and even a global object reference - none of which are necessarily required my an ECMAScript implementation) we must rely upon the spice of 'larger' languages to help it gain some taste.

We can start by taking a look at some of the most popular languages that are available today: Python, Perl, PHP, Ruby, and Java -- all of which have, at least, one embeddable JavaScript interpreter.

One thing is the same in all the interpreter implementations, as well, they all have the ability to introduce (at least) simple objects into interpreter (from the parent language) and extract values again. Sometimes this may be as simple as executing a JavaScript function and getting its return value (which is often translated from its internal JavaScript form back into the native language).

There's a couple points upon which I like to evaluate the embeddability of a JavaScript interpreter, specifically:

  1. Object Translation: If objects/values are passed to/from the interpreter to/from the native language - is that translation handled automatically?
  2. Simplicity: How hard is it to get up-and-running? (Is extra compilation required or is it written using native language code?)
  3. Bleed-through: Can JavaScript communicate to the base language or is it a one-way-street?

The first point is the easiest one to find compatibility with - virtually all embeddable JavaScript interpreters do some form of object translation. Some do it better (like JE and Rhino) but it generally shouldn't be a problem for simple scripts.

PHP

» PHPJS

A flexible, pure-PHP, JavaScript interpreter that even accepts compiling to an intermediary bytecode. There is no bleed-through but good object translation.

include "js.php";

# Introduce a new JavaScript function, named print,
# which calls a PHP function
function show($msg) {
  echo "$msg\n";
}

$jsi_vars["print"] = "show";

# Add in a new pure-JavaScript function which calls
# our previously-introduced print function
jsc::compile("function alert(msg){ print('Alert:' + msg); }");

# Prints out 'Alert: text'
js_exec("alert('text');");

» J2P5: Pure-PHP ECMAScript Engine

Probably the simplest of the available interpreters - there doesn't appear to be a clear way of communicating from JavaScript-to-PHP (or vice versa). Although, it is implemented in pure-PHP which allows for some nice cross-platform compatibility.

include "js/js.php";

$script = <<<EOD
  print("Hello from JavaScript");
EOD;

js::run($script);

Perl

» JavaScript::SpiderMonkey

An embedding of Mozilla's Spidermonkey JavaScript engine into Perl. Since it uses Spidermonkey it'll require that extra source code and compilation. Object translation is good but there's no bleed-through (JavaScript calling native Perl functionality that isn't explicitly defined).

use JavaScript::SpiderMonkey;

# Instantiate the interpreter
my $j = JavaScript::SpiderMonkey->new();

# Introduce a new JavaScript function, named print,
# which calls a Perl function
$j->function_set("print", sub { print @_, "\n" } );

# Add in a new pure-JavaScript function which calls
# our previously-introduced print function
$j->eval("function alert(msg){ print('Alert:' + msg); }");

# Prints out 'Alert: text'
$j->eval("alert('text');");

» JE: Pure-Perl ECMAScript Engine

A pure-Perl JavaScript engine - shows incredible promise (probably my favorite new engine in addition to Rhino). Has tremendous potential (including the ability to serialize the runtime environment!).

use JE;

# Instantiate the interpreter
my $j = new JE;

# Introduce a new JavaScript function, named print,
# which calls a Perl function
$j->new_function(print => sub { print @_, "\n" } );

# Add in a new pure-JavaScript function which calls
# our previously-introduced print function
$j->eval("function alert(msg){ print('Alert:' + msg); }");

# Prints out 'Alert: text'
$j->method(alert => "text");

# So does this
$j->eval("alert('text');");

# Introduce the ability to do remote requests
use Net::FTP;

$j->bind_class( package => "Net::FTP", name => "FTP" );

# Execute native Perl functionality (FTP module)
# directly from JavaScript
$j->eval(<<'--end--');
  var connect = new FTP("ftp.mozilla.org");
  connect.get("index.html");
--end--

Note the extreme bleed-through that you can achieve with JE (in addition to excellent object translation).

Java

» Rhino

Probably one of the most famous embeddable JavaScript implementations. Implemented in pure Java has excellent object translation and perfect bleed-through. The bleeding can even be controlled explicitly at runtime (to create a more confined environment).

In the following code (using in some of the jQuery build system) two functions are defined which utilize a number of native Java packages - all without ever writing a single line of Java code.

importPackage(java.io);

function writeFile( file, stream ) {
  var buffer = new PrintWriter( new FileWriter( file ) );
  buffer.print( stream );
  buffer.close();
}

function read( file ) {
  var f = new File(file);
  var reader = new BufferedReader(new FileReader(f));
  var line = null;
  var buffer = new java.lang.StringBuffer(f.length());
  while( (line = reader.readLine()) != null) {
    buffer.append(line);
    buffer.append("\n");
  }
  return buffer.toString();
}

Python

» Python-Spidermonkey

Previously this was one of the most depressing embedding efforts (and, really, the only one available for Python) but it has since had some new life blown into it - which is much appreciated. It supports decent object translation and bleed-through (including the ability to call native classes, much like in JE).

from spidermonkey import Runtime

j = RunTime().new_context()

# Introduce a new JavaScript function, named print,
# which calls a Python function
j.bind_callable("print", lambda msg: print(msg));

# Add in a new pure-JavaScript function which calls
# our previously-introduced print function
j.eval_script("function alert(msg){ print('Alert:' + msg); }");

# Prints out 'Alert: text'
j.eval_script("alert('text');");

Ruby

While there was a previous effort to embed Spidermonkey in Ruby it is largely defunct now, superseded by the new (strangely named) Johnson project.

» Johnson

This is a, relatively, new project that's working to completely overhaul how communication is currently done in-between Ruby and JavaScript (using Spidermonkey to power the engine). There is complete bleed-through: Ruby can dig in and manipulate JavaScript objects at run-time and JavaScript can call back and access native Ruby functionality. Additionally they're examining the ability to provide native browser environments using the env.js script that I created last year. While the cross-platform ease-of-use isn't there yet the project absolutely has a ton of potential.

require "johnson"

j = Johnson::Runtime.new

# Introduce a new JavaScript function, named print,
# which calls a Ruby function
j.print = lambda {|msg| puts msg};

# Add in a new pure-JavaScript function which calls
# our previously-introduced print function
j.evaluate("function alert(msg){ print('Alert:' + msg); }");

# Prints out 'Alert: text'
j.evaluate("alert('text');");

Update: Another example of Johnson in action from John Barnette:

require "johnson"

class Monkey
  def eat
    puts "Nom, nom, nom, bananas!"
  end
end

j = Johnson::Runtime.new

# toss a monkey into the runtime
m = Monkey.new
j[:m] = m

# add a JSland function to our monkey...
j.evaluate("m.chow = function() { this.eat() }")

# ...and now it's available as an instance method on our native Ruby object!
m.chow

There's a ton of potential in all of these projects - providing interesting features for blurring the lines in-between JavaScript and different host languages. For your next project it should be pretty easy to find a solution to embedding JavaScript as your quick-and-dirty scripting language of choice.

Tags: ruby, java, python, php, perl, javascript

Amazon S3

Amazon S3 was just released today, giving developers/companies the ability to instantly store files/data up to 5GB in size - and as many as you want. They just charge pennies for bandwidth and storage costs.

Are you looking for a new way to make money?

Wrap a quick reverse proxy on top of the public S3 URLs, require any of the above to use a secure password, charge $X dollars/month. Presto, instant data storage company.

Tags: amazon, s3, java, programming, perl, lazyweb

Programming News via RSS

In your newsreader, subscribe to your favorite programming module RSS feed:

Unfortunately, those are really the only languages with any sort of repository, which is a shame. Regardless, I'm finding that being subscribed to both the Perl and Javascript RSS feeds is really helping me to catch the latest developments/advancements and include them in my projects.

Update: Added PHP, thanks to Brendyn!

Tags: raa, cpan, jsan, rss, ruby, perl, javascript, module

JSAN Improved

JSAN (The Javascript Archive Network) was recently announced at the North American Perl Conference as a repository for Javascript code, simliar to the archive that Perl has (CPAN). When I first checked it out, it was pretty barebones, but now it has many more features and a growing number of packages for people to play with. I definitely recommend that you check out the service - especially some of the modules and their test frameworks - it all has a lot of potential. I plan on wrapping up some of my Javascript code in the upcoming weeks so that I can distribute it on this site. Based upon the clarity of the code that's already up there - I have a good mark to strive for.

Tags: javascript, perl, archive, package, jsan

Google Address Translation

I've just finished up an excellent hack which brings the power of address translation (converting a US Postal Address into a Latitude/Longitude) to the Google Maps API - something that wasn't provided in the default distribution. There's a ton of information available, including demos, screenshots, and code on the project page: Google Address Translation.

Tags: google, maps, api, hacks, geo, perl, javascript, programming

Google Search History RSS

This tool goes through your current Google Search History, grabs all of your recent searches and turns it into an RSS feed. Would work best set up as a nightly/hourly cron job, redirecting to a file.

This tool is written in Perl and uses a few, slick, modules: WWW::Mechanize, XML::LibXML, and XML::RSS. I was influenced by the very nice webscrape tool when building this.

A sample, from my searches, can be found here:
http://ejohn.org/apps/ghistory/google.rdf

And how it looks in my newsreader (Newsgator):
Google Search History RSS Feed

Downloads

Tags: perl, google, search, rss, popular

Project Updates

Even though I was terribly busy, I still managed to make a number of project updates this weekend. Most of the updates were just writing up some documentation and getting them out the door, but that's something.

  • FOAF Layout - Did a possible FOAF layout for Bob Aman. I wanted a clean, concise, layout which downgraded nicely (and even had a little bit of Javascript flare).
  • Log Session Analyis - Analyzes Apache logs looking for all unique sessions that occur. Also grabs a bunch of other fun stuff (such as number of people reading RSS feeds.
  • Dom Snap - Make two DOM objects 'snap' to each other and move around together.
  • Finally wrote some documentation for three of my Perl Modules, and put them up on CPAN: Net::Netflix, Net::Amazon::DVD2IMDB, and Net::DVDProfiler. I hope to package up a couple other modules and get them out the door here soon.

Also, I've moved this site over to a new server (which is also hosting juniperbay.com, amoungst other things). It's terribly nice - hopefully the uptime will be much better then my old server.

Tags: apache, javascript, perl, modules, projects, site

RedBull Competition

Tonight is the 4th RedBull Programming Competition and I've got a feeling that team Perl is going to do well. Looking at the other teams, the majority of them are freshman and, therefore, not a major concern.

I'm hoping for some good challanges this time around as this is my fourth time competing. The first time I was on a team with Tristan and Scott working to build a Multi-User Dungeon. The result was interesting, we had randomly generated dungeons and monsters with a simple AI. For the second competition my team was with Jordan, Chris, Pete, and Luke (the original team Perl). We built a file browser and won the competition. The third time I went alone and hacked out another simple dungeon.

I enjoy programming under pressure like this, it's enjoyable and the results are always fun (although, I almost never touch them later, which is unfortunate). I hope to post some updates from the competition itself, and possibly some pictures. Go Team Perl!

Tags: competition, perl, programming

· « Previous entries

JavaScript Books

Secrets of the JavaScript Ninja

JavaScript Secrets

Secret techniques of top JavaScript programmers. Coming Fall 2009.

Pro JavaScript Techniques

Pro JavaScript

The best techniques for professional JavaScript. Published by Apress.

Micro Updates

John Resig Twitter Updates

@jeresig

Infrequent, short, updates and links.

JavaScript Jobs



Hosting provided by: Ruby Hosting by Engine Yard