JE
view release on metacpan or search on metacpan
$self->prop({
name => 'Date',
autoload =>
'require JE::Object::Date;
JE::Object::Date::_new_constructor($global)',
dontenum => 1,
});
$self->prop({
name => 'RegExp',
autoload =>
'require JE::Object::RegExp;
JE::Object::RegExp->new_constructor($global)',
dontenum => 1,
});
$self->prop({
name => 'Error',
autoload =>
'require JE::Object::Error;
JE::Object::Error::_new_constructor($global)',
dontenum => 1,
});
# No EvalError
$self->prop({
name => 'RangeError',
autoload => 'require JE::Object::Error::RangeError;
JE::Object::Error::RangeError
->_new_subclass_constructor($global)',
dontenum => 1,
});
$self->prop({
name => 'ReferenceError',
autoload => 'require JE::Object::Error::ReferenceError;
JE::Object::Error::ReferenceError
->_new_subclass_constructor($global)',
dontenum => 1,
});
$self->prop({
name => 'SyntaxError',
autoload => 'require JE::Object::Error::SyntaxError;
JE::Object::Error::SyntaxError
->_new_subclass_constructor($global)',
dontenum => 1,
});
$self->prop({
name => 'TypeError',
autoload => 'require JE::Object::Error::TypeError;
JE::Object::Error::TypeError
->_new_subclass_constructor($global)',
dontenum => 1,
});
$self->prop({
name => 'URIError',
autoload => 'require JE::Object::Error::URIError;
JE::Object::Error::URIError
->_new_subclass_constructor($global)',
dontenum => 1,
});
# E 15.1.1
$self->prop({
name => 'NaN',
value => JE::Number->new($self, 'NaN'),
dontenum => 1,
dontdel => 1,
});
$self->prop({
name => 'Infinity',
value => JE::Number->new($self, 'Infinity'),
dontenum => 1,
dontdel => 1,
});
$self->prop({
name => 'undefined',
value => $self->undefined,
dontenum => 1,
dontdel => 1,
});
# E 15.1.2
$self->prop({
name => 'eval',
value => JE::Object::Function->new({
scope => $self,
name => 'eval',
argnames => ['x'],
function_args => [qw< args >],
function => sub {
my($code) = @_;
return $self->undefined unless defined
$code;
return $code if typeof $code ne 'string';
my $old_at = $@; # hope it's not tied
defined (my $tree =
($JE::Code::parser||$self)
->parse($code))
or die;
my $ret = execute $tree
$JE::Code::this,
$JE::Code::scope, 1;
ref $@ ne '' and die;
$@ = $old_at;
$ret;
},
no_proto => 1,
}),
dontenum => 1,
});
$self->prop({
name => 'parseInt',
value => JE::Object::Function->new({
scope => $self,
name => 'parseInt', # E 15.1.2.2
argnames => [qw/string radix/],
no_proto => 1,
function_args => [qw< scope args >],
function => sub {
my($scope,$str,$radix) = @_;
$radix = defined $radix
? $radix->to_number->value
$ret= $sign * $str;
}
elsif($radix == 16) {
$ret= $sign * hex $str;
}
elsif($radix == 8) {
$ret= $sign * oct $str;
}
elsif($radix == 2) {
$ret= $sign * eval
"0b$str";
}
else { my($num, $place);
for (reverse split //, $str){
$num += ($_ =~ /[0-9]/ ? $_
: ord(uc) - 55)
* $radix**$place++
}
$ret= $num*$sign;
}
return JE::Number->new($self,$ret);
},
}),
dontenum => 1,
});
$self->prop({
name => 'parseFloat',
value => JE::Object::Function->new({
scope => $self,
name => 'parseFloat', # E 15.1.2.3
argnames => [qw/string/],
no_proto => 1,
function_args => [qw< scope args >],
function => sub {
my($scope,$str,$radix) = @_;
defined $str or $str = '';
ref $str eq 'JE::Number' and return $str;
ref $str eq 'JE::Object::Number'
and return $str->to_number;
return JE::Number->new($self, $str =~
/^$s
(
[+-]?
(?:
(?=[0-9]|\.[0-9]) [0-9]*
(?:\.[0-9]*)?
(?:[Ee][+-]?[0-9]+)?
|
Infinity
)
)
/ox
? $1 : 'nan');
},
}),
dontenum => 1,
});
$self->prop({
name => 'isNaN',
value => JE::Object::Function->new({
scope => $self,
name => 'isNaN',
argnames => [qw/number/],
no_proto => 1,
function_args => ['args'],
function => sub {
JE::Boolean->new($self,
!defined $_[0] ||
shift->to_number->id eq 'num:nan');
},
}),
dontenum => 1,
});
$self->prop({
name => 'isFinite',
value => JE::Object::Function->new({
scope => $self,
name => 'isFinite',
argnames => [qw/number/],
no_proto => 1,
function_args => ['args'],
function => sub {
my $val = shift;
JE::Boolean->new($self,
defined $val &&
($val = $val->to_number->value)
== $val &&
$val + 1 != $val
);
},
}),
dontenum => 1,
});
# E 15.1.3
$self->prop({
name => 'decodeURI',
autoload => q{ require 'JE/escape.pl';
JE::Object::Function->new({
scope => $global,
name => 'decodeURI',
argnames => [qw/encodedURI/],
no_proto => 1,
function_args => ['scope','args'],
function => \&JE'_decodeURI,
})
},
dontenum => 1,
});
$self->prop({
name => 'decodeURIComponent',
autoload => q{ require 'JE/escape.pl';
JE::Object::Function->new({
scope => $global,
name => 'decodeURIComponent',
argnames => [qw/encodedURIComponent/],
no_proto => 1,
function_args => ['scope','args'],
function => \&JE'_decodeURIComponent
})
},
dontenum => 1,
"".new JE ->eval(q| Function('foo','return[a]')() | )
=item *
The C<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
=item *
Currently if a try-(catch)-finally statementâs C<try> and C<catch> blocks
don't return anything, the return value is taken from the C<finally> block.
This is incorrect. There should be no return value. In other words, this
should return 3:
eval(' 3; try{}finally{5} ')
=item *
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")
=item *
Serialisation of RegExp objects with Data::Dump::Streamer is currently
broken (and has been since 0.022).
=back
=head2 Limitations
=over 4
=item *
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 C<toPrecision>, etc.) goes the wrong way.
=item *
A Perl subroutine called from JavaScript can sneak past a C<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";
=item *
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.
=back
=head2 Incompatibilities with ECMAScript...
...that are probably due to typos in the spec.
=over 4
=item *
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 'I<TryStatement> : B<try> I<Block Catch Finally>' algorithm. Step 5 should
probably read 'Let I<C> = Result(4),' rather than 'If Result(4).type is not B<normal>, Let I<C> = Result(4).'
=item *
If the expression between the two colons in a C<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 I<ExpressionNoIn> is not present,
go to step 4,' rather than 'If the first I<Expression> is not present, go
to step 4.'
=item *
The C<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 I<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.
=back
=head1 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
B<Note:> JE will probably end up with Unicode::Collate in
the list of dependencies.
=head1 AUTHOR, COPYRIGHT & LICENSE
Copyright (C) 2007-14 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 L<Data::Float>, which is copyrighted (C)
2006, 2007, 2008 by Andrew Main (Zefram).
=head1 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.
=head1 SEE ALSO
The other JE man pages, especially the following (the rest are listed on
the L<JE::Types> page):
=over 4
=item L<JE::Destroyer>
=item L<JE::Types>
( run in 0.470 second using v1.01-cache-2.11-cpan-804bf51f3ce )