Provided by: libje-perl_0.060-1_all bug

NAME

       JE - Pure-Perl ECMAScript (JavaScript) Engine

VERSION

       Version 0.060 (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.

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

         $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" } );

         $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, short for JavaScript::Engine (imaginative, isn't it?), is a pure-Perl JavaScript
       engine. Here are some of its strengths:

       -   Easy to install (no C compiler necessary*)

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

       -   The JavaScript datatypes provide "TO_JSON" methods for compatibility with JSON.pm.

       JE's greatest weakness is that it's slow (well, what did you expect?).  It also uses and
       leaks lots of memory.  (There is an experimental JE::Destroyer (q.v.) module that solves
       this if you load it first and then call "JE::Destroyer::destroy($j)" on the JE object when
       you have finished with it.)

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

       There is currently an experimental version of the run-time engine, which is supposed to be
       faster, although it currently makes compilation slower. (If you serialise the compiled
       code and use that, you should notice a speed-up.) It will eventually replace the current
       one when it is complete.  (It does not yet respect tainting or max_ops, or report line
       numbers correctly.) You can activate it by setting to 1 the ridiculously named
       YES_I_WANT_JE_TO_OPTIMISE environment variable, which is just a temporary hack that will
       later be removed.

USAGE

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

         $je->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 JE::Types
       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 JE::Types.

METHODS

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

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

           The (optional) options it can take are "max_ops" and "html_mode", which correspond to
           the methods listed below.

       $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 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->{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->max_ops
       $j->max_ops( $new_value )
           Use this to set the maximum number of operations that "eval" (or JE::Code's "execute")
           will run before terminating. (You can use this for runaway scripts.) The exact method
           of counting operations is consistent from one run to another, but is not guaranteed to
           be consistent between versions of JE. In the current implementation, an operation
           means an expression or sub-expression, so a simple "return" statement with no
           arguments is not counted.

           With no arguments, this method returns the current value.

           As shorthand, you can pass "max_ops => $foo" to the constructor.

           If the number of operations is exceeded, then "eval" will return undef and set $@ to a
           'max_ops (xxx) exceeded.

       $j->html_mode
       $j->html_mode( $new_value )
           Use this to turn on 'HTML mode', in which HTML comment delimiters are treated much
           like "//". "new_value" is a boolean. Since this violates ECMAScript, it is off by
           default.

           With no arguments, this method returns the current value.

           As shorthand, you can pass "html_mode => 1" to the constructor.

       $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->true
           Returns the JavaScript true value.

       $j->false
           Returns the JavaScript false value.

       $j->bind_class( LIST )
           (This method can create a potential security hole. Please see "BUGS", below.)

   Synopsis
        $j->bind_class(
            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:

        $j->bind_class(
            package => 'Net::FTP',
            wrapper => sub { new JE_Proxy_for_Net_FTP @_ }
        );

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

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

       name
           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, the constructor will raise an error when called. If there is
           already a constructor with the same name, however, it will be left as it is (though
           methods will still be added to its prototype object). This allows two Perl classes to
           be bound to a single JavaScript class:

            $j->bind_class( name => 'Foo', package => 'Class::One', methods => ... );
            $j->bind_class( name => 'Foo', package => 'Class::Two' );

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

       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.

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

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

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

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

       unwrap => 1
           If you specify this and it's true, objects passed as arguments to the methods or code
           refs specified above are 'unwrapped' if they are proxies for Perl objects (see below).
           And null and undefined are converted to "undef".

           This is experimental right now. I might actually make this the default.  Maybe this
           should provide more options for fine-tuning, or maybe what is currently the default
           behaviour should be removed. If anyone has any opinions on this, please e-mail the
           author.

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

           If "wrapper" is supplied, no constructor will be created.

       After a class has been bound, 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), that provides the
       interface that JS operators require (see JE::Types). 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. But, if the "unwrap" option above is used when a class is
       bound, the original Perl object will be passed to any methods or properties belonging to
       that class. This behaviour is still subject to change. See "unwrap", above.

       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.

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

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

       $j->prototype_for( $class_name )
       $j->prototype_for( $class_name, $new_val )
           Mostly for internal use, this method is used to store/retrieve the prototype objects
           used by JS's built-in data types. The class name should be 'String', 'Number', etc.,
           but you can actually store anything you like in here. :-)

TAINTING

       If a piece of JS code is tainted, you can still run it, but any strings or numbers
       returned, assigned or passed as arguments by the tainted code will be tainted (even if it
       did not originated from within the code). E.g.,

         use Taint::Util;
         taint($code = "String.length");
         $foo = 0 + new JE  ->eval($code);  # $foo is now tainted

       This does not apply to string or number objects, but, if the code created the object, then
       its internal value will be tainted, because it created the object by passing a simple
       string or number argument to a constructor.

IMPLEMENTATION NOTES

       Apart from items listed under "BUGS", below, JE follows the ECMAScript v3 specification.
       There are cases in which ECMAScript leaves the precise semantics to the discretion of the
       implementation. Here is the behaviour in such cases:

       •   The global "parseInt" can interpret its first argument either as decimal or octal if
           it begins with a 0 not followed by 'x', and the second argument is omitted. JE uses
           decimal.

       •   Array.prototype.toLocaleString uses ',' as the separator.

       The spec. states that, whenever it (the spec.), say to throw a SyntaxError, an
       implementation may provide other behaviour instead. Here are some instances of this:

       •   "return" may be used outside a function. It's like an 'exit' statement, but it can
           return a value:

             var thing = eval('return "foo"; this = statement(is,not) + executed')

       •   "break" and "continue" may be used outside of loops. In which case they act like
           "return" without arguments.

       •   Reserved words (except "case" and "break") can be used as identifiers when there is no
           ambiguity.

       •   Regular expression syntax that is not valid ECMAScript in general follows Perl's
           behaviour. (See JE::Object::RegExp for the exceptions.)

       JE also supports the "escape" and "unescape" global functions (not part of ECMAScript
       proper, but in the appendix).

BUGS

       To report bugs, please e-mail the author.

   Bona Fide Bugs
       •   "bind_class" has a security hole: An object methodXs corresponding Function object can
           be applied to any Perl object or class from within JS.  (E.g., if you have allowed a
           Foo object's "wibbleton" method to be called from JS, then a Bar object's method of
           the same name can be, too.)

           Fixing this is a bit complicated. If anyone would like to help, please let me know.
           (The problem is that the same code would be repeated a dozen times in "bind_class"'s
           closures--a maintenance nightmare likely to result in more security bugs. Is there any
           way to eliminate all those closures?)

       •   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".

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

       •   Sometimes line numbers reported in error messages are off. E.g., in the following

           code--
             foo(
                 (4))

           --, if "foo" is not a function, line 2 will be reported instead of line 1.

       •   Currently, [:blahblahblah:]-style character classes donXt work if followed by a
           character class escape (\s, \d, etc.) within the class.  "/[[:alpha:]\d]/" is
           interpreted as "/[\[:alph]\d\]/".

       •   If, in perl 5.8.x, you call the "value" method of a JE::Object that has a custom fetch
           subroutine for one of its enumerable properties that throws an exception, you'll get
           an 'Attempt to free unreferenced scalar' warning.

       •   On Solaris in perl 5.10.0, the Date class can cause an 'Out of memory' error which I
           find totally inexplicable. Patches welcome. (I don't have Solaris, so I can't
           experiment with it.)

       •   Case-tolerant regular expressions allow a single character to match multiple
           characters, and vice versa, in those cases where a character's uppercase equivalent is
           more than one character; e.g., "/ss/" can match the double S ligature. This is
           contrary to the ECMAScript spec. See the source code of JE::Object::RegExp for more
           details.

       •   Currently any assignment that causes an error will result in the 'Cannot assign to a
           non-lvalue' error message, even if it was for a different cause. For instance, a
           custom "fetch" routine might die.

       •   The parser doesnXt currently support Unicode escape sequences in a regular expression
           literalXs flags. It currently passes them through verbatim to the RegExp constructor,
           which then croaks.

       •   Under perl 5.8.8, the following produces a double free; something I need to look into:

             "".new JE  ->eval(q| Function('foo','return[a]')() | )

       •   The "var" statement currently evaluates the rhs before the lhs, which is wrong. This
           affects the following, which should return 5, but returns undefined:

             with(o={x:1})var x = (delete x,5); return o.x

       •   Currently if a try-(catch)-finally statementXs "try" and "catch" blocks don't return
           anything, the return value is taken from the "finally" block.  This is incorrect.
           There should be no return value. In other words, this should return 3:

             eval(' 3; try{}finally{5} ')

       •   Compound assignment operators (+=, etc.) currently get the value of the rhs first,
           which is wrong. The following should produce "1b", but gives "2b":

             a = 1;  a += (a=2,"b")

       •   Serialisation of RegExp objects with Data::Dump::Streamer is currently broken (and has
           been since 0.022).

   Limitations
       •   JE is not necessarily IEEE 754-compliant. It depends on the OS. For this reason the
           Number.MIN_VALUE and Number.MAX_VALUE properties may not have the same values as
           ECMAScript, and sometimes rounding (via "toPrecision", etc.) goes the wrong way.

       •   A Perl subroutine called from JavaScript can sneak past a "finally" block and avoid
           triggering it:

             $j = new JE;
             $j->new_function(outta_here => sub { last outta });
             outta: {
                 $j->eval('
                     try { x = 1; outta_here() }
                     finally { x = 2 }
                 ');
             }
             print $j->{x}, "\n";

       •   NaN and Infinity do not work properly on some Windows compilers.  32-bit ActivePerl
           seems not to work, but I have been told 64-bit is OK.  Strawberry Perl works fine,
           which is what most people are using.

   Incompatibilities with ECMAScript...
       ...that are probably due to typos in the spec.

       •   In a try-catch-finally statement, if the 'try' block throws an error and the 'catch'
           and 'finally' blocks exit normally--i.e., not as a result of
           throw/return/continue/break--, the error originally thrown within the 'try' block is
           supposed to be propagated, according to the spec. JE does not re-throw the error.
           (This is consistent with other ECMAScript implementations.)

           I believe there is a typo in the spec. in clause 12.14, in the 'TryStatement : try
           Block Catch Finally' algorithm. Step 5 should probably read 'Let C = Result(4),'
           rather than 'If Result(4).type is not normal, Let C = Result(4).'

       •   If the expression between the two colons in a "for(;;)" loop header is omitted, the
           expression before the first colon is not supposed to be evaluated. JE does evaluate
           it, regardless of whether the expression between the two colons is present.

           I think this is also a typo in the spec. In the first algorithm in clause 12.6.3, step
           1 should probably read 'If ExpressionNoIn is not present, go to step 4,' rather than
           'If the first Expression is not present, go to step 4.'

       •   The "setTime" method of a Date object does what one would expect (it sets the number
           of milliseconds stored in the Date object and returns that number).  According to the
           obfuscated definition in the ECMAScript specification, it should always set it to NaN
           and return NaN.

           I think I've found yet another typo in the spec. In clause 15.9.5.27, 'Result(1)' and
           and 'Result(2)' are probably supposed to be 'Result(2)' and 'Result(3)', respectively.

PREREQUISITES

       perl 5.8.4 or higher

       Scalar::Util 1.14 or higher

       Exporter 5.57 or higher

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

       The TimeDate distribution (more precisely, Time::Zone and Date::Parse)

       Encode 2.08 or higher

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

AUTHOR, COPYRIGHT & LICENSE

       Copyright (C) 2007-12 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.

       Some of the code was derived from Data::Float, which is copyrighted (C) 2006, 2007, 2008
       by Andrew Main (Zefram).

ACKNOWLEDGEMENTS

       Some of the

       Thanks to Max Maischein, Kevin Cameron, Chia-liang Kao and Damyan Ivanov for their
       contributions,

       to Andy Armstrong, Yair Lenga, Alex Robinson, Christian Forster, Imre Rad, Craig Mackenna
       and Toby Inkster for their suggestions,

       and to the CPAN Testers for their helpful reports.

SEE ALSO

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

       JE::Destroyer
       JE::Types
       JE::Object
       JE::Object::Function
       JE::LValue
       JE::Scope
       JE::Code
       JE::Parser

       ECMAScript Language Specification (ECMA-262)

           http://www.ecma-international.org/publications/files/ecma-st/ECMA-262.pdf
           <http://www.ecma-international.org/publications/files/ecma-st/ECMA-262.pdf>

       JavaScript.pm, JavaScript::SpiderMonkey and JavaScript::Lite--all interfaces to Mozilla's
       open-source SpiderMonkey JavaScript engine.

       JavaScript::V8

       WWW::Mechanize::Plugin::JavaScript