Help-Site Computer Manuals
  Algorithms & Data Structures   Programming Languages   Revision Control
  Cameras   Computers   Displays   Keyboards & Mice   Motherboards   Networking   Printers & Scanners   Storage
  Windows   Linux & Unix   Mac

Pure-Perl ECMAScript Engine

JE - Pure-Perl ECMAScript Engine


JE - Pure-Perl ECMAScript (JavaScript) Engine


Version 0.019 (alpha release)

The API is still subject to change. If you have the time and the interest, please experiment with this module (or even lend a hand :-). If you have any ideas for the API, or would like to help with development, please e-mail the author.


  use JE;

  $j = new JE; # create a new global object

  $j->eval('({"this": "that", "the": "other"}["this"])');

  # returns "that"

  $parsed = $j->parse('new Array(1,2,3)');


  $rv = $parsed->execute; # returns a JE::Object::Array

  $rv->value;             # returns a Perl array ref

  $obj = $j->eval('new Object');

  # create a new object

  $foo = $j->{document}; # get property

  $j->{document} = $obj; # set property

  $j->{document} = {};   # gets converted to a JE::Object

  $j->{document}{location}{href}; # autovivification

  $j->method(alert => "text"); # invoke a method

  # create global function from a Perl subroutine:

  $j->new_function(print => sub { print @_, "\n" } );


          function correct(s) {

                  s = s.replace(/[EA]/g, function(s){

                          return ['E','A'][+(s=='E')]


                  return s.charAt(0) +

                         s.substring(1,4).toLowerCase() +



          print(correct("ECMAScript")) // :-)



JE is a pure-Perl JavaScript engine. Here are some of its strengths:

Easy to install (no C compiler necessary*)

Compatible with the Data::Dump::Streamer manpage, so the runtime environment can be serialised

The parser can be extended/customised to support extra (or fewer) language features (not yet complete)

All JavaScript datatypes can be manipulated directly from Perl (they all have overloaded operators)

JE's greatest weakness is that it's slow (well, what did you expect?). It also uses and leaks lots of memory, but that will be fixed.

* If you are using perl 5.9.3 or lower, then the Tie::RefHash::Weak manpage is required. Recent versions of it require the Variable::Magic manpage, an XS module (which requires a compiler of course), but version 0.02 of the former is just pure Perl with no XS dependencies.


Simple Use

If you simply need to run a few JS functions from Perl, create a new JS environment like this:

  my $je = new JE;

If necessary, make Perl subroutines available to JavaScript:

  $je->new_function(warn => sub { warn @_ });

  $je->new_function(ok => \&Test::More::ok);

Then pass the JavaScript functions to eval:


  function foo() {

      return 42


  // etc.


  # or perhaps:

  use File::Slurp;

  $je->eval(scalar read_file 'functions.js');

Then you can access those function from Perl like this:

  $return_val = $je->{foo}->();

  $return_val = $je->eval('foo()');

The return value will be a special object that, when converted to a string, boolean or number, will behave exactly as in JavaScript. You can also use it as a hash, to access or modify its properties. (Array objects can be used as arrays, too.) To call one of its JS methods, you should use the method method: $return_val-method('foo')>. See the JE::Types manpage for more information.

Custom Global Objects

To create a custom global object, you have to subclass JE. For instance, if all you need to do is add a self property that refers to the global object, then override the new method like this:

  package JEx::WithSelf;

  @ISA = 'JE';

  sub new {

      my $self = shift->SUPER::new(@_);

      $self->{self} = $self;

      return $self;


Using Perl Objects from JS

See bind_class, below.

Writing Custom Data Types

See the JE::Types manpage.


See also JE::Object, which this class inherits from, and JE::Types.

$j = JE->new
This class method constructs and returns a new JavaScript environment, the JE object itself being the global object.

$j->parse( $code, $filename, $first_line_no )
parse parses the code contained in $code and returns a parse tree (a JE::Code object).

If the syntax is not valid, undef will be returned and $@ will contain an error message. Otherwise $@ will be a null string.

The JE::Code class provides the method execute for executing the pre-compiled syntax tree.

$filename and $first_line_no, which are both optional, will be stored inside the JE::Code object and used for JS error messages. (See also add_line_number in the JE::Code man page.)

$j->compile( STRING )
Just an alias for parse.

$j->eval( $code, $filename, $lineno )
eval evaluates the JavaScript code contained in $code. E.g.:

  $j->eval('[1,2,3]') # returns a JE::Object::Array which can be used as

                      # an array ref

If $filename and $lineno are specified, they will be used in error messages. $lineno is the number of the first line; it defaults to 1.

If an error occurs, undef will be returned and $@ will contain the error message. If no error occurs, $@ will be a null string.

This is actually just a wrapper around parse and the execute method of the JE::Code class.

If the JavaScript code evaluates to an lvalue, a JE::LValue object will be returned. You can use this like any other return value (e.g., as an array ref if it points to a JS array). In addition, you can use the set and get methods to set/get the value of the property to which the lvalue refers. (See also the JE::LValue manpage.) E.g., this will create a new object named document:


Note that I used this.document rather than just document, since the latter would throw an error if the variable did not exist.

$j->new_function($name, sub { ... })
$j->new_function(sub { ... })
This creates and returns a new function object. If $name is given, it will become a property of the global object.

Use this to make a Perl subroutine accessible from JavaScript.

For more ways to create functions, see the JE::Object::Function manpage.

This is actually a method of JE::Object, so you can use it on any object:

  $j->prop('Math')->new_function(double => sub { 2 * shift });

$j->new_method($name, sub { ... })
This is just like new_function, except that, when the function is called, the subroutine's first argument (number 0) will be the object with which the function is called. E.g.:


          reverse => sub { scalar reverse shift }


  # ... then later ...

  $j->eval(q[ 'a string'.reverse() ]); # returns 'gnirts a'

$j->upgrade( @values )
This method upgrades the value or values given to it. See UPGRADING VALUES in the JE::Types manpage for more detail.

If you pass it more than one argument in scalar context, it returns the number of arguments--but that is subject to change, so don't do that.

Returns the JavaScript undefined value.

Returns the JavaScript null value.

$j->bind_class( LIST )



     package => 'Net::FTP',

     name    => 'FTP', # if different from package

     constructor => 'new', # or sub { Net::FTP->new(@_) }

     methods => [ 'login','get','put' ],

     # OR:

     methods => {

         log_me_in => 'login', # or sub { shift->login(@_) }

         chicken_out => 'quit',


     static_methods => {

         # etc. etc. etc.


     to_primitive => \&to_primitive # or a method name

     to_number    => \&to_number

     to_string    => \&to_string

     props => [ 'status' ],

     # OR:

     props => {

         status => {

             fetch => sub { 'this var never changes' }

             store => sub { system 'say -vHysterical hah hah' }


         # OR:

         status => \&fetch_store # or method name


     static_props => { ... }

     hash  => 1, # Perl obj can be used as a hash

     array => 1, # or as an array

     # OR (not yet implemented):

     hash  => 'namedItem', # method name or code ref

     array => 'item',       # likewise

     # OR (not yet implemented):

     hash => {

         fetch => 'namedItem',

         store => sub { shift->{+shift} = shift },


     array => {

         fetch => 'item',

         store => sub { shift->[shift] = shift },


     isa => 'Object',

     # OR:

     isa => $j->{Object}{prototype},



 # OR:



     package => 'Net::FTP',

     wrapper => sub { new JE_Proxy_for_Net_FTP @_ }



(Some of this is random order, and probably needs to be rearranged.)

This method binds a Perl class to JavaScript. LIST is a hash-style list of key/value pairs. The keys, listed below, are all optional except for package or name--you must specify at least one of the two.

Whenever it says you can pass a method name to a particular option, and that method is expected to return a value (i.e., this does not apply to props => { property_name => { store => 'method' } }), you may append a colon and a data type (such as ':String') to the method name, to indicate to what JavaScript type to convert the return value. Actually, this is the name of a JS function to which the return value will be passed, so 'String' has to be capitalised. This also means than you can use 'method:eval' to evaluate the return value of 'method' as JavaScript code. One exception to this is that the special string ':null' indicates that Perl's undef should become JS's null, but other values will be converted the default way. This is useful, for instance, if a method should return an object or null, from JavaScript's point of view. This ':' feature does not stop you from using double colons in method names, so you can write 'Package::method:null' if you like, and rest assured that it will split on the last colon. Furthermore, just 'Package::method' will also work. It won't split it at all.

The name of the Perl class. If this is omitted, name will be used instead.

The name the class will have in JavaScript. This is used by Object.prototype.toString and as the name of the constructor. If omitted, package will be used.

constructor => 'method_name'
constructor => sub { ... }
If constructor is given a string, the constructor will treat it as the name of a class method of package.

If it is a coderef, it will be used as the constructor.

If this is omitted, no constructor will be made.

methods => [ ... ]
methods => { ... }
If an array ref is supplied, the named methods will be bound to JavaScript functions of the same names.

If a hash ref is used, the keys will be the names of the methods from JavaScript's point of view. The values can be either the names of the Perl methods, or code references.

Like methods but they will become methods of the constructor itself, not of its prototype property.

to_primitive => sub { ... }
to_primitive => 'method_name'
When the object is converted to a primitive value in JavaScript, this coderef or method will be called. The first argument passed will, of course, be the object. The second argument will be the hint ('number' or 'string') or will be omitted.

If to_primitive is omitted, the usual valueOf and toString methods will be tried as with built-in JS objects, if the object does not have overloaded string/boolean/number conversions. If the object has even one of those three, then conversion to a primitive will be the same as in Perl.

If to_primitive => undef is specified, primitivisation without a hint (which happens with < and ==) will throw a TypeError.

If this is omitted, to_primitive($obj, 'number') will be used. If set to undef, a TypeError will be thrown whenever the object is numified.

If this is omitted, to_primitive($obj, 'string') will be used. If set to undef, a TypeError will be thrown whenever the object is strung.

props => [ ... ]
props => { ... }
Use this to add properties that will trigger the provided methods or subroutines when accessed. These property definitions can also be inherited by subclasses, as long as, when the subclass is registered with bind_class, the superclass is specified as a string (via isa, below).

If this is an array ref, its elements will be the names of the properties. When a property is retrieved, a method of the same name is called. When a property is set, the same method is called, with the new value as the argument.

If a hash ref is given, for each element, if the value is a simple scalar, the property named by the key will trigger the method named by the value. If the value is a coderef, it will be called with the object as its argument when the variable is read, and with the object and the new value as its two arguments when the variable is set. If the value is a hash ref, the fetch and store keys will be expected to be either coderefs or method names. If only fetch is given, the property will be read-only. If only store is given, the property will be write-only and will appear undefined when accessed. (If neither is given, it will be a read-only undefined property--really useful.)

Like props but they will become properties of the constructor itself, not of its prototype property.

If this option is present, then this indicates that the Perl object can be used as a hash. An attempt to access a property not defined by props or methods will result in the retrieval of a hash element instead (unless the property name is a number and array is specified as well).

The value you give this option should be one of the strings '1-way' and '2-way' (also 1 and 2 for short).

If you specify '1-way', only properties corresponding to existing hash elements will be linked to those elements; properties added to the object from JavaScript will be JavaScript's own, and will not affect the wrapped object. (Consider how node lists and collections work in web browsers.)

If you specify '2-way', an attempt to create a property in JavaScript will be reflected in the underlying object.

To do: Make this accept '1-way:String', etc.

This is just like hash, but for arrays. This will also create a property named 'length'.

To do: Make this accept '1-way:String', etc.

isa => 'ClassName'
isa => $prototype_object
(Maybe this should be renamed 'super'.)

The name of the superclass. 'Object' is the default. To make this new class's prototype object have no prototype, specify undef. Instead of specifying the name of the superclass, you can provide the superclass's prototype object.

If you specify a name, a constructor function by that name must already exist, or an exception will be thrown. (I supposed I could make JE smart enough to defer retrieving the prototype object until the superclass is registered. Well, maybe later.)

wrapper => sub { ... }
If wrapper is specified, all other arguments will be ignored except for package (or name if package is not present).

When an object of the Perl class in question is 'upgraded,' this subroutine will be called with the global object as its first argument and the object to be 'wrapped' as the second. The subroutine is expected to return an object compatible with the interface described in the JE::Types manpage.

If wrapper is supplied, no constructor will be created.

After binding a class, objects of the Perl class will, when passed to JavaScript (or the upgrade method), appear as instances of the corresponding JS class. Actually, they are 'wrapped up' in a proxy object (a JE::Object::Proxy object), such that operators like typeof and === will work. If the object is passed back to Perl, it is the proxy, not the original object that is returned. The proxy's value method will return the original object. Note: I might change this slightly so that objects passed to JS functions created by bind_class will be unwrapped. I still trying to figure out what the exact behaviour should be.

Note that, if you pass a Perl object to JavaScript before binding its class, JavaScript's reference to it (if any) will remain as it is, and will not be wrapped up inside a proxy object.

If constructor is not given, a constructor function will be made that throws an error when invoked, unless wrapper is given.

To use Perl's overloading within JavaScript,, you don't have to do anything. If the object has "", 0+ or bool overloading, that will automatically be detected and used.

This returns a parser object (see the JE::Parser manpage) which allows you to customise the way statements are parsed and executed (only partially implemented).


  • JE is not necessarily IEEE 754-compliant. It depends on the OS. For this reason the Number.MIN_VALUE and Number.MAX_VALUE properties do not exist.

  • The RegExp class is incomplete. The Date class is still nonexistent.

  • Functions objects do not always stringify properly. The body of the function is missing. This produces warnings, too.

  • The JE::Scope class, which has an AUTOLOAD sub that delegates methods to the global object, does not yet implement the can method, so if you call $scope->can('to_string') you will get a false return value, even though scope objects can to_string.

  • JE::LValue's can method returns the method that JE::LValue::AUTOLOAD calls when methods are delegated. But that means that if you call can's return value, it's not the same as invoking a method, because a different object is passed:
     $lv = $je->eval('this.document');
     $lv->to_string; # passes a JE::Object to JE::Object's to_string method
            # passes the JE::LValue to JE::Object's to_string method

    If this is a problem for anyone, I have a fix for it (returning a closure), but I think it would have a performance penalty, so I don't want to fix it. :-(

  • hasOwnProperty does not work properly with arrays and arguments objects.

  • Currently some tests for bitshift operators fail on Windows. Patches are welcome.


perl 5.8.3 or later (to be precise: Exporter 5.57 or later)

Tie::RefHash::Weak, for perl versions earlier than 5.9.4

Note: JE will probably end up with Date::Parse and Unicode::Collate in the list of dependencies.


Copyright (C) 2007 Father Chrysostomos <sprout [at] cpan [dot] org>

This program is free software; you may redistribute it and/or modify it under the same terms as perl.


Thanks to Max Maischein [ webmaster  corion net ] > for letting me use his tests,

to Andy Armstrong [ andy  hexten net ] > and Yair Lenga [ yair lenga  gmail com ] > for their suggestions,

and to the CPAN Testers for their helpful failure reports.


The other JE man pages, especially the following (the rest are listed on the the JE::Types manpage page):

the JE::Types manpage
the JE::Object manpage
the JE::Object::Function manpage
the JE::LValue manpage
the JE::Scope manpage
the JE::Code manpage
the JE::Parser manpage

ECMAScript Language Specification (ECMA-262) and the JavaScript::SpiderMonkey manpage--both interfaces to Mozilla's open-source SpiderMonkey JavaScript engine.

the WWW::Mechanize::Plugin::JavaScript manpage