=head1 NAME

JE::Types - JavaScript types and objects

This is just documentation, not a module.

=head1 DESCRIPTION

The various JavaScript types and objects are represented by Perl
classes in JE. Each class provides whichever methods listed
below apply.

If you are creating your own object classes in Perl for
JavaScript to use, you can subclass JE::Object, but you don't
have to, in which case you ought to implement the C<prop>, C<delete>,
C<method>,
C<typeof>, C<class>, C<id>, C<primitive>, C<prototype> and C<to_object> 
methods;
otherwise TypeErrors may occur unexpectedly.

=head1 UPGRADING VALUES

When a value is passed to the C<prop> and C<method> methods of objects, and
to various other functions, it will be "upgraded" to a Perl object
representing a JavaScript value. This is done by the C<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 C<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

B<WARNING:> The 'upgrading' of simple scalars (strings/numbers) and regexps
is still 
subject to change.

B<To do:> Make &JE::upgrade detect whether a simple scalar is a string or 
number.

B<To do:> Convert Regexp objects to
JE::Object::RegExp objects.

=head1 WHICH CLASSES ARE WHICH

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

The last two are for internal use. 
  

=head1 METHODS

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,
C<'some_string'()> will attempt to call the C<call> method of JE::String,
thus resulting in a TypeError).

=over 4

=item prop($name)

=item prop($name, $new_value)

Gets or sets a property. Setting a property returns the new
value. The new value will be converted to a JS value
automatically if it is not one already. (See
L</UPGRADING VALUES>.) The return value will be a Perl undef if the
property does not exist. See also the S<< C<prop({ ... })> >> usage below.

=item keys

Returns a list of the names of enumerable properties. This is a list of
Perl strings, not JE::Strings.

=item delete($name)

=item delete($name, $even_if_it's_undeletable)

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.

If the second argument is given and is true, the property will be deleted
even if it is marked is undeletable, if the object supports it.

The return value is a Perl scalar, not a JE::Boolean.

=item method($name, $arg1, $arg2, ...)

Invokes the specified method through the object. The arguments
are automatically upgraded.

=item value

This returns a value that is supposed to be useful in Perl. The 
C<< value >> method of a JE::Object,
for instance, produces an array ref.

=item call(@args)

Runs the code associated with the object if it is a function.
The arguments
are automatically upgraded.

=item apply($obj, @args)

Runs the code associated with the object if it is a function. C<$obj> will
be passed to the function as its invocant (its 'this' value).
The arguments
are automatically upgraded.

=item construct(@args)

This is just like calling a function
in JS with the C<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).

=back

The rest of these are mostly for internal use:

=over 4

=item I<Class>->new($global_obj, @args)

The C<@args> are in the same order that they are passed to the constructor
function in JavaScript (for objects, not primitives. For primitive classes, 
there should be only two
arguments, the global object and the value).

Some object classes also provide a hash ref syntax. See each object class's
respective man page.

User-defined classes do not need to accept arguments in the same order as
those that come with JE. They can do whatever they like.

=item prop({ ... })

The C<prop> method can be called with a hash ref as its argument. In this
case, the prototype chain is I<not> searched.
The elements of the hash are as follows:

  name      property name
  value     new value
  dontenum  whether this property is unenumerable
  dontdel   whether this property is undeletable
  readonly  whether this property is read-only
  fetch     subroutine called when the property is fetched
  store     subroutine called when the property is set
  autoload  see below

If C<dontenum>, C<dontdel> or C<readonly> is given, the attribute in 
question will be set.
If C<value> is given, the value of the property will be set, regardless of
the attributes.

C<fetch> and C<store>, if specified, must be subroutines for
fetching/setting the value of the property. The 'fetch' subroutine will be
called with ($object, $storage_space) as the arguments, where
C<$storage_space> is a hash key inside the object that the two subroutines
can use for storing the value (they can ignore it if they like). The
'store' subroutine will be call with
($object, $new_value, $storage_space) as
the arguments. Values assigned to the storage space from within these 
routines are I<not>
upgraded, neither is the return value of C<fetch>. C<fetch> and C<store> do 
not necessarily have to go
together. If you only specify C<fetch>, then the value will be set as
usual, but C<fetch> will be able to mangle the value when it is retrieved.
Likewise, if you only specify C<store>, the value will be retrieved the
usual way, so you can use this for validating or normalising the assigned
value, for
instance. B<Note:> Currently, a simple scalar or unblessed coderef in the
storage space will cause autoloading, but that is subject to change.

C<autoload> can be a string or a coderef. It will be called/evalled the
first time the property is accessed (accessing it with a hash ref as
described here does not count). If it is a string, it will be
evaluated in a scope that has a variable name C<$global>, containing a 
reference to the global object. The result will become the
property's value. The value returned is not currently upgraded. The behaviour when a simple scalar or unblessed reference is returned is
undefined. C<autoload> will be
ignored completely if C<value> or C<fetch> is also given.

This hash ref calling convention is not supported by Arguments objects or
by the primitive classes. It 
does not work on Array
objects when the property name is C<length> or an array index (a 
non-negative integer 
below
4294967295). It does not work on strings or String objects if the
property name is C<length>.

=item exists($property_name)

Returns a boolean indicating whether the property exists and is not
inherited from a prototype. Used by 
C<Object.prototype.hasOwnProperty>. (The C<in> operator checks to see 
whether
the return value of C<prop> is defined.)

B<To do:> Make C<hasOwnProperty> use the C<exists> method. Right
now it uses C<prop> with hashref syntax.

B<To do:> Implement this method.

=item is_readonly($property_name)

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 C<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 C<prop> method.

=item is_enum($property_name)

Not supported (yet) by the primitive JE classes. This returns a boolean 
indicating whether a given property is enumerable.
This is used by C<Object.prototype.propertyIsEnumerable>.

=item typeof

Returns a Perl string containing the type of the object. Used
by the JS C<typeof> operator.

=item class

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 defoult JavaScript C<toString>
method. If you create your own object class without subclassing JE::Object,
you should I<still> provide the C<class> method, so that this
JS code will still work:

  YourClass.prototype.toString = Object.prototype.toString;
  (new YourClass).toString();

=item id

This returns a unique id for the object or primitive, used by 
the JavaScript C<===>
operator. This id is unique as a I<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.

=item primitive

Returns true or false.

=item prototype

=item prototype ( $obj )

This applies to objects only, not to primitives. This method returns the 
prototype of the object, or undef if there is no prototype. If C<$obj> is 
specified,
the prototype is set to that object first. The C<prop> method uses this
method, as does C<< JE::Object->new >>.

=item to_primitive($preferred_type)

=item to_boolean

=item to_string

=item to_number

=item to_object

These each perform the appropriate type conversion. $preferred_type, which 
is 
optional, must be either 'string' or 'number'.

Calling C<to_string> or C<to_number> on a object is not exactly the same as 
calling
C<to_primitive('string')> or C<to_primitive('number')>, because the
argument to C<to_primitive> is merely a I<suggestion.>

The last four methods in this list should not be overridden by subclasses
of JE::Object.

=item global

Returns a reference to the global object.

=back

=head1 OVERLOADED OPERATORS

All classes overload the "" (stringification) operator. See each
class's respective man page (both primitives and objects) for more info on
overloaded ops.

=head1 SEE ALSO

L<JE> and all the modules listed above under L<WHICH CLASSES ARE WHICH>.

=cut




