NAME

JE - Pure-Perl ECMAScript (JavaScript) Engine

"JE" is short for "JavaScript::Engine."

VERSION

Version 0.014 (alpha release)

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

SYNOPSIS

 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

 $j->prop(document => $obj); # set property
 $j->prop('document'); # get a property
 # Also:
 $j->{document} = $obj;
 $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" } );

 $j->eval(<<'--end--');
         function correct(s) {
                 s = s.replace(/[EA]/g, function(s){
                         return ['E','A'][+(s=='E')]
                 })
                 return s.charAt(0) +
                        s.substring(1,4).toLowerCase() +
                        s.substring(4)
         }
         print(correct("ECMAScript")) // :-)
 --end--

DESCRIPTION

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

-

Easy to install (no C compiler necessary)

-

Compatible with Data::Dump::Streamer, 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?).

METHODS

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( STRING )

parse parses the code contained in STRING 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.

$j->compile( STRING )

Just an alias for parse.

$j->eval ( STRING )

eval evaluates the JavaScript code contained in STRING. E.g.:

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

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 JE::LValue.) E.g., this will create a new object named document:

$j->eval('this.document')->set({});

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 JE::Object::Function.

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.:

$j->eval('String.prototype')->new_method(
        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 JE::Types 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.

$j->undefined

Returns the JavaScript undefined value.

$j->null

Returns the JavaScript null value.

$j->bind_class( LIST )

Synopsis

$j->bind_class(
    package => 'Net::FTP',
    name    => 'FTP', # if different from package
    constructor_name => 'FTP', # if different from name
    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
    isa => 'Object',
    # OR:
    prototype => $j->{Object}{prototype},
);

Description

(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 are as follows (only package is required; the rest are optional):

package

The name of the Perl class.

name

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

constructor_name

The name the constructor will have. If omitted, name will be used instead. This only applies if constructor is specified.

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.

static_methods

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. This may change. (Perhaps we should see whether the class has overloading to determine this.)

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

to_number

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.

to_string

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.

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.

4 POD Errors

The following errors were encountered while parsing the POD:

Around line 831:

You forgot a '=back' before '=head2'

Around line 864:

=over without closing =back

Around line 964:

'=end for later' is invalid. (Stack: =over; =begin for)

Around line 1152:

'=end for me' is invalid. (Stack: =over; =begin for; =begin for)