| JE documentation | view source | Contained in the JE distribution. |
JE::Types - JavaScript types and objects
This is just documentation, not a module.
The various JavaScript types and objects are represented by Perl classes in JE (which are listed below). This document describes the basic interface implemented by these classes. Information specific to each class can be found on its own manual page.
When a value is passed from Perl to JavaScript, it will be "upgraded" to a
Perl object
representing a JavaScript value. This is done by the upgrade method of
the global object.
If the value to be upgraded is a blessed reference, and the class into
which it is blessed has been bound using JE's bind_class method, it is
wrapped up in a proxy object that provides the methods JS needs. A blessed
reference whose class has not been bound will be
left alone (we assume you know what you are doing).
Otherwise the
conversion is as follows:
From To ------------------------- undef undefined array ref Array hash ref Object code ref Function '0' number other scalar string
WARNING: The 'upgrading' of simple scalars (strings/numbers) and regexps is still subject to change.
To do: Make &JE::upgrade detect whether a simple scalar is a string or number.
To do: Convert Regexp objects to JE::Object::RegExp objects.
Each built-in JavaScript class or primitive type is a Perl class underneath. Here is the complete list of object classes:
JavaScript Perl ----------------- Object JE::Object Function JE::Object::Function Array JE::Object::Array String JE::Object::String Boolean JE::Object::Boolean Number JE::Object::Number Date JE::Object::Date RegExp JE::Object::RegExp Error JE::Object::Error RangeError JE::Object::Error::RangeError ReferenceError JE::Object::Error::ReferenceError SyntaxError JE::Object::Error::SyntaxError TypeError JE::Object::Error::TypeError URIError JE::Object::Error::URIError
And here are the primitive types:
string JE::String number JE::Number boolean JE::Boolean null JE::Null undefined JE::Undefined
And I might also mention a few special cases:
Global JE Math JE::Object::Math Arguments JE::Object::Function::Arguments Function scope JE::Object::Function::Call RegExp constructor JE::Object::Function::RegExpConstructor
The last three are for internal use.
Every JS data type can be used as a string, boolean or number. It works exactly as it does in JavaScript. For example:
$num = $je->eval('42');
$num2 = $je->eval('NaN');
print $num2; # prints NaN
print 0+$num2; # prints nan or NaN, depending or your system
# (or something really weird on Windows).
$zero_str = $je->eval("'0'");
print "true" if $zero_str; # prints 'true'
print "false" unless 0+$zero_str; # prints 'false'
$false = $je->eval('false');
print $false; # prints 'false'
print "false" unless $false; # also prints 'false'
To access the property of a JS object, or of the JS environment itself (i.e., a global variable), just use it as a hash ref:
$je->{String}; # gives you the String constructor function
$je->{undefined}; # the undefined value
my $obj = $je->eval('var obj = new Object; return obj');
$obj->{foo} = 'bar';
keys will return a list of the object's enumerable properties, including
those inherited from its prototype. The following example prints
'baz foo ':
$obj = $je->eval('Object.prototype.foo="bar"; ({baz:43}) ');
print "$_ " for keys %$obj;
exists and delete act upon properties of the object itself, ignoring
those of
its prototype, so exists $obj->{foo} will return false.
To call a method on an object or primitive data type, use the method
method:
my $number = $je->eval('42');
$number->method('toString', 16); # returns the number in hexadecimal
Just use a function as though it were a coderef:
$je->{Array}->();
If you need to specify the invocant ('this' value), use the call_with
method:
$je->{Number}{prototype}{toString}->call_with($je->eval('42'), 16);
To convert one of the fancy objects returned by JE into a simple Perl
value, use the value method.
$number->value; # simple Perl scalar $str->value; # likewise $obj->value; # hash ref $array->value; # array ref
Currently the value method of objects and arrays is not recursive, but
I plan to make it so later on. The only way to get consistent behaviour
between this and future versions is to pass recursive => 0 as
arguments.
If you are going to write you own custom data types, proxy objects, or subclasses of JE's classes, you'll need to read this. If not, you shouldn't need to, but you might like to anyway. :-)
Be warned that some of the methods described here can be hard
to use, and can easily result in code that's hard to debug, if misused.
This applies to those that expect their arguments already to be objects
compatible with the JE::Types interface. If you are not sure that a value you have is such, run it through the global object's upgrade method (or
just use the PUBLIC API, above).
These are the methods that the JavaScript engine itself uses (as opposed
to those provided for convenient access from the Perl side). Each class
provides whichever of the following methods are applicable. If
an object does not support a particular method, a TypeError will be thrown
when JavaScript code (indirectly) tries to call that method. (For instance,
'some_string'() will attempt to call the call method of JE::String,
thus resulting in a TypeError).
Gets or sets a property. Setting a property returns the new
value. The return value will be a Perl undef if the
property does not exist. See also JE::Object, for the
prop({ ... }) usage.
The new value is expected already to be an object compatible with the JE::Types interface.
Returns a list of the names of enumerable properties. This is a list of Perl strings, not JE::Strings.
Deletes the property named $name, if it is deletable. If the property did not exist or it was deletable, then true is returned. If the property exists and could not be deleted, false is returned.
JE::Object will also take a second argument, that allows one to indicate whether an undeletable property should be deleted. This is required by custom classes if the object in question is the global object.
The return value is a Perl scalar, not a JE::Boolean.
This returns a value that is supposed to be useful in Perl. The
value method of a JE::Object,
for instance, produces an array ref.
Runs the code associated with the object if it is a function. The arguments are passed as-is, and are not upgraded.
Runs the code associated with the object if it is a function. $obj will
be passed to the function as its invocant (its 'this' value).
The arguments are passed, as-is, and are not upgraded.
This is just like calling a function
in JS with the new keyword (which itself calls this method). It calls
the constructor, if this
function has one (functions written in JS
don't have this). Otherwise, an empty object will be created and passed to
the
function as its invocant. The return value of the function will be
returned if it is an object. Otherwise it will be discarded, and the object
originally passed to the function will be returned instead (possibly
modified).
Returns a boolean indicating whether the property exists and is not
inherited from a prototype. Used by
Object.prototype.hasOwnProperty. (The in operator checks to see
whether
the return value of prop is defined.)
To do: Implement this method in subclasses of JE::Object.
Not supported by the primitive JE classes. This returns a boolean
indicating whether a given property is readonly. If
it doesn't exist, then the is_readonly method of the object's prototype
is called with the same arguments. If there is no prototype, false is
returned.
This is used internally by JE::Object's prop method.
Not supported (yet) by the primitive JE classes. This returns a boolean
indicating whether a given property is enumerable.
This is used by Object.prototype.propertyIsEnumerable.
Returns a Perl string containing the type of the object. Used
by the JS typeof operator.
This applies to object classes only (though is going to change, so that
primitives can pretend to be objects). It returns
a
Perl string containing
the type of object. This is only used by the default JavaScript toString
method. If you create your own object class without subclassing JE::Object,
you should still provide the class method, so that this
JS code will still work:
YourClass.prototype.toString = Object.prototype.toString; (new YourClass).toString();
This returns a unique id for the object or primitive, used by
the JavaScript ===
operator. This id is unique as a string, not as a number.
The JE primitive classes provide a unique string beginning with the data type. The JE::Object and its subclasses return the memory address of the object itself. If you subclass JE::Object, you should not have to implement this method, unless you have multiple objects that you would like JS to consider the same object.
Note that the id 'num:nan' is treated specially. It is never considered equal to itself.
Returns true or false.
This applies to objects only, not to primitives. This method returns the
prototype of the object, or undef if there is no prototype. If $obj is
specified,
the prototype is set to that object first. The prop method uses this
method, as does JE::Object->new.
These each perform the appropriate type conversion. $preferred_type, which is optional, must be either 'string' or 'number'.
Calling to_string or to_number on a object is not exactly the same as
calling
to_primitive('string') or to_primitive('number'), because the
argument to to_primitive is merely a suggestion.
The last four methods in this list should not be overridden by subclasses of JE::Object.
Returns a reference to the global object.
This will only be called if it is implemented. Of JE's types, only primitive strings and numbers implement this.
$taint_brush will always be a tainted empty string. If the
object's internal value is not tainted, this method should return a tainted
clone
of
the object. Otherwise, it should return the object itself.
JE and all the modules listed above under WHICH CLASSES ARE WHICH.
| JE documentation | view source | Contained in the JE distribution. |