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

Writing ECMAScript 4, Today

A very cool new utility has just been released by Olav Junker Kjær called Mascara which is an ECMAScript 4 to JavaScript translator (written in Python).

Using this utility you can begin writing ECMAScript 4 code today, receiving its full benefits (such as IDE integration and compile-time type-checking) while still being able to run the resulting code in all modern browsers.

A simple demonstration is up on the Mascara web site which provides a view into the translated source code, along with run-time (and inline) error messages.

A full break-down of the features currently supported are:

  • Type verification
  • Classes and inheritance, constructors, super initializers
  • Static members
  • Type inference from initialization
  • Parameterized types, Map and Vector
  • Union types
  • Structural types
  • Getters/setters
  • Namespaces
  • Nullable types

Definitely be aware, however, that while the above feature list is more than enough to get started there are still a a few items left to be implemented.

The most important question, when looking at the above code, should be: How do I begin using this today? Olav went ahead and made it easy to do IDE integration - even setting up instructions on how to integrate with Eclipse on Windows (he currently shows how to integrate using the JScript command-line interface, but it can easily be expanded). I'm quite excited by this prospect - having the ability to do compile-time type-checking and be able to succinctly write classes with inheritance will be a major boon to development.

Additionally, he provides information on how to do automatic CGI translation (naturally, you would want to do this only in a development environment).

He's continuing to provide frequent updates on the Mascara blog - be sure to follow along if you're interested in starting to use ECMAScript 4 sooner, rather than later.

Tags: javascript, ecmascript, python

The Browser Scripting Revolution

In the bustle of announcements surrounding OSCON, Blackhat, and the Ajax Experience one single, incredibly important, announcement was made: The introduction of two new Mozilla projects: IronMonkey and ScreamingMonkey.

The critical, core, component of this is the Tamarin virtual machine (which is an Open Sourced version of the ActionScript Virtual Machine that powered the Adobe Flash Player). Tamarin already supports ECMAScript 3 (and, thusly, JavaScript, ActionScript, and JScript) and parts of the upcoming ECMAScript 4 specification.

Briefly, since they're both still under planning, here's what IronMonkey and ScreamingMonkey are setting out to achieve.

IronMonkey

IronMonkey is setting out with the goal of mapping Microsoft's Common Intermediate Language (CIL) to ActionScript Byte Code (ABC), allowing additional language implementations, such as IronPython and IronRuby, to run in the Tamarin Virtual Machine.

IronPython and IronRuby are implementations of Python and Ruby, respectively, that runs on .NET Common Language Runtime (CLR) (and, incidentally, also on Mono), written in C#.

IronRuby is built on top of the Dynamic Language Runtime (DLR)... DLR will ship as part of the Common Language Runtime (CLR) in the future...

To break all of this down: There are implementations of Python and Ruby that are capable of being compiled down to a Common Intermediate Language, which will then be able to be run on Tamarin via IronMonkey.

This is a huge, huge, deal. This means that JavaScript will no longer be the only viable scripting language in browsers that use that Tamarin engine. At the very least, there'll be two more languages to work with. However, if IronMonkey works out well, I wouldn't be surprised if we see an implementation of PHP that runs in the browser.

ScreamingMonkey

Tamarin being able to run JavaScript 2, Python, and Ruby really doesn't mean a whole lot (to the general web-developer public) if the languages don't work in all modern browsers (even though it'll give development on the Mozilla platform a considerable boost). This is where ScreamingMonkey comes into play.

ScreamingMonkey is the effort, being led by Mark Hammond, to allow the Tamarin engine to run within non-Mozilla browsers, starting with Internet Explorer.

Unfortunately, the Internet Explorer team is caught up fixing bugs in their existing ECMAScript implementation (JScript), thus their likelihood of implementing ECMAScript 4, in a reasonable time frame, is slim to none.

The result of this effort will be for a developer to be able to reference ECMAScript 4 or JavaScript 2 from a script tag and have it load a required plugin in order to execute it, for example:

<script type="application/ecmascript;version=4">...</script>

or:

<script type="application/javascript;version=2">...</script>

There's a detailed plan of attack laid out and it will require a lot of work. The end result still needs to be actualized, but it will most likely be in the form of a standalone Tamarin runtime (possibly embedded in another distribution) that will be able to hook into its relevant browsers.

As with IronMonkey, this is a huge announcement. This immediately helps to give credence to using the upcoming JavaScript 2 language as its cross-browser support is practically assured. While we're still a long ways off from being able to use this particular project, the result of it will surely be incredible.

Regardless of the outcome of either one of these projects, it's obvious that browser scripting is beginning to shift in some appreciable ways. Although, should these projects succeed the resulting effect upon the web development industry will be incalculable.

Tags: ruby, python, javascript, ecmascript, tamarin, .net, mozilla

Two Way Web Poster

Just a heads up to those going to the 2005 HCI International Conference - a poster of mine is going to be presented there (by Tristan O'Tierney) concerning the work that I did on my recent Independent Study with Jon Schull. The title of the poster/project is called Two Way Web. It's a very slick framework for easily deploying and creating modifyable web pages with no programming required. We're probably going to be launching it here soon (open source, Python, AJAX), so I'll be sure to let everyone know when that happens.

Tags: ajax, conferences, posters, python

Current Projects

jQuery JavaScript Library

jQuery

Comprehensive DOM, Event, Animation, and Ajax JavaScript Library.

Recent Projects

Pro JavaScript Techniques

JavaScript Book

The best techniques for professional JavaScript. Published by Apress.


Hosting provided by the cool dudes at Engine Yard.